5 Commits
v0.3.0 ... main

Author SHA1 Message Date
3a3676a22d Merge pull request 'fix(rust): drop the stray spaces in the running-server handoff line' (#34) from fix/rust-handoff-spaces into main
All checks were successful
Release installer / release (push) Successful in 4m57s
sync-project-tree / sync (push) Successful in -1m31s
Reviewed-on: #34
Reviewed-by: Colby Whitlock <whitlocktech@gmail.com>
2026-09-26 15:41:23 +00:00
9d73367e63 test(rust): pin the running-server handoff line whole
All checks were successful
PR Checks / rust-gates (pull_request) Successful in 1m0s
The existing assertions checked fragments ("doctor --game rust
--server-id alpha"), which the stray-space version also contained. The
whole first line is now compared, so a wrapped source line cannot put
its indent back into the sentence. Fails against the pre-fix literal.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-09-26 10:14:22 -05:00
d61f46ffb6 fix(rust): drop the stray spaces in the running-server handoff line
All checks were successful
PR Checks / rust-gates (pull_request) Successful in 57s
The D156 line printed "confirms it                  connected." — a
wrapped source line left a run of spaces inside the string literal.
Found by the phase 18 step 7 re-walk on Debian 12.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-09-26 10:09:33 -05:00
dc3d360cf2 Merge pull request 'fix(release): static musl Linux binaries, so the installer runs on Debian 12 (D158)' (#33) from ci/static-musl-installer into main
All checks were successful
sync-project-tree / sync (push) Successful in 19s
Release installer / release (push) Successful in 7m50s
Reviewed-on: #33
Reviewed-by: Colby Whitlock <whitlocktech@gmail.com>
2026-09-26 14:53:13 +00:00
9f43260ee7 fix(release): static musl Linux binaries, so the installer runs on Debian 12 (D158)
All checks were successful
PR Checks / rust-gates (pull_request) Successful in 1m1s
The Linux installers were linked against the release runner's glibc and
needed glibc 2.39: v0.3.0 (and v0.2.0) failed on the first line on
Debian 12 (2.36) and Ubuntu 22.04 (2.35) with "GLIBC_2.39 not found" --
found by the Rust phase 18 walk, step 7. Both Linux targets are now
x86_64/aarch64-unknown-linux-musl, built with cargo-zigbuild (zig is the
one C compiler `ring` needs for both musl targets; Ubuntu packages a
musl gcc for x86_64 only), and the package step refuses a Linux binary
that `file` does not call statically linked. Windows is unchanged.

Tried in rust:1-slim-bookworm: both targets build, both are "statically
linked", and the x86_64 binary runs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-09-26 04:47:07 -05:00
2 changed files with 35 additions and 16 deletions

View File

@@ -64,11 +64,15 @@ env:
GITEA_HOST: gitea.whitlocktech.com
REPO: RunicGateway/installer
BIN: runicgateway-installer
LINUX_TARGET: x86_64-unknown-linux-gnu
# Both Linux binaries are STATIC (musl), D158. Linked against the runner's glibc
# they needed glibc 2.39 and would not start on Debian 12 or Ubuntu 22.04 — the
# hosts an operator is most likely to have (Rust phase 18 walk, step 7). The
# sidecar the installer deploys is already static for the same reason (D149).
LINUX_TARGET: x86_64-unknown-linux-musl
WINDOWS_TARGET: x86_64-pc-windows-gnu
# The installer has to run wherever the sidecar it installs can run, and link
# publishes an arm64 Linux binary from v1.2.0 (PLAN.md §5.2, step 4 of 4).
ARM64_TARGET: aarch64-unknown-linux-gnu
ARM64_TARGET: aarch64-unknown-linux-musl
jobs:
release:
@@ -280,13 +284,14 @@ jobs:
set -euo pipefail
SUDO=""; [ "$(id -u)" -ne 0 ] && SUDO="sudo"
$SUDO apt-get update
# libc6-dev-arm64-cross is named explicitly on purpose: gcc-aarch64-linux-gnu only
# *recommends* it, and this install runs --no-install-recommends. Without it the Rust
# half of the arm64 build succeeds and then `ring` (under ureq's rustls) dies compiling
# C, on a missing bits/libc-header-start.h.
# `ring` (under ureq's rustls) compiles C, so each Linux target needs a C compiler that
# targets musl. Ubuntu packages one for x86_64 only; zig (via cargo-zigbuild) is one
# compiler for both, so both Linux builds go through it. python3-pip installs it;
# `file` is for the static-link check after the build.
$SUDO apt-get install -y --no-install-recommends \
build-essential gcc-mingw-w64-x86-64 gcc-aarch64-linux-gnu libc6-dev-arm64-cross \
build-essential gcc-mingw-w64-x86-64 python3-pip file \
curl ca-certificates git jq
pip3 install --quiet --break-system-packages ziglang cargo-zigbuild
if ! command -v cargo >/dev/null 2>&1; then
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs \
@@ -295,6 +300,7 @@ jobs:
echo "${HOME}/.cargo/bin" >> "$GITHUB_PATH"
export PATH="${HOME}/.cargo/bin:${PATH}"
rustup component add rustfmt
rustup target add "${LINUX_TARGET}"
rustup target add "${WINDOWS_TARGET}"
rustup target add "${ARM64_TARGET}"
@@ -322,9 +328,9 @@ jobs:
run: cargo test --locked
# ── RUST ADAPTER: build both targets ─────────────────────────────────
- name: cargo build --release (Linux)
- name: cargo build --release (Linux, static musl)
if: ${{ steps.plan.outputs.release == 'true' }}
run: cargo build --release --locked --target "${LINUX_TARGET}"
run: cargo zigbuild --release --locked --target "${LINUX_TARGET}"
- name: cargo build --release (Windows, cross via MinGW)
if: ${{ steps.plan.outputs.release == 'true' }}
@@ -338,13 +344,9 @@ jobs:
# arm64 Linux binary (PLAN.md §5.2). Without this step the target is installed and the
# artifact is packaged, but nothing ever builds it — which is exactly how the first release
# attempt failed, at `cp: cannot stat target/aarch64-unknown-linux-gnu/release/...`.
- name: cargo build --release (Linux arm64, cross)
- name: cargo build --release (Linux arm64, static musl)
if: ${{ steps.plan.outputs.release == 'true' }}
env:
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc
CC_aarch64_unknown_linux_gnu: aarch64-linux-gnu-gcc
AR_aarch64_unknown_linux_gnu: aarch64-linux-gnu-ar
run: cargo build --release --locked --target "${ARM64_TARGET}"
run: cargo zigbuild --release --locked --target "${ARM64_TARGET}"
# ── RUST ADAPTER: package artifacts (+ checksums) ────────────────────
# SHA256SUMS is the trust anchor for these unsigned binaries (PLAN.md §3),
@@ -356,6 +358,13 @@ jobs:
cp "target/${LINUX_TARGET}/release/${BIN}" "dist/${BIN}-linux-x86_64"
cp "target/${ARM64_TARGET}/release/${BIN}" "dist/${BIN}-linux-aarch64"
cp "target/${WINDOWS_TARGET}/release/${BIN}.exe" "dist/${BIN}-windows-x86_64.exe"
# A "static" binary that is quietly dynamic fails only on the operator's host, on the
# first line, with a glibc version error — so it is refused here instead (D158).
for f in "dist/${BIN}-linux-x86_64" "dist/${BIN}-linux-aarch64"; do
if ! file "$f" | grep -q 'statically linked'; then
echo "::error::$f is not statically linked: $(file -b "$f")"; exit 1
fi
done
# Every artifact must be listed: `sha256sum -c` passes silently over a
# file the sums do not mention, and an operator verifying a download
# would get a pass on a binary nobody vouched for.

View File

@@ -185,7 +185,7 @@ pub fn handoff(
protocol = doc.protocol,
when = if running {
format!(
"The plugin loads now; `doctor --game rust --server-id {server_id}` confirms it connected."
"The plugin loads now; `doctor --game rust --server-id {server_id}` confirms it connected."
)
} else {
"The plugin connects when the server next starts.".to_string()
@@ -265,6 +265,16 @@ mod tests {
running.contains("doctor --game rust --server-id alpha"),
"{running}"
);
// The whole first line, so a wrapped source line cannot leave its indent in the sentence
// again (installer#34: "confirms it connected.").
assert_eq!(
running.lines().find(|l| !l.is_empty()),
Some(
"Rust server \"alpha\" is set up. The plugin loads now; \
`doctor --game rust --server-id alpha` confirms it connected."
),
"{running}"
);
}
#[test]