diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index 70042658..bf21536f 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -156,6 +156,17 @@ jobs: # ceiling absorbs the worst-case "Cargo.lock churned + Swatinem # cache evicted" combo without killing useful runs. timeout-minutes: 30 + # security-events:write lets the upload-sarif step publish bca's own + # self-scan offenders to GitHub code scanning (Security tab + PR + # annotations) — dogfooding the SARIF path we document for adopters + # in commands/check.md and recipes/ci.md. actions:read is required by + # upload-sarif on private/internal repos (harmless on public ones) + # and matches ci.yml's clippy job. The workflow-level default is + # contents:read. + permissions: + contents: read + security-events: write + actions: read # The workspace-minus-vendored exclude list lives in `.bcaignore` # at the repo root and is wired in via `exclude_from` in the # auto-discovered `bca.toml` manifest, so the invocations below @@ -262,6 +273,29 @@ jobs: env: BCA_SINCE: origin/${{ github.base_ref || 'main' }} + # Dogfood bca's own SARIF writer: re-run the gate as a pure + # emitter (`--no-fail` keeps exit 0 regardless of offenders) so + # this step runs even when the gate above is red, and upload the + # result to Code Scanning below. Path selection, thresholds, and + # the baseline all come from the auto-discovered `bca.toml` + # manifest — same config the gate uses — so the published alerts + # match the gate's offender set. `if: always()` mirrors the report + # steps: the SARIF is most useful precisely when CI is red. + - name: Generate self-scan SARIF + if: always() + run: bca check --output-format sarif --no-fail --output bca.sarif + + # Fork PRs get a read-only GITHUB_TOKEN without security-events + # scope, so the upload would error; skip it there (and when no + # SARIF was produced). `category: bca` keeps these alerts a + # distinct analysis from ci.yml's `category: clippy` upload. + - name: Upload self-scan SARIF to code scanning + if: always() && hashFiles('bca.sarif') != '' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) + uses: github/codeql-action/upload-sarif@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0 + with: + sarif_file: bca.sarif + category: bca + - name: Upload reports artifact if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/big-code-analysis-book/src/recipes/ci.md b/big-code-analysis-book/src/recipes/ci.md index 5063f630..ba1c02c3 100644 --- a/big-code-analysis-book/src/recipes/ci.md +++ b/big-code-analysis-book/src/recipes/ci.md @@ -43,8 +43,11 @@ the [Quality reports recipe](quality-reports.md). `big-code-analysis` runs the recipes below against its own source on every push and PR. The workflow source — [`.github/workflows/pages.yml`](https://github.com/dekobon/big-code-analysis/blob/main/.github/workflows/pages.yml) — -exercises the threshold gate, the baseline ratchet, and both report -formats end-to-end against the workspace itself. The output sits on +exercises the threshold gate, the baseline ratchet, both report +formats, and a SARIF upload to GitHub Code Scanning end-to-end against +the workspace itself. (The SARIF upload runs on same-repo pushes and +PRs only; fork PRs skip it because the upload needs a write-scoped +token, exactly as the clippy SARIF job does.) The output sits on GitHub Pages alongside this book: - HTML hotspot report: