feat(drill): the staging drill, the week before each forced wipe (stage 9c, D307-D309, D317-D319)

A Gitea job that checks each new Rust staging build in the seven days before the
monthly forced wipe:

- tools/drill/static.sh: staging's managed assemblies (DepotDownloader) and
  Oxide's staging build; whether Oxide has caught up (fieldlist --oxide-behind),
  the swap's field list compared, and the plugin compiled.
- tools/drill/drill.js: window (D318), gate (one check per depot manifest),
  live (rust-staging runs rnt.run all; rust-carbon is stopped and restarted when
  both 6000-map rigs run, D309) and report (one issue per build, state on the
  drill branch; a build waits up to three days for Oxide, D317).
- tools/drill/rig-start.sh: the rig's startup; installs the branch and Oxide's
  build for it, and refuses to start a mismatched pair.
- RunicNpcTest 0.7.2: stage 5's five fights look for a field with room for their
  280 m line (D319), and the spawn check names what did not spawn.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
This commit is contained in:
2026-10-07 01:29:45 -05:00
parent 9b316c6266
commit c25f73c525
9 changed files with 1058 additions and 8 deletions

68
tools/drill/rig-start.sh Normal file
View File

@@ -0,0 +1,68 @@
#!/bin/bash
# The staging drill rig's startup (docs/runicnpc/PLAN.md D307). Never shipped.
#
# rust-staging runs the published egg in its vanilla mode. That image's entrypoint always runs
# `app_update 258550` before the startup, and the egg cannot be told otherwise, so the server's
# startup is this script in front of the egg's own command line:
#
# bash ./staging-drill.sh ./RustDedicated -batchmode …
#
# It moves the install to a Steam branch, lays Oxide's build for that branch over it, writes down what
# it installed (staging-drill.json), and becomes the server. The branch is `staging` unless the file
# staging-drill.branch names another (`public` rehearses the drill on a pair known to match).
# tools/drill/drill.js writes this file to the rig as /staging-drill.sh before every start, so the
# copy in git is the one that runs.
#
# Steam keeps the branch: the entrypoint's own app_update, which names none, then answers "already
# up to date" and leaves a staging install on staging (seen 2026-10-06).
cd /home/container || exit 1
branch=staging
if [ -s staging-drill.branch ]; then branch=$(tr -dc 'a-z0-9-' < staging-drill.branch); fi
if [ "$branch" = public ]; then
OXIDE_URL=https://github.com/OxideMod/Oxide.Rust/releases/latest/download/Oxide.Rust-linux.zip
else
OXIDE_URL=https://downloads.oxidemod.com/artifacts/Oxide.Rust/$branch/Oxide.Rust-linux.zip
fi
# The branch Steam has INSTALLED: MountedConfig's key (UserConfig's is only the one asked for). The
# public branch has no key.
mounted() {
sed -n '/"MountedConfig"/,/}/s/^[[:space:]]*"BetaKey"[[:space:]]*"\([^"]*\)".*/\1/p' steamapps/appmanifest_258550.acf | head -1
}
# A branch switch downloads the whole server (5.4 GB), and one can fail ("UpdateResult" 13 on
# 2026-10-06, the next attempt fine). Rust on one branch with Oxide's build for another dies at boot,
# so the server is not started on a pair that does not match.
want=$branch
[ "$want" = public ] && want=""
for attempt in 1 2; do
echo "[staging-drill] Rust: app_update 258550 -beta $branch (attempt $attempt)"
./steamcmd/steamcmd.sh +force_install_dir /home/container +login anonymous +app_update 258550 -beta "$branch" +quit
installed=$(mounted)
[ "${installed:-public}" = "${want:-public}" ] && break
done
if [ "${installed:-public}" != "${want:-public}" ]; then
echo "[staging-drill] Steam installed '${installed:-public}', not '$branch': not starting"
exit 1
fi
# Oxide's build carries its own patched Assembly-CSharp.dll, so it goes on AFTER Rust.
echo "[staging-drill] Oxide: $OXIDE_URL"
oxide_modified=$(curl -sSIL "$OXIDE_URL" | tr -d '\r' | sed -n 's/^[Ll]ast-[Mm]odified: //p' | tail -1)
if curl -sSL --fail -o oxide-drill.zip "$OXIDE_URL" && unzip -o -q oxide-drill.zip; then
oxide_ok=true
else
oxide_ok=false
echo "[staging-drill] Oxide's $branch build could not be installed"
fi
rm -f oxide-drill.zip
buildid=$(sed -n 's/^[[:space:]]*"buildid"[[:space:]]*"\([0-9]*\)".*/\1/p' steamapps/appmanifest_258550.acf | head -1)
printf '{"buildid":"%s","branch":"%s","oxideModified":"%s","oxideInstalled":%s,"at":"%s"}\n' \
"$buildid" "${installed:-public}" "$oxide_modified" "$oxide_ok" "$(date -u +%Y-%m-%dT%H:%M:%SZ)" > staging-drill.json
echo "[staging-drill] $(cat staging-drill.json)"
if [ "$oxide_ok" != true ]; then exit 1; fi
exec "$@"