You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(gate): never plan an add and a remove of the manual-review label together
#10155 is flapping in production on beta.7: the label is
removed and re-added roughly every 90 seconds -- four cycles in eight minutes,
each pair a GitHub write and a subscriber notification. The audit trail shows
both operations in the SAME pass, two seconds apart.
Three post-plan transforms surface the manual-review hold -- the merge
circuit-breaker, the close circuit-breaker, and the close-audit holdout (#8831).
All three carried the identical idempotency check, which looks for an existing
ADD (`labelOp !== "remove"`) and therefore cannot see a planned REMOVE. When the
planner has already scheduled a release -- section 1b does, whenever nothing IT
knows about still wants a hold -- the transform appended an add next to that
remove, and the executor performed both.
Latent until #10116. `noManualReviewHoldWanted` used to include
`!mergeableStateUnstable`, which suppressed the release on exactly these PRs and
accidentally masked the missing case. Removing that term (correctly -- it was the
latch keeping #10098 stuck) let the release fire and exposed the contradiction.
#10116 did not create this; the label was previously a sticky latch, quieter but
strictly more broken.
The planner cannot fix it from its side. Section 1b's doc calls
noManualReviewHoldWanted "every reason that would ADD this label, in one place";
it is not, and cannot be, because these three run AFTER planning -- #8831 landed
long after that comment was written. Extending the planner's list would just be
one more thing to remember on the next transform.
So one shared withManualReviewHoldLabel() drops a planned release of the same
label before adding, and all three call sites use it. The contradiction becomes
unrepresentable where the add happens. The remove is dropped rather than the add
skipped: a transform only gets there by having just diverted a merge or a close,
so its hold is strictly newer than the release decided before that diversion.
Scoped to this label only -- dropping every label remove would silently defeat
the stale-disposition-label cleanup, which is its own mutation test.
gate.closeAuditHoldoutPct is 20 (the maximum) in the global Orb config, so about
one in five would-close PRs is eligible for the path that triggered this.
Closes#10164
0 commit comments