fix(oci): derive publish mode from trigger to end twin-publish race (GOV-15) #457
Loading…
Reference in a new issue
No description provided.
Delete branch "fix/GOV-15-twin-trigger-publish-mode"
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?
Ports the GOV-13 twin-trigger publish-mode fix into this repo's OCI build workflow as part of the GOV-15 rollout. A worked reference is auto-buyer (NiceGuyIT) PR #78.
The
build-oci-image.ymlworkflow triggers on push to bothbranches: [main]andtags: [v*], and resolved its publish tags fromgit describeviaci-build/get-tags.nu --joined, which returns[vX.Y.Z, latest]on a tagged commit. Because a release commit is simultaneously a push to main and thev*tag push, both events fire, both build the same image, and both race to overwrite the mutable:latesttag (and 409 on immutable generic-package artifacts). The two runs resolved the identical tag set and wrote the same destinations.The fix derives the publish MODE from the trigger rather than from
git describe, so the two runs publish DISJOINT tags: the tag-push run publishes onlyvX.Y.Z(release train), the main-push run publishes onlylatest(latest train), and they never collide. The helperci-build/get-tags.nuis replaced with the canonical--mode release|latest|dry-runversion that returns a single{ mode, train, tag, describe }record. A newworkflow_dispatchtrigger adds a dry-run path that builds and prints every registry action without pushing and without writing the build cache.Repo-specific wiring is preserved unchanged: the
lets-chatimage name, thea8n-toolsprivate org registry auth, the LC-214 build-arg provenance injection, theDockerfile.webpath, and the GOV-20type=ghabuild cache plus its Actions-runtime export step.--cache-tonow runs only on a real publish so a dry-run mutates neither the registry nor the cache.Verification (all PASS): the workflow YAML parses,
nu-checkpasses on the helper, the four functional modes resolve the correct tag (release -> v9.9.9, latest -> latest, dry-run+simulate -> release/v9.9.9, dry-run -> latest/latest), and both error paths (unknown mode, release with no version) exit non-zero.The OCI build workflow triggers on push to both `branches: [main]` and `tags: [v*]`, and resolved its tag set from `git describe` via `ci-build/get-tags.nu --joined`, which returns `[vX.Y.Z, latest]` on a tagged commit. A release commit is simultaneously a push to main and a `v*` tag push, so both events fire, both build the same image, and both race to overwrite the mutable `:latest` tag (and 409 on immutable artifacts). Fix: derive the publish MODE from the trigger, not from `git describe`, so the two runs publish DISJOINT tags. The helper is rewritten to take `--mode release|latest|dry-run` and return a single `{ mode, train, tag, describe }` record; the tag-push run publishes only `vX.Y.Z`, the main-push run publishes only `latest`, and they never write the same destination. A `workflow_dispatch` trigger adds a dry-run path that builds and prints without mutating the registry (and without writing the gha buildcache). The GOV-20 `type=gha` build cache and the Actions-runtime export step are preserved; `--cache-to` now only runs on a real publish. #GOV-15 #GOV-13