Uh oh!
There was an error while loading. Please reload this page.
chore(promote): develop → main — fr-gate ancestry-only fix - #110
Merged
Conversation
The no-items fallback gated the promotion PR itself, which is unsatisfiable BY CONSTRUCTION: set-pr-status parks that PR in 'Code review', and it can only leave that column by merging -- which this gate blocks. data-ingestors deadlocked on exactly this in today's prod hop. It happened because the range's only new commit was the train's own mirror merge, whose content master already held (a manual promotion had carried it there first): 1 commit ahead, 0 files changed. Both associated PRs were correctly filtered as train plumbing, leaving no cargo -- so the fallback fired on a promotion that ships nothing. Now distinguished by whether the range changes any file: 0 files -> ancestry-only, nothing shipped, nothing to gate -> pass >0 files -> real content we could not attribute -> gate the promotion PR, i.e. fail closed and force a human look An unset file count defaults to the fail-closed branch, so a failure to compute it can never turn into a pass.
The early exit sat ~150 lines above the UNATTRIB fail-closed check, so a
tree-identical range containing a commit we could not verify (e.g.
commits/{sha}/pulls erroring three times) would have passed the gate --
and my PR body wrongly claimed that check was untouched.
0 files changed means 'nothing shipped' only if every commit was
successfully accounted for, so the ancestry pass now requires UNATTRIB to
be empty as well.The emptiness check used a two-dot git diff, which counts files the BASE moved on alone -- so it measured 'how do the two tips differ', not 'what did this promotion contribute'. On data-ingestors that reports 6 files (master's own commits that staging lacks) where the correct three-dot answer is 0, so the ancestry-only branch would never have been taken and the deadlock this PR exists to fix would have survived. I had verified the premise with the compare API (three-dot) but implemented local two-dot git -- validating with one method and shipping another. Now uses the compare API directly, so the check and its verification are the same operation. The API also avoids local three-dot's silent merge-base pick: this repo's history has multiple merge bases after the mirror reconciliations. Any failure to count yields -1, which takes the fail-closed branch.
fix(fr-gate): an ancestry-only promotion has nothing to gate
LukasWodka
commented
Jul 30, 2026
ContributorAuthor
👋 Heads-up — Code review queue is at 35 / 30 Above the WIP limit. The team convention is to review existing PRs before opening new work. Open PRs currently in Code review (oldest first):
Pull from review before opening new work. (This is a nudge from the kanban WIP check, not a block.) |
Uh oh!
There was an error while loading. Please reload this page.
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.
Promotes the fr-gate fix from #109. Reusable workflows only take effect from
main, so this is what makes it live.What it fixes: the no-items fallback gated the promotion PR itself, which is unsatisfiable by construction —
set-pr-statusparks that PR inCode review, and the only way out is merging, which the gate blocks. data-ingestors deadlocked on exactly this in today's prod hop and was reported as a governance failure (❌ #423 — Status='Code review') rather than a bug.An empty item set now splits by what the promotion actually contributes, measured three-dot via the compare API:
-1)Two fail-opens Bugbot caught during review, both real:
exit 0jumped over theUNATTRIBfail-closed check ~150 lines below it, so a tree-identical range containing an unverifiable commit would have passed. Now requiresUNATTRIBempty.git diff, which counts files the base moved on alone — 6 on the data-ingestors case where the correct three-dot answer is 0. It would not have fixed its own motivating bug. Now uses the compare API, matching how the premise was verified in the first place.Verified against live repos:
data-ingestors compare(master...staging).files = 0→ passes;client compare(main...staging).files = 36→ does not.actionlint+shellcheckclean.Note
Medium Risk
Changes promotion merge-gating behavior for empty attribution cases; incorrect emptiness detection could pass ungated content or block valid promotions, though the design fails closed on API errors and requires empty UNATTRIB.
Overview
Fixes a deadlock in the reusable FR gate when a release-train promotion has no attributable PRs but also ships no new file content.
The Discover items step now records
changed_filesusing the GitHub compare API with three-dot semantics (base...head), with retries and fail-closed behavior if the count cannot be obtained. The verify step receivesCHANGED_FILESand, when the item list is empty, passes only ifchanged_filesis 0 andUNATTRIBis empty—otherwise it still gates the promotion PR or fails on unattributable commits. This separates ancestry-only mirror merges (base already has every byte) from real content or broken attribution, without using two-dot diffs that miscount files on diverged branches.Reviewed by Cursor Bugbot for commit 7c4ffed. Bugbot is set up for automated code reviews on this repo. Configure here.