CI: publish a :main image to the Forgejo registry on every push to main #64

Closed
opened 2026-07-15 15:42:24 +00:00 by claude-bot · 2 comments
Contributor

Companion to #3 (which covers the authoritative tag-time images via release.yml). To deploy the dev server without building on the host, CI should also publish a continuously-updated image on every merge to main:

  • Extend ci.yml's docker job: after the build + health smoke pass on a push to main, push to the registry as git.rhoving.com/rbrooks/iris-wled:main and :sha-<short>
  • Auth via the built-in Actions token (docker/login-action), same as release.yml — no long-lived PAT
  • amd64 is sufficient for the dev server; decide whether :main should also carry arm64 (slower CI) or leave multi-arch to the tagged releasesresolved by #79: Iris publishes linux/amd64 only, everywhere. Nothing to decide.
  • Do NOT push on pull_request events — only merged main
  • Registry hygiene: old :sha-* images accumulate; enable/configure registry cleanup or prune in the workflow

Depends on: #41 (CI must be green for the push step to ever run).
Enables: the pull-based dev deploy issue.

Companion to #3 (which covers the authoritative tag-time images via release.yml). To deploy the dev server without building on the host, CI should also publish a continuously-updated image on every merge to `main`: - [ ] Extend `ci.yml`'s docker job: after the build + health smoke pass on a `push` to `main`, push to the registry as `git.rhoving.com/rbrooks/iris-wled:main` and `:sha-<short>` - [ ] Auth via the built-in Actions token (`docker/login-action`), same as release.yml — no long-lived PAT - [x] ~~amd64 is sufficient for the dev server; decide whether `:main` should also carry arm64 (slower CI) or leave multi-arch to the tagged releases~~ — **resolved by #79**: Iris publishes `linux/amd64` only, everywhere. Nothing to decide. - [ ] Do NOT push on `pull_request` events — only merged main - [ ] Registry hygiene: old `:sha-*` images accumulate; enable/configure registry cleanup or prune in the workflow Depends on: #41 (CI must be green for the push step to ever run). Enables: the pull-based dev deploy issue.
claude-bot added this to the v1.0.0 milestone 2026-07-15 15:42:24 +00:00
Author
Contributor

Enables #65.

Enables #65.
Author
Contributor

Done — and verified by pulling, not by a green badge

Shipped in b252b8f, fixed in d8900ac.

Every merge to main now retags the E2E-tested iris:e2e and pushes it as :main and :sha-<short>. The image is retagged, never rebuilt, so the published artifact is bit-for-bit the one the E2E exercised, at no extra build cost.

Verification — the dev host pulled it with its own credentials:

Digest: sha256:f4d5c6cb6191b6f6885e29af0e34761061de4f8853e452c12146004ba32ab0ea
Status: Downloaded newer image for git.rhoving.com/rbrooks/iris-wled:main

The bug worth recording

The first real run failed:

unknown: unexpected status from POST request to
https://git.rhoving.com/v2/rbrooks/iris-wled/blobs/uploads/: 401 Unauthorized

docker login succeeded; the push was rejected. secrets.GITHUB_TOKEN does not carry write:package scope on this instance. I had copied the auth pattern from release.yml — which has never run (no tags, release_counter: 0), so the pattern was never actually exercised. The working pattern was already here: marginalia uses a REGISTRY_TOKEN repo secret with write:package.

Two consequences:

  • release.yml had the identical latent bug, fixed in the same commit. It would otherwise have failed during an actual release and taken #3/#4 with it. That fix remains unverified — it only gets exercised when a v* tag is pushed, i.e. at #10.
  • The username is pinned to rbrooks rather than ${{ github.actor }}. The token belongs to rbrooks, and since #56 enabled Renovate automerge a merged dependency PR runs as renovate-bot, which would not match — an intermittent failure appearing only on automerged PRs.

One checkbox not done

Registry hygiene. :sha-* accrues one tag per merge and nothing bounds it. This is deliberately not repo work: the right mechanism is a Forgejo owner-level package cleanup rule (Settings → Packages → Cleanup Rules, keep N versions). A prune loop in the workflow would need package-delete scope and a silently-failing cleanup step is worse than none.

Closing with that recorded rather than leaving the issue open on an instance-configuration task. It is not urgent — one tag per merge — but it will grow.

## Done — and verified by pulling, not by a green badge Shipped in `b252b8f`, fixed in `d8900ac`. Every merge to `main` now retags the E2E-tested `iris:e2e` and pushes it as `:main` and `:sha-<short>`. The image is **retagged, never rebuilt**, so the published artifact is bit-for-bit the one the E2E exercised, at no extra build cost. **Verification** — the dev host pulled it with its own credentials: ``` Digest: sha256:f4d5c6cb6191b6f6885e29af0e34761061de4f8853e452c12146004ba32ab0ea Status: Downloaded newer image for git.rhoving.com/rbrooks/iris-wled:main ``` ### The bug worth recording The first real run failed: ``` unknown: unexpected status from POST request to https://git.rhoving.com/v2/rbrooks/iris-wled/blobs/uploads/: 401 Unauthorized ``` `docker login` succeeded; the **push** was rejected. `secrets.GITHUB_TOKEN` does not carry `write:package` scope on this instance. I had copied the auth pattern from `release.yml` — which **has never run** (no tags, `release_counter: 0`), so the pattern was never actually exercised. The working pattern was already here: `marginalia` uses a `REGISTRY_TOKEN` repo secret with `write:package`. Two consequences: - **`release.yml` had the identical latent bug**, fixed in the same commit. It would otherwise have failed during an actual release and taken #3/#4 with it. **That fix remains unverified** — it only gets exercised when a `v*` tag is pushed, i.e. at #10. - The username is pinned to `rbrooks` rather than `${{ github.actor }}`. The token belongs to rbrooks, and since #56 enabled Renovate automerge a merged dependency PR runs as `renovate-bot`, which would not match — an intermittent failure appearing only on automerged PRs. ### One checkbox not done **Registry hygiene.** `:sha-*` accrues one tag per merge and nothing bounds it. This is deliberately *not* repo work: the right mechanism is a Forgejo **owner-level package cleanup rule** (Settings → Packages → Cleanup Rules, keep N versions). A prune loop in the workflow would need package-delete scope and a silently-failing cleanup step is worse than none. Closing with that recorded rather than leaving the issue open on an instance-configuration task. It is not urgent — one tag per merge — but it will grow.
Sign in to join this conversation.
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
rbrooks/Iris-WLED#64
No description provided.