deps(frontend): bump the frontend-minor-patch group across 1 directory with 28 updates #4565
Workflow file for this run
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: Frontend Checks | |
| permissions: | |
| contents: read | |
| security-events: write | |
| pull-requests: write | |
| on: | |
| pull_request: | |
| branches: ['master', 'develop'] | |
| paths: | |
| - 'Clients/**' | |
| - '.github/workflows/frontend-checks.yml' | |
| push: | |
| branches: ['master', 'develop'] | |
| paths: | |
| - 'Clients/**' | |
| - '.github/workflows/frontend-checks.yml' | |
| jobs: | |
| security-audit: | |
| name: Security Audit | |
| runs-on: ubuntu-latest | |
| defaults: | |
| run: | |
| working-directory: Clients | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Set up Node | |
| uses: actions/setup-node@v7 | |
| with: | |
| node-version: '22' | |
| cache: 'npm' | |
| cache-dependency-path: Clients/package-lock.json | |
| - name: Install dependencies | |
| run: npm ci --legacy-peer-deps | |
| - name: Run npm audit | |
| run: npm audit --audit-level=high | |
| continue-on-error: true | |
| - name: Run npm audit (JSON output for review) | |
| run: npm audit --json > ../audit-results.json || true | |
| - name: Upload audit results | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: frontend-npm-audit-results | |
| path: audit-results.json | |
| retention-days: 30 | |
| lint-and-typecheck: | |
| name: Lint, Types & i18n | |
| runs-on: ubuntu-latest | |
| defaults: | |
| run: | |
| working-directory: Clients | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Set up Node | |
| uses: actions/setup-node@v7 | |
| with: | |
| node-version: '22' | |
| cache: 'npm' | |
| cache-dependency-path: Clients/package-lock.json | |
| - name: Install dependencies | |
| run: npm ci --legacy-peer-deps | |
| - name: Prettier format check | |
| run: npm run format-check | |
| - name: TypeScript type check | |
| run: npm run typecheck | |
| - name: i18n audit (catch dictionary drift) | |
| run: npm run i18n:audit:strict | |
| - name: Dependency vulnerability audit | |
| run: | | |
| npm audit --audit-level=high --omit=dev || true | |
| node $GITHUB_WORKSPACE/scripts/security/npm-audit-gate.js . | |
| unit-and-component-tests: | |
| name: Unit & Component Tests (shard ${{ matrix.shard }}/4) | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| shard: [1, 2, 3, 4] | |
| defaults: | |
| run: | |
| working-directory: Clients | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Set up Node | |
| uses: actions/setup-node@v7 | |
| with: | |
| node-version: '22' | |
| cache: 'npm' | |
| cache-dependency-path: Clients/package-lock.json | |
| - name: Install dependencies | |
| run: npm ci --legacy-peer-deps | |
| - name: Run tests (shard ${{ matrix.shard }}/4) | |
| run: npx vitest run --shard=${{ matrix.shard }}/4 | |
| # Runs the CI test command with coverage on every push and pull request, | |
| # uploading the coverage report and enforcing the configured thresholds. | |
| coverage: | |
| name: Coverage | |
| runs-on: ubuntu-latest | |
| defaults: | |
| run: | |
| working-directory: Clients | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Set up Node | |
| uses: actions/setup-node@v7 | |
| with: | |
| node-version: '22' | |
| cache: 'npm' | |
| cache-dependency-path: Clients/package-lock.json | |
| - name: Install dependencies | |
| run: npm ci --legacy-peer-deps | |
| - name: Run tests with coverage | |
| run: npm run test:ci | |
| - name: Dependency vulnerability audit | |
| run: | | |
| npm audit --audit-level=high --omit=dev || true | |
| node $GITHUB_WORKSPACE/scripts/security/npm-audit-gate.js . | |
| - name: Upload coverage report | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: frontend-coverage-report | |
| path: Clients/coverage/ | |
| retention-days: 14 | |
| - name: Post coverage gate failure comment | |
| if: github.event_name == 'pull_request' && failure() | |
| uses: actions/github-script@v9 | |
| with: | |
| script: | | |
| const fs = require("fs"); | |
| const summaryPath = "Clients/coverage/coverage-summary.json"; | |
| if (!fs.existsSync(summaryPath)) { | |
| console.log("coverage-summary.json not found, skipping comment"); | |
| return; | |
| } | |
| const json = JSON.parse(fs.readFileSync(summaryPath, "utf8")); | |
| const total = json.total; | |
| const threshold = { statements: 50, branches: 40, functions: 45, lines: 50 }; | |
| const rows = ["| Metric | Threshold | Actual | Status |", "|--------|----------:|------:|:------:|"]; | |
| let passed = true; | |
| for (const key of ["statements", "branches", "functions", "lines"]) { | |
| const actual = total[key].pct; | |
| const ok = actual >= threshold[key]; | |
| if (!ok) passed = false; | |
| rows.push(`| ${key.charAt(0).toUpperCase() + key.slice(1)} | ${threshold[key]}% | ${actual}% | ${ok ? "✅" : "❌"} |`); | |
| } | |
| if (passed) { | |
| console.log("All coverage thresholds pass"); | |
| return; | |
| } | |
| const body = `## Coverage Gate Failed\n\n${rows.join("\n")}\n\n<!-- coverage-gate -->`; | |
| const { data: comments } = await github.rest.issues.listComments({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number, | |
| }); | |
| const marker = "<!-- coverage-gate -->"; | |
| const existing = comments.find(c => c.body && c.body.includes(marker)); | |
| if (existing) { | |
| await github.rest.issues.updateComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| comment_id: existing.id, | |
| body, | |
| }); | |
| } else { | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number, | |
| body, | |
| }); | |
| } | |
| - name: Post coverage gate success comment | |
| if: github.event_name == 'pull_request' && success() | |
| uses: actions/github-script@v9 | |
| with: | |
| script: | | |
| const body = "## ✅ Coverage Gate Passed\n\nAll coverage thresholds are met.\n\n<!-- coverage-gate -->"; | |
| const { data: comments } = await github.rest.issues.listComments({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number, | |
| }); | |
| const marker = "<!-- coverage-gate -->"; | |
| const existing = comments.find(c => c.body && c.body.includes(marker)); | |
| if (existing) { | |
| await github.rest.issues.updateComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| comment_id: existing.id, | |
| body, | |
| }); | |
| } else { | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number, | |
| body, | |
| }); | |
| } | |
| dependency-review: | |
| name: Dependency Review | |
| runs-on: ubuntu-latest | |
| if: github.event_name == 'pull_request' | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Dependency Review | |
| uses: actions/dependency-review-action@v5 | |
| with: | |
| fail-on-severity: high | |
| deny-licenses: GPL-3.0, AGPL-3.0 | |
| allow-ghsas: GHSA-mh99-v99m-4gvg, GHSA-qwww-vcr4-c8h2 |