feat(installer): implement Phase 1 — the installer core
All checks were successful
PR Checks / rust-gates (pull_request) Successful in 1m31s
All checks were successful
PR Checks / rust-gates (pull_request) Successful in 1m31s
Adds the Rust crate at the repo root and implements `install` end to end for the overlay half of a deployment: resolve the published bundle, find and validate the ServUO root, refuse to deploy under a running shard, sync the plugin overlay, and record what was deployed in install.json. `doctor`, `update` and `uninstall` parse and answer with the phase they arrive in rather than "unrecognized command", and the run states plainly that the uo-link sidecar (Phase 2) and the patch tier (Phase 3) were not installed — `--patches` in particular reports REQUESTED BUT NOT APPLIED, since a quiet completion would be read as a patched shard. Landing on `edge` rather than `main`: release.yml publishes a binary on every push to main, and an installer that deploys the overlay but cannot install the sidecar is not something to hand an operator. pr-checks.yml now gates PRs into edge on the same rules, so the branch the work happens on is not the ungated one. Notable decisions, all documented in docs/installer/PLAN.md §5 Phase 1: - The code lives in a library called `rgdeploy` with a thin binary that keeps the published name. Windows' UAC installer detection refuses to launch an unsigned executable whose file name contains "install" (os error 740), and Cargo names test harnesses after their target — so a target under that name makes `cargo test` unrunnable on Windows. - The running-shard check matches processes by path, not by process name: on Linux a live shard is `mono`/`dotnet` with ServUO.exe as an argument, and a name match would report "not running" for a shard that is running. - install.json records a state (`deployed` / `kept-operator-modified`), not the run's verb, so an unchanged re-run produces an identical record and writes nothing. - The Bridge.cfg keep rule compares against the hash the installer last deployed, not the last hash it saw — otherwise a kept file is overwritten on the very next run. - Downloads are verified against the bundle's SHA256 while being written, then every extracted file is re-hashed against the release's own manifest.json, whose protocol and version are cross-checked against the bundle. Verified against a real ServUO 57.4 tree and end to end into a scratch tree: 24 files deployed, an unchanged re-run that writes nothing, an edited Bridge.cfg kept across repeated runs while code files are overwritten, bundle pinning, and a refusal with a shard running out of the tree. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
48
README.md
48
README.md
@@ -27,22 +27,34 @@ never restarts the shard.
|
||||
|
||||
## Status
|
||||
|
||||
**Planning — no installer code exists yet.**
|
||||
**Phase 1 (installer core) is built, on the `edge` branch. Nothing is released yet.**
|
||||
|
||||
The design of record is
|
||||
[`installer/PLAN.md`](https://gitea.whitlocktech.com/RunicGateway/docs/src/branch/main/installer/PLAN.md)
|
||||
in the docs repo: phases, locked decisions, and the Phase 0 prerequisites in other
|
||||
repos (a `servuo-plugins` release workflow, a non-interactive config read-back in
|
||||
`link`, and the bundle-manifest CI here) that must land before Phase 1 is useful.
|
||||
`link`, and the bundle-manifest CI here), all of which have landed —
|
||||
[`bundles/current.json`](bundles/current.json) names the current protocol-checked
|
||||
sidecar + overlay combination, recomposed on every component release and nightly
|
||||
(see [`bundles/README.md`](bundles/README.md)).
|
||||
|
||||
All three Phase 0 prerequisites have now landed, so **what the installer will
|
||||
install already exists and is published**, ahead of the binary that installs it:
|
||||
[`bundles/current.json`](bundles/current.json) names the current
|
||||
protocol-checked sidecar + overlay combination, recomposed on every component
|
||||
release and nightly. See [`bundles/README.md`](bundles/README.md).
|
||||
| Phase | State |
|
||||
|---|---|
|
||||
| 0 — prerequisites in the other repos | ✅ merged |
|
||||
| 1 — installer core: bundle resolution, ServUO detection, overlay sync, `install.json` | ✅ on `edge` |
|
||||
| 2 — uo-link install + service registration | next |
|
||||
| 3 — the opt-in stock-file patch tier | |
|
||||
| 4 — `doctor`, `update`, `uninstall` | |
|
||||
|
||||
Besides that, this repo currently holds its governance documents and issue/PR
|
||||
templates.
|
||||
**Why `edge`:** `release.yml` publishes an installer binary on every push to
|
||||
`main`, and a binary that deploys the overlay but cannot yet install the sidecar
|
||||
is not something to hand an operator. Phases 1 and 2 land on `edge`; the
|
||||
`edge → main` cutover cuts the first release. PRs into `edge` run the same gates
|
||||
as PRs into `main`.
|
||||
|
||||
Until then, the way to install is by hand —
|
||||
[INSTALL.md Appendix A](https://gitea.whitlocktech.com/RunicGateway/docs/src/branch/main/installer/INSTALL.md#appendix-a--installing-by-hand)
|
||||
is the same deployment done with `curl`, `tar` and `systemctl`.
|
||||
|
||||
## Related repos
|
||||
|
||||
@@ -82,13 +94,29 @@ templates.
|
||||
|
||||
## Build & run
|
||||
|
||||
Once the crate exists it will be a standard cargo project:
|
||||
A standard cargo project, with the crate at the repo root:
|
||||
|
||||
```bash
|
||||
cargo build --release
|
||||
cargo run -- --help
|
||||
cargo run -- install --servuo /path/to/ServUO --verify # dry run: writes nothing
|
||||
cargo fmt --check && cargo clippy --all-targets -- -D warnings && cargo test
|
||||
```
|
||||
|
||||
`RUNICGATEWAY_STATE_DIR` relocates `install.json` (normally `/etc/runicgateway`
|
||||
or `%ProgramData%\RunicGateway`), which is how a run is tested without root.
|
||||
|
||||
Two layout notes that look odd until you know why:
|
||||
|
||||
- **The library target is `rgdeploy`, not `runicgateway_installer`.** Windows' UAC
|
||||
installer detection refuses to launch an unsigned executable whose file name
|
||||
contains `install` (`os error 740`), and Cargo names test harnesses after their
|
||||
target — so a target under that name makes `cargo test` unrunnable on Windows.
|
||||
The published binary keeps its documented name; `[[bin]] test = false` keeps
|
||||
Cargo from building a harness under it. Expect a UAC prompt when running the
|
||||
built binary on Windows; it needs Administrator anyway.
|
||||
- **`Cargo.lock` is committed**, and CI builds `--locked`.
|
||||
|
||||
See [CONTRIBUTING.md](CONTRIBUTING.md) for the development setup, the local
|
||||
checks CI will run, and the branch/PR workflow.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user