4 Commits
v1.2.0 ... main

Author SHA1 Message Date
be0efd348c Merge pull request 'docs(readme): give operators an entry point before the build steps' (#30) from docs/installer-first-setup into main
Some checks failed
Release sidecar / release (push) Successful in 10s
SonarQube / analysis (push) Failing after 13s
sync-project-tree / sync (push) Successful in -30s
Reviewed-on: #30
Reviewed-by: Colby Whitlock <whitlocktech@gmail.com>
2026-08-07 21:33:00 +00:00
3dbc2f490c docs(readme): give operators an entry point before the build steps
All checks were successful
PR Checks / rust-gates (pull_request) Successful in 1m32s
The README opened straight into cargo build, which is the wrong first
instruction for someone standing up a shard: the installer places this
binary, its config, a service account and the service registration.

Adds a short operator section pointing at the installer (and at INSTALL.md
Appendix A3-A4 for installing by hand, still supported), marks everything
below it as development, and lists the installer under related repos.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-07 16:05:56 -05:00
7b6584006e Merge pull request 'fix(release): tag only, and stop pushing to main' (#28) from fix/release-tag-only into main
All checks were successful
sync-project-tree / sync (push) Successful in 8s
SonarQube / analysis (push) Successful in 43s
Release sidecar / release (push) Successful in 10m22s
Reviewed-on: #28
Reviewed-by: Colby Whitlock <whitlocktech@gmail.com>
2026-08-07 19:17:11 +00:00
36141a23df fix(release): tag only, and stop pushing to main
All checks were successful
PR Checks / rust-gates (pull_request) Successful in 1m0s
The "Commit version bump and push tag" step had two problems, and the
first hid the second.

It has never once executed. An empty template expression written
literally in one of its comments makes the runner fail to build the
step's script, and a step it cannot build is skipped WITHOUT failing
the job. That is why sidecar/Cargo.toml still says 0.1.0 after six
releases, and why the tag-reuse handling added in #27 was dead on
arrival. The tags exist because Gitea's release API creates one when it
publishes -- the pipeline has been working by accident.

And had it executed, it would have been declined: main is protected, so
the push is rejected by the pre-receive hook. The installer's bundle job
hit exactly that today. A release must not depend on a write to a
protected branch.

So the tag is the version, as it already is in servuo-plugins, whose
release workflow was written this way on purpose and has never needed a
protection exception. The workflow still writes the real version into
Cargo.toml before building, so a released binary self-reports
correctly; what it no longer does is commit that edit back. Nothing
downstream reads the file -- the next version is computed from the
newest tag.

The comment is reworded so the step can actually run, and warns against
writing that token in a comment again. No literal occurrence is left in
this file.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-05 17:16:42 -05:00
2 changed files with 49 additions and 15 deletions

View File

@@ -279,33 +279,43 @@ jobs:
ls -l dist && echo "----" && cat dist/SHA256SUMS ls -l dist && echo "----" && cat dist/SHA256SUMS
# ── RELEASE ENGINE: commit the bump, tag, push ─────────────────────── # ── RELEASE ENGINE: commit the bump, tag, push ───────────────────────
- name: Commit version bump and push tag # Tag only — `main` is never pushed to.
#
# This step used to commit the version bump back to main first. Two things
# were wrong with that. It has never once executed: an EMPTY template
# expression written literally in a comment (the `$`+`{{ }}` token, which
# is why it is spelled out here) made the runner fail to build the script
# and skip the whole step silently, which is why sidecar/Cargo.toml still
# says 0.1.0 after six releases (the tags exist because the release API
# creates one when it publishes). And had it executed, it would have been
# declined — main is protected, and a release must not depend on a write
# to a protected branch.
#
# So the tag is the version, as it already is in servuo-plugins. The
# workflow still writes the real version into Cargo.toml before building,
# so a released binary self-reports correctly; what it no longer does is
# commit that edit back. The next version is computed from the newest tag,
# never from Cargo.toml, so nothing downstream depends on the file.
- name: Push the release tag
if: ${{ steps.plan.outputs.release == 'true' }} if: ${{ steps.plan.outputs.release == 'true' }}
env: env:
REGISTRY_USER: ${{ secrets.REGISTRY_USER }} REGISTRY_USER: ${{ secrets.REGISTRY_USER }}
REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }} REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
run: | run: |
set -euo pipefail set -euo pipefail
VERSION="${{ steps.plan.outputs.version }}"
TAG="${{ steps.plan.outputs.tag }}" TAG="${{ steps.plan.outputs.tag }}"
# Secrets can arrive with a trailing newline (depending on how they were # Secrets can arrive with a trailing newline (depending on how they were
# pasted); a stray CR/LF corrupts the remote URL ("credential url cannot # pasted); a stray CR/LF corrupts the remote URL ("credential url cannot
# be parsed"). Strip line breaks before building the URL. Passing them via # be parsed"). Strip line breaks before building the URL. They are passed
# env (not inline ${{ }}) also keeps a newline from breaking this script. # via env rather than interpolated into this script, so a newline cannot
# break it — do NOT write a template token literally in a comment here,
# or the runner will skip this step without failing the job.
CI_USER="$(printf '%s' "${REGISTRY_USER}" | tr -d '\r\n')" CI_USER="$(printf '%s' "${REGISTRY_USER}" | tr -d '\r\n')"
CI_TOKEN="$(printf '%s' "${REGISTRY_TOKEN}" | tr -d '\r\n')" CI_TOKEN="$(printf '%s' "${REGISTRY_TOKEN}" | tr -d '\r\n')"
git config user.name "uo-link-ci" git config user.name "uo-link-ci"
git config user.email "ci@whitlocktech.com" git config user.email "ci@whitlocktech.com"
git remote set-url origin \ git remote set-url origin \
"https://${CI_USER}:${CI_TOKEN}@${GITEA_HOST}/${REPO}.git" "https://${CI_USER}:${CI_TOKEN}@${GITEA_HOST}/${REPO}.git"
git add "${WORKDIR}/Cargo.toml" "${WORKDIR}/Cargo.lock"
if ! git diff --cached --quiet; then
git commit -m "chore(release): bump version to ${TAG} [skip ci]"
git push origin "HEAD:main"
else
echo "Version unchanged (first release) — no bump commit needed."
fi
# The tag may already exist when finishing a run that died after tagging # The tag may already exist when finishing a run that died after tagging
# (see the plan step). `git tag` on an existing name fails under # (see the plan step). `git tag` on an existing name fails under
# `set -e`; pushing an identical existing tag is a harmless no-op. A # `set -e`; pushing an identical existing tag is a harmless no-op. A

View File

@@ -12,11 +12,34 @@ ServUO plugin (C#, net48) ──loopback TCP, newline-JSON──► Rust sidec
The shard never speaks WebSocket and exposes no port of its own — the sidecar is the only The shard never speaks WebSocket and exposes no port of its own — the sidecar is the only
network-facing component, which is what keeps the game unreachable from the internet. network-facing component, which is what keeps the game unreachable from the internet.
## Running a shard? Don't build this
The [**Runic Gateway installer**](https://gitea.whitlocktech.com/RunicGateway/installer) installs
this sidecar for you — the released binary, its config, a hardened service account and the service
registration — alongside the shard plugin, in one run, on Linux or Windows:
```bash
sudo ./runicgateway-installer-linux-x86_64 install
```
It ends by printing the base URL, WebSocket URL, protocol version and auth token to paste into
**Admin → Shard** on your site. Guide:
[installer/INSTALL.md](https://gitea.whitlocktech.com/RunicGateway/docs/src/branch/main/installer/INSTALL.md).
Installing it yourself is supported too — the release binaries on this repo's
[releases page](https://gitea.whitlocktech.com/RunicGateway/link/releases) are the same ones the
installer fetches, and
[INSTALL.md Appendix A3A4](https://gitea.whitlocktech.com/RunicGateway/docs/src/branch/main/installer/INSTALL.md#a3-install-the-sidecar)
covers placing the binary and registering the service by hand.
Everything below this line is for **developing on the sidecar**.
## Related repos ## Related repos
| Repo | What | | Repo | What |
|------|------| |------|------|
| **this**`RunicGateway/link` | The Rust sidecar (`sidecar/`). | | **this**`RunicGateway/link` | The Rust sidecar (`sidecar/`). |
| [RunicGateway/installer](https://gitea.whitlocktech.com/RunicGateway/installer) | The **installer** — deploys this sidecar and the plugin onto a shard host. The supported way to set one up. |
| [RunicGateway/servuo-plugins](https://gitea.whitlocktech.com/RunicGateway/servuo-plugins) | The **C# ServUO plugin** — the shard side of the bridge (`overlay/`, `patches/`, `deploy.ps1`, test scaffolding). | | [RunicGateway/servuo-plugins](https://gitea.whitlocktech.com/RunicGateway/servuo-plugins) | The **C# ServUO plugin** — the shard side of the bridge (`overlay/`, `patches/`, `deploy.ps1`, test scaffolding). |
| [RunicGateway/docs](https://gitea.whitlocktech.com/RunicGateway/docs) | All project documentation — design docs, protocol spec, integration guide, research. | | [RunicGateway/docs](https://gitea.whitlocktech.com/RunicGateway/docs) | All project documentation — design docs, protocol spec, integration guide, research. |
@@ -28,9 +51,10 @@ network-facing component, which is what keeps the game unreachable from the inte
| `.gitea/workflows/pr-checks.yml` | Gates every PR into `main` on `cargo fmt --check`, `cargo clippy -D warnings`, and `cargo test`. | | `.gitea/workflows/pr-checks.yml` | Gates every PR into `main` on `cargo fmt --check`, `cargo clippy -D warnings`, and `cargo test`. |
| `.gitea/workflows/release.yml` | Builds + releases the sidecar binary (Linux + Windows) on every merge to `main`. | | `.gitea/workflows/release.yml` | Builds + releases the sidecar binary (Linux + Windows) on every merge to `main`. |
## Build & run ## Build & run (development)
The sidecar is a standard cargo crate: Building from source is for working *on* the sidecar; a deployment gets its binary from a release,
via the installer or by hand. The sidecar is a standard cargo crate:
```bash ```bash
cd sidecar cd sidecar
@@ -39,7 +63,7 @@ cp sidecar.toml.example sidecar.toml # then edit
cargo run --release cargo run --release
``` ```
Deploying it rather than developing on it: `--config <PATH>` names the config file (as does Deploying it by hand rather than developing on it: `--config <PATH>` names the config file (as does
`$UOLINK_CONFIG`), and `--print-config` prints the resolved settings — **including the auth token `$UOLINK_CONFIG`), and `--print-config` prints the resolved settings — **including the auth token
the website needs** — as JSON, provisioning the config file on first run. That is the supported way the website needs** — as JSON, provisioning the config file on first run. That is the supported way
to read the token back; it is not meant to be scraped from the log. to read the token back; it is not meant to be scraped from the log.