Skip to content

fix: retry manifest state writes on contents API 409 conflicts - #261

Merged
joshua-temple merged 2 commits into
mainfrom
fix/state-write-409-retry
Jun 23, 2026
Merged

joshua-temple merged 2 commits into
mainfrom
fix/state-write-409-retry

Conversation

@joshua-temple

Copy link
Copy Markdown
Collaborator

Problem

Concurrent per-environment finalize jobs (hotfix/promote) PUT the shared manifest.yaml via the GitHub Contents API at the same blob SHA; the second writer gets HTTP 409 and its env state is dropped. The live fleet caught this on a multi-env hotfix chain (rc v0.3.0-rc.22), where parallel test and staging finalize runs raced and the loser's environment state was never written.

Fix

Adds a shared optimistic-lock read-modify-write in internal/statewrite: fetch the current manifest, re-apply this caller's env-scoped mutation, PUT, and retry on 409 (bounded, backed off) so the loser re-reads the winner's state and both merge. Promote and hotfix finalize both route through it; orchestrate/rollback inherit it via promote. As defense-in-depth, the generated hotfix finalize path uses a per-repo concurrency group so finalize runs queue instead of racing.

Verification

New internal/statewrite package with a stubbed-client test proving a 409-then-success sequence merges both writers' state and that exhaustion surfaces a clean error; merge-semantics and generator concurrency assertions added. go build/test ./..., golangci-lint, and the generator actionlint/generated-bytes tests all green. schema_version unchanged; no manifest field. The stubbed-client unit test is the regression guard (act+gitea cannot reproduce the parallel Contents-API race); the 4env fleet step is the live counterpart.

Signed-off-by: Joshua Temple <joshua.temple@stablekernel.com>
@joshua-temple
joshua-temple enabled auto-merge (squash) June 23, 2026 13:58
Signed-off-by: Joshua Temple <joshua.temple@stablekernel.com>
@joshua-temple
joshua-temple merged commit 7a2166c into main Jun 23, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant