feat(runway): wire the git merger into the server - #463
Draft
behinddwalls wants to merge 1 commit into
Draft
Conversation
## Summary ### Why? The git merger exists but nothing constructs it — the server still builds the noop factory, so a deployed Runway acknowledges every merge as an instant success. This is the change that makes Runway actually merge. It is deliberately last in the stack and deliberately opt-in: the switch is the presence of `MERGE_CHECKOUT_PATH`. Unset, the server keeps wiring noop, which is what local development, the compose stack, and the e2e suite depend on — none of them have a git checkout to hand the merger. ### What? `newMergerFactory` now reads the environment and returns either backend. With `MERGE_CHECKOUT_PATH` set it builds a git merger from the `MERGE_*` / `GIT_*` variables — remote, target branch, default strategy, committer identity, and the pinned git runtime — and logs the resolved configuration at startup. Without it, noop, with a log line saying so. A malformed configuration fails startup rather than degrading silently: `parseStrategy` rejects an unrecognized `MERGE_DEFAULT_STRATEGY`, and `DEFAULT` itself is rejected because it cannot be the value a `DEFAULT` step resolves to. `gitMergerFactory` hands the same merger instance to every queue. The merger owns one checkout and serializes its own operations, so a second instance over the same directory would race; a deployment that lands multiple targets wires a per-queue map instead. This is also why the factory is built once at startup rather than per request. Documents the new variables in the service README and adds the merger-extension overview to the Runway README. ## Test Plan ✅ `bazel build //service/runway/...` — wiring compiles ✅ `bazel test //runway/...` — 6/6 pass Not covered by automated tests: the git path only engages when `MERGE_CHECKOUT_PATH` points at a real checkout, so the env-to-`Params` mapping is exercised by the merger's own suite rather than through `main`. Watch the `git merger configured` startup log — with checkout, target, and default strategy — on the first deployment that sets the variable; its absence means the server silently fell back to noop.
This was referenced Jul 29, 2026
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.
Summary
Why?
The git merger exists but nothing constructs it — the server still builds the noop factory, so a deployed Runway acknowledges every merge as an instant success. This is the change that makes Runway actually merge.
It is deliberately last in the stack and deliberately opt-in: the switch is the presence of
MERGE_CHECKOUT_PATH. Unset, the server keeps wiring noop, which is what local development, the compose stack, and the e2e suite depend on — none of them have a git checkout to hand the merger.What?
newMergerFactorynow reads the environment and returns either backend. WithMERGE_CHECKOUT_PATHset it builds a git merger from theMERGE_*/GIT_*variables — remote, target branch, default strategy, committer identity, and the pinned git runtime — and logs the resolved configuration at startup. Without it, noop, with a log line saying so. A malformed configuration fails startup rather than degrading silently:parseStrategyrejects an unrecognizedMERGE_DEFAULT_STRATEGY, andDEFAULTitself is rejected because it cannot be the value aDEFAULTstep resolves to.gitMergerFactoryhands the same merger instance to every queue. The merger owns one checkout and serializes its own operations, so a second instance over the same directory would race; a deployment that lands multiple targets wires a per-queue map instead. This is also why the factory is built once at startup rather than per request.Documents the new variables in the service README and adds the merger-extension overview to the Runway README.
Test Plan
✅
bazel build //service/runway/...— wiring compiles✅
bazel test //runway/...— 6/6 passNot covered by automated tests: the git path only engages when
MERGE_CHECKOUT_PATHpoints at a real checkout, so the env-to-Paramsmapping is exercised by the merger's own suite rather than throughmain. Watch thegit merger configuredstartup log — with checkout, target, and default strategy — on the first deployment that sets the variable; its absence means the server silently fell back to noop.Stack