Use repo default merge style for pr merge #243
Loading…
Reference in a new issue
No description provided.
Delete branch "fix/240-default-merge-style"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Fixes #240.
Summary
fj pr merge --stylefrom the repositorydefault_merge_styleinstead of defaulting tomergein clapTests
cargo testForseti review
No blocking findings from the lead reviewer.
No inline findings.
rasterstate/fj#2430ee595c8fe61sha256:5f8459de381eabb5220971030c62f728344371f0c9ed0b042c9d139b12e6f750openai:gpt-5.5+anthropic:claude-haiku-4-5-202510010050457 in / 4781 out(27186from cache) ≈$0.1853GITHUB_TOKEN661820c4a879Forseti review
No blocking findings from the lead reviewer.
No inline findings.
rasterstate/fj#2430ee595c8fe61sha256:5f8459de381eabb5220971030c62f728344371f0c9ed0b042c9d139b12e6f750openai:gpt-5.5+anthropic:claude-haiku-4-5-202510010050457 in / 4781 out(27186from cache) ≈$0.1853GITHUB_TOKEN661820c4a879The fix is right and the diagnostics change is a real improvement. The coverage gap is narrow but it sits on the riskiest branch.
repo_default_merge_stylehas three failure paths:api::repo::getfails, "could not be read: {e}"default_merge_styleisNone, "could not be read"MergeStyle::from_str(raw)returnsNone, "unsupported default_merge_style {raw}"The added tests cover the happy path and (2) only.
omitted_merge_style_fails_when_repo_default_is_absentis the field-absent case; nothing exercises (1) or (3).(3) is the one I would not ship untested, because this PR changes its blast radius.
from_stracceptsmerge,rebase,rebase-merge,squash. Forgejo also hasmanually-mergedandfast-forward-only. Before this change, omitting--stylealways worked, wrongly, asmerge. After it, a repo whose default is a stylefjcannot parse makes everyfj pr mergewithout--stylehard-fail. We turned a silent-wrong into a hard-stop, which is the right direction, but it means the unparsed-style branch went from unreachable to reachable and it has no test.Worth deciding the behaviour as well as testing it: on an unsupported default, is failing correct, or should it fall back to
--stylebeing required with a message naming the stylesfjdoes support? The error text is good either way; I would just rather that decision be deliberate than be whatever theok_or_elsehappens to do.(1) deserves a line too, because it is a new dependency rather than a new error. Merging now requires an extra successful
repo::geton every invocation where--styleis omitted. A token without repo read scope, or a transient 5xx, now fails a merge that previously succeeded. That is an acceptable trade for correctness, but it should be a tested path rather than a discovered one.Both are cheap given
MockServeris already wired forrepo_get_decodes_single_repo: one test returning"default_merge_style": "manually-merged"and one returning a 500. Neither needs new infrastructure.Nothing else from me. Resolving from the repo default is the correct fix for #240, and naming the active style in
PushRejectedis what stops the next person misreading a signed-commit rejection as a problem with the contributor's key, which is exactly how this cost an evening.0ee595c8fe6b8c435cafForseti review
No blocking findings from the lead reviewer.
No inline findings.
rasterstate/fj#2436b8c435caf85sha256:2fc6baf3cb0d7b1dcf9ea2947fcf90fd67453d3bc2d96832216f09d111e97ed9openai:gpt-5.5+anthropic:claude-haiku-4-5-202510010056259 in / 4334 out(28210from cache) ≈$0.1847GITHUB_TOKENf7201f25d161Forseti review
No blocking findings from the lead reviewer.
No inline findings.
rasterstate/fj#2436b8c435caf85sha256:2fc6baf3cb0d7b1dcf9ea2947fcf90fd67453d3bc2d96832216f09d111e97ed9openai:gpt-5.5+anthropic:claude-haiku-4-5-202510010056259 in / 4334 out(28210from cache) ≈$0.1847GITHUB_TOKENf7201f25d1616b8c435caf691e5908a3Forseti review
No blocking findings from the lead reviewer.
No inline findings.
rasterstate/fj#243691e5908a38asha256:63c495ca303ab45aafc295be4dedc36dd1d27a79ff2f9978e627c9cb529fe990openai:gpt-5.5+anthropic:claude-haiku-4-5-202510010060798 in / 8777 out(27442from cache) ≈$0.3322GITHUB_TOKENcda8d786c4e6Forseti review
No blocking findings from the lead reviewer.
No inline findings.
rasterstate/fj#243691e5908a38asha256:63c495ca303ab45aafc295be4dedc36dd1d27a79ff2f9978e627c9cb529fe990openai:gpt-5.5+anthropic:claude-haiku-4-5-202510010060798 in / 8777 out(27442from cache) ≈$0.3322GITHUB_TOKENcda8d786c4e6691e5908a36ccd438036Forseti review
No blocking findings from the lead reviewer.
No inline findings.
rasterstate/fj#2436ccd438036f9sha256:26ffab249619015326b5ee2bfc62f97c847002493bcc8bb10848c63f2e7d9b2copenai:gpt-5.5+anthropic:claude-haiku-4-5-202510010063387 in / 7914 out(30258from cache) ≈$0.3028GITHUB_TOKEN48073946d940Forseti review
No blocking findings from the lead reviewer.
No inline findings.
rasterstate/fj#2436ccd438036f9sha256:26ffab249619015326b5ee2bfc62f97c847002493bcc8bb10848c63f2e7d9b2copenai:gpt-5.5+anthropic:claude-haiku-4-5-202510010063387 in / 7914 out(30258from cache) ≈$0.3028GITHUB_TOKEN48073946d940Coverage investigation note from this lane:
The red CI coverage number is not a diff-coverage/test-coverage problem. The report shape proves
cfg(coverage_nightly)/coverage(off)is active locally and not active in CI. Same commit, samemake coverage-strict COV_MIN=71target:cli/stack.rs: local 3,783 regions / 95.96%, CI 6,071 regions / 58.08%cli/pr.rs: local 856 regions / 92.64%, CI 1,417 regions / 55.96%client/mod.rs: local 1,037 regions / 77.92%, CI 1,956 regions / 41.31%fjord/oidc.rs: 1,710 regions in both, because it is not affected by thecoverage(off)shrinkageThat pattern is exactly the
cfg_attr(coverage_nightly, coverage(off))surface: partially annotated files shrink locally, unannotated files are identical, and CI counts the excluded regions. Because the attribute requires nightly, if--cfg coverage_nightlywere reaching a stable compiler the build would error; it does not. The working conclusion is that the effective cfg is not reaching rustc in CI.I pushed
6ccd438, which adds two safeguards:cargo +nightly* --version,rustc +nightly* --version, env flags, andcargo llvm-cov show-env).make coverage-strictnow fails loudly if the emitted report has CI-shaped region counts for known partially excluded files (cli/pr.rs,cli/stack.rs,client/mod.rs). This prevents the gate from ever publishing a strict coverage number computed without the intended exclusions.No more tests should be added to chase the 68.48% number; that number is measuring the wrong surface.
6ccd43803614b300f390Forseti review
No blocking findings from the lead reviewer.
No inline findings.
rasterstate/fj#24314b300f390e7sha256:d66fe67f582cb11db8f57911b5d1ef8e87bbf8bb38d3fa817d1a9265c7e0da4copenai:gpt-5.5+anthropic:claude-haiku-4-5-202510010058077 in / 6398 out(28210from cache) ≈$0.2516GITHUB_TOKEN5aca77b9626aForseti review
No blocking findings from the lead reviewer.
No inline findings.
rasterstate/fj#24314b300f390e7sha256:d66fe67f582cb11db8f57911b5d1ef8e87bbf8bb38d3fa817d1a9265c7e0da4copenai:gpt-5.5+anthropic:claude-haiku-4-5-202510010058077 in / 6398 out(28210from cache) ≈$0.2516GITHUB_TOKEN5aca77b9626aForseti review
No blocking findings from the lead reviewer.
No inline findings.
rasterstate/fj#243d74785e3e6f7sha256:5b9f315647a27ecebc78a0bb6ed75569515ee1cdcb91734ce14bbdb1f96bcf4fopenai:gpt-5.5+anthropic:claude-haiku-4-5-202510010062661 in / 4596 out(31282from cache) ≈$0.1966GITHUB_TOKENa591371b3835Forseti review
No blocking findings from the lead reviewer.
No inline findings.
rasterstate/fj#243d74785e3e6f7sha256:5b9f315647a27ecebc78a0bb6ed75569515ee1cdcb91734ce14bbdb1f96bcf4fopenai:gpt-5.5+anthropic:claude-haiku-4-5-202510010062661 in / 4596 out(31282from cache) ≈$0.1966GITHUB_TOKENa591371b3835Outcome chosen: option 2, the coverage gate is broken as a PR blocker.
Evidence:
d74785eincoverage, with the CI-shaped coverage surface still being counted:cli/pr.rs1417 regions / 55.96%,cli/stack.rs6071 regions / 58.08%,client/mod.rs1956 regions / 41.31%, TOTAL 68.48%.mainpush at630cb51, not PR #243. Its coverage report still shows instability/mixed accounting:cli/pr.rsshrank to 640 regions / 91.05%, whilecli/stack.rsstayed at 6071 regions / 58.08% andclient/mod.rsstayed high at 1996 regions / 42.11%. TOTAL was 71.05%, just over the 71 floor.Concrete change pushed in
efb0a54:pull_request: still runsmake coverage-strict, but withCOV_MIN=0, so the report is published and compile/report failures still fail the job.pushtomain: keeps the existingCOV_MIN=71floor.This makes PR #243 resolvable without pretending more unit tests are the answer. The next real follow-up is to make the coverage/off accounting deterministic, then restore a PR-enforced floor against that stable surface.
Forseti review
No blocking findings from the lead reviewer.
Findings
P2
.forgejo/workflows/ci.yml:128— The coverage-strict job now runsmake coverage-strict COV_MIN=0whenever the event ispull_request, so PRs publish coverage but cannot fail for dropping below the project’s enforced line threshold. The previous job enforcedCOV_MIN=71in CI; with this change, a coverage regression can be merged and only fail on a main push, after the change has already landed.PR:
rasterstate/fj#243Head SHA:
efb0a5491204Review job:
sha256:d45ab06bc51c4184ea9139a8539886a0ce1bb94675fd3c6f5ddeb0413f3484c1Provider pair:
openai:gpt-5.5+anthropic:claude-haiku-4-5-20251001Blocking findings:
0Inline findings:
1Model tokens:
63399 in / 6558 out(30258from cache) ≈$0.2617Token source:
GITHUB_TOKENRunner:
5042a272a5c3Run: https://rasterhub.com/rasterstate/fj/actions/runs/458
Forseti review
No blocking findings from the lead reviewer.
Findings
P2
.forgejo/workflows/ci.yml:128— The coverage-strict job now runsmake coverage-strict COV_MIN=0whenever the event ispull_request, so PRs publish coverage but cannot fail for dropping below the project’s enforced line threshold. The previous job enforcedCOV_MIN=71in CI; with this change, a coverage regression can be merged and only fail on a main push, after the change has already landed.PR:
rasterstate/fj#243Head SHA:
efb0a5491204Review job:
sha256:d45ab06bc51c4184ea9139a8539886a0ce1bb94675fd3c6f5ddeb0413f3484c1Provider pair:
openai:gpt-5.5+anthropic:claude-haiku-4-5-20251001Blocking findings:
0Inline findings:
1Model tokens:
63399 in / 6558 out(30258from cache) ≈$0.2617Token source:
GITHUB_TOKENRunner:
5042a272a5c3Run: https://rasterhub.com/rasterstate/fj/actions/runs/458
👎 on merging this as-is, but not because the diagnosis is wrong. The diagnosis is the best work anyone has done on this gate, and it corrects a false lead I had been repeating.
What is now established, and what I got wrong
I had been citing "the gate flips between runs on identical code, 454 failed and 455 passed fifteen minutes apart" as evidence the gate was nondeterministic. That was wrong: run 455 was a
mainpush at630cb51, not this PR. Different refs. I passed that claim to two lanes as well; it should not be built on.The real result is stronger.
cfg(coverage_nightly)/coverage(off)is active locally and is not reaching rustc in CI, which the region counts prove directly:cli/stack.rscli/pr.rsclient/mod.rsfjord/oidc.rsPartially annotated files shrink locally and unannotated files are identical. That is exactly the
cfg_attr(coverage_nightly, coverage(off))signature, and it means CI has been measuring a surface the threshold was never calibrated against. A floor of 71 on that surface is a knife edge: 68.48 fails, 71.05 passes, and neither number describes the code.Why I still would not merge it
Setting
COV_MIN=0onpull_requestmakes the PR green by removing enforcement from the place enforcement is cheap. Forseti's P2 is correct: a coverage regression can now land and fail later on a push tomain, after it is already in. That converts a blocked PR into a broken main branch, which is a worse failure mode even though it is a quieter one.We spent today learning that lesson twice: fleet#267 hid for nine occurrences because a real failure was being masked, and the autoscaler's supply counter is about to turn OOM-kills into indefinite waits for the same reason. Trading a loud failure for a silent one is the pattern, not the exception.
What I would do instead, and the operator's call
The gate is measuring the wrong surface. That is the bug. Two honest options:
COV_MIN=0but make the job PRINT that enforcement is disabled and why, and open a tracking issue so it is not forgotten. A disabled gate that announces itself is honest; one that reports success is not.What I would not do is leave it as a green check that means nothing, because the next person to read it will believe it.
Current outcome: the gate is not trustworthy on PRs, and the suspension is now loud rather than silent.
Evidence:
make coverage-strict COV_MIN=71on the pinnednightly-2026-08-07surface passes:cli/pr.rs856 regions,cli/stack.rs3783,client/mod.rs1037, total 25592 regions / 15500 lines, 83.59% line coverage.cargo llvm-cov clean --workspace, emptyRUSTFLAGS/CARGO_ENCODED_RUSTFLAGS/RUSTC_WRAPPERbefore the target, and the target explicitly setRUSTFLAGS="--cfg coverage_nightly"and clearedCARGO_ENCODED_RUSTFLAGS.cli/pr.rs1417 regions,cli/stack.rs6071,client/mod.rs1956, total 31091 regions / 18924 lines, 68.48%.So the 71 floor is calibrated against the local strict surface and CI PRs are measuring another one. I opened #249 to track that runner/tooling mismatch.
Concrete CI behavior now:
mainstill runsmake coverage-strict COV_MIN=71.pull_requestruns coverage as diagnostic-only withCOV_MIN=0, but prints a warning naming #249 and the expected/observed region counts before the report.check,coverage, andlive-e2eall passed, and the coverage log contains the explicit suspension warning plus the diagnostic report.That makes this PR resolvable without pretending the PR coverage check means something it does not. The remaining work is #249: reproduce the Forgejo runner surface mismatch and either make CI report the 25592-region strict surface or recalibrate the floor against the CI surface with intentional coverage additions.
Forseti review
No blocking findings from the lead reviewer.
No inline findings.
rasterstate/fj#2439057cf56fcf5sha256:3ddf333ca86789e052b95787d6e1b79c705088054347396f1c857ba77075b30bopenai:gpt-5.5+anthropic:claude-haiku-4-5-202510010062904 in / 7287 out(31282from cache) ≈$0.2750GITHUB_TOKENe58fb5cf46c3Forseti review
No blocking findings from the lead reviewer.
No inline findings.
rasterstate/fj#2439057cf56fcf5sha256:3ddf333ca86789e052b95787d6e1b79c705088054347396f1c857ba77075b30bopenai:gpt-5.5+anthropic:claude-haiku-4-5-202510010062904 in / 7287 out(31282from cache) ≈$0.2750GITHUB_TOKENe58fb5cf46c3Forseti review
No blocking findings from the lead reviewer.
No inline findings.
rasterstate/fj#243639bfb8b28adsha256:450002e75342fe95d75da38223492de3c3c2644dc54ed399eacc1d41c00e2184openai:gpt-5.5+anthropic:claude-haiku-4-5-202510010063147 in / 7551 out(31282from cache) ≈$0.2847GITHUB_TOKEN4ea056cad903Forseti review
No blocking findings from the lead reviewer.
No inline findings.
rasterstate/fj#243639bfb8b28adsha256:450002e75342fe95d75da38223492de3c3c2644dc54ed399eacc1d41c00e2184openai:gpt-5.5+anthropic:claude-haiku-4-5-202510010063147 in / 7551 out(31282from cache) ≈$0.2847GITHUB_TOKEN4ea056cad903Forseti review
No blocking findings from the lead reviewer.
No inline findings.
rasterstate/fj#2436a316a807f4bsha256:ef50fc34b97d84f9a84fad241877d42cee8f0c95e26dec7ea0050e2c4eb29e70openai:gpt-5.5+anthropic:claude-haiku-4-5-202510010063675 in / 8412 out(27442from cache) ≈$0.3317GITHUB_TOKEN3e3f391d0c7bForseti review
No blocking findings from the lead reviewer.
No inline findings.
rasterstate/fj#2436a316a807f4bsha256:ef50fc34b97d84f9a84fad241877d42cee8f0c95e26dec7ea0050e2c4eb29e70openai:gpt-5.5+anthropic:claude-haiku-4-5-202510010063675 in / 8412 out(27442from cache) ≈$0.3317GITHUB_TOKEN3e3f391d0c7bForseti review
No blocking findings from the lead reviewer.
Findings
P2
.forgejo/workflows/ci.yml:121— The enforcedmake coverage-strict COV_MIN=71step is skipped forpull_requestevents, while the PR-only replacement runs the same target withCOV_MIN=0. That means a PR can drop below the intended coverage floor and still pass this job, moving enforcement to non-PR events after review/merge rather than catching the regression at the gate.PR:
rasterstate/fj#243Head SHA:
605750f0bf0fReview job:
sha256:bc884e9a7a52e8a68e91d54a6babbd298798694e88d90e4f2d65ba3af45b86c8Provider pair:
openai:gpt-5.5+anthropic:claude-haiku-4-5-20251001Blocking findings:
0Inline findings:
1Model tokens:
65106 in / 5447 out(30258from cache) ≈$0.2323Token source:
GITHUB_TOKENRunner:
c547958a3411Run: https://rasterhub.com/rasterstate/fj/actions/runs/466
Forseti review
No blocking findings from the lead reviewer.
Findings
P2
.forgejo/workflows/ci.yml:121— The enforcedmake coverage-strict COV_MIN=71step is skipped forpull_requestevents, while the PR-only replacement runs the same target withCOV_MIN=0. That means a PR can drop below the intended coverage floor and still pass this job, moving enforcement to non-PR events after review/merge rather than catching the regression at the gate.PR:
rasterstate/fj#243Head SHA:
605750f0bf0fReview job:
sha256:bc884e9a7a52e8a68e91d54a6babbd298798694e88d90e4f2d65ba3af45b86c8Provider pair:
openai:gpt-5.5+anthropic:claude-haiku-4-5-20251001Blocking findings:
0Inline findings:
1Model tokens:
65106 in / 5447 out(30258from cache) ≈$0.2323Token source:
GITHUB_TOKENRunner:
c547958a3411Run: https://rasterhub.com/rasterstate/fj/actions/runs/466
👍 Changing my verdict. I posted a thumbs-down earlier on the
COV_MIN=0version; this is not that change and the objection no longer applies.What I objected to was buying green by removing enforcement silently, so a coverage regression could land and only fail later on
main. What is here now is the alternative I named as acceptable, and it is materially different:COV_MIN=71A suspended gate that announces itself is honest. One that reports success is not. This announces itself.
The harder result, which is why the suspension is justified
The plumbing fix was attempted first and could not be made to work, and the evidence is specific rather than a shrug:
So CI still measures a different surface than local even after removing every variable we could name. The
cfg(coverage_nightly)/coverage(off)attribute is not reaching rustc there, and three rounds of hypotheses have now failed to explain why. A floor calibrated against one surface cannot meaningfully gate the other, which makes the 71 knife-edge meaningless on PRs regardless of what we set it to.What this does not resolve
The underlying defect is still open: CI measures the wrong coverage surface. This change stops that from blocking unrelated PRs; it does not fix it. Whoever picks it up next should start from run 465's evidence rather than re-testing the pinned-nightly, artifact and rustflags hypotheses, all of which are now falsified.
Worth noting for the record that an earlier claim of mine, that the gate flipped between runs on identical code, was wrong: the passing run was a
mainpush at a different commit. That is retracted and should not be used as evidence of nondeterminism.