Merge branch 'fix/code-review-findings-story-6-1' #10
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Build and Deploy | |
| on: | |
| push: | |
| branches: [master] | |
| pull_request: | |
| branches: [master] | |
| # Concurrency: For PRs, cancel in-progress runs. For master pushes, queue deployments. | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: ${{ github.event_name == 'pull_request' }} | |
| jobs: | |
| # ============================================ | |
| # STAGE 1: Security & Linting (runs in parallel) | |
| # ============================================ | |
| security: | |
| name: Security Scan (npm audit) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '20' | |
| cache: 'npm' | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Run npm audit (high/critical) | |
| run: npm audit --audit-level=high | |
| semgrep: | |
| name: Security Scan (Semgrep SAST) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Run Semgrep SAST | |
| uses: returntocorp/semgrep-action@v1 | |
| with: | |
| config: >- | |
| p/javascript | |
| p/typescript | |
| p/security-audit | |
| lint: | |
| name: Lint & Type Check | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '20' | |
| cache: 'npm' | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Generate Astro types | |
| run: npx astro sync | |
| - name: TypeScript check (src only) | |
| run: npx tsc --noEmit --project tsconfig.ci.json | |
| - name: Run gts lint | |
| run: npm run lint | |
| - name: Run gts check (formatting) | |
| run: npm run check | |
| # ============================================ | |
| # STAGE 2: Build + Unit Tests (parallel, needs lint/security) | |
| # ============================================ | |
| build: | |
| name: Build | |
| needs: [security, semgrep, lint] | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '20' | |
| cache: 'npm' | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Build Astro site | |
| run: npm run build | |
| - name: Run Closure Compiler lint check | |
| run: npx google-closure-compiler --jscomp_warning=lintChecks --js='dist/**/*.js' --checks_only || true | |
| - name: Upload build artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: dist | |
| path: dist/ | |
| retention-days: 1 | |
| unit-tests: | |
| name: Unit Tests | |
| needs: [security, semgrep, lint] | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '20' | |
| cache: 'npm' | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Run Vitest with coverage | |
| run: npm run test:coverage -- --reporter=github-actions | |
| - name: Upload coverage report | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: coverage-report | |
| path: coverage/ | |
| retention-days: 7 | |
| # ============================================ | |
| # STAGE 3: E2E + Lighthouse (after build, parallel) | |
| # ============================================ | |
| e2e-tests: | |
| name: E2E Tests | |
| needs: build | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '20' | |
| cache: 'npm' | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Cache Playwright browsers | |
| uses: actions/cache@v4 | |
| id: playwright-cache | |
| with: | |
| path: ~/.cache/ms-playwright | |
| key: playwright-browsers-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }} | |
| - name: Install Playwright (all browsers) | |
| if: steps.playwright-cache.outputs.cache-hit != 'true' | |
| run: npx playwright install --with-deps | |
| - name: Install Playwright deps (if cache hit) | |
| if: steps.playwright-cache.outputs.cache-hit == 'true' | |
| run: npx playwright install-deps | |
| - name: Download build artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: dist | |
| path: dist/ | |
| - name: Start server and run E2E tests | |
| run: | | |
| npx serve dist -l 4321 & | |
| npx wait-on http://localhost:4321 | |
| npm run test:e2e | |
| env: | |
| CI: true | |
| - name: Upload Playwright report on failure | |
| uses: actions/upload-artifact@v4 | |
| if: failure() | |
| with: | |
| name: playwright-report | |
| path: playwright-report/ | |
| retention-days: 7 | |
| lighthouse: | |
| name: Lighthouse CI | |
| needs: build | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '20' | |
| cache: 'npm' | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Download build artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: dist | |
| path: dist/ | |
| - name: Run Lighthouse CI | |
| uses: treosh/lighthouse-ci-action@v12 | |
| with: | |
| configPath: ./lighthouserc.json | |
| uploadArtifacts: true | |
| # ============================================ | |
| # STAGE 4: Deploy (master push only, after all checks) | |
| # ============================================ | |
| deploy: | |
| name: Deploy to GitHub Pages | |
| needs: [build, unit-tests, e2e-tests, lighthouse] | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/master' | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Download build artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: dist | |
| path: dist/ | |
| - name: Deploy to GitHub Pages | |
| uses: peaceiris/actions-gh-pages@v4 | |
| with: | |
| github_token: ${{ secrets.GITHUB_TOKEN }} | |
| publish_dir: ./dist |