Skip to content

fix(orchestrate): re-apply the component state leaf on a rejected finalize push - #537

Merged
joshua-temple merged 1 commit into
mainfrom
fix/orchestrate-finalize-reapply
Jul 9, 2026
Merged

joshua-temple merged 1 commit into
mainfrom
fix/orchestrate-finalize-reapply

Conversation

@joshua-temple

Copy link
Copy Markdown
Collaborator

Problem

The Go orchestrate finalize path committed the state leaf once, then relied on a textual git pull --rebase to land it. Two component finalizes appending adjacent leaves under state.components conflict on that rebase and hard-fail, despite a doc-comment claiming the retry loop re-runs the write. The promote, hotfix, and rollback finalizers already re-derive and re-apply their owned leaf per attempt; orchestrate was the outlier.

Fix

Add a WithReapply(func() error) option to the shared push-retry. On a rejected (non-fast-forward) push it re-fetches trunk, resets away the stale local commit, and invokes the closure to re-derive the owned leaf onto the fresh trunk bytes before retrying, so a concurrent sibling's leaf survives. Wired for component-scoped orchestrate runs only; single-component finalize stays on the textual path, byte- and behavior-identical. Retry count raised 3 to 10 with exponential jittered backoff, and a greppable per-attempt log line is emitted (live-proof instrumentation for a later stage). The false doc-comment is corrected.

Scope / safety

  • PushWithRebaseRetry is orchestrator-only; promote uses a separate CommitAndPushWithRetry; neither promote/hotfix/rollback passes WithReapply, so there is no double-apply.
  • Single-component output unchanged (the reapply path is gated on component != "").

Verification

New tests: two component lanes append adjacent leaves and B lands first, so A must re-apply; asserts all leaves survive (red-before proven by disabling the wiring, green-after); a regression guard that the old textual path conflicts. go build, go test ./... -race (2667 pass), golangci-lint all clean.

…alize push

The Go orchestrate finalize path committed the state leaf once and then relied on a textual git pull --rebase to land it, so two component finalizes appending adjacent leaves under state.components conflicted on the rebase and hard-failed, despite a doc-comment claiming the loop re-runs the write. The promote, hotfix, and rollback finalizers already re-derive and re-apply their owned leaf per attempt. Add a WithReapply option to the shared push-retry: on a rejected push it re-fetches trunk, resets away the stale local commit, and re-derives the owned leaf onto the fresh bytes before retrying, so a concurrent sibling's leaf survives. Wire it for component-scoped orchestrate runs only, leaving single-component finalize on the textual path byte-identical. Raise the retry count to ten with exponential jittered backoff and emit a per-attempt log line. Correct the false doc-comment.

Signed-off-by: Joshua Temple <joshua.temple@stablekernel.com>
@joshua-temple
joshua-temple merged commit 1a4bf73 into main Jul 9, 2026
20 checks passed
@joshua-temple
joshua-temple deleted the fix/orchestrate-finalize-reapply branch July 9, 2026 06:31
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