Compare commits
1 Commits
main
...
docs/insta
| Author | SHA1 | Date | |
|---|---|---|---|
| 152ffef86e |
@@ -29,6 +29,7 @@ release/start scripts. The installer never writes a launcher.
|
||||
| Code signing | **Unsigned.** `SHA256SUMS` is the trust anchor; SmartScreen/Gatekeeper warnings are expected and documented, as with most self-hosted tooling |
|
||||
| Language | **Rust** — single static binary per OS, reuses the cross-compile pattern already proven in `link/.gitea/workflows/release.yml` |
|
||||
| Plugin source | **Release tarball artifact** — no git and no Gitea credentials on the shard host |
|
||||
| Composition | **Published bundle manifest** (§7.1). CI names an exact, protocol-checked combination of component versions; the installer fetches it at run time and `--bundle <tag>` pins one. Component releases regenerate JSON, not the installer binary |
|
||||
| Token handoff | **Print token + prefilled admin URL** at the end of the run |
|
||||
| Repo | **New repo**, `RunicGateway/installer`. It deploys *both* other components, so living inside `link/` would invert the dependency |
|
||||
| ServUO version | **Warn and skip.** Patches are verified against stock 57.4 only; on anything else the base install proceeds and the patch tier is skipped with a warning. Forks are the norm in a public audience — refusing outright would block most operators |
|
||||
@@ -167,6 +168,9 @@ servuo-plugins v<ver> (new release, Phase 0)
|
||||
└── SHA256SUMS
|
||||
```
|
||||
|
||||
Binding those together is the **bundle manifest** (§7.1) — published by the installer repo's CI, not
|
||||
by any component, and the thing the installer actually resolves against.
|
||||
|
||||
```bash
|
||||
scp runicgateway-installer-linux-x86_64 user@server:/tmp/
|
||||
chmod +x runicgateway-installer-linux-x86_64
|
||||
@@ -221,7 +225,10 @@ Repo work that must land before an installer can exist.
|
||||
2. **`link`: make the sidecar installable.** Confirm/settle default data paths, and add a way to
|
||||
read back config non-interactively (e.g. `--print-config` emitting JSON: bind addresses, token,
|
||||
protocol version, db path) so the installer does not have to scrape logs for the token.
|
||||
3. **Decide and document the compat matrix format** (§7).
|
||||
3. **Bundle CI in the installer repo** (§7). Compose job (read both repos' latest releases → run the
|
||||
two gates → publish `bundle.json`), the nightly cron, and the dispatch step appended to each
|
||||
component's release workflow. This must exist before Phase 1 is useful, since the installer
|
||||
resolves what to install *from* the bundle.
|
||||
4. **`docs`: this file, plus `docs/installer/INSTALL.md`** (the operator-facing guide) once the
|
||||
shape is settled.
|
||||
|
||||
@@ -267,12 +274,16 @@ degrade loudly rather than silently.
|
||||
The last check matters most: it is the only thing that distinguishes "files copied" from "the bridge
|
||||
actually works" (§2.1).
|
||||
|
||||
`runicgateway update` — asymmetric by component, deliberately:
|
||||
`runicgateway update` — resolves the current bundle (§7.1), then acts asymmetrically by component,
|
||||
deliberately:
|
||||
|
||||
- **uo-link**: query the Gitea releases API → compare versions → download → verify checksum →
|
||||
- **uo-link**: compare the bundle's version against what is installed → download → verify checksum →
|
||||
replace binary → restart service.
|
||||
- **plugin overlay**: download the newer overlay tarball → verify → re-sync → record commit → tell
|
||||
the operator ServUO must restart (the installer does not restart the shard).
|
||||
- **plugin overlay**: download the bundle's overlay tarball → verify → re-sync → record commit →
|
||||
tell the operator ServUO must restart (the installer does not restart the shard).
|
||||
|
||||
Because both come from one bundle, an update always moves to a combination whose protocol versions
|
||||
were checked together, rather than to two independently-latest artifacts that may disagree.
|
||||
|
||||
`runicgateway uninstall` — **removes only what it exclusively owns, and never edits the ServUO
|
||||
tree.** The installer cannot know what the operator has changed in those files since deployment, so
|
||||
@@ -321,7 +332,7 @@ later without changing anything here.
|
||||
|
||||
---
|
||||
|
||||
## 7. Version tracking and the compat matrix
|
||||
## 7. Version tracking, the bundle, and release orchestration
|
||||
|
||||
Three components version independently, bound by a protocol contract:
|
||||
|
||||
@@ -329,13 +340,72 @@ Three components version independently, bound by a protocol contract:
|
||||
`X-UOLink-Version` on every response; a mismatch is rejected `409`.
|
||||
- **website** — stores an expected protocol version in `uoLinkConfig` (admin-managed).
|
||||
- **plugin overlay** — has no queryable version before ServUO boots. The overlay release
|
||||
`manifest.json` declares it, and `install.json` records what was deployed. `doctor` compares the
|
||||
recorded overlay protocol version against the sidecar's live one.
|
||||
`manifest.json` declares it, and `install.json` records what was deployed.
|
||||
|
||||
**Open risk:** the v3 cutover is mid-flight — protocol work landed on `edge` branches with the
|
||||
`edge → main` cutover still open across four repos. Until that lands, `main` and `edge` disagree
|
||||
about `PROTOCOL_VERSION`, so the installer must not hardcode a version anywhere; it reads what the
|
||||
artifacts declare. See `docs/link/v3.md`.
|
||||
### 7.1 The bundle manifest
|
||||
|
||||
**The bundle is the compat matrix.** Rather than the installer hardcoding versions or blindly
|
||||
resolving "latest", CI publishes a small manifest naming an exact, checked combination:
|
||||
|
||||
```json
|
||||
{
|
||||
"bundle": "2026.08.01",
|
||||
"protocol": 3,
|
||||
"link": { "version": "3.0.1", "sha256": "a91f..." },
|
||||
"overlay": { "version": "2.4.0", "commit": "a81f42c", "sha256": "7c3e..." }
|
||||
}
|
||||
```
|
||||
|
||||
The installer fetches the current bundle at run time; `--bundle <tag>` pins an older one for a
|
||||
reproducible install. Because the bundle is data, **a new `link` release regenerates ~20 lines of
|
||||
JSON and leaves the installer binary untouched** — operators do not re-download the installer to
|
||||
pick up a sidecar patch, and the installer does not accumulate releases whose code is byte-identical.
|
||||
|
||||
Two gates run at compose time, both cheap and both worth it:
|
||||
|
||||
1. The sidecar's `PROTOCOL_VERSION` must equal the overlay manifest's declared protocol version.
|
||||
This is the check that catches an `edge`/`main` protocol mismatch before it reaches an operator.
|
||||
2. Every referenced asset must exist and its SHA256 must match the publishing repo's `SHA256SUMS`.
|
||||
|
||||
### 7.2 What triggers a bundle
|
||||
|
||||
| Trigger | Why |
|
||||
|---|---|
|
||||
| `link` publishes a release | Its release job `POST`s to the installer repo's workflow-dispatch endpoint as its final step. `link/.gitea/workflows/release.yml` already declares `workflow_dispatch: {}` and already holds a `write:repository` token |
|
||||
| `servuo-plugins` publishes a release | Same, once Phase 0 gives it a release workflow |
|
||||
| Nightly cron on the installer repo | Recomputes from whatever the latest releases actually are, so a missed or failed dispatch self-heals instead of silently pinning operators to a stale sidecar |
|
||||
|
||||
`repository_dispatch` is deliberately avoided — support for it is uncertain on this Gitea version,
|
||||
whereas dispatching an existing `workflow_dispatch` workflow via the API works today.
|
||||
|
||||
### 7.3 Stale-overlay handling: dispatch, don't wait
|
||||
|
||||
Each component **self-releases on merge to its own `main`**, using the same conventional-commit
|
||||
engine. Note that "updated since the last release" must mean *releasable* commits — the engine sets
|
||||
`RELEASE=false` when nothing but `docs:`/`chore:` has landed, so a docs typo correctly does **not**
|
||||
cut an overlay release, and the bundle keeps using the existing one.
|
||||
|
||||
So by the time the installer's CI looks, the release normally already exists. If it finds
|
||||
`servuo-plugins` main ahead of its latest release *with* releasable commits, it:
|
||||
|
||||
1. fires that repo's release workflow via workflow-dispatch and **does not wait for it**,
|
||||
2. composes this bundle from the assets that exist right now,
|
||||
3. writes a loud warning into the job summary.
|
||||
|
||||
The new overlay release lands minutes later on its own and the nightly cron folds it into the next
|
||||
bundle. This gets the automation without the flaky part: dispatching another repo's workflow is
|
||||
fine — that workflow still runs its own gates — but *polling* it is not, because Gitea's dispatch
|
||||
endpoint returns no run handle, so the job would have to guess which run is its own and hold a
|
||||
runner idle meanwhile. The warning exists so a genuinely broken release workflow surfaces once
|
||||
rather than being silently retriggered every night forever.
|
||||
|
||||
### 7.4 Open risk
|
||||
|
||||
The v3 cutover is mid-flight — protocol work landed on `edge` branches with the `edge → main`
|
||||
cutover still open across four repos. Until that lands, `main` and `edge` disagree about
|
||||
`PROTOCOL_VERSION`, so the installer must not hardcode a version anywhere; it reads what the
|
||||
artifacts declare, and §7.1's gate 1 is what stops a mismatched pair from being published as a
|
||||
bundle. See `docs/link/v3.md`.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user