Skip to content

feat: auto-bump image version on rw2 release#1

Open
DanielKow wants to merge 7 commits into
masterfrom
feature/ci-release-pipeline
Open

feat: auto-bump image version on rw2 release#1
DanielKow wants to merge 7 commits into
masterfrom
feature/ci-release-pipeline

Conversation

@DanielKow

Copy link
Copy Markdown
Contributor

Summary

Adds .github/workflows/bump-image.yml, the receiving half of the RocketWelder release pipeline. When rocket-welder2 finishes promoting a new image to ACR, it sends a cross-repo repository_dispatch and this workflow updates the deployment bundle to point at the new image version.

What it consumes

This workflow is triggered by the rw2-released repository_dispatch event sent from rocket-welder2 (its promote-images.yml notify-compose job). The image version arrives in client_payload.version.

Flow (bump → commit → tag)

  1. Checks out master with full history (fetch-depth: 0) so all tags are available.
  2. Reads the version from client_payload.version into an env: var (injection-safe), and fails fast if it is empty ([ -z "$VERSION" ] && exit 1).
  3. Runs ./update-version.sh set "$VERSION" --format=json, which rewrites rocketwelder.version and the image tag in docker-compose.yml (+ arch-specific compose files).
  4. Computes the next compose tag (vX.Y.Z) from the latest existing v* tag — bumped independently of the image version line.
  5. Stages with git add -A. A no-op guard (if git diff --cached --quiet) skips the release entirely when nothing changed, so an unchanged version never produces an empty commit/tag.
  6. Otherwise commits to master, pushes, then creates and pushes the new vX.Y.Z compose tag.

Secrets / permissions

  • No secret is required in this repo. The job uses the default GITHUB_TOKEN with permissions: contents: write to push the commit and tag.
  • The dispatch itself is sent from rocket-welder2 using its COMPOSE_DISPATCH_TOKEN secret — that token lives in rocket-welder2, not here.

Other safeguards

  • concurrency: { group: compose-bump, cancel-in-progress: false } — serializes overlapping releases so two dispatches can't race on the tag bump.
  • The docker-compose.yml.bak that update-version.sh writes is covered by .gitignore (*.bak), so git add -A does not stage it.

Activation note

repository_dispatch workflows only become active after the file lands on the default branch. This PR must be merged to master before the rw2-released dispatch will trigger anything.

echo "No version change — nothing to release."
else
git commit -m "Release v$CNEW (image $VERSION)"
git push origin HEAD:master

@DanielKow DanielKow May 25, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[COULD] Optional hardening — not blocking.

Moderator ruling: Confirmed low-risk and clean-failing: compose-bump serializes automated runs, so the only trigger is a human pushing to compose master in the ~seconds window, and set -e aborts before the tag is created (no half-state — a re-dispatch fixes it cleanly). The suggested git pull --no-rebase retry adds complexity for a rare, self-healing case. Acceptable as-is; Engineer may add the merge-then-push guard if cheap. Not expected for merge.

Severity: MINOR
Category: Robustness (non-fast-forward push)

Evidence: bump-image.yml:44 git push origin HEAD:master pushes the commit made on the checked-out (dispatch-time) master.

Issue: If master advances between checkout and push, the push is rejected (non-ff) and the release fails. The compose-bump concurrency group already prevents two automated runs from racing, so the only realistic trigger is a human pushing to master during the ~seconds-long window — low risk.

Optional hardening: git pull --no-rebase origin master (merge, per repo rule — no rebase) before commit, or a small retry. Not blocking.

— Reviewer

Tagged by Moderator

@DanielKow

Copy link
Copy Markdown
Contributor Author

Reviewer summary — PR #1 (rocketwelder-compose)

Verdict: essentially clean. 1 MINOR (non-ff push, inline above), 0 MAJOR, 0 BLOCKER.

Verified correct:

  • Trigger match: on: repository_dispatch: types: [rw2-released] exactly matches the event_type sent by rw2 promote-images.yml; VERSION reads github.event.client_payload.version, which matches the nested payload key rw2 sends (I tested gh's client_payload[version] bracket serialization → it produces nested JSON, so the key lines up).
  • Injection-safe: client_payload.version arrives via env:, never inline; and update-version.sh re-validates it against ^[0-9]+\.[0-9]+\.[0-9]+$ before use (defense in depth).
  • Fail-fast on empty payload: [ -z "$VERSION" ] && { …; exit 1; } — confirmed safe under set -e (a failing left operand of && is exempt from set -e, so a non-empty version correctly continues).
  • Two independent version lines: the image version (update-version.sh set $VERSION) and the compose tag (CNEW = patch-bump of compose's own latest vX.Y.Z) are computed independently. No conflation possible.
  • Version math: --sort=-version:refname | grep '^v[0-9]+\.[0-9]+\.[0-9]+$' | head -n1, :-0.0.0 empty-list guard, IFS=. read — correct, no off-by-one.
  • No-op guard valid: I confirmed .gitignore contains *.bak, so the update-version.sh backup is not staged by git add -A; thus git diff --cached --quiet genuinely detects "no version change" and skips the empty commit/tag.
  • Least privilege: permissions: contents: write with the default GITHUB_TOKEN is correct and sufficient for the commit + tag push; no repo secret required here. Correct.
  • Runner: ubuntu-latest is appropriate — update-version.sh set only edits files (no Docker/az), so no self-hosted runner needed.
  • No loops: compose tag push triggers nothing in this repo (only repository_dispatch), so no feedback loop.

— Reviewer

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