merge failure recovery docs and error catalogue#9566
Conversation
There was a problem hiding this comment.
No issues found across 19 files
Confidence score: 5/5
- Automated review surfaced no issues in the provided summaries.
- No files require special attention.
Shadow auto-approve: would auto-approve. Introduces a new MergeInProgressError with structured error code, updates error catalogue, docs, and frontend error handling. All changes are additive and well-tested, with no refactoring of existing logic or risk to core business functionality.
Re-trigger cubic
Merging this PR will improve performance by 32.11%
|
| Benchmark | BASE |
HEAD |
Efficiency | |
|---|---|---|---|---|
| ⚡ | test_base_schema_duplicate_CoreProposedChange |
2.2 ms | 1.5 ms | +49.84% |
| ⚡ | test_schemabranch_duplicate |
7.7 ms | 6.6 ms | +16.48% |
Tip
Curious why this is faster? Comment @codspeedbot explain why this is faster on this PR, or directly use the CodSpeed MCP with your agent.
Comparing ifc-2437-merge-failure-recovery-docs-and-catalogue (66b6354) with stable (1653400)1
Footnotes
9ff5cb3 to
66b6354
Compare
ajtmccarty
left a comment
There was a problem hiding this comment.
@opsmill/frontend could you please review the small frontend changes in this PR when you have time?
There was a problem hiding this comment.
support new error codes
There was a problem hiding this comment.
match on new error code for "merge in-progress" for retrying during E2E tests
Why
The write-block increment rejects mid-merge writes with a hardcoded message string, and the only way for a client to tell "retry, this is transient" from "give up, this branch is read-only" was to string-match the error message. The E2E retry helper already did exactly this (
error.message === MERGE_IN_PROGRESS_MESSAGE), which silently breaks the moment the wording changes. The new write-blocking behavior was also undocumented for both users and contributors.Goal: give the merge write-block rejections stable, structured GraphQL error codes so clients (and the E2E suite) can branch on a code instead of a message, and document the during-merge write-blocking in the user docs and the dev knowledge base.
Non-goals: no change to the write-block behavior itself, the messages users see, or which operations are blocked (all from the prior increment); the
MERGE_FAILEDstate andinfrahub recoverrecovery flow are out of scope; REST endpoints keep their existing 422 wrapping.Closes IFC-2562
What changed
Behavioral changes (API surface):
extensions({code, http_status, data}), in addition to the unchanged human message:BRANCH_ALREADY_MERGED(HTTP 400) — write to aMERGEDbranch. Payload:{branch_name}.BRANCH_NEEDS_REBASE(HTTP 400) — write to aNEED_REBASEbranch. Payload:{branch_name}.MERGE_IN_PROGRESS(HTTP 423 Locked) — write blocked by an in-progress merge, on either the branch being merged or the default branch. Payload:{branch_name, merging_branch}.MERGE_IN_PROGRESSis the transient/retryable signal; clients should match on the code and retry rather than treating the failure as permanent.parseCatalogueError(error.extensions).code === ERROR_CODES.MERGE_IN_PROGRESSinstead of comparing the message string.Implementation notes:
MergeInProgressError(BranchStatusError)(HTTP 423) carrying amerging_branchattribute. Both gates inBranchStatusChecker.check_merging_status(source-branch and default-branch) and the cache-unreachable DB fallback raise it; the messages are unchanged. The default-branch DB-fallback case usesmin(merging_branch_names)for a deterministicmerging_branch.MERGE_IN_PROGRESScode (decision: one code for "blocked by an active merge"). A client retrying a write to the source branch self-corrects — once the merge lands the code flips toBRANCH_ALREADY_MERGEDand the retry helper fails fast.extensions.http_status.tasks/backend.py:export-error-cataloguebuilt its output path from the shell-escaped repo path, so in a worktree whose path contains a.it wrote to a literalinfrahub\.worktrees/...directory instead of the real one. Switched to the unescapedREPO_BASEsince the path is used for a filesystem write, not a shell command.How to review
Focus areas:
backend/infrahub/branch/status_checker.py— the four raise-site swaps toMergeInProgressErrorand themerging_branchvalues passed on each path.backend/infrahub/errors/{catalogue,payloads}.py,exceptions.py,graphql/error_formatter.py— the catalogue entries, payload models, and the_build_payloadmatch arms.frontend/app/tests/e2e/utils/graphql.ts— the actual consumer change (string match → code match).Checklist
uv run towncrier create ...)Summary by cubic
Introduce a structured
MERGE_IN_PROGRESSerror and enforce merge-time write blocking on the source and default branches. Updates align with IFC-2437 by making merge state visible to clients so they can safely retry and by clarifying behavior in docs.New Features
MergeInProgressError(HTTP 423) with payload{ branch_name, merging_branch }; raised by the status checker when merge protection is active (cache-first with DB fallback).BRANCH_ALREADY_MERGED,BRANCH_NEEDS_REBASE, andMERGE_IN_PROGRESS.MERGE_IN_PROGRESSexample; error catalogue lists the new codes; internal knowledge base coversMERGINGstate and the write blocker.MERGE_IN_PROGRESScode instead of the message.error-catalogue.json; adjusted the export task to write to the repo base path.Migration
extensions.code === "MERGE_IN_PROGRESS"and retry after a short delay.Written for commit 9ff5cb3. Summary will update on new commits.