fix(ci): make the dependabot auto-merge guard refuse instead of merging - #372
Merged
Conversation
The "Wait for CI checks to pass" step printed a refusal and then `exit 0`, which makes the STEP SUCCEED. The merge steps below it gate only on `steps.metadata.outputs.update-type` -- never on this step's outcome. A step whose `if:` contains no status function carries an implicit `success()`, so a later step is skipped only when an earlier one FAILS. A guard that exits zero therefore announced "skipping auto-merge" and then ran `gh pr merge --squash`. Nothing has merged wrongly, and the reason is worth stating precisely rather than as a near-miss: `main` is protected with required contexts (cargo audit, cargo deny, gate / gate), which refuses the merge independently. The defect is that this guard contributed no defence-in-depth while its own message asserted otherwise -- a check reporting a verdict it never enforced. Branch protection also only enforces checks it knows about, so a required check that silently never reports is invisible to it. harmonia and the canonical reusable in forkwright/.github both already carry this fix with a comment naming the same failure mode; this copy predates them. Refs #371
Uh oh!
There was an error while loading. Please reload this page.
forkwright pushed a commit
that referenced
this pull request
Aug 16, 2026
🤖 I have created a release *beep* *boop* --- ## [0.1.24](v0.1.23...v0.1.24) (2026-08-14) ### Bug Fixes * **ci:** make the dependabot auto-merge guard refuse instead of merging ([#372](#372)) ([56147fb](56147fb)), closes [#371](#371) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This was referenced Aug 19, 2026
forkwright added a commit
that referenced
this pull request
Aug 21, 2026
Closes#371 Replaces 55 lines of locally-copied auto-merge logic with a pinned call to the canonical reusable in `forkwright/.github`. The copy is how this repo's version drifted. It kept `exit 0` on the refusal path long after the canonical workflow had corrected it to `exit 1` — so the guard printed "refusing auto-merge" and then merged, because Actions skips a later step only when an earlier one *fails*. #372 fixed that instance; this removes the copy that produced it, which is what the issue actually asked for. ## Why this was blocked, and why it no longer is The reusable used to match the osv check by exact suffix, testing for names ending in `osv scanner` or `osv-scan`. This repo's job is named `osv-scanner`, which ends with neither — so adopting then would have made auto-merge refuse every PR whose osv check had reported and **passed**. forkwright/.github#38 replaced that with normalisation: strip every non-alphanumeric, lowercase, test containment. All four tokens the reusable requires resolve here: | required token | this repo's check | normalised | |---|---|---| | `gateattestation` / `gategate` | `gate / gate` | `gategate` ✓ | | `cargodeny` | `cargo deny` | `cargodeny` ✓ | | `cargoaudit` | `cargo audit` | `cargoaudit` ✓ | | `osvscan` | `osv-scanner` | `osvscanner` contains it ✓ | Those four are exactly the required contexts on `main` plus the gate, so the reusable is checking the same set branch protection does — with the addition it was adopted for: it verifies the checks **reported at all**, which branch protection cannot, since a required check that silently never reports is not a failure it can see. ## Two deliberate differences from `gate-attestation.yml` Both are commented inline, because both look like inconsistencies and neither is. **This caller declares `concurrency`; `gate-attestation.yml` deliberately does not.** The difference is in the reusables. `hybrid-gate.yml` declares its own group, so a caller-level duplicate self-cancels it. This one declares none — so without a caller-level block, a superseded push to a dependabot PR leaves the earlier run racing the newer one, both waiting on checks and both able to merge. **This caller does not pass `secrets: inherit`; `gate-attestation.yml` does.** That keyword forwards every repository secret to a workflow in another repository. This reusable reads `secrets.GITHUB_TOKEN` and nothing else, which a called workflow receives regardless — so inheriting would widen the blast radius of a change in `forkwright/.github` for no capability gained. ## Verification `pre-push-verify.sh` derives the crates a branch touches from its diff; this branch touches none, so there is nothing for it to build. The verification that matters here is GitHub resolving the `uses:` ref and the reusable's own jobs reporting, which only CI can do. The YAML was parsed locally to rule out a malformed file before pushing. The refusal path itself is exercised by the next dependabot PR rather than by this one — this PR is not authored by `dependabot[bot]`, so the job's `if:` correctly skips it. Worth watching the first dependabot bump after this lands to confirm the guard fails rather than skips on a red check. Co-authored-by: forkwright <cody@forkwright.com>
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 freeto 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.
The "Wait for CI checks to pass" step printed a refusal and then
exit 0,which makes the STEP SUCCEED.
The merge steps below it gate only on
steps.metadata.outputs.update-type-- never on this step's outcome. A step whose
if:contains no statusfunction carries an implicit
success(), so a later step is skipped onlywhen an earlier one FAILS. A guard that exits zero therefore announced
"skipping auto-merge" and then ran
gh pr merge --squash.Nothing has merged wrongly, and the reason is worth stating precisely
rather than as a near-miss:
mainis protected with required contexts(cargo audit, cargo deny, gate / gate), which refuses the merge
independently. The defect is that this guard contributed no
defence-in-depth while its own message asserted otherwise -- a check
reporting a verdict it never enforced. Branch protection also only
enforces checks it knows about, so a required check that silently never
reports is invisible to it.
harmonia and the canonical reusable in forkwright/.github both already
carry this fix with a comment naming the same failure mode; this copy
predates them.
Refs #371