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:
145
tools/drill/static.sh
Normal file
145
tools/drill/static.sh
Normal file
@@ -0,0 +1,145 @@
|
||||
#!/bin/bash
|
||||
# The staging drill's static half (docs/runicnpc/PLAN.md D308). Never shipped.
|
||||
#
|
||||
# tools/drill/static.sh (WORK=drill-work BRANCH=staging by default)
|
||||
#
|
||||
# Needs no server. It downloads only RustDedicated_Data/Managed/*.dll from a Steam branch, and
|
||||
# Oxide's build for that branch, and:
|
||||
#
|
||||
# 1. asks whether Oxide's build has caught up with Rust's (tools/fieldlist --oxide-behind). Until it
|
||||
# has, an Oxide server on that branch dies at boot, so the drill waits for it (D317);
|
||||
# 2. regenerates the swap's field list (tools/fieldlist, D232) from Rust's own Assembly-CSharp.dll
|
||||
# and compares it with the one plugin/RunicNPC.cs carries;
|
||||
# 3. compiles plugin/RunicNPC.cs against those assemblies with Oxide's laid over them, as an Oxide
|
||||
# server would. Oxide's patched Assembly-CSharp.dll is needed: the plugin uses members Rust
|
||||
# ships non-public (IAISenses, for one).
|
||||
#
|
||||
# It writes $WORK/static.json and, beside it, oxide-behind.txt, fields.diff and compile.txt. In
|
||||
# static.json, oxideBehind is a count (-1: not measured), fields "same"/"differs", compile
|
||||
# "ok"/"errors", and either is "error" when its step could not run. The script exits 0 whenever it
|
||||
# ran; what it found is in static.json. DEPOTDOWNLOADER and DOTNET point at other copies (on
|
||||
# Windows, DEPOTDOWNLOADER=…/DepotDownloader.exe from Git Bash).
|
||||
|
||||
set -uo pipefail
|
||||
|
||||
ROOT=$(cd "$(dirname "$0")/../.." && pwd)
|
||||
WORK=${WORK:-$ROOT/drill-work}
|
||||
BRANCH=${BRANCH:-staging}
|
||||
if [ "$BRANCH" = public ]; then
|
||||
OXIDE_URL=${OXIDE_URL:-https://github.com/OxideMod/Oxide.Rust/releases/latest/download/Oxide.Rust-linux.zip}
|
||||
else
|
||||
OXIDE_URL=${OXIDE_URL:-https://downloads.oxidemod.com/artifacts/Oxide.Rust/$BRANCH/Oxide.Rust-linux.zip}
|
||||
fi
|
||||
DD_URL=https://github.com/SteamRE/DepotDownloader/releases/download/DepotDownloader_3.4.0/DepotDownloader-linux-x64.zip
|
||||
DOTNET=${DOTNET:-dotnet}
|
||||
|
||||
mkdir -p "$WORK"
|
||||
rm -rf "$WORK/depot" "$WORK/oxide" "$WORK/refs" "$WORK/fields"
|
||||
rm -f "$WORK"/static.json "$WORK"/oxide-behind.txt "$WORK"/fields.diff "$WORK"/compile.txt
|
||||
|
||||
managed=error
|
||||
behind=-1
|
||||
fields=error
|
||||
compile=error
|
||||
note=""
|
||||
oxide_modified=""
|
||||
manifest=""
|
||||
manifest_date=""
|
||||
|
||||
finish() {
|
||||
printf '{"branch":"%s","manifest":"%s","manifestDate":"%s","managed":"%s","oxideBehind":%s,"fields":"%s","compile":"%s","oxideModified":"%s","note":"%s"}\n' \
|
||||
"$BRANCH" "$manifest" "$manifest_date" "$managed" "$behind" "$fields" "$compile" "$oxide_modified" "$note" > "$WORK/static.json"
|
||||
cat "$WORK/static.json"
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Git Bash does not translate paths inside a response file; elsewhere this is the path as it is.
|
||||
native() { if command -v cygpath > /dev/null; then cygpath -m "$1"; else printf '%s' "$1"; fi; }
|
||||
|
||||
# ---- Rust's managed assemblies, from Steam (no login: the dedicated server is anonymous) ----
|
||||
|
||||
DD=${DEPOTDOWNLOADER:-}
|
||||
if [ -z "$DD" ]; then
|
||||
curl -sSL --fail -o "$WORK/dd.zip" "$DD_URL" && unzip -oq "$WORK/dd.zip" -d "$WORK/dd" && chmod +x "$WORK/dd/DepotDownloader" \
|
||||
|| { note="DepotDownloader could not be fetched"; finish; }
|
||||
DD=$WORK/dd/DepotDownloader
|
||||
fi
|
||||
|
||||
printf 'regex:^RustDedicated_Data/Managed/[^/]+\\.dll$\n' > "$WORK/files.txt"
|
||||
"$DD" -app 258550 -depot 258552 -branch "$BRANCH" -filelist "$WORK/files.txt" -dir "$WORK/depot" -os linux \
|
||||
> "$WORK/depot.txt" 2>&1
|
||||
MANAGED=$WORK/depot/RustDedicated_Data/Managed
|
||||
# Which build this is, from Steam itself: the Linux depot's manifest and its date. (api.steamcmd.net
|
||||
# answered a build id a day stale on 2026-10-06, so the drill does not ask it.)
|
||||
manifest=$(tr -d '\r' < "$WORK/depot.txt" | sed -n 's/^Manifest \([0-9]*\) (\(.*\))$/\1/p' | head -1)
|
||||
manifest_date=$(tr -d '\r' < "$WORK/depot.txt" | sed -n 's/^Manifest \([0-9]*\) (\(.*\))$/\2/p' | head -1)
|
||||
if [ ! -f "$MANAGED/Assembly-CSharp.dll" ]; then
|
||||
note="no Assembly-CSharp.dll from Steam's $BRANCH branch: $(tail -3 "$WORK/depot.txt" | tr '\n"' ' ')"
|
||||
finish
|
||||
fi
|
||||
managed=ok
|
||||
|
||||
# ---- Oxide's build for the branch ----
|
||||
|
||||
oxide_modified=$(curl -sSIL "$OXIDE_URL" | tr -d '\r' | sed -n 's/^[Ll]ast-[Mm]odified: //p' | tail -1)
|
||||
if ! { curl -sSL --fail -o "$WORK/oxide.zip" "$OXIDE_URL" && unzip -oq "$WORK/oxide.zip" -d "$WORK/oxide"; }; then
|
||||
note="Oxide's $BRANCH build could not be downloaded"
|
||||
finish
|
||||
fi
|
||||
OXIDE_MANAGED=$WORK/oxide/RustDedicated_Data/Managed
|
||||
|
||||
# The tool is built once, here, so a build failure is not mistaken for anything it reports.
|
||||
if ! "$DOTNET" build "$ROOT/tools/fieldlist" -c Release -o "$WORK/fieldlist" > "$WORK/fieldlist-build.txt" 2>&1; then
|
||||
note="tools/fieldlist did not build: $(grep -m1 'error' "$WORK/fieldlist-build.txt" | tr '"' ' ')"
|
||||
finish
|
||||
fi
|
||||
FIELDLIST=("$DOTNET" "$WORK/fieldlist/FieldList.dll")
|
||||
|
||||
# ---- 1. Has Oxide caught up? ----
|
||||
|
||||
if "${FIELDLIST[@]}" --oxide-behind "$MANAGED" "$OXIDE_MANAGED/Assembly-CSharp.dll" > "$WORK/oxide-behind.txt" 2>&1; then
|
||||
behind=$(sed -n 's/^behind \([0-9]*\)$/\1/p' "$WORK/oxide-behind.txt" | head -1)
|
||||
behind=${behind:--1}
|
||||
fi
|
||||
|
||||
# ---- 2. The swap's field list (D232) ----
|
||||
|
||||
mkdir -p "$WORK/fields"
|
||||
cp "$ROOT/plugin/RunicNPC.cs" "$WORK/fields/RunicNPC.cs"
|
||||
block() { sed -n '/\/\/ <fieldlist>/,/\/\/ <\/fieldlist>/p' "$1" | grep -v "Generated by tools/fieldlist" | tr -d '\r'; }
|
||||
if "${FIELDLIST[@]}" "$MANAGED" "$WORK/fields/RunicNPC.cs" > "$WORK/fields/run.txt" 2>&1; then
|
||||
if diff -u --label carried <(block "$ROOT/plugin/RunicNPC.cs") --label "$BRANCH" <(block "$WORK/fields/RunicNPC.cs") > "$WORK/fields.diff"; then
|
||||
fields=same
|
||||
else
|
||||
fields=differs
|
||||
fi
|
||||
else
|
||||
cp "$WORK/fields/run.txt" "$WORK/fields.diff"
|
||||
fi
|
||||
|
||||
# ---- 3. Compile against the branch with Oxide's build laid over ----
|
||||
|
||||
mkdir -p "$WORK/refs"
|
||||
cp "$MANAGED"/*.dll "$WORK/refs/"
|
||||
cp "$OXIDE_MANAGED"/*.dll "$WORK/refs/"
|
||||
# Oxide.References.dll bundles its own older copy of Newtonsoft.Json, which Oxide's compiler never
|
||||
# references; with it, every JObject is ambiguous.
|
||||
rm -f "$WORK/refs/Oxide.References.dll"
|
||||
|
||||
DOTNET_DIR=$(dirname "$(readlink -f "$(command -v "$DOTNET")")")
|
||||
CSC=$(ls "$DOTNET_DIR"/sdk/*/Roslyn/bincore/csc.dll 2>/dev/null | tail -1)
|
||||
if [ -z "$CSC" ]; then
|
||||
note="no csc.dll under $DOTNET_DIR/sdk"
|
||||
finish
|
||||
fi
|
||||
|
||||
# A response file: some 250 references outgrow a Windows command line.
|
||||
for f in "$WORK/refs"/*.dll; do printf '"-r:%s"\n' "$(native "$f")"; done > "$WORK/refs.rsp"
|
||||
if "$DOTNET" "$CSC" -nologo -noconfig -nostdlib -target:library -nowarn:1701,1702 -warn:0 \
|
||||
-out:"$WORK/RunicNPC.dll" "@$WORK/refs.rsp" "$ROOT/plugin/RunicNPC.cs" > "$WORK/compile.txt" 2>&1; then
|
||||
compile=ok
|
||||
else
|
||||
compile=errors
|
||||
fi
|
||||
|
||||
finish
|
||||
Reference in New Issue
Block a user