Skip to content

feat(api)!: answer failed merge guards with 409 ref_guard_failed - #571

Merged
ThomasK33 merged 1 commit into
mainfrom
568-ref-guard-merge
Oct 27, 2026
Merged

ThomasK33 merged 1 commit into
mainfrom
568-ref-guard-merge

Conversation

@ThomasK33

Copy link
Copy Markdown
Member

A failed merge guard now answers 409 with code ref_guard_failed and two new members: guard and current_sha. A merge with expected_source_sha whose source branch does not exist now fails that guard (409, current_sha 40 zeros) instead of answering 404. This is PR 1 of 2 for #568. PR 2 adds the problem members to the notes 409s.

What

  • POST /api/v1/repos/merge and POST /api/repos/{repo_name}/merge, stale expected_target_sha: 409 with code ref_guard_failed, guard: expected_target_sha and current_sha = the target tip. Before, the code was conflict with no guard or current_sha.
  • Same routes, a source branch that does not contain expected_source_sha: 409 ref_guard_failed, guard: expected_source_sha, current_sha = the source tip.
  • Same routes, expected_source_sha set and the source branch missing: 409 ref_guard_failed with current_sha 40 zeros. Before, this was 404. Without expected_source_sha, a missing source branch is still 404. The target lookup and the target guard still run first.
  • detail and error text do not change. Nothing else changes: the content type stays application/json (the api: problem-details later tiers (specific codes, instance, result envelope, git/LFS writers, problem+json) — held on SDK trigger #352 SDK gate has not fired), and every other route keeps its status and code.
  • errors.go: ref_guard_failed (409) joins the specific-code map. One new writer sends it, and writeProblem asserts that the code always carries both members and that no other code carries them.
  • Docs: http-api.md (error codes, merge row, merge guards), wire-compatibility.md (the RFC 9457 row, the api: a stale expected_*_sha on commit-pack and diff-commit answers 412; the upstream spec lists only 409 #533 guard rows for commit-pack, diff-commit and the notes forms, a new restore-commit row, and the snapshot provenance), and the ADR-22 amendment note.

Why

The upstream docs OpenAPI of 2026-10-27 (c494c01b) adds the specific code ref_guard_failed with the schema RefGuardProblemDetails and says that the merge guards use it. The Oct 22 changelog already said that a deleted source branch answers 409. Vendoring the spec alone fails TestSpecificProblemCodesMatchUpstream, so the spec, the code map and the first behavior change land together.

Snapshot

  • docs/upstream/openapi.yaml is the audit copy of the docs spec: Last-Modified 2026-10-27 21:25:57 GMT, ETag W/"BXslwivBc1LQOzE_", SHA-256 c494c01b2299053d8e6591a4aa794e65d2e38859407da6d320322d9f0d0119d0.
  • At 21:47:38 UTC the cluster spec still served 10f3e009 (the previous snapshot), so the change is documented in the docs only.
  • At 21:47:38 UTC the docs spec had moved again (Last-Modified 21:45:58, SHA-256 b598ce96…). Its only change is two message descriptions on commit lists and files/metadata. I did not widen this PR. Upstream drift (spec 2026-10-27 21:45): commit list and files/metadata messages are the subject line only; spec b598ce96 #570 tracks that revision.

Not in this PR

Proof

  • Tests first. On main's handler, 4 new or changed subtests fail on each backend (PostgreSQL and SQLite): the stale target guard, the pin outside the source branch, the pin on a missing source branch (404 today) and the path-style route. All return code conflict or 404. With the fix they pass.
  • TestProblemMembersMatchUpstream now pins guard and current_sha and the guard enum to RefGuardProblemDetails in the vendored spec. The shared oracle (assertProblemFields) accepts those two members only on code ref_guard_failed, and there it requires both: a guard from the spec enum and a 40-hex current_sha.
  • Mutation checks: 10 mutants, all killed. They covered the generic code on the target guard, the pin as current_sha, the old 404 for a missing source, a dropped guard member, a renamed current_sha member, the code-map entry removed, the source guard ahead of the target guard, the spec without the ref_guard_failed item, an extra value in the spec's guard enum, and an oracle that expects conflict.
  • Gates on this head: go test -race ./internal/api/... ok (PostgreSQL and SQLite), golangci-lint v2.15.0 (the mise.toml pin) 0 issues, and the docs gate (0 broken links, the link-checker tests pass).
  • githttp TestMerge_ExpectedSourceSHA passes on the local lane. The PostgreSQL and S3-WAL lanes did not start on my host: its disk is full, so SeaweedFS refused writes in TestMain before any test ran. The required test and test-s3wal CI jobs run that test on this head.

Refs #568

BREAKING CHANGE: a failed merge guard on POST /api/v1/repos/merge and POST /api/repos/{repo_name}/merge now answers code ref_guard_failed instead of conflict, with guard and current_sha members. A merge with expected_source_sha whose source branch does not exist answers 409 ref_guard_failed with current_sha 40 zeros instead of 404. Clients that branch on code conflict for a merge guard must check ref_guard_failed.


Generated with xum • Model: anthropic:claude-opus-5-5 • Thinking: high

Refs #568

_Generated with [`xum`](https://github.com/coder/xum) • Model: `anthropic:claude-opus-5-5` • Thinking: `high`_

Change-Id: Id3704634ec263d38bd926e07c6fb6533124ebf29
Signed-off-by: Thomas Kosiewski <tk@coder.com>
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@ThomasK33

Copy link
Copy Markdown
Member Author

@codex security review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-27T22:07:23.128942Z 7077c72 Manual request
🔒 Security Review ✅ Completed 2026-10-27T22:13:52.161330Z 7077c72 Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Chef's kiss.

Reviewed commit: 7077c72618

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review

Security review completed. No security issues were found in this pull request.

Reviewed commit: 7077c72618

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

1 similar comment
@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review

Security review completed. No security issues were found in this pull request.

Reviewed commit: 7077c72618

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant