docs(installer): Phase 5 — scope, the §5.3 correction, and the operator guide #96
@@ -83,10 +83,16 @@ Download the installer for your OS, plus `SHA256SUMS`, from the
|
||||
|
||||
```
|
||||
runicgateway-installer-linux-x86_64
|
||||
runicgateway-installer-linux-aarch64
|
||||
runicgateway-installer-windows-x86_64.exe
|
||||
SHA256SUMS
|
||||
```
|
||||
|
||||
`linux-aarch64` is for arm64 hosts — Ampere/Graviton instances, Pi-class boxes. `uname -m` says
|
||||
`aarch64` on those and `x86_64` otherwise. There is no macOS build and no Windows-on-arm build: the
|
||||
shard dials the sidecar out on loopback, so the two have to share a host, and no ServUO host is
|
||||
either of those.
|
||||
|
||||
**Linux**
|
||||
|
||||
```bash
|
||||
@@ -218,7 +224,8 @@ reports "unchanged" and writes nothing.
|
||||
| `--host <name>` | `install` | The hostname to print in the website URLs. |
|
||||
| `--site-url <url>` | `install` | Your site's base URL, for the Admin → Shard link. |
|
||||
| `--yes` | all | Assume the default answer to every prompt. Combine with the flags above for an unattended run. **On `uninstall` it means yes** — that prompt defaults to no, and typing `uninstall --yes` is not an accident. |
|
||||
| `--purge` | `uninstall` | Also delete `sidecar.toml`, `uo-link.db` and the cached patch set, all of which are otherwise kept. |
|
||||
| `--no-backup` | `install`, `update` | Do not copy the files this run is about to overwrite. They are otherwise saved under the state directory — see [§7](#7-day-two). |
|
||||
| `--purge` | `uninstall` | Also delete `sidecar.toml`, `uo-link.db`, the cached patch set and every backup, all of which are otherwise kept. |
|
||||
|
||||
Exit codes are `0` success, `1` the run failed, `2` the arguments were unusable. Two commands also
|
||||
use `1` for a run that *completed* and found something wrong, so they can be read from a script:
|
||||
@@ -238,6 +245,7 @@ else still was).
|
||||
| `/etc/runicgateway/install.json` | What the installer deployed: versions, commit, per-file hashes, applied patches, timestamps |
|
||||
| `/etc/runicgateway/patches/` | Copies of the patches the tier evaluated, so `uninstall` can print the exact hunks long after the release tarball is gone, and a refused one is still on hand to apply yourself |
|
||||
| `/etc/runicgateway/patches/originals/` | Each file the patch tier edited, exactly as it was beforehand — a revert you can verify rather than reconstruct |
|
||||
| `/etc/runicgateway/backups/<timestamp>/` | Copies of the files a run replaced, with a `manifest.json` naming each. Newest three kept; skip with `--no-backup` |
|
||||
| `/var/lib/runicgateway/uo-link.db` | The sidecar's SQLite store (event history, cached profiles, link map) |
|
||||
| `/etc/systemd/system/runicgateway-link.service` | The service unit, running as a dedicated user |
|
||||
|
||||
@@ -250,6 +258,7 @@ else still was).
|
||||
| `%ProgramData%\RunicGateway\install.json` | As above |
|
||||
| `%ProgramData%\RunicGateway\patches\` | As above |
|
||||
| `%ProgramData%\RunicGateway\patches\originals\` | As above |
|
||||
| `%ProgramData%\RunicGatewayackups\<timestamp>\` | As above |
|
||||
| `%ProgramData%\RunicGateway\uo-link.db` | The sidecar's SQLite store |
|
||||
| Service `RunicGatewayLink` | Automatic start, restart on failure, running as `NT SERVICE\RunicGatewayLink` |
|
||||
|
||||
@@ -520,6 +529,8 @@ first thing a maintainer will want.
|
||||
✓ Protocol sidecar 3 = overlay manifest 3
|
||||
✗ Shard connected no — the shard is running (pid 8123) but has not dialed in
|
||||
✓ Bundle 2026.08.04 — up to date
|
||||
✓ Backups 2026-08-04T09:12:44Z — 3 file(s) replaced by update to bundle 2026.08.04
|
||||
3 kept in /etc/runicgateway/backups
|
||||
```
|
||||
|
||||
Rows come from asking the installed sidecar (`--version`, `--print-config`) rather than from reading
|
||||
@@ -557,6 +568,16 @@ together — never to two independently-latest artifacts that may disagree.
|
||||
Your `sidecar.toml`, your `Bridge.cfg` edits and your database are not touched. `Bridge.cfg` is
|
||||
overwritten only if you have not changed it; a modified copy is reported, not clobbered.
|
||||
|
||||
**Anything it does overwrite is copied first.** Every `.cs` file the overlay owns is replaced
|
||||
unconditionally — that is deliberate, they are code — so if you have edited one, the run saves your
|
||||
copy under `backups/<timestamp>/` in the state directory before writing, alongside `sidecar.toml`
|
||||
and any stock ServUO file the patch tier is about to touch. Each backup carries a `manifest.json`
|
||||
saying where every file came from. The newest three are kept; `--no-backup` skips taking one.
|
||||
|
||||
Putting a file back is yours to do — the installer will not restore an old file over a newer
|
||||
release, because it cannot know what has changed since. A run that overwrites nothing takes no
|
||||
backup, so a no-op `update` leaves nothing behind.
|
||||
|
||||
It updates the ServUO tree `install.json` names — not a tree it detects — and it needs the shard
|
||||
stopped, exactly as `install` does. There is nothing to update on a host that was never installed;
|
||||
it says so rather than performing a first install under a verb that promises to preserve.
|
||||
@@ -581,7 +602,7 @@ your work.
|
||||
| | |
|
||||
|---|---|
|
||||
| **Removed** | The sidecar binary, its service entry, `install.json` |
|
||||
| **Kept** | `sidecar.toml`, `uo-link.db`, and the cached patch set with its pre-patch originals (`--purge` drops all of them) |
|
||||
| **Kept** | `sidecar.toml`, `uo-link.db`, the cached patch set with its pre-patch originals, and every backup an upgrade took (`--purge` drops all of them) |
|
||||
| **Printed, not done** | Every overlay file deployed into your ServUO tree, by path, for you to delete — with any file you have edited since deployment flagged, so you do not delete your own work by mistake |
|
||||
| **Printed, not done** | The exact hunks each applied patch added to `EventSink.cs`, `PlayerVendorGumps.cs` and `Logging.cs`, for you to revert — with how each landed, since one placed into a file you had already modified is worth a closer look. The pre-patch copy kept under `patches/originals/` is there to diff against. |
|
||||
|
||||
@@ -679,6 +700,10 @@ for the *comparison* while writing back your file's own endings, which is why it
|
||||
|
||||
### A3. Install the sidecar
|
||||
|
||||
On an arm64 host substitute `uo-link-sidecar-linux-aarch64` for the asset name below (`uname -m`
|
||||
says `aarch64`); releases from v1.2.0 carry both. Take the version from the bundle you fetched in
|
||||
A1 rather than the one written here.
|
||||
|
||||
```bash
|
||||
curl -LO https://gitea.whitlocktech.com/RunicGateway/link/releases/download/v1.1.0/uo-link-sidecar-linux-x86_64
|
||||
curl -LO https://gitea.whitlocktech.com/RunicGateway/link/releases/download/v1.1.0/SHA256SUMS
|
||||
|
||||
@@ -17,7 +17,10 @@ release layout is exactly what Phase 5 changes. So the `edge → main` cutover i
|
||||
things:
|
||||
|
||||
1. **Phase 5, packaging polish** (§5) — the last work before a first release, rather than the first
|
||||
work after it.
|
||||
work after it. Its scope is now settled: **no `.deb` and no MSI** (§5.1 — both would give the
|
||||
service, its unit and its user a second owner), **Linux `aarch64` for both components** (§5.2),
|
||||
**a backup of what an upgrade overwrites** (§5.3), and the docs a first release invalidates
|
||||
(§5.4).
|
||||
2. **The Windows SCM half being verified on a real host.** systemd registration has now been run for
|
||||
real (see [Phase 2 as built](#phase-2--uo-link-install-and-service)), and doing it found a bug no
|
||||
amount of unit testing had. `sc create`, the virtual service account, the failure actions and the
|
||||
@@ -277,9 +280,11 @@ operators.
|
||||
- **`servuo-plugins` had no release workflow.** Only `link` did. "Pull latest repository" is replaced
|
||||
by a release tarball, which had to be built first — Phase 0 item 1, now in review
|
||||
([servuo-plugins#7](https://gitea.whitlocktech.com/RunicGateway/servuo-plugins/pulls/7)).
|
||||
- **arm64 is not buildable today.** `link/release.yml` cross-compiles only
|
||||
`x86_64-unknown-linux-gnu` and `x86_64-pc-windows-gnu`. An arm64 `.deb` needs another cross
|
||||
toolchain.
|
||||
- **arm64 was not buildable today.** `link/release.yml` cross-compiled only
|
||||
`x86_64-unknown-linux-gnu` and `x86_64-pc-windows-gnu`, so `platform_key()` refused every other
|
||||
host by name. That was a property of the workflows, not of Rust — Phase 5 adds
|
||||
`aarch64-unknown-linux-gnu` to both components in the order §5.2 sets out. There is no `.deb`, so
|
||||
the cross toolchain is the whole cost.
|
||||
- **The compat matrix has no home.** `PROTOCOL_VERSION` lives in `link/sidecar/src/main.rs`. The
|
||||
sidecar publishes it via `X-UOLink-Version` and `/health`, and the website stores an expected
|
||||
value — but the *plugin's* protocol version is not queryable before boot. Phase 0 item 1 gives it
|
||||
@@ -296,12 +301,13 @@ Components are published as Gitea release artifacts. Operators download from the
|
||||
Runic Gateway Installer v1.0.0
|
||||
├── runicgateway-installer-windows-x86_64.exe
|
||||
├── runicgateway-installer-linux-x86_64
|
||||
├── runicgateway-installer-linux-aarch64 (Phase 5)
|
||||
└── SHA256SUMS
|
||||
|
||||
uo-link v1.1.0 (existing release, extended)
|
||||
├── uo-link-sidecar-windows-x86_64.exe
|
||||
├── uo-link-sidecar-linux-x86_64
|
||||
├── runicgateway-link_<ver>_amd64.deb (Phase 5)
|
||||
├── uo-link-sidecar-linux-aarch64 (Phase 5)
|
||||
└── SHA256SUMS
|
||||
|
||||
servuo-plugins v<ver> (new release, Phase 0)
|
||||
@@ -794,7 +800,7 @@ a clever automatic revert risks silently eating their work. It removes and it re
|
||||
| Action | Scope |
|
||||
|---|---|
|
||||
| Removed | uo-link binary, its service entry (systemd unit / Windows service), `install.json` |
|
||||
| Kept | `sidecar.toml`, `uo-link.db`, and the cached patch set with its pre-patch originals (`--purge` to drop them) |
|
||||
| Kept | `sidecar.toml`, `uo-link.db`, the cached patch set with its pre-patch originals, and (from Phase 5) the backups an upgrade took — `--purge` to drop them |
|
||||
| **Printed, not done** | Every overlay file deployed into the ServUO tree, listed by path, for the operator to delete |
|
||||
| **Printed, not done** | The exact hunks each applied patch added to `EventSink.cs`, `PlayerVendorGumps.cs`, `Logging.cs`, rendered from the cached `.patch` files — with the rung that applied each one (§2.2.1), since a `region-match` apply means the surrounding file was already the operator's — for them to revert by hand |
|
||||
|
||||
@@ -876,21 +882,160 @@ Windows host, since only half of `service.rs` compiles on either.
|
||||
|
||||
### Phase 5 — packaging polish
|
||||
|
||||
`.deb` packaging, Windows MSI, arm64 cross build, and optional automated backup before upgrade.
|
||||
Deliberately last *of the build phases*: v1 can register services directly (`sc create` / a written
|
||||
systemd unit) and ship plain binaries. Nothing in Phases 1–4 should have to change to add these.
|
||||
The last work before the first release. It was sketched as four items — `.deb` packaging, Windows
|
||||
MSI, arm64 cross build, optional automated backup before upgrade — and the org lead settled its scope
|
||||
on 2026-08-05: **two of the four are dropped rather than deferred**, because what stops them is an
|
||||
ownership conflict that does not improve with time, and two are built.
|
||||
|
||||
**It now runs before the `edge → main` cutover rather than after it** (org lead, 2026-08-05). The
|
||||
original order assumed the cutover would cut a v1 and packaging would follow as a v1.x — but this
|
||||
phase changes the *release layout* (§3), so shipping first would mean a first release that is
|
||||
superseded by the next one, and operators who downloaded a bare binary being told to re-download a
|
||||
package. Deferring the cutover costs nothing: nothing is published from `edge`, and the guide's
|
||||
Appendix A is the supported path meanwhile.
|
||||
**It runs before the `edge → main` cutover rather than after it.** The original order assumed the
|
||||
cutover would cut a v1 and packaging would follow as a v1.x — but this phase changes the *release
|
||||
layout* (§3), so shipping first would mean a first release that is superseded by the next one, and
|
||||
operators who downloaded a bare binary being told to re-download a package. Deferring the cutover
|
||||
costs nothing: nothing is published from `edge`, and the guide's Appendix A is the supported path
|
||||
meanwhile.
|
||||
|
||||
The two entry criteria for the cutover are therefore this phase and the outstanding **Windows SCM
|
||||
| Item | Decision | State |
|
||||
|---|---|---|
|
||||
| `.deb` for uo-link | **Dropped** (§5.1) | — |
|
||||
| Windows MSI | **Dropped** (§5.1) | — |
|
||||
| arm64 cross build | **Build** — Linux `aarch64`, both components (§5.2) | In review: [installer#9](https://gitea.whitlocktech.com/RunicGateway/installer/pulls/9), [link#26](https://gitea.whitlocktech.com/RunicGateway/link/pulls/26), [installer#10](https://gitea.whitlocktech.com/RunicGateway/installer/pulls/10); step 3 waits on link's first arm64 release |
|
||||
| Backup before upgrade | **Build** — on by default, scoped to what a run overwrites (§5.3) | In review: [installer#11](https://gitea.whitlocktech.com/RunicGateway/installer/pulls/11) |
|
||||
| Docs the release invalidates | **Do** (§5.4) | Pending |
|
||||
|
||||
#### 5.1 What ships is plain binaries: no `.deb`, no MSI
|
||||
|
||||
Both were proposed before Phases 2 and 4 existed. They now collide with the components those phases
|
||||
made the installer own, and the collision is the deciding argument in each case.
|
||||
|
||||
- **A `.deb` under link's release would own `/usr/bin/runicgateway-link`, the systemd unit and the
|
||||
service user** — the same three things `service.rs` writes, hardens and removes, and that
|
||||
`install.json` records so `doctor` and `uninstall` can reason about them. Two owners for one file
|
||||
is not a packaging detail: `uninstall` deleting a dpkg-owned binary leaves the package *installed*
|
||||
and broken, an `apt upgrade` replacing that binary makes `doctor` report drift no operator caused,
|
||||
and the unit text would live in two repos free to disagree about the account it runs as. The
|
||||
variant that avoids all of that — a binary-only `.deb`, no unit, no user — buys apt-managed
|
||||
upgrades of one file, which `update` already does from a **protocol-checked** bundle (§7.1). That
|
||||
is the stronger of the two guarantees, so the package would be trading correctness for
|
||||
familiarity.
|
||||
- **An MSI contradicts a decision already locked**: the installer does not install itself (Phase 0.4
|
||||
as built). It would also add a second uninstall path — Add/Remove Programs — beside the
|
||||
`uninstall` verb, which owns state an MSI cannot see: `install.json`, the cached patch set and its
|
||||
pre-images, and the ServUO-tree report that is printed rather than done (Phase 4). Unsigned, it
|
||||
raises the same SmartScreen prompt a bare `.exe` does (§3), so it does not even buy the dialog it
|
||||
looks like it should.
|
||||
|
||||
So §3's release layout loses its `.deb` line and gains no installer package. Nothing in Phases 1–4
|
||||
changes — this item is a removal, which is why settling it is cheap and shipping it first would not
|
||||
have been.
|
||||
|
||||
**What would reopen it.** If operators ask for `apt`- or `winget`-managed installs, the thing to
|
||||
package is the sidecar as a standalone service *with the installer taught to detect and defer to a
|
||||
package-managed one*. That is a design change to who owns the service, not packaging polish, and it
|
||||
is out of scope here.
|
||||
|
||||
#### 5.2 arm64 — Linux `aarch64`, both components
|
||||
|
||||
§2.6 recorded arm64 as "not buildable today", which was true of the *workflows* rather than of Rust:
|
||||
`link/release.yml` and `installer/release.yml` cross-compile `x86_64` Linux and Windows only, so
|
||||
`platform_key()` (`src/bundle.rs`) refuses every other host by name. Ampere/Graviton instances and
|
||||
Pi-class boxes are a realistic ServUO home, and the installer's dependency set was already chosen to
|
||||
avoid OpenSSL and any C toolchain of its own (Phase 1 as built) — which is what makes this two build
|
||||
steps per workflow rather than a toolchain project.
|
||||
|
||||
**Both components or neither.** An installer that runs on `aarch64` but resolves a bundle carrying no
|
||||
`aarch64` sidecar has moved the failure later, not fixed it. Windows-on-arm and macOS stay unbuilt:
|
||||
no supported MinGW target here for the first, and no shard host is the second.
|
||||
|
||||
**The order is forced by the bundle CI, which is strict on purpose** (Phase 0.3 as built): an
|
||||
unrecognized `link` asset name is a hard failure, and `linux-x86_64` + `windows-x86_64` are asserted
|
||||
present. So a link release carrying a new binary reddens the compose job unless it is taught the name
|
||||
first — and requiring the name before link publishes it fails *every* bundle for as long as the gap
|
||||
lasts. Hence:
|
||||
|
||||
| Step | Repo / branch | Change | Why it is this one first |
|
||||
|---|---|---|---|
|
||||
| 1 | `installer` `main` | `bundle.yml` maps `*-linux-aarch64` → `linux-aarch64`, and **does not** add it to the required list | The compose job runs from `main`; teaching it the name first means link's next release composes instead of failing |
|
||||
| 2 | `link` `main` | `release.yml` adds `aarch64-unknown-linux-gnu`, cross-linked with `gcc-aarch64-linux-gnu` | Publishes the first `aarch64` sidecar; the nightly cron folds it into a bundle |
|
||||
| 3 | `installer` `main` | `linux-aarch64` joins the required list | Only safe once a release actually carries it — from here a dropped target reddens CI instead of silently vanishing from every bundle |
|
||||
| 4 | `installer` `edge` | `release.yml` adds the same target; `platform_key()` learns `("linux", "aarch64")` | The installer binary itself, on the branch that carries the crate |
|
||||
|
||||
`bundle.yml` is therefore edited on `main` only and never on `edge`, so the cutover merge has nothing
|
||||
to conflict over.
|
||||
|
||||
**What building it found.** Neither crate cross-compiles with the arm64 *compiler* alone.
|
||||
`gcc-aarch64-linux-gnu` only **recommends** `libc6-dev-arm64-cross`, and both release workflows
|
||||
install with `--no-install-recommends` — so the C that each crate pulls in (bundled SQLite under
|
||||
`sqlx` for the sidecar, `ring` under `ureq`'s rustls for the installer) dies on a missing
|
||||
`bits/libc-header-start.h` while every Rust dependency builds fine. Both halves were reproduced in a
|
||||
`rust:1-slim-bookworm` container, failure then fix, before either workflow was written.
|
||||
|
||||
#### 5.3 Backup before overwrite
|
||||
|
||||
**Scoped by what cannot be fetched again.** Not the sidecar binary or the overlay files — both are
|
||||
re-downloadable and hash-named in the bundle. Not the database either: `link/sidecar/src/store.rs`
|
||||
creates every table `IF NOT EXISTS` and every one of them holds shard state the sweeps repopulate, so
|
||||
it is a cache with a schema rather than a record. What an `update` can destroy irrecoverably is:
|
||||
|
||||
1. **An operator's own edits to a deployed `.cs` file.** Phase 1 overwrites those unconditionally and
|
||||
by design — `Bridge.cfg` is the single exception — so the one place the tool knowingly discards
|
||||
work is the one place it should keep a copy.
|
||||
2. **`sidecar.toml`**, whose token the website already holds. Mint a new one and the site's saved
|
||||
config starts answering `409`/`401` with nothing on the sidecar to explain why (§2.4).
|
||||
|
||||
So the rule is **copy what this run is about to overwrite, plus `sidecar.toml`** — not a snapshot of
|
||||
everything. A snapshot of all 24 overlay files would be mostly byte-identical to a release tarball
|
||||
that is still downloadable, and the noise would bury the two files that matter.
|
||||
|
||||
- **Where:** `<state>/backups/<utc-timestamp>/`, each file mirroring its path in the tree it came
|
||||
from, beside a `manifest.json` naming the source path, its SHA256, and the bundle moved from and
|
||||
to. In the state directory, not the ServUO tree — the same rule the tier's `patches/originals/`
|
||||
follows, and for the same reason: `uninstall` has promised never to clean up in there.
|
||||
- **When: whenever the run is about to overwrite something**, whichever verb was typed. This
|
||||
section first said "`update`, and `install` over an existing record", justified by a first install
|
||||
overwriting nothing — **which is wrong**, and building it is what showed that. A tree deployed by
|
||||
hand per [`INSTALL.md`](INSTALL.md) Appendix A2 — the path this project recommends while the
|
||||
binary is unreleased — has `.cs` files the first `install` plans as `Change` and overwrites, with
|
||||
no prior record anywhere to notice. The direct test covers that case, and a genuine first install
|
||||
onto a clean tree still writes nothing, because there is nothing to copy. `--verify` writes none
|
||||
either, for the reason it runs no part of the sidecar half (Phase 2): a dry run must not create
|
||||
state.
|
||||
- **`sidecar.toml` joins a backup that is already being taken; it is never the reason for one.**
|
||||
Nothing in the installer rewrites it, so treating it as a trigger would leave a dated directory
|
||||
behind after every no-op `update` — the empty-backup problem one step along. It is copied so that
|
||||
a restored set of files arrives with the token that matches it.
|
||||
- **`--no-backup`** opts out, for an operator with their own snapshotting.
|
||||
- **Retention is three.** Older ones are pruned as new ones are written; an unbounded directory of
|
||||
ServUO source copies on a shard host is its own support problem. `uninstall` keeps them and
|
||||
`--purge` drops them, alongside the config, the database and the cached patch set — same rule as
|
||||
Phase 4, and the same reason: they are the only offline record of what was there before.
|
||||
- **The directory is created lazily and the manifest is written last**, so a directory carrying one
|
||||
is a *complete* backup. Listing and pruning consider only those: a run interrupted mid-copy must
|
||||
neither be mistaken for a backup nor be able to evict a good one by being newer than it. It is
|
||||
left on disk for a human to look at rather than silently deleted.
|
||||
- **Restore is printed, not done.** Consistent with the uninstall report, and for the identical
|
||||
reason: the installer cannot know what has changed since, and a clever automatic restore over a
|
||||
newer overlay eats work rather than saving it. `doctor` names the most recent backup and its
|
||||
timestamp, so an operator asking "can I go back" does not have to know the layout to answer.
|
||||
|
||||
#### 5.4 Documentation the release layout invalidates
|
||||
|
||||
Not optional, and grouped here because a first release is the moment these are read for the first
|
||||
time by someone who was not in the room:
|
||||
|
||||
- **`installer/README.md`'s status table still says Phase 1 is built and Phase 2 is next**, four
|
||||
phases later. It is the first thing a visitor to the repo reads.
|
||||
- **`INSTALL.md`** gains the `aarch64` download lines, the backup behaviour and `--no-backup`.
|
||||
- **This file:** §3 loses the `.deb` and gains the `aarch64` assets, §2.6's arm64 bullet is now
|
||||
historical, and §7.1's example bundle grows the third asset key.
|
||||
|
||||
#### Cutover entry criteria
|
||||
|
||||
The `edge → main` cutover is gated on this phase **and** on the outstanding **Windows SCM
|
||||
verification** (see the status header and [Phase 2 as built](#phase-2--uo-link-install-and-service)).
|
||||
The second is not busywork: running the systemd half for real found a bug that unit tests could not,
|
||||
and `sc create` remains the only code in the crate that has never executed.
|
||||
and `sc create` remains the only code in the crate that has never executed. The smoke script at the
|
||||
workspace root was run on 2026-08-05 and stopped at its first check — an unelevated shell — so
|
||||
nothing in that half has executed yet; it needs one run from an elevated PowerShell.
|
||||
|
||||
---
|
||||
|
||||
@@ -1016,6 +1161,7 @@ resolving "latest", CI publishes a small manifest naming an exact, checked combi
|
||||
"repo": "RunicGateway/link", "tag": "v1.1.0", "version": "1.1.0", "protocol": 3,
|
||||
"assets": {
|
||||
"linux-x86_64": { "name": "uo-link-sidecar-linux-x86_64", "url": "…", "sha256": "27d491ef…" },
|
||||
"linux-aarch64": { "name": "uo-link-sidecar-linux-aarch64", "url": "…", "sha256": "…" },
|
||||
"windows-x86_64": { "name": "uo-link-sidecar-windows-x86_64.exe", "url": "…", "sha256": "fbefd886…" }
|
||||
}
|
||||
},
|
||||
@@ -1030,7 +1176,8 @@ resolving "latest", CI publishes a small manifest naming an exact, checked combi
|
||||
|
||||
Note `link.assets` is a **map keyed by platform**, not the single `sha256` this section originally
|
||||
sketched: link publishes a Linux binary and a Windows `.exe`, and the installer runs on both, so one
|
||||
hash could only ever have described one of them. `schema` versions this document's shape and is
|
||||
hash could only ever have described one of them. Phase 5's `linux-aarch64` (§5.2) is the first
|
||||
addition that map was shaped for, and it costs the bundle nothing but a key. `schema` versions this document's shape and is
|
||||
independent of `protocol` and of either component's release version — all three move separately.
|
||||
|
||||
The installer fetches the current bundle at run time; `--bundle <tag>` pins an older one for a
|
||||
|
||||
Reference in New Issue
Block a user