ci(release): recompose the installer bundle after publishing #9

Merged
whitlocktech merged 1 commits from ci/dispatch-bundle into main 2026-08-04 16:18:29 +00:00
Member

The dispatch half of installer Phase 0 item 3, and the TODO this workflow's header has carried since #7 — deliberately left unimplemented while there was nothing to dispatch, since a step that 404s on every release is worse than no step. There is now something to dispatch.

Main PR: RunicGateway/installer#3. Sibling: RunicGateway/link#25. Docs: RunicGateway/docs#85.

Why

The installer does not resolve "latest" at run time — it deploys the exact overlay named by a published bundle manifest (PLAN.md §7.1). An overlay release that nobody recomposes around is therefore a release no operator will ever be offered.

What changed

One step appended to release.yml, gated on release == 'true', that POSTs to RunicGateway/installer's bundle.yml workflow-dispatch endpoint. Plus the header TODO replaced by a description of what now exists.

That job re-reads this tarball's manifest.json and checks its declared protocol against the sidecar's PROTOCOL_VERSION before publishing anything (§7.1 gate 1) — the check this repo cannot perform for itself, since the C# plugin announces no version on the wire and none is queryable before ServUO boots.

Two things it deliberately does not do

It does not wait (§7.3). Gitea's dispatch endpoint returns no run handle, so there is nothing to poll — a waiting step would have to guess which run is its own while holding a runner idle.

It cannot fail this job. By the time the step runs, the release is published and correct; failing the run would misreport that. Every branch of the case warns rather than exits non-zero. That also keeps this from becoming a new hard credential requirement — REGISTRY_TOKEN having write on the installer repo is a nicety, and without it that repo's nightly cron picks the release up anyway. The header now says so.

Verification

The workflow parses; the new step is last, gated on steps.plan.outputs.release == 'true', and contains no path that can exit non-zero. Not exercised end to end here — it fires on the next release-cutting merge to main, and a 403/404 from it degrades to a warning by design.

The bundle job on the other side was exercised against this repo's live v0.1.1 release: it verified runicgateway-overlay-0.1.1.tar.gz against the published SHA256SUMS, read protocol=3 and servuo.min_version=57.4 out of the tarball's manifest.json, and cross-checked manifest.version against the release tag. See installer#3.

AI-assisted contribution

  • This PR was written with AI assistance (Claude Code / Claude Opus 5); commits carry the Co-Authored-By trailer.
The dispatch half of installer Phase 0 item 3, and **the TODO this workflow's header has carried since #7** — deliberately left unimplemented while there was nothing to dispatch, since a step that `404`s on every release is worse than no step. There is now something to dispatch. Main PR: RunicGateway/installer#3. Sibling: RunicGateway/link#25. Docs: RunicGateway/docs#85. ## Why The installer does not resolve "latest" at run time — it deploys the exact overlay named by a published **bundle manifest** ([`PLAN.md` §7.1](https://gitea.whitlocktech.com/RunicGateway/docs/src/branch/main/installer/PLAN.md)). An overlay release that nobody recomposes around is therefore a release no operator will ever be offered. ## What changed One step appended to `release.yml`, gated on `release == 'true'`, that `POST`s to `RunicGateway/installer`'s `bundle.yml` workflow-dispatch endpoint. Plus the header TODO replaced by a description of what now exists. That job re-reads this tarball's `manifest.json` and checks its declared `protocol` against the sidecar's `PROTOCOL_VERSION` before publishing anything (§7.1 gate 1) — **the check this repo cannot perform for itself**, since the C# plugin announces no version on the wire and none is queryable before ServUO boots. ## Two things it deliberately does not do **It does not wait** (§7.3). Gitea's dispatch endpoint returns no run handle, so there is nothing to poll — a waiting step would have to guess which run is its own while holding a runner idle. **It cannot fail this job.** By the time the step runs, the release is published and correct; failing the run would misreport that. Every branch of the `case` warns rather than exits non-zero. That also keeps this from becoming a new hard credential requirement — `REGISTRY_TOKEN` having write on the installer repo is a nicety, and without it that repo's nightly cron picks the release up anyway. The header now says so. ## Verification The workflow parses; the new step is last, gated on `steps.plan.outputs.release == 'true'`, and contains no path that can exit non-zero. Not exercised end to end here — it fires on the next release-cutting merge to `main`, and a `403`/`404` from it degrades to a warning by design. The bundle job on the other side *was* exercised against this repo's live `v0.1.1` release: it verified `runicgateway-overlay-0.1.1.tar.gz` against the published `SHA256SUMS`, read `protocol=3` and `servuo.min_version=57.4` out of the tarball's `manifest.json`, and cross-checked `manifest.version` against the release tag. See installer#3. ## AI-assisted contribution - [x] This PR was written with AI assistance (Claude Code / Claude Opus 5); commits carry the `Co-Authored-By` trailer.
wtclaude added 1 commit 2026-08-04 16:16:50 +00:00
Phase 0 item 3 of docs/installer/PLAN.md wired up from this side. The installer
does not resolve "latest" at run time — it installs the exact combination named
by a published bundle manifest (PLAN.md §7.1), so until now a new overlay release
was invisible to operators until the installer repo's nightly cron noticed it.

Adds a final step that POSTs to RunicGateway/installer's bundle workflow-dispatch
endpoint. That job re-reads this tarball's manifest.json and checks its declared `protocol`
against the sidecar's PROTOCOL_VERSION before publishing anything (gate 1) — the
check this repo cannot perform for itself, since the C# plugin announces no
version on the wire. It replaces the TODO the header has carried since #7, which
was deliberately left unimplemented while there was nothing to dispatch.

Dispatch, don't wait (PLAN.md §7.3): Gitea's dispatch endpoint returns no run
handle, so there is nothing to poll — a waiting step would have to guess which
run is its own while holding a runner idle. The bundle job runs its own gates
regardless of who started it.

A dispatch failure is a warning, never a failure of this job. By the time this
step runs the release is published and correct, so failing the run would
misreport that; the installer's nightly cron recomposes from whatever the latest
releases actually are, making a dropped dispatch cost latency rather than
correctness. That also means REGISTRY_TOKEN having write on the installer repo
is a nicety, not a new hard requirement — noted in the header.

Verified the workflow still parses and that the new step is last, gated on
release=='true', and contains no path that can exit non-zero.

Co-Authored-By: Claude <noreply@anthropic.com>
whitlocktech approved these changes 2026-08-04 16:18:12 +00:00
whitlocktech merged commit 7fa8953ffa into main 2026-08-04 16:18:29 +00:00
whitlocktech deleted branch ci/dispatch-bundle 2026-08-04 16:18:30 +00:00
Sign in to join this conversation.
No Reviewers
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: RunicGateway/servuo-plugins#9
No description provided.