Windows combined package 0.2.0 (proto-cuda/windows-app): v4 exes from target-integration, peers = seed then Mac, fresh appdir devnet-v4, one miner and one worker per card with --identities 8, --evm-address (PAYOUT_EVM or derived per vendor from the PC name), voting on (VOTE=0 opts out), --prepare-packs for the hot swap with --exit-on-seed-change as the fallback, --yes on the node, STATUS regex tolerant of the v4 now= segment, version in the dashboard header. Mac app 0.2.0 (packaging/mac): v4 binaries, Metal worker rebuilt for macOS 11, data folder devnet-v4, EVM payout, identities in one process, synced= flag honoured. Seed (infra/seed-nodes): stage-v4.sh builds v4 on the VM as a niced, memory-capped transient service and installs a disabled igneumd-v4 unit with a fresh data dir; switch-v4.sh swaps the units (--back reverses); health.sh reports active-v4. Runbook: docs/plans/cutover-2026-10-04.md. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
108 lines
6.2 KiB
Bash
Executable file
108 lines
6.2 KiB
Bash
Executable file
#!/bin/bash
|
|
# Builds packaging/mac/dist/Igneum-Miner-<version>.dmg: "Igneum Miner.app" + README.txt + "Stop Igneum Miner.command" +
|
|
# a link to /Applications, on a branded image (volume "Igneum Miner", coin volume icon, background with the drag arrow,
|
|
# icons placed). Reuses the binaries already built in the repo (nothing is compiled here); copies of the binaries are
|
|
# stripped and re-signed ad hoc (strip invalidates the linker signature, and arm64 macOS refuses to run an unsigned
|
|
# binary). The originals are not touched. 3 October 2026; 0.2.0 for devnet v4 on 4 October 2026.
|
|
#
|
|
# packaging/mac/build-dmg.sh build
|
|
# NODE=<path> packaging/mac/build-dmg.sh use another node binary
|
|
# 0.2.0 defaults: igneumd and igneum-miner from vendor/igneum-node/target-integration/release (the devnet-v4 integration
|
|
# build of vendor/igneum-node-v4 at dc749905) and the Metal worker rebuilt from proto-metal/main.swift (the hot-swap
|
|
# source: its ready line says "prepare 1") with `-target arm64-apple-macos11`, so the worker loads on any Apple silicon
|
|
# macOS and not only on the build machine's (the committed proto-metal/igneum-bench-hotswap carries minos 16.0).
|
|
# WORKER=<path> skips that rebuild; REBUILD_WORKER=0 uses proto-metal/igneum-bench-hotswap as is.
|
|
# Needs: brand/icons/igneum.icns and dmg-background.tiff (python3 brand/icons/make-icons.py) and dmgbuild
|
|
# (pip3 install dmgbuild) for the icon layout. Without dmgbuild a plain hdiutil image is built and said so.
|
|
set -euo pipefail
|
|
HERE="$(cd "$(dirname "$0")" && pwd)"
|
|
ROOT="$(cd "$HERE/../.." && pwd)"
|
|
VERSION="0.2.0"
|
|
NODE="${NODE:-$ROOT/vendor/igneum-node/target-integration/release/igneumd}"
|
|
MINER="${MINER:-$ROOT/vendor/igneum-node/target-integration/release/igneum-miner}"
|
|
WORKER="${WORKER:-}"
|
|
REBUILD_WORKER="${REBUILD_WORKER:-1}"
|
|
ICONS="$ROOT/brand/icons"
|
|
BUILD="$HERE/build"
|
|
DIST="$HERE/dist"
|
|
DMG="$DIST/Igneum-Miner-$VERSION.dmg"
|
|
STAGE="$BUILD/dmg"
|
|
APP="$STAGE/Igneum Miner.app"
|
|
STAMP="$(date -u +%Y%m%d%H%M)"
|
|
|
|
if [ ! -x "$NODE" ]; then
|
|
if [ -x "$ROOT/vendor/igneum-node/target/release/kaspad" ]; then
|
|
echo "note: $NODE is missing; using target/release/kaspad renamed to igneumd"
|
|
NODE="$ROOT/vendor/igneum-node/target/release/kaspad"
|
|
else
|
|
echo "no node binary at $NODE"; exit 1
|
|
fi
|
|
fi
|
|
[ -x "$MINER" ] || { echo "missing: $MINER"; exit 1; }
|
|
for f in "$NODE" "$MINER"; do
|
|
file "$f" | grep -q 'arm64' || { echo "$f is not an arm64 binary"; exit 1; }
|
|
done
|
|
[ -f "$ICONS/igneum.icns" ] || { echo "no $ICONS/igneum.icns; run: python3 brand/icons/make-icons.py"; exit 1; }
|
|
|
|
rm -rf "$BUILD"
|
|
mkdir -p "$APP/Contents/MacOS" "$APP/Contents/Resources/bin" "$DIST"
|
|
|
|
# the Metal worker: rebuilt from main.swift for macOS 11 and later (about 7 s), else the committed hot-swap binary
|
|
if [ -z "$WORKER" ]; then
|
|
if [ "$REBUILD_WORKER" = 1 ] && command -v swiftc >/dev/null 2>&1; then
|
|
mkdir -p "$BUILD/worker"
|
|
echo "building the Metal worker from proto-metal/main.swift with -target arm64-apple-macos11"
|
|
(cd "$ROOT/proto-metal" && nice -n 19 swiftc -O -target arm64-apple-macos11 -o "$BUILD/worker/igneum-bench" main.swift -framework Metal)
|
|
WORKER="$BUILD/worker/igneum-bench"
|
|
else
|
|
WORKER="$ROOT/proto-metal/igneum-bench-hotswap"
|
|
echo "note: using $WORKER as built (its load command says minos $(otool -l "$WORKER" | awk '/minos/ { print $2; exit }'); a rebuild with -target arm64-apple-macos11 needs swiftc)"
|
|
fi
|
|
fi
|
|
[ -x "$WORKER" ] || { echo "missing: $WORKER"; exit 1; }
|
|
file "$WORKER" | grep -q 'arm64' || { echo "$WORKER is not an arm64 binary"; exit 1; }
|
|
echo "worker: $WORKER (minos $(otool -l "$WORKER" | awk '/minos/ { print $2; exit }'))"
|
|
|
|
# the bundle
|
|
sed "s/VERSION_STAMP/$STAMP/" "$HERE/app/Info.plist" > "$APP/Contents/Info.plist"
|
|
plutil -lint "$APP/Contents/Info.plist" >/dev/null
|
|
printf 'APPL????' > "$APP/Contents/PkgInfo"
|
|
cp "$HERE/app/launcher.sh" "$APP/Contents/MacOS/Igneum Miner"
|
|
cp "$HERE/app/igneum-miner.sh" "$APP/Contents/Resources/igneum-miner.sh"
|
|
cp "$ICONS/igneum.icns" "$APP/Contents/Resources/igneum.icns"
|
|
cp "$NODE" "$APP/Contents/Resources/bin/igneumd"
|
|
cp "$MINER" "$APP/Contents/Resources/bin/igneum-miner"
|
|
cp "$WORKER" "$APP/Contents/Resources/bin/igneum-bench"
|
|
chmod 755 "$APP/Contents/MacOS/Igneum Miner" "$APP/Contents/Resources/igneum-miner.sh" "$APP/Contents/Resources/bin/"*
|
|
|
|
# strip the copies, then sign them ad hoc again
|
|
for b in "$APP/Contents/Resources/bin/"*; do
|
|
before=$(stat -f %z "$b")
|
|
strip "$b" 2>/dev/null || strip -x "$b"
|
|
codesign -s - -f "$b" 2>/dev/null
|
|
codesign -v "$b"
|
|
echo "$(basename "$b"): $before -> $(stat -f %z "$b") bytes, signed ad hoc"
|
|
done
|
|
# each copy must still run
|
|
v="$("$APP/Contents/Resources/bin/igneumd" --version 2>&1 || true)"; echo "node: ${v%%$'\n'*}"
|
|
v="$("$APP/Contents/Resources/bin/igneum-miner" 2>&1 || true)"; case "$v" in usage*) ;; *) echo "igneum-miner copy does not run: $v"; exit 1 ;; esac
|
|
v="$(echo quit | "$APP/Contents/Resources/bin/igneum-bench" --serve 2>&1)"; case "$v" in "ready metal"*) echo "worker: $v" ;; *) echo "igneum-bench copy does not serve: $v"; exit 1 ;; esac
|
|
case "$v" in *"prepare 1"*) ;; *) echo "note: this worker has no prepare support (no hot swap at the hour boundary); the miner falls back to exit 42" ;; esac
|
|
v="$("$APP/Contents/Resources/bin/igneum-miner" 2>&1 || true)"; case "$v" in *"--evm-address"*) ;; *) echo "igneum-miner copy is not the devnet-v4 miner (no --evm-address in its usage)"; exit 1 ;; esac
|
|
|
|
# the rest of the image
|
|
cp "$HERE/dmg/README.txt" "$STAGE/README.txt"
|
|
cp "$HERE/app/Stop Igneum Miner.command" "$STAGE/Stop Igneum Miner.command"
|
|
chmod 755 "$STAGE/Stop Igneum Miner.command"
|
|
|
|
rm -f "$DMG"
|
|
if command -v dmgbuild >/dev/null 2>&1; then
|
|
dmgbuild -s "$HERE/dmg/settings.py" -D "app=$APP" -D "stage=$STAGE" -D "icons=$ICONS" "Igneum Miner" "$DMG"
|
|
else
|
|
echo "note: dmgbuild is not installed (pip3 install dmgbuild); building a plain image without icon positions or background"
|
|
ln -s /Applications "$STAGE/Applications"
|
|
cp "$ICONS/igneum.icns" "$STAGE/.VolumeIcon.icns"
|
|
hdiutil create -volname "Igneum Miner" -srcfolder "$STAGE" -ov -format ULFO -fs HFS+ "$DMG" >/dev/null
|
|
fi
|
|
hdiutil verify "$DMG" >/dev/null
|
|
echo "built $DMG ($(du -h "$DMG" | cut -f1), $(stat -f %z "$DMG") bytes, version $VERSION build $STAMP)"
|