diff --git a/installer/INSTALL.md b/installer/INSTALL.md index c8fc730..4421bcb 100644 --- a/installer/INSTALL.md +++ b/installer/INSTALL.md @@ -650,7 +650,7 @@ Throughout: `` is your ServUO root, and **the shard is stopped**. ### A1. Fetch the bundle (so you install a checked pair) ```bash -curl -s https://gitea.whitlocktech.com/RunicGateway/installer/raw/branch/main/bundles/current.json +curl -s https://gitea.whitlocktech.com/RunicGateway/installer/raw/branch/bundles/current.json ``` It names the sidecar tag, the overlay tag, their agreed `protocol`, and the SHA256 of every asset. diff --git a/installer/PLAN.md b/installer/PLAN.md index c931e14..36ef520 100644 --- a/installer/PLAN.md +++ b/installer/PLAN.md @@ -35,7 +35,7 @@ described a ServUO integration that does not match how `servuo-plugins` actually |---|---| | 0.1 `servuo-plugins` release workflow | ✅ Merged — [servuo-plugins#7](https://gitea.whitlocktech.com/RunicGateway/servuo-plugins/pulls/7) + [#8](https://gitea.whitlocktech.com/RunicGateway/servuo-plugins/pulls/8); first overlay release is [`v0.1.1`](https://gitea.whitlocktech.com/RunicGateway/servuo-plugins/releases/tag/v0.1.1) | | 0.2 `link` installable (data paths + `--print-config`) | ✅ Merged — [link#24](https://gitea.whitlocktech.com/RunicGateway/link/pulls/24) (docs half [docs#84](https://gitea.whitlocktech.com/RunicGateway/docs/pulls/84)); released as [`v1.1.0`](https://gitea.whitlocktech.com/RunicGateway/link/releases/tag/v1.1.0) | -| 0.3 Bundle CI in the installer repo | ✅ Merged — [installer#3](https://gitea.whitlocktech.com/RunicGateway/installer/pulls/3), plus the dispatch step in each component ([link#25](https://gitea.whitlocktech.com/RunicGateway/link/pulls/25), [servuo-plugins#9](https://gitea.whitlocktech.com/RunicGateway/servuo-plugins/pulls/9)). First bundle: [`2026.08.04`](https://gitea.whitlocktech.com/RunicGateway/installer/src/branch/main/bundles/current.json) | +| 0.3 Bundle CI in the installer repo | ✅ Merged — [installer#3](https://gitea.whitlocktech.com/RunicGateway/installer/pulls/3), plus the dispatch step in each component ([link#25](https://gitea.whitlocktech.com/RunicGateway/link/pulls/25), [servuo-plugins#9](https://gitea.whitlocktech.com/RunicGateway/servuo-plugins/pulls/9)). First bundle: [`2026.08.04`](https://gitea.whitlocktech.com/RunicGateway/installer/src/branch/bundles/current.json) | | 0.4 This file + `INSTALL.md` | ✅ Merged — [docs#87](https://gitea.whitlocktech.com/RunicGateway/docs/pulls/87). [`INSTALL.md`](INSTALL.md) is the operator guide, written before the binary because it *is* the specification of the run | | — Repo bootstrap (governance + CI) | ✅ [`RunicGateway/installer`](https://gitea.whitlocktech.com/RunicGateway/installer) created; workflows merged ([installer#1](https://gitea.whitlocktech.com/RunicGateway/installer/pulls/1), [#2](https://gitea.whitlocktech.com/RunicGateway/installer/pulls/2)) | @@ -433,7 +433,9 @@ Repo work that must land before an installer can exist. - **Bundles are committed to the installer repo, not published as releases** — see §7.1 for where and why. That was the one genuinely open question here, and the deciding factor is that - this repo's *own* releases are the installer binaries. + this repo's *own* releases are the installer binaries. They were committed to `main` until + 2026-08-05, when the first run that actually had a bundle to write found `main` protected; + they now live on a `bundles` branch (§7.1). - **Gate 1 reads the sidecar's protocol from source at the release tag**, not from the binary. `--print-config` (Phase 0.2) would answer authoritatively, but only for releases from `v1.1.0` onward, and `--bundle ` has to be able to recompose a bundle from an older pair. Reading @@ -1200,24 +1202,44 @@ Two gates run at compose time, both cheap and both worth it: #### Where bundles are published -Committed to the installer repo under `bundles/`, so the installer's fetch is a plain anonymous -`GET` against a public repo — the shard host has no Gitea credentials (§1): +Committed to the installer repo, on a **`bundles` branch of their own** and at its root, so the +installer's fetch is a plain anonymous `GET` against a public repo — the shard host has no Gitea +credentials (§1): ``` -bundles/current.json → …/RunicGateway/installer/raw/branch/main/bundles/current.json -bundles/bundle-.json → …/raw/branch/main/bundles/bundle-2026.08.04.json (--bundle) +current.json → …/RunicGateway/installer/raw/branch/bundles/current.json +bundle-.json → …/raw/branch/bundles/bundle-2026.08.04.json (--bundle) ``` Every bundle is kept forever, so `--bundle` stays reproducible. Tags are UTC dates; a second bundle on the same day — a sidecar release in the morning and an overlay release in the afternoon is the normal way that happens — becomes `2026.08.04.2`, so one tag always names exactly one matrix. +**A branch, not `main`, and that correction cost a day.** This section originally said bundles were +committed to `main` and "needs no new branch-protection exception: `release.yml`'s version-bump +commit already requires the CI user to be able to push to `main`". Both halves were wrong. `main` is +protected and declines a push from CI (`pre-receive hook declined`), and `release.yml` had never +pushed anything — its bump step has never executed in any repo carrying it, because an **empty +template expression written literally in one of its comments** makes the runner fail to build the +step and skip it *without failing the job*. The tags exist because Gitea's release API creates one +when it publishes. So the assumption that a working push path already existed was never tested by +anything. + +Publishing to a branch of its own keeps every property the original choice was for — a reviewable +diff, a git history of the compat matrix, plain anonymous raw URLs, no credentials on the shard host +— and needs no exception at all. The alternative, whitelisting a scheduled job for pushes to the +default branch, buys nothing this does not. + **Not one Gitea release per bundle**, which was the obvious alternative. This repo's own releases are the installer *binaries*, and `/releases/latest` returns whichever release is newest regardless of kind — interleaving bundle releases would make "latest" intermittently resolve to a release -carrying no installer binary. Committing also yields a reviewable diff and a git history of the -compat matrix, and needs no new branch-protection exception: `release.yml`'s version-bump commit -already requires the CI user to be able to push to `main`. +carrying no installer binary. + +**The release workflows tag and never write to a branch**, for the same reason and settled at the +same time (org lead, 2026-08-05): the tag *is* the version, as `servuo-plugins` has always done it. +The version is still written into `Cargo.toml` before building — so a released binary self-reports +correctly — but is no longer committed back, and the next version is computed from the newest tag. +A first release must not depend on a write to a protected branch. ### 7.2 What triggers a bundle