igneum/packaging/windows/push-inputs.sh
igneum-josh 9e2fdb1b97 Windows CI: the one-click app built on GitHub runners, no PC needed
windows.yml: parse job (every .ps1 through the Windows PowerShell 5.1 parser with a negative fixture, PSScriptAnalyzer
as warnings, parenthesis check of every .bat/.cmd with a negative fixture), build job (engine on the MSVC target,
window host through BUILD-APP.bat as it is, payload through make-payload.sh in Git Bash, installer through
build-installer.ps1, smoke run of both exes, launcher DRY_RUN, three artifacts for 90 days).
push-inputs.sh publishes payload-inputs.zip (node, miner, workers, NVRTC DLLs) to the downloads host from the Mac;
fetch-ci-artifacts.sh pulls the green run's installer and payload back into the downloads folder.
Host: --version and --help, version.h shared with host.rc. Launcher: DRY_RUN=1 prints the plan and starts nothing.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-04 11:32:20 +01:00

95 lines
5.6 KiB
Bash
Executable file

#!/usr/bin/env bash
# Publishes payload-inputs.zip: the pieces of the Windows app that the GitHub build (.github/workflows/windows.yml)
# cannot make on a hosted runner, because they come from the node fork (vendor/, not in git) or from NVIDIA's
# redistributables (large, not in git). Run it on the Mac after every node or worker cross-build:
#
# packaging/windows/push-inputs.sh [--no-deploy]
#
# What goes in (flat): igneumd.exe, igneum-miner.exe (vendor/igneum-node/target-integration/x86_64-pc-windows-gnu/
# release, IGNEUM_WIN_RELEASE overrides), the three mingw runtime DLLs, igneum-worker-cuda.exe with nvrtc64_*_0.dll,
# nvrtc-builtins64_*.dll and the licence texts (proto-cuda/nvrtc, fetch-redist.sh + build-windows.sh),
# igneum-worker-opencl.exe (proto-opencl), and inputs.json (sha256 and size of each file, the commits, the date).
# The zip, its .sha256 and the .json land in the downloads folder (dl/<token>/) and the folder is deployed with the
# Vercel CLI, exactly as the other packages are. The workflow fetches them with the DL_TOKEN repository secret and
# refuses a zip whose sha256 does not match.
#
# Where things are read from (never in the repo): the token in ~/.config/igneum/dl-token, the downloads folder in
# ~/.config/igneum/dlsite-dir (one line, the path of the dlsite directory; IGNEUM_DLSITE overrides), the Vercel login
# in ~/.config/igneum/vercel.
set -euo pipefail
HERE="$(cd "$(dirname "$0")" && pwd)"
ROOT="$(cd "$HERE/../.." && pwd)"
REL="${IGNEUM_WIN_RELEASE:-$ROOT/vendor/igneum-node/target-integration/x86_64-pc-windows-gnu/release}"
MINGW=/opt/homebrew/opt/mingw-w64/toolchain-x86_64/x86_64-w64-mingw32
NVRTC_DIR="$ROOT/proto-cuda/nvrtc"
CL_WORKER="$ROOT/proto-opencl/igneum-worker-opencl.exe"
TOKEN_FILE="$HOME/.config/igneum/dl-token"
DLSITE="${IGNEUM_DLSITE:-}"
[ -n "$DLSITE" ] || { [ -f "$HOME/.config/igneum/dlsite-dir" ] && DLSITE="$(tr -d '[:space:]' < "$HOME/.config/igneum/dlsite-dir")"; } || true
DEPLOY=1
[ "${1:-}" = "--no-deploy" ] && DEPLOY=0
[ -f "$TOKEN_FILE" ] || { echo "no $TOKEN_FILE (the downloads token)" >&2; exit 1; }
TOKEN="$(tr -d '[:space:]' < "$TOKEN_FILE")"
[ -n "$DLSITE" ] && [ -d "$DLSITE/dl/$TOKEN" ] || { echo "no downloads folder: set IGNEUM_DLSITE or write the dlsite path to ~/.config/igneum/dlsite-dir (it must hold dl/<token>/)" >&2; exit 1; }
[ -f "$REL/igneumd.exe" ] || { echo "no $REL/igneumd.exe; cross-compile the node first (proto-cuda/windows-node/cross-build.sh)" >&2; exit 1; }
[ -f "$REL/igneum-miner.exe" ] || { echo "no $REL/igneum-miner.exe; cross-compile the miner first" >&2; exit 1; }
STAGE="$(mktemp -d)/payload-inputs"
mkdir -p "$STAGE"
cp "$REL/igneumd.exe" "$REL/igneum-miner.exe" "$STAGE/"
for dll in lib/libstdc++-6.dll lib/libgcc_s_seh-1.dll bin/libwinpthread-1.dll; do
name="$(basename "$dll")"
if [ -f "$MINGW/$dll" ]; then cp "$MINGW/$dll" "$STAGE/"; x86_64-w64-mingw32-strip "$STAGE/$name" 2>/dev/null || true
else echo "note: $name not in the mingw toolchain (the node exe is linked -static, so it may not need it)"; fi
done
if [ -f "$NVRTC_DIR/igneum-worker-cuda.exe" ]; then
cp "$NVRTC_DIR/igneum-worker-cuda.exe" "$STAGE/"
for f in "$NVRTC_DIR"/redist/bin/nvrtc*.dll "$NVRTC_DIR"/redist/LICENSE-*.txt "$NVRTC_DIR/THIRD-PARTY.md"; do [ -f "$f" ] && cp "$f" "$STAGE/"; done
ls "$STAGE"/nvrtc64_*_0.dll >/dev/null 2>&1 || echo "warning: igneum-worker-cuda.exe without nvrtc64_*_0.dll (run $NVRTC_DIR/fetch-redist.sh)"
else echo "warning: no $NVRTC_DIR/igneum-worker-cuda.exe (run $NVRTC_DIR/build-windows.sh); the app will build the CUDA worker on the PC"; fi
[ -f "$CL_WORKER" ] && cp "$CL_WORKER" "$STAGE/" || echo "warning: no $CL_WORKER"
# the manifest: what is in the zip, from where, when
NODE_COMMIT="$(git -C "$ROOT/vendor/igneum-node-v4" rev-parse --short HEAD 2>/dev/null || git -C "$ROOT/vendor/igneum-node" rev-parse --short HEAD 2>/dev/null || echo unknown)"
REPO_COMMIT="$(git -C "$ROOT" rev-parse --short HEAD 2>/dev/null || echo unknown)"
{
echo '{'
echo " \"built_at\": \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\","
echo " \"node_source_commit\": \"$NODE_COMMIT\","
echo " \"repo_commit\": \"$REPO_COMMIT\","
echo ' "files": {'
first=1
for f in "$STAGE"/*; do
name="$(basename "$f")"
sum="$(shasum -a 256 "$f" | cut -d' ' -f1)"
bytes="$(stat -f %z "$f")"
[ $first = 1 ] || echo ','
first=0
printf ' "%s": { "sha256": "%s", "bytes": %s }' "$name" "$sum" "$bytes"
done
echo
echo ' }'
echo '}'
} > "$STAGE/inputs.json"
DEST="$DLSITE/dl/$TOKEN"
OUT="$DEST/payload-inputs.zip"
rm -f "$OUT"
(cd "$(dirname "$STAGE")" && zip -qr "$OUT" "payload-inputs" -x '*.DS_Store')
shasum -a 256 "$OUT" | awk '{print $1}' > "$DEST/payload-inputs.sha256"
cp "$STAGE/inputs.json" "$DEST/payload-inputs.json"
echo "payload-inputs.zip: $(stat -f %z "$OUT") bytes, sha256 $(cat "$DEST/payload-inputs.sha256")"
cat "$DEST/payload-inputs.json"
rm -rf "$(dirname "$STAGE")"
if [ "$DEPLOY" = 1 ]; then
echo "deploying $DLSITE"
(cd "$DLSITE" && npx vercel@latest --global-config "$HOME/.config/igneum/vercel" deploy --prod --yes 2>&1 | grep -v "$TOKEN" || true)
code="$(curl -s -o /dev/null -w '%{http_code}' "https://dl.igneum.network/dl/$TOKEN/payload-inputs.json")"
echo "https://dl.igneum.network/dl/<token>/payload-inputs.json -> HTTP $code"
[ "$code" = 200 ] || { echo "the manifest is not reachable yet; check the deploy output" >&2; exit 1; }
else
echo "not deployed (--no-deploy): cd $DLSITE && npx vercel@latest --global-config ~/.config/igneum/vercel deploy --prod --yes"
fi
echo "Next: the GitHub build picks it up on the next push to master (or: gh workflow run windows.yml --repo igneum-network/igneum)."