Skip to content

feat: komodo-pin — move a deploy pin from the release that produced it - #57

Merged
cshuttle merged 1 commit into
mainfrom
feat/komodo-pin
Aug 19, 2026
Merged

feat: komodo-pin — move a deploy pin from the release that produced it#57
cshuttle merged 1 commit into
mainfrom
feat/komodo-pin

Conversation

@cshuttle

Copy link
Copy Markdown
Owner

komodo-deploy.yml redeploys a stack. That is the right event for a self-builder running a floating :latest, and it does nothing for a stack whose compose interpolates a pinned version — redeploying without moving the pin re-runs the same image.

Observed on cshuttle/nmon, 2026-08-18: the merge fired the deploy hook, the stack redeployed, and the app on screen did not change, because the deploy repo still named the previous release. Getting that release live took a hand-driven chain — wait for the ghcr tag list, run Renovate, run it again for the automerge — repeated for five releases in one evening.

For a pinned stack the deploy event is the pin moving. So this writes the version it was handed into the deploy repo's pin file and stops; whatever that repo already does on a push (a ResourceSync, a path-change route) is what deploys. No second deploy path to keep in step with the first.

Not a dependency bot

Renovate still owns "is there a newer version, and may it land unattended", and after this runs it finds the pin already current. What this removes is the wait: Renovate's schedule, plus the ghcr tag list, which lags the packages API by minutes — measured at 3 and 8 on two consecutive releases the same night. Called from a release, the version is already known; there is nothing to discover and nothing to poll.

What it refuses

It edits the line that decides which image production runs, in a repo the caller cannot see from its own CI, and nothing downstream re-checks the result. So it fails rather than guesses:

  • a version, or a current pin, that is not vMAJOR.MINOR.PATCH
  • a key matching zero or several lines in the file
  • a version older than the one pinned — the release dispatch button can re-run an old version, and that must not roll production back
  • a major is not committed at all: it opens a PR, because a major means the deploy needs a human step, the same reason release-image.yml makes the version a human decision

Testing

python3 + stdlib only — the ARC runner image has no gh, jq or PyYAML. All ten decisions are unit-tested in selftest by extracting the embedded script from the YAML and driving it against a stubbed API, asserting on the requests it makes: the minor path commits to the branch with only that one line changed (rest of the file byte-for-byte), the major path writes to a pin/* branch and opens a PR while committing nothing to main, and each refusal writes nothing at all.

Local: python3 tests/test_komodo_pin.py → 10 passed. actionlint clean.

Rollout

Needs a token with Contents R/W (plus PRs write) on the deploy repo only, as an Actions secret on the caller repo. Consumers land after this is released and tagged.

🤖 Generated with Claude Code

komodo-deploy.yml redeploys a stack, which is right for a self-builder on a
floating :latest and does nothing for a stack whose compose interpolates a
pinned version: redeploying without moving the pin re-runs the same image.
Observed 2026-08-18 on cshuttle/nmon — the merge fired the deploy hook, the
stack redeployed, and the app on screen did not change, because the deploy
repo still named the previous release.

For those stacks the deploy event is the PIN MOVING, so this writes the
version it was handed into the deploy repo's pin file and stops. Whatever that
repo already does on a push deploys it; no second deploy path to keep in step
with the first.

It is not a dependency bot and does not replace one. Renovate still owns "is
there a newer version and may it land unattended" and will find the pin
already current. What this removes is the wait: Renovate's schedule plus the
ghcr tag list, which lags the packages API by minutes (measured at 3 and 8 on
two consecutive releases the same night). Called from a release, the version
is already known — nothing to discover, nothing to poll.

A major opens a PR rather than committing, because a major means the deploy
needs a human step — the same reason release-image makes the version a human
decision. The script also refuses what it cannot verify: a non-semver version
or current pin, a key matching zero or several lines, and any version older
than the one pinned, since the release dispatch button can re-run an old
version and must not roll production back.

python3 + stdlib only (the ARC image has no gh, jq or PyYAML). The ten
decisions above are unit-tested in selftest by extracting the embedded script
and driving it against a stubbed API — it edits what production runs, in a
repo the caller cannot see, and nothing downstream re-checks the result.
@cshuttle
cshuttle merged commit 8d758e9 into main Aug 19, 2026
9 checks passed
@cshuttle
cshuttle deleted the feat/komodo-pin branch August 19, 2026 02:37
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