Merge pull request #1164 from charityagbenu12-cmd/fix/somzilla-issues #75
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: Coverage | |
| # Per-package coverage collection, minimum thresholds and a PR comment with the | |
| # delta against the target branch (issue #1090). | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| branches: [main, develop] | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| jobs: | |
| # ── Per-package collection ──────────────────────────────────────────────── | |
| # Each package uploads its coverage-summary.json; the report job aggregates | |
| # them. Failures here are the package's own threshold, checked by its test | |
| # runner. `continue-on-error` keeps one package's gate from hiding another's | |
| # numbers — the aggregate `--check` in the report job is the blocking gate. | |
| backend: | |
| name: Backend | |
| runs-on: ubuntu-latest | |
| continue-on-error: true | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: "20" | |
| cache: "npm" | |
| cache-dependency-path: backend/package-lock.json | |
| - run: npm ci | |
| working-directory: backend | |
| - name: Run tests with coverage | |
| working-directory: backend | |
| env: | |
| NODE_ENV: test | |
| JWT_SECRET: test-secret | |
| ADMIN_API_KEY: test-admin-key | |
| run: npm test -- --coverage --ci | |
| - uses: actions/upload-artifact@v7 | |
| if: always() | |
| with: | |
| name: coverage-backend | |
| path: backend/coverage/coverage-summary.json | |
| if-no-files-found: warn | |
| client: | |
| name: Client | |
| runs-on: ubuntu-latest | |
| continue-on-error: true | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: "20" | |
| cache: "npm" | |
| cache-dependency-path: client/package-lock.json | |
| - run: npm ci | |
| working-directory: client | |
| - name: Run tests with coverage | |
| working-directory: client | |
| run: npm run test:coverage | |
| - uses: actions/upload-artifact@v7 | |
| if: always() | |
| with: | |
| name: coverage-client | |
| path: client/coverage/coverage-summary.json | |
| if-no-files-found: warn | |
| sdk: | |
| name: SDK | |
| runs-on: ubuntu-latest | |
| continue-on-error: true | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: "23.4.0" | |
| cache: "npm" | |
| cache-dependency-path: sdk/package-lock.json | |
| - run: npm ci | |
| working-directory: sdk | |
| - name: Run tests with coverage | |
| working-directory: sdk | |
| env: | |
| NODE_OPTIONS: --experimental-vm-modules | |
| run: npm test -- --ci --coverage | |
| - uses: actions/upload-artifact@v7 | |
| if: always() | |
| with: | |
| name: coverage-sdk | |
| path: sdk/coverage/coverage-summary.json | |
| if-no-files-found: warn | |
| contracts: | |
| name: Contracts | |
| runs-on: ubuntu-latest | |
| continue-on-error: true | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: dtolnay/rust-toolchain@stable | |
| with: | |
| components: llvm-tools-preview | |
| - uses: Swatinem/rust-cache@v2 | |
| with: | |
| workspaces: contracts | |
| - name: Install cargo-llvm-cov | |
| uses: taiki-e/install-action@cargo-llvm-cov | |
| - name: Run tests with coverage | |
| working-directory: contracts | |
| run: | | |
| mkdir -p coverage | |
| cargo llvm-cov --workspace --summary-only --json --output-path coverage/llvm-cov.json | |
| # Reduce to a single line-coverage percentage for the aggregator. | |
| node -e " | |
| const data = require('./coverage/llvm-cov.json'); | |
| const lines = data.data[0].totals.lines; | |
| require('fs').writeFileSync('coverage/lines.txt', String(lines.percent)); | |
| " | |
| - uses: actions/upload-artifact@v7 | |
| if: always() | |
| with: | |
| name: coverage-contracts | |
| path: contracts/coverage/lines.txt | |
| if-no-files-found: warn | |
| # ── Aggregate, gate and comment ─────────────────────────────────────────── | |
| report: | |
| name: Coverage Report | |
| runs-on: ubuntu-latest | |
| needs: [backend, client, sdk, contracts] | |
| if: always() | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: "20" | |
| - name: Download coverage artifacts | |
| uses: actions/download-artifact@v7 | |
| with: | |
| pattern: coverage-* | |
| path: artifacts | |
| - name: Place summaries where the aggregator expects them | |
| run: | | |
| set -e | |
| for pkg in backend client sdk; do | |
| if [ -f "artifacts/coverage-$pkg/coverage-summary.json" ]; then | |
| mkdir -p "$pkg/coverage" | |
| cp "artifacts/coverage-$pkg/coverage-summary.json" "$pkg/coverage/" | |
| fi | |
| done | |
| if [ -f "artifacts/coverage-contracts/lines.txt" ]; then | |
| mkdir -p contracts/coverage | |
| cp artifacts/coverage-contracts/lines.txt contracts/coverage/ | |
| fi | |
| # The delta needs the target branch's numbers. Restore them from the | |
| # cache written by the last run on that branch; absent a cache hit the | |
| # report simply omits the delta column. | |
| - name: Restore baseline coverage | |
| if: github.event_name == 'pull_request' | |
| uses: actions/cache/restore@v4 | |
| with: | |
| path: coverage-baseline.json | |
| key: coverage-baseline-${{ github.base_ref }}-${{ github.sha }} | |
| restore-keys: | | |
| coverage-baseline-${{ github.base_ref }}- | |
| - name: Build report | |
| run: | | |
| node scripts/coverage-report.js \ | |
| --baseline coverage-baseline.json \ | |
| --out coverage-report.md \ | |
| --json coverage-current.json | |
| cat coverage-report.md >> "$GITHUB_STEP_SUMMARY" | |
| - name: Comment on PR | |
| if: github.event_name == 'pull_request' | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const fs = require('fs'); | |
| const body = fs.readFileSync('coverage-report.md', 'utf8') | |
| + '\n<!-- syncro-coverage-report -->'; | |
| const { owner, repo } = context.repo; | |
| const issue_number = context.issue.number; | |
| // Update the existing comment rather than adding one per push. | |
| const comments = await github.paginate( | |
| github.rest.issues.listComments, { owner, repo, issue_number }); | |
| const existing = comments.find((c) => | |
| c.user.type === 'Bot' && c.body.includes('<!-- syncro-coverage-report -->')); | |
| if (existing) { | |
| await github.rest.issues.updateComment({ owner, repo, comment_id: existing.id, body }); | |
| } else { | |
| await github.rest.issues.createComment({ owner, repo, issue_number, body }); | |
| } | |
| # Save this branch's numbers so PRs targeting it can compute a delta. | |
| # The cached filename must match what the restore step expects. | |
| - name: Save baseline coverage | |
| if: github.event_name == 'push' | |
| run: cp coverage-current.json coverage-baseline.json | |
| - name: Cache baseline coverage | |
| if: github.event_name == 'push' | |
| uses: actions/cache/save@v4 | |
| with: | |
| path: coverage-baseline.json | |
| key: coverage-baseline-${{ github.ref_name }}-${{ github.sha }} | |
| - name: Enforce minimum coverage | |
| run: node scripts/coverage-report.js --check |