name: CI/CD Pipeline on: push: branches: [ main, develop, preview-capabilities-phase1-2 ] pull_request: branches: [ main, develop ] env: NODE_VERSION: '20' FIREBASE_PROJECT_ID: ${{ secrets.FIREBASE_PROJECT_ID }} SUPABASE_URL: ${{ secrets.SUPABASE_URL }} SUPABASE_ANON_KEY: ${{ secrets.SUPABASE_ANON_KEY }} SUPABASE_SERVICE_ROLE_KEY: ${{ secrets.SUPABASE_SERVICE_ROLE_KEY }} ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} GOOGLE_CLOUD_PROJECT_ID: ${{ secrets.GOOGLE_CLOUD_PROJECT_ID }} GCS_BUCKET_NAME: ${{ secrets.GCS_BUCKET_NAME }} jobs: # Lint and Test Backend backend-lint-test: name: Backend - Lint & Test runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} cache: 'npm' cache-dependency-path: backend/package-lock.json - name: Install backend dependencies working-directory: ./backend run: npm ci - name: Run ESLint working-directory: ./backend run: npm run lint - name: Run TypeScript check working-directory: ./backend run: npm run type-check - name: Run backend tests working-directory: ./backend run: npm test env: NODE_ENV: test SUPABASE_URL: ${{ env.SUPABASE_URL }} SUPABASE_ANON_KEY: ${{ env.SUPABASE_ANON_KEY }} - name: Upload test coverage uses: codecov/codecov-action@v3 with: file: ./backend/coverage/lcov.info flags: backend name: backend-coverage # Lint and Test Frontend frontend-lint-test: name: Frontend - Lint & Test runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} cache: 'npm' cache-dependency-path: frontend/package-lock.json - name: Install frontend dependencies working-directory: ./frontend run: npm ci - name: Run ESLint working-directory: ./frontend run: npm run lint - name: Run TypeScript check working-directory: ./frontend run: npm run type-check - name: Run frontend tests working-directory: ./frontend run: npm test env: NODE_ENV: test - name: Upload test coverage uses: codecov/codecov-action@v3 with: file: ./frontend/coverage/lcov.info flags: frontend name: frontend-coverage # Security Scan 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 to GitHub Security tab uses: github/codeql-action/upload-sarif@v2 if: always() with: sarif_file: 'trivy-results.sarif' # Build Backend build-backend: name: Build Backend runs-on: ubuntu-latest needs: [backend-lint-test, security-scan] steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} cache: 'npm' cache-dependency-path: backend/package-lock.json - name: Install backend dependencies working-directory: ./backend run: npm ci - name: Build backend working-directory: ./backend run: npm run build - name: Upload backend build artifacts uses: actions/upload-artifact@v3 with: name: backend-build path: backend/dist/ retention-days: 7 # Build Frontend build-frontend: name: Build Frontend runs-on: ubuntu-latest needs: [frontend-lint-test, security-scan] steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} cache: 'npm' cache-dependency-path: frontend/package-lock.json - name: Install frontend dependencies working-directory: ./frontend run: npm ci - name: Build frontend working-directory: ./frontend run: npm run build - name: Upload frontend build artifacts uses: actions/upload-artifact@v3 with: name: frontend-build path: frontend/dist/ retention-days: 7 # Integration Tests integration-tests: name: Integration Tests runs-on: ubuntu-latest needs: [build-backend, build-frontend] services: postgres: image: postgres:15 env: POSTGRES_PASSWORD: postgres POSTGRES_DB: test_db options: >- --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 ports: - 5432:5432 steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} cache: 'npm' cache-dependency-path: backend/package-lock.json - name: Download backend build artifacts uses: actions/download-artifact@v3 with: name: backend-build path: backend/dist/ - name: Install backend dependencies working-directory: ./backend run: npm ci --only=production - name: Run integration tests working-directory: ./backend run: npm run test:integration env: NODE_ENV: test DATABASE_URL: postgresql://postgres:postgres@localhost:5432/test_db SUPABASE_URL: ${{ env.SUPABASE_URL }} SUPABASE_ANON_KEY: ${{ env.SUPABASE_ANON_KEY }} # Deploy to Staging deploy-staging: name: Deploy to Staging runs-on: ubuntu-latest needs: [integration-tests] if: github.ref == 'refs/heads/develop' environment: staging steps: - name: Checkout code uses: actions/checkout@v4 - name: Download build artifacts uses: actions/download-artifact@v3 with: name: backend-build path: backend/dist/ - name: Download frontend build artifacts uses: actions/download-artifact@v3 with: name: frontend-build path: frontend/dist/ - name: Setup Firebase CLI uses: w9jds/firebase-action@master with: args: deploy --only hosting,functions --project staging-${{ env.FIREBASE_PROJECT_ID }} env: FIREBASE_TOKEN: ${{ secrets.FIREBASE_TOKEN }} - name: Run smoke tests run: | echo "Running smoke tests against staging environment..." # Add smoke test commands here curl -f https://staging-${{ env.FIREBASE_PROJECT_ID }}.web.app/health || exit 1 # Deploy to Production deploy-production: name: Deploy to Production runs-on: ubuntu-latest needs: [integration-tests] if: github.ref == 'refs/heads/main' environment: production steps: - name: Checkout code uses: actions/checkout@v4 - name: Download build artifacts uses: actions/download-artifact@v3 with: name: backend-build path: backend/dist/ - name: Download frontend build artifacts uses: actions/download-artifact@v3 with: name: frontend-build path: frontend/dist/ - name: Setup Firebase CLI uses: w9jds/firebase-action@master with: args: deploy --only hosting,functions --project ${{ env.FIREBASE_PROJECT_ID }} env: FIREBASE_TOKEN: ${{ secrets.FIREBASE_TOKEN }} - name: Run production health checks run: | echo "Running health checks against production environment..." # Add health check commands here curl -f https://${{ env.FIREBASE_PROJECT_ID }}.web.app/health || exit 1 - name: Notify deployment success if: success() run: | echo "Production deployment successful!" # Add notification logic here (Slack, email, etc.) # Performance Testing performance-tests: name: Performance Tests runs-on: ubuntu-latest needs: [deploy-staging] if: github.ref == 'refs/heads/develop' steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} - name: Install dependencies run: npm ci - name: Run performance tests run: npm run test:performance env: TEST_URL: https://staging-${{ env.FIREBASE_PROJECT_ID }}.web.app - name: Upload performance results uses: actions/upload-artifact@v3 with: name: performance-results path: performance-results/ retention-days: 30 # Dependency Updates dependency-updates: name: Dependency Updates runs-on: ubuntu-latest if: github.event_name == 'schedule' steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} - name: Check for outdated dependencies run: | echo "Checking for outdated dependencies..." npm outdated || echo "No outdated dependencies found" - name: Create Dependabot PR if: failure() run: | echo "Creating Dependabot PR for outdated dependencies..." # Add logic to create PR with dependency updates