-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Gemini's take:
Based on your goal to parallelize the Merge Queue for stacked PRs while enforcing dependency failures, I have brainstormed two designs.
The core constraint of GitHub's Merge Queue is that a PR must target the queue's branch (e.g., main) to enter. Therefore, the "Cascading" model (B targets A) must be temporarily abandoned during the merge phase.
Design 1: Just-in-Time (JIT) Retargeting with Sentinel Checks
This design modifies the lifecycle of a GHerrit stack to allow all PRs to target main strictly for the purpose of merging, while adding a safety mechanism to prevent broken chains.
1. The Strategy
Instead of waiting for PR A to land before retargeting B, GHerrit will retarget the entire stack to main at the moment of enqueueing.
- Review Phase: Keep current behavior.
Atargetsmain,BtargetsA. - Merge Phase: When the user runs
gherrit submit(or triggers via comment), GHerrit performs the following simultaneously:
- Updates
BandCto targetmain. (Note: SinceBphysically containsA's commits, this is a valid git operation). - Adds
A,B, andCto the Merge Queue.
2. The "Sentinel" Action (Safety Mechanism)
Since B and C now technically target main directly, GitHub treats them as independent. If A fails tests and is ejected, GitHub would normally try to run B on its own. Since B contains A's code (and thus A's bugs), B would eventually fail, but this wastes CI time and is not "fail-fast."
To solve this, inject a lightweight Sentinel GitHub Action that runs on the merge_group event.
- Logic:
- Parse the
gherrit-metatag in the PR body to find theparentPR ID. - Use the GitHub API to check the status of the Parent PR.
- Fail Immediately if the Parent PR is NOT
mergedAND NOT present in the currentmerge_group.
- Result: If
Afails and is removed,B's Sentinel check sees thatAis gone.Bfails instantly.C's Sentinel check seesBfailed.Cfails instantly.
3. Constraints
-
Merge Strategy: You must use "Rebase and Merge" or "Create a Merge Commit" for the repository. You cannot use "Squash and Merge."
-
Why?
BcontainsA's commits. IfAis squashed on merge,mainreceivesCommit_A_Squashed.Battempts to land withCommit_A_Original. This results in duplicate commits or conflicts. "Rebase and Merge" ensures git detects the duplicate patch-IDs and appliesBcleanly. -
Diff UX: For a brief moment during the merge queue processing,
Bwill targetmainand showA's commits in its file diffs. This is acceptable as the PR is already approved and "in flight," but it may look confusing if a user checks the PR link during this window.
Design 2: The "Bundle" (Super-PR) Approach
If the "Squash and Merge" constraint or the complexity of JIT retargeting is too high, this alternative achieves parallelism by collapsing the stack.
1. The Strategy
When the user requests a merge for the stack A -> B -> C:
- GHerrit creates a synthetic "Bundle PR" (
S) targetingmain. Sis pushed to a phantom branch that matches the head ofC. (Effectively,ScontainsA+B+C).Senters the Merge Queue.- All tests run on
S(effectively testingA,B, andCin parallel).
2. Reconciliation
Once S merges:
- GHerrit detects the merge.
- GHerrit updates the original PRs (
A,B,C) to mark them as "Merged" (or closes them manually) and links them to the landed commit(s).
3. Pros & Cons
- Pros: Works with Squash and Merge (the whole stack becomes one squash commit, or user can choose). Guarantees atomic success/failure (if
Abreaks,Sbreaks, soBandCnever land). - Cons: Loss of granularity in GitHub's "Merged PRs" list (you see one "Stack Merge" PR instead of 3 individual PRs).
Recommendation
Design 1 is the robust solution that preserves your current "Gerrit-style" granular history and PR/commit 1:1 mapping. It effectively tricks GitHub into parallelizing the tests while the Sentinel Action reimplements the dependency graph that GitHub ignores.