Derive OCI publish mode from trigger, not git describe #75

Merged
David merged 2 commits from fix/GOV-15-twin-trigger-publish-mode into main 2026-06-26 21:43:13 +02:00
Owner

Ports the GOV-13 twin-trigger publish-mode fix into this repo's OCI build workflow as part of the GOV-15 rollout.

The build-oci-image.yml workflow triggered on push to both branches: [main] and tags: [v*] and resolved its tag set from git describe via oci-build/get-tags.nu --joined, which returned [vX.Y.Z, latest] on a tagged commit. A release commit is at once a main push and a v* tag push, so both events fired, both built the same image, and both raced to overwrite the mutable :latest tag (a 409 on immutable artifacts, an overwrite race on the OCI latest tag).

This change derives the publish MODE from the trigger instead of from git describe: a v* tag push resolves the release train and publishes only the immutable vX.Y.Z tag, a main push resolves the latest train and publishes only the rolling latest tag, and a manual workflow_dispatch resolves a dry-run that builds and prints but mutates nothing. The two real triggers now write disjoint tag sets, so the two runs never race to the same destination.

Scope is a minimal port: the helper oci-build/get-tags.nu is replaced with the canonical --mode interface, a workflow_dispatch trigger with dry-run/simulate-tag inputs is added, and the build, push and print steps now use the single resolved tag with the push and --cache-to gated on dry-run. The image name (vervain-server), registry/secret wiring, type=gha cache strategy, Dockerfile path, and push paths are all left untouched.

Verification: YAML parses, nu-check on the helper returns true, all four functional modes resolve the correct tag/train (release -> v9.9.9, latest -> latest, dry-run simulate -> release/v9.9.9, dry-run plain -> latest/latest), and both error paths (bogus mode, release without a version) exit non-zero. The repo just pre-commit suite (compile, clippy, fmt, 437 tests) passed before commit.

Ports the GOV-13 twin-trigger publish-mode fix into this repo's OCI build workflow as part of the GOV-15 rollout. The `build-oci-image.yml` workflow triggered on push to both `branches: [main]` and `tags: [v*]` and resolved its tag set from `git describe` via `oci-build/get-tags.nu --joined`, which returned `[vX.Y.Z, latest]` on a tagged commit. A release commit is at once a main push and a `v*` tag push, so both events fired, both built the same image, and both raced to overwrite the mutable `:latest` tag (a 409 on immutable artifacts, an overwrite race on the OCI `latest` tag). This change derives the publish MODE from the trigger instead of from `git describe`: a `v*` tag push resolves the `release` train and publishes only the immutable `vX.Y.Z` tag, a main push resolves the `latest` train and publishes only the rolling `latest` tag, and a manual `workflow_dispatch` resolves a dry-run that builds and prints but mutates nothing. The two real triggers now write disjoint tag sets, so the two runs never race to the same destination. Scope is a minimal port: the helper `oci-build/get-tags.nu` is replaced with the canonical `--mode` interface, a `workflow_dispatch` trigger with dry-run/simulate-tag inputs is added, and the build, push and print steps now use the single resolved tag with the push and `--cache-to` gated on dry-run. The image name (`vervain-server`), registry/secret wiring, type=gha cache strategy, Dockerfile path, and push paths are all left untouched. Verification: YAML parses, `nu-check` on the helper returns true, all four functional modes resolve the correct tag/train (release -> v9.9.9, latest -> latest, dry-run simulate -> release/v9.9.9, dry-run plain -> latest/latest), and both error paths (bogus mode, release without a version) exit non-zero. The repo `just pre-commit` suite (compile, clippy, fmt, 437 tests) passed before commit.
fix(ci): derive OCI publish mode from trigger, not git describe
All checks were successful
Check / fmt + clippy + build + tests (pull_request) Successful in 1m52s
9f707709ba
The build-oci-image workflow triggered on push to both `branches: [main]` and `tags: [v*]` and resolved its tag set from `git describe` via `oci-build/get-tags.nu --joined`, which returned `[vX.Y.Z, latest]` on a tagged commit. A release commit is simultaneously a main push and a `v*` tag push, so both events fired, both built the same image, and both raced to overwrite the mutable `:latest` tag.

Derive the publish MODE from the trigger instead: a `v*` tag push resolves the `release` train and publishes only the immutable `vX.Y.Z` tag, a main push resolves the `latest` train and publishes only the rolling `latest` tag, and a manual `workflow_dispatch` resolves a dry-run that builds and prints but mutates nothing. The two real triggers now write disjoint tag sets, so the two runs never race to the same destination.

Rewrite `oci-build/get-tags.nu` to the canonical `--mode` interface returning a single resolved record, add a `workflow_dispatch` trigger with dry-run/simulate-tag inputs, replace the multi-tag build and print logic with the single resolved tag, and gate the push and cache-to on dry-run so a manual run pushes nothing.

#GOV-15
#GOV-13
Merge branch 'main' into fix/GOV-15-twin-trigger-publish-mode
All checks were successful
Check / fmt + clippy + build + tests (pull_request) Successful in 2m22s
Create release / Create release from merged PR (pull_request) Has been skipped
1ed6bfe275
David merged commit ca0c65f5ab into main 2026-06-26 21:43:13 +02:00
David deleted branch fix/GOV-15-twin-trigger-publish-mode 2026-06-26 21:43:13 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/vervain-server!75
No description provided.