video-accessibility/.github/workflows/ci.yml
2025-08-24 16:28:33 -05:00

312 lines
No EOL
7.8 KiB
YAML

name: CI
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main, develop ]
env:
PYTHON_VERSION: "3.11"
NODE_VERSION: "20"
jobs:
backend-lint-and-test:
name: Backend Lint & Test
runs-on: ubuntu-latest
services:
mongodb:
image: mongo:7.0
ports:
- 27017:27017
options: >-
--health-cmd "echo 'db.runCommand("ping").ok' | mongosh --quiet"
--health-interval 10s
--health-timeout 5s
--health-retries 5
redis:
image: redis:7-alpine
ports:
- 6379:6379
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Install Poetry
uses: snok/install-poetry@v1
with:
version: latest
virtualenvs-create: true
virtualenvs-in-project: true
- name: Load cached dependencies
id: cached-poetry-dependencies
uses: actions/cache@v4
with:
path: backend/.venv
key: poetry-${{ runner.os }}-${{ env.PYTHON_VERSION }}-${{ hashFiles('backend/poetry.lock') }}
- name: Install dependencies
if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
working-directory: ./backend
run: poetry install --no-interaction --no-root
- name: Install project
working-directory: ./backend
run: poetry install --no-interaction
- name: Run linting (ruff)
working-directory: ./backend
run: poetry run ruff check .
- name: Run type checking (mypy)
working-directory: ./backend
run: poetry run mypy .
- name: Run unit tests
working-directory: ./backend
env:
MONGODB_URI: mongodb://localhost:27017
MONGODB_DB: test_accessible_video
REDIS_URL: redis://localhost:6379
JWT_SECRET: test_jwt_secret_for_ci
GEMINI_API_KEY: fake_key_for_testing
GCP_PROJECT_ID: test-project
GCS_BUCKET: test-bucket
SENDGRID_API_KEY: fake_sendgrid_key
EMAIL_FROM: test@example.com
CLIENT_BASE_URL: http://localhost:3000
run: |
poetry run pytest tests/unit/ -v --cov=app --cov-report=xml --cov-report=term-missing
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
with:
file: ./backend/coverage.xml
flags: backend
name: backend-coverage
frontend-lint-and-test:
name: Frontend Lint & Test
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
cache-dependency-path: frontend/package-lock.json
- name: Install dependencies
working-directory: ./frontend
run: npm ci
- name: Run linting (ESLint)
working-directory: ./frontend
run: npm run lint
- name: Run type checking (TypeScript)
working-directory: ./frontend
run: npm run type-check
- name: Run unit tests (Vitest)
working-directory: ./frontend
run: npm run test -- --coverage --reporter=verbose
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
with:
file: ./frontend/coverage/lcov.info
flags: frontend
name: frontend-coverage
integration-tests:
name: Integration Tests
runs-on: ubuntu-latest
needs: [backend-lint-and-test, frontend-lint-and-test]
services:
mongodb:
image: mongo:7.0
ports:
- 27017:27017
options: >-
--health-cmd "echo 'db.runCommand("ping").ok' | mongosh --quiet"
--health-interval 10s
--health-timeout 5s
--health-retries 5
redis:
image: redis:7-alpine
ports:
- 6379:6379
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Install Poetry
uses: snok/install-poetry@v1
- name: Install backend dependencies
working-directory: ./backend
run: poetry install
- name: Run integration tests
working-directory: ./backend
env:
MONGODB_URI: mongodb://localhost:27017
MONGODB_DB: test_accessible_video_integration
REDIS_URL: redis://localhost:6379
JWT_SECRET: test_jwt_secret_for_integration
GEMINI_API_KEY: fake_key_for_testing
GCP_PROJECT_ID: test-project
GCS_BUCKET: test-bucket
SENDGRID_API_KEY: fake_sendgrid_key
EMAIL_FROM: test@example.com
CLIENT_BASE_URL: http://localhost:3000
run: |
poetry run pytest tests/integration/ -v
build-backend:
name: Build Backend Docker Image
runs-on: ubuntu-latest
needs: [backend-lint-and-test]
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build backend image
uses: docker/build-push-action@v5
with:
context: ./backend
file: ./backend/Dockerfile
push: false
tags: accessible-video-backend:${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=max
build-frontend:
name: Build Frontend
runs-on: ubuntu-latest
needs: [frontend-lint-and-test]
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
cache-dependency-path: frontend/package-lock.json
- name: Install dependencies
working-directory: ./frontend
run: npm ci
- name: Build for production
working-directory: ./frontend
env:
VITE_API_BASE_URL: https://api.example.com # Placeholder for production
VITE_APP_ENV: production
run: npm run build
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: frontend-dist
path: frontend/dist/
retention-days: 7
security-scan:
name: Security Scan
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@master
with:
scan-type: 'fs'
scan-ref: '.'
format: 'sarif'
output: 'trivy-results.sarif'
- name: Upload Trivy scan results
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: 'trivy-results.sarif'
- name: Run Semgrep security scan
uses: semgrep/semgrep-action@v1
with:
config: auto
generateBaseline: false
dependency-check:
name: Dependency Check
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Install Poetry
uses: snok/install-poetry@v1
- name: Check backend dependencies
working-directory: ./backend
run: |
poetry check
poetry run pip-audit
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: Check frontend dependencies
working-directory: ./frontend
run: |
npm audit --audit-level moderate
npx better-npm-audit audit