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