ci: make path-filtered required gates always report (unblock stuck PRs)#216
Merged
Merged
Conversation
Seven gates were workflow-level path-filtered (on.*.paths). When a PR touched none of a gate's paths the workflow never ran, so its REQUIRED status check stayed "Expected" forever and the PR sat at mergeable_state=blocked — even with every other check green and the PR approved (e.g. #213 flake.lock bump, #215 scripts-only). The asymmetry this fixes: a path-filtered workflow that never runs BLOCKS, whereas a job skipped via `if:` reports SUCCESS to required checks. For each of abi-drift, backend-assurance, e2e, lsp-dap-bsp, proofs, truthfulness, zig-test: * drop the workflow-level `on.*.paths` filter (always run, so the required check is always created), * add a lightweight `changes` job that recomputes the gate's original path set via `git diff origin/<base>...HEAD` (the same pattern abi-drift/zig-test already used internally for per-cartridge scoping), * gate every heavy job with `needs: changes` + `if: needs.changes.outputs.run == 'true'`. When nothing relevant changed the heavy job is skipped (a passing required check), so unrelated PRs are no longer blocked AND don't pay for the heavy work. Fail-safe: the detector defaults to run=true and only skips when a SUCCESSFUL diff shows no relevant path changed (any fetch/diff error or unknown base => run). The dangerous direction — skipping a gate that should run — cannot happen on detection failure. Each regex mirrors the gate's original `paths:`, so a relevant change runs it exactly as before. No branch-protection change needed: job/check names are unchanged. workflow_dispatch added to all 7 for manual full runs. Validated locally: actionlint clean on all 7 (only pre-existing shellcheck infos remain, untouched); detection regexes unit-tested against representative change-sets (77/77, incl. #213/#215 -> skip and abi/ffi/src changes -> run). Note: editing a workflow file no longer self-triggers its heavy gate (kept out of each regex), so workflow-only PRs like THIS one exercise the skip path and stay green. https://claude.ai/code/session_019tMcRS1Dm1nWjjYP4WvbJa
🔍 Hypatia Security ScanFindings: 272 issues detected
View findings[
{
"reason": "Stale AI session file -- delete",
"type": "stale",
"file": "GEMINI.md",
"action": "delete",
"rule_module": "root_hygiene",
"severity": "medium"
},
{
"reason": "Issue in abi-drift.yml",
"type": "missing_timeout_minutes",
"file": "abi-drift.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in codeql.yml",
"type": "missing_timeout_minutes",
"file": "codeql.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in container-publish.yml",
"type": "missing_timeout_minutes",
"file": "container-publish.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in dogfood-gate.yml",
"type": "missing_timeout_minutes",
"file": "dogfood-gate.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in dogfood-gate.yml",
"type": "missing_timeout_minutes",
"file": "dogfood-gate.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in dogfood-gate.yml",
"type": "missing_timeout_minutes",
"file": "dogfood-gate.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in dogfood-gate.yml",
"type": "missing_timeout_minutes",
"file": "dogfood-gate.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in dogfood-gate.yml",
"type": "missing_timeout_minutes",
"file": "dogfood-gate.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in dogfood-gate.yml",
"type": "missing_timeout_minutes",
"file": "dogfood-gate.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
}
]Powered by Hypatia Neurosymbolic CI/CD Intelligence |
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this fixes
PRs #213 (dependabot
flake.lock) and #215 (scripts-only) are stuck atmergeable_state: blockeddespite every check green (and #213 approved). Root cause: seven gates are workflow-level path-filtered (on.*.paths). When a PR touches none of a gate's paths the workflow never runs, so its required status check stays "Expected" forever → permanent block.The asymmetry this exploits: a path-filtered workflow that never runs blocks; a job skipped via
if:reports SUCCESS to required checks. This converts the former into the latter.Change (uniform across all 7)
abi-drift,backend-assurance,e2e,lsp-dap-bsp,proofs,truthfulness,zig-test:on.*.pathsfilter → the workflow always runs, so the required check is always created.changesjob that recomputes the gate's original path set viagit diff origin/<base>...HEAD(the same patternabi-drift/zig-testalready use internally).needs: changes+if: needs.changes.outputs.run == 'true'. Nothing relevant changed → heavy job skipped → passes → PR unblocked and no wasted CI.No branch-protection change needed — job/check names are unchanged.
workflow_dispatchadded to all 7 for manual full runs.Safety
run=trueand only setsfalsewhen a successful diff shows no relevant path changed (any fetch/diff error or unknown base ⇒ run). The dangerous direction — skipping a gate that should run — can't happen on detection failure.paths:, so a relevant change runs it exactly as before (verified: 77/77 unit checks —abi/→proofs+abi-drift,ffi/→zig+truthfulness+abi-drift,SafetyLemmas.idr→backend-assurance+proofs, etc.; chore(deps): bump nixpkgs from8c3cedeto8c91a71#213/feat(scripts): extend §1.5 verb-canary coverage (Phase E) #215 → all skip).Validation
Self-validating: editing a workflow file no longer self-triggers its heavy gate (kept out of each regex), so this PR's own checks exercise the skip path — the gates should report skipped/success here, demonstrating the unblock live.
Draft — why
I can't runtime-test the
run=truebranch (it needs the GH runners), and this changes how required gates fire, so it wants your eyes before merge. Mark ready / squash-merge when you're satisfied. After it lands, re-check #213/#215 — they should flip fromblockedto mergeable.https://claude.ai/code/session_019tMcRS1Dm1nWjjYP4WvbJa
Generated by Claude Code