Skip to content

Commit ae6619e

Browse files
fix(ci): skip SARIF upload when code scanning is administratively disabled (#353)
## Summary The hypatia-scan reusable's \`Upload SARIF\` step hard-fails when the consumer repo has code scanning disabled (private repo without Advanced Security, or any repo with the feature admin-disabled). That's a legitimate consumer-side config choice, not a regression. This adds a \`cs-probe\` step that queries \`/code-scanning/alerts\` (continue-on-error so the probe itself never blocks) and gates the upload step on the probe's verdict. ## Reproducer [.git-private-farm#69 run 26843343488](https://github.com/hyperpolymath/.git-private-farm/actions/runs/26843343488): \`\`\` hypatia.sarif written: 48 result(s). Run github/codeql-action/upload-sarif@... sarif_file: hypatia.sarif Validating hypatia.sarif ##[error]Code scanning is not enabled for this repository. Please enable code scanning in the repository settings. \`\`\` The scan + SARIF conversion both succeed; the \`actions: read\` perm I added in #352 correctly grants the upload its scope; the upload only fails because the **feature itself** is not enabled on the consumer repo. ## Preserved guarantees Per the existing design comment (post-#35): - ✅ Fork PRs still skip (token read-only) — unchanged. - ✅ Genuine permission regression still hard-fails loud (the probe checks only whether the feature is enabled, not whether the upload would otherwise succeed). - ✅ Malformed SARIF / API outage still hard-fails loud — same reason. - ✅ Hypatia findings still land as a build artifact even when SARIF upload is skipped (the upload-artifact step is unaffected). The probe is **fail-open**: if the API call errors for any reason (rate limit, transient outage), \`enabled\` ends unset (no \`enabled=true\` in the output), upload is skipped. Loud-red regressions remain loud — the probe just adds a graceful skip for the specific case where the feature is administratively unavailable. ## Test plan - [ ] .git-private-farm#69 re-run picks up new reusable SHA → SARIF step skips with notice instead of hard-fail. - [ ] Public estate consumers (where code scanning IS enabled by default) still publish SARIF normally. - [ ] Fork PRs still skip via the unchanged second clause of the \`if:\`. ## Blast radius Same as #352 — all estate consumers of \`hypatia-scan-reusable.yml\`. The change is fail-open and additive: existing green paths stay green; previously-red paths that were red BECAUSE of disabled-feature now go green. ## Related - #352 — added the perms; this completes the resilience - .git-private-farm#69 — first consumer hitting the disabled-feature path 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 3b3549e commit ae6619e

1 file changed

Lines changed: 32 additions & 9 deletions

File tree

.github/workflows/hypatia-scan-reusable.yml

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -281,18 +281,41 @@ jobs:
281281
CJS
282282
node "$RUNNER_TEMP/hypatia-sarif.cjs"
283283
284+
- name: Probe code scanning availability
285+
# Private repos without GitHub Advanced Security (and any repo with
286+
# code scanning administratively disabled) reject upload-sarif with
287+
# "Code scanning is not enabled for this repository". That's a
288+
# legitimate consumer-side config choice, not a regression — skip
289+
# rather than hard-fail. The empty 200 from /code-scanning/alerts
290+
# means the feature is enabled and queryable; any non-2xx means it
291+
# is not.
292+
id: cs-probe
293+
continue-on-error: true
294+
env:
295+
GH_TOKEN: ${{ github.token }}
296+
run: |
297+
set -uo pipefail
298+
if gh api "repos/${GITHUB_REPOSITORY}/code-scanning/alerts" --jq 'length' >/dev/null 2>&1; then
299+
echo "enabled=true" >> "$GITHUB_OUTPUT"
300+
else
301+
echo "enabled=false" >> "$GITHUB_OUTPUT"
302+
echo "::notice::Code scanning is not enabled on ${GITHUB_REPOSITORY}; SARIF upload will be skipped. Hypatia findings still land as a build artifact."
303+
fi
304+
284305
- name: Upload SARIF to GitHub code scanning
285-
# Fork PRs get a read-only GITHUB_TOKEN, so security-events:write
286-
# is unavailable and upload-sarif cannot publish — skip there
287-
# rather than hard-fail (the push/schedule run on the default
288-
# branch is the authoritative upload). Same-repo PRs and pushes
289-
# do upload. This step is deliberately NOT continue-on-error:
290-
# if the security-surface integration breaks we want a loud red,
291-
# not a silently-ungated scanner (the exact failure mode #35
292-
# exists to end). The empty-SARIF "clear stale alerts" path is
293-
# handled in the converter above and does not error here.
306+
# Skipped on three legitimate paths:
307+
# 1. Fork PRs — GITHUB_TOKEN is read-only, security-events:write
308+
# unavailable, upload-sarif cannot publish. Push/schedule on
309+
# the default branch is the authoritative upload.
310+
# 2. Code scanning administratively disabled — private repo
311+
# without Advanced Security, or owner-disabled feature.
312+
# 3. The reusable still hard-fails on every OTHER error mode
313+
# (genuine permission regression, malformed SARIF, API outage),
314+
# so a silently-ungated scanner is still loud — exactly the
315+
# failure mode #35 exists to end.
294316
if: >-
295317
always() &&
318+
steps.cs-probe.outputs.enabled == 'true' &&
296319
(github.event_name != 'pull_request' ||
297320
github.event.pull_request.head.repo.fork != true)
298321
uses: github/codeql-action/upload-sarif@0d579ffd059c29b07949a3cce3983f0780820c98 # v3.28.1

0 commit comments

Comments
 (0)