Merge pull request 'docs(installer): record Phase 1 as built' (#90) from feat/installer-phase-1 into main
Reviewed-on: #90
This commit is contained in:
@@ -5,6 +5,11 @@ installation and connects it to a Runic Gateway website.
|
||||
|
||||
> **Status: the installer binary is not released yet.**
|
||||
>
|
||||
> Phase 1 — the installer core: bundle resolution, ServUO detection, the overlay sync and
|
||||
> `install.json` — is built and lives on the installer repo's `edge` branch. It is deliberately not
|
||||
> released: a binary that deploys the overlay but cannot yet install the sidecar would not do what
|
||||
> this guide describes. The first release follows Phase 2.
|
||||
>
|
||||
> Everything it installs *is* released and published — the sidecar, the plugin overlay, and the
|
||||
> [bundle manifest](https://gitea.whitlocktech.com/RunicGateway/installer/src/branch/main/bundles/current.json)
|
||||
> that names the checked combination of the two. This guide is the operator-facing contract those
|
||||
@@ -496,6 +501,7 @@ The report is also written to a file, so it survives the scrollback.
|
||||
|
||||
| Symptom | Cause and fix |
|
||||
|---|---|
|
||||
| **Windows asks for Administrator as soon as you launch it** | Expected, and it needs Administrator anyway. Windows applies *installer detection* to unsigned executables whose file name contains `install` and elevates them before the program starts. Run it from an already-elevated PowerShell and you will not see the prompt. |
|
||||
| **"ServUO is running — stop it before installing"** | Correct, and not overridable. `ServUO.exe` locks `Scripts.dll` and rewrites `Saves/` on exit; deploying underneath it corrupts one or both. Stop the shard, install, start it again. |
|
||||
| Shard boots clean but nothing reaches the site | The classic silent failure: ServUO ignores the script build's exit code and reloaded a **stale `Scripts.dll`**. Run `dotnet build Scripts/Scripts.csproj -c Release -p:Platform=x64` and read the errors it prints. |
|
||||
| `[bridge status` says `connected=False` | The sidecar is not listening on `127.0.0.1:7788`. Check the service is running, and that `[shard] bind` in `sidecar.toml` matches `Host`/`Port` in `Bridge.cfg`. |
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
# Runic Gateway Installer — plan
|
||||
|
||||
Status: **Phase 0 complete.** Every prerequisite in another repo has landed, the installer repo
|
||||
publishes the bundle manifest, and [`INSTALL.md`](INSTALL.md) now specifies the operator-facing run
|
||||
— so *what* the installer installs and *what using it looks like* both exist ahead of the binary.
|
||||
No installer code exists yet; **Phase 1 is next.** This document is the design of record; it
|
||||
supersedes the informal overview it grew out of, which described a ServUO integration that does not
|
||||
match how `servuo-plugins` actually ships (see
|
||||
Status: **Phase 1 built, on `edge`.** Phase 0's prerequisites all landed, the installer repo
|
||||
publishes the bundle manifest, and [`INSTALL.md`](INSTALL.md) specified the operator-facing run
|
||||
before the binary existed. The crate now exists and implements the installer core — bundle
|
||||
resolution, ServUO detection and validation, the overlay sync and `install.json` — on the
|
||||
`edge` branch, not `main`, so no half-capable binary is released (see
|
||||
[Phase 1 as built](#phase-1--installer-core)). **Phase 2 (uo-link install + service) is next.**
|
||||
This document is the design of record; it supersedes the informal overview it grew out of, which
|
||||
described a ServUO integration that does not match how `servuo-plugins` actually ships (see
|
||||
[Corrections](#corrections-to-the-original-overview)).
|
||||
|
||||
| Phase 0 item | State |
|
||||
@@ -458,6 +460,79 @@ Repo work that must land before an installer can exist.
|
||||
timestamp.
|
||||
- Idempotent re-runs; a second run with no upstream change reports "unchanged" and writes nothing.
|
||||
|
||||
**As built** ([installer#4](https://gitea.whitlocktech.com/RunicGateway/installer/pulls/4)) — the
|
||||
crate at the repo root, `install` implemented end to end, `doctor`/`update`/`uninstall` parsed and
|
||||
answered with the phase they arrive in rather than "unrecognized command". The decisions that were
|
||||
not already settled above:
|
||||
|
||||
- **It lands on `edge`, not `main`.** `release.yml` publishes an installer binary on every push to
|
||||
`main`, and its crate guard was written to arm "the moment Phase 1 lands the crate" — which would
|
||||
have published a binary that deploys the overlay but cannot install the sidecar, contradicting
|
||||
everything `INSTALL.md` promises a release does. Phases 1 and 2 land on `edge`; the `edge → main`
|
||||
cutover cuts the first release. `pr-checks.yml` gates PRs into `edge` on the same rules, so the
|
||||
branch where the work happens is not the ungated one. No workflow needed a temporary edit.
|
||||
- **The run says what it did *not* do.** A Phase 1 `install` ends with an unmissable block naming
|
||||
the sidecar as not installed, pointing at `INSTALL.md` A3/A4, and printing the bundle's binary URL
|
||||
and SHA256 so a hand install matches the pair. `--patches` is the sharp edge here: it is accepted
|
||||
(so the flag surface is the published one) but reports `REQUESTED BUT NOT APPLIED — no stock
|
||||
ServUO file has been touched`. A `--patches` run that completed quietly would be read as a
|
||||
patched shard.
|
||||
- **The crate is a library plus a thin binary, and the library is not named after it.** Windows
|
||||
applies UAC *installer detection* to unsigned executables whose file name contains `install`: it
|
||||
demands elevation before the process starts, and a non-interactive session gets `os error 740`
|
||||
instead of a program. That is survivable for the shipped binary — it needs Administrator anyway,
|
||||
and `INSTALL.md` already says to run it from an elevated shell — but Cargo names test harnesses
|
||||
after their target, so a target called `runicgateway_installer` makes `cargo test` **unrunnable on
|
||||
Windows**, on the machine the shard smoke tests live on. The code therefore sits in a library
|
||||
called `rgdeploy`, the binary target keeps its published name, and `[[bin]] test = false` stops
|
||||
Cargo building a harness under it. Nothing an operator sees changes.
|
||||
- **Dependencies chosen for the MinGW cross-build:** `ureq` (blocking HTTP over rustls/ring — no
|
||||
OpenSSL to cross-compile, and no async runtime for a tool that makes four sequential requests),
|
||||
`flate2` on its pure-Rust backend, `tar`, `sha2`, `serde`/`serde_json`, `chrono`, `anyhow`, and
|
||||
`sysinfo` for the running-shard check.
|
||||
- **The shard-running check matches by path, not by process name.** `deploy.ps1` can look for a
|
||||
process called `ServUO` because it only runs on Windows; on Linux the same shard is `mono` or
|
||||
`dotnet` with `ServUO.exe` as an argument, and a name match would answer "not running" for a live
|
||||
shard — the one wrong answer that corrupts `Scripts.dll`. The installer requires a process whose
|
||||
executable or command line names *both* the tree being deployed into and `ServUO.exe`, so a second
|
||||
shard elsewhere on the host does not block this deploy, and the installer never matches itself.
|
||||
- **ServUO's version is read from `Server/AssemblyInfo.cs`**, not from `ServUO.exe`'s PE metadata:
|
||||
it is the same *source* tree the patch tier diffs against, needs no dependency, and works
|
||||
identically on Linux. `57.4.0.0` and `57.4` are normalized to compare equal. An unreadable version
|
||||
is reported as `unknown` and treated as **not** supported — an unreadable version is not evidence
|
||||
of a good one — which is what Phase 3 will gate the tier on.
|
||||
- **`install.json` records a state, not a verb.** Per-file entries are `deployed` or
|
||||
`kept-operator-modified`, never `add`/`change`/`unchanged`. Recording the run's verb made the
|
||||
record differ between a first run and an identical second one, which rewrote the file on every
|
||||
run and broke "a second run writes nothing" in the least visible way available. What later
|
||||
commands need is whose copy is in the tree, and that does not change because time passed.
|
||||
- **The `Bridge.cfg` decision compares against the last hash the installer *deployed*, not the last
|
||||
hash it *saw*.** Once a file has been kept, the record's on-disk hash is the operator's content —
|
||||
so a rule phrased as "is the tree still what the record last saw?" matches on the very next run
|
||||
and overwrites exactly the file it had just protected. A keep has to stay kept for as long as the
|
||||
edit is there; a live three-run test covers it, because the bug only appears from the second run
|
||||
on.
|
||||
- **A prior record is only consulted when it names this tree.** A host whose `install.json` points
|
||||
at a different ServUO root — a shard moved or rebuilt beside the old one — is treated as having no
|
||||
prior deployment, which errs toward keeping the operator's file.
|
||||
- **The download is verified twice, for two different reasons.** The tarball's SHA256 is checked
|
||||
against the bundle while it is being written (the trust anchor — these artifacts are unsigned);
|
||||
then every extracted file is re-hashed against the release's own `manifest.json`, which catches a
|
||||
truncated extraction and is what makes the hashes copied into `install.json` worth trusting. The
|
||||
manifest's `protocol` and `version` are also cross-checked against the bundle, so an artifact that
|
||||
disagrees with the matrix that named it stops the run before anything is written.
|
||||
- **`RUNICGATEWAY_STATE_DIR` relocates the installer's own state**, so a run can be tested without
|
||||
root. Documented in `--help` rather than hidden: an undocumented variable that moves where a tool
|
||||
writes is worse than a documented one, and `doctor` must honour the same value to find what
|
||||
`install` wrote.
|
||||
|
||||
Verified on this machine against a real ServUO 57.4 tree (`--verify`, which reported the tree's
|
||||
`Bridge.cfg` as operator-owned and 23 code files as changed) and end to end into a scratch tree:
|
||||
24 files deployed, a second run reporting `unchanged` and leaving `install.json` untouched, an
|
||||
edited `Bridge.cfg` kept across three further runs while a hand-edited `.cs` was overwritten each
|
||||
time, a pinned `--bundle`, a missing bundle tag, and a refusal — pid and path named, exit 1 — with a
|
||||
process running out of the tree.
|
||||
|
||||
### Phase 2 — uo-link install and service
|
||||
|
||||
- Linux: binary → `/usr/bin/runicgateway-link`, config → `/etc/runicgateway/sidecar.toml`, db →
|
||||
|
||||
Reference in New Issue
Block a user