While tools/ci/github-suspended stands the public host git.igneum.network holds a rewritten copy whose master is replaced at cut-over by the rewrite of the box mirror's final tip, so a landing there is lost: pre-push.sh (forgejo_master_frozen, hook mode) and merge-to-master.sh (forgejo_master_refusal) refuse one and name the box route; a branch pushed there for safekeeping passes. The installed hook hands the gate "<remote name> <url>", and the remote rules read $2, the name: "origin" matched no *github.com*, so the GitHub refusal and the CI rule never bound a named push. Hook mode now resolves the URL ($3, else git remote get-url) and the self-test drives the hook by name through a fixture repository for the GitHub remote, the public host and a safekeeping branch. GATE_ROOT is the script's own repository, so the helpers are read from it wherever the hook is driven from. gate-manifest-check.sh under pipefail piped names_in into grep -q; GNU sed took SIGPIPE when grep matched early and the check read it as a missing run line (a research lane's gate on build-3, 13:4x UK: forty names "missing", the Mac never saw it because BSD sed had finished writing). The names are matched through a here-string now, proved green five times on build-3; the same shape is removed from playbook-quit, pc1-step-budget and second-engine. mirror_master fast-forwards every box with a build-server file (build-3 and build-4 sat at 7 October 15:27). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
34 lines
3.1 KiB
Bash
Executable file
34 lines
3.1 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# The second-engine class (C35, 5 October 2026, PC 1 22:31 UTC): a playbook started a second Igneum engine beside the
|
|
# installed app through a redirected PIPE (PowerShell's Process.Start with RedirectStandardOutput). A pipe's write end is
|
|
# inherited by every process the engine starts (its miners and workers); when the job was aborted, the installed app's
|
|
# jobs runner waited for an EOF the orphaned grandchildren never sent and its quit hung for 24 minutes, and the second
|
|
# engine's miners mined on against the relaunched app. Rule for every playbook that starts an engine: (1) the engine's
|
|
# output goes to a FILE (Start-Process -RedirectStandardOutput <file>), never a pipe into the script; (2) the engine's
|
|
# whole process tree is ended at the end and on the budget (taskkill /T /F), so nothing is orphaned; the installed
|
|
# app's miners come back only after that (the job runner restarts them when the script ends). This check fails CI when
|
|
# a playbook starts an engine without both, or without IGNEUM_APP_NO_OTA = '1' (the third line, same night: the second
|
|
# engine's updater found itself under min_supported_version and ran the installer, which quit the installed app).
|
|
set -euo pipefail
|
|
cd "$(dirname "$0")/../.."
|
|
fail=0
|
|
while IFS= read -r f; do
|
|
grep -qE "igneum-app(\.exe)?['\"]? *(--sweep|-ArgumentList '--sweep'|--no-open)|ArgumentList '--sweep'|\.Arguments = '--sweep'" "$f" || continue
|
|
if grep -qE 'RedirectStandardOutput *= *\$true|UseShellExecute *= *\$false|Register-ObjectEvent|BeginOutputReadLine' "$f"; then
|
|
echo "second-engine: $f starts an engine through a pipe (RedirectStandardOutput/BeginOutputReadLine); use Start-Process -RedirectStandardOutput <file>"; fail=1
|
|
fi
|
|
if ! grep -qE 'taskkill /T /F' "$f"; then
|
|
echo "second-engine: $f starts an engine without ending its process tree (taskkill /T /F) at the end"; fail=1
|
|
fi
|
|
if grep -qE 'settings\.json|\.json' "$f" && grep -qE 'Set-Content[^\n]*-Encoding +utf8' <<<"$(grep -vE '^\s*#' "$f")"; then
|
|
echo "second-engine: $f writes JSON with Set-Content -Encoding utf8 (a BOM the engine refuses: the copy read as defaults, no payout address, nothing mined); use [IO.File]::WriteAllText with UTF8Encoding(\$false)"; fail=1
|
|
fi
|
|
if grep -qE 'settings\.json|Set-Content|WriteAllText|Out-File' <<<"$(grep -vE '^\s*#' "$f" | grep -E 'ConvertTo-Json' || true)"; then
|
|
echo "second-engine: $f rewrites settings.json through ConvertTo-Json (a lossy round trip: big integers become doubles and the engine reads the whole file as defaults; run 4, 6 October 2026); copy the file verbatim, the engine applies Settings::for_measurement under --sweep"; fail=1
|
|
fi
|
|
if ! grep -qE "IGNEUM_APP_NO_OTA *= *'1'" "$f"; then
|
|
echo "second-engine: $f starts an engine without IGNEUM_APP_NO_OTA = '1' (its updater would run the installer, which quits the installed app: PC 1, 5 October 2026, 22:31 UTC)"; fail=1
|
|
fi
|
|
done < <(git ls-files 'relay/playbooks/**' 'tools/windows/**' 'packaging/**' | grep -E '\.ps1$')
|
|
[ "$fail" = 0 ] && echo "second-engine: every playbook that starts an engine logs to a file and ends its tree"
|
|
exit $fail
|