@@ -471,6 +471,89 @@ jobs:
471471 echo "Bundle staged: $APP"
472472 find "$APP" -maxdepth 3 -print | head -20
473473
474+ - name : Smoke test .app bundle
475+ working-directory : build
476+ run : |
477+ set -euo pipefail
478+ APP="$RUNNER_TEMP/$APP_BUNDLE"
479+ ENGINE="$APP/Contents/Resources/bin/spring"
480+ LAUNCHER="$APP/Contents/MacOS/$APP_NAME"
481+
482+ echo "--- Code signature verification ---"
483+ codesign --verify --deep --strict "$APP" 2>&1
484+ echo "Signature valid"
485+
486+ echo "--- Dylib path audit ---"
487+ # No Mach-O in the bundle may reference /opt/homebrew.
488+ FAIL=0
489+ while IFS= read -r macho; do
490+ COUNT=$(otool -L "$macho" | grep -c '/opt/homebrew/' || true)
491+ if [ "$COUNT" -ne 0 ]; then
492+ echo "::error::$macho has $COUNT unrewritten /opt/homebrew/ paths"
493+ otool -L "$macho" | grep '/opt/homebrew/'
494+ FAIL=1
495+ fi
496+ done < <(find "$APP" -type f \( -name '*.dylib' -o -name 'spring' -o -name 'Beyond All Reason' \))
497+ if [ "$FAIL" -ne 0 ]; then
498+ exit 1
499+ fi
500+ echo "All Mach-Os use @executable_path-relative paths"
501+
502+ echo "--- Game content verification ---"
503+ GAME_DIR="$APP/Contents/Resources/game"
504+ if [ ! -d "$GAME_DIR/games" ]; then
505+ echo "::error::$GAME_DIR/games does not exist"
506+ exit 1
507+ fi
508+ SDD_COUNT=$(find "$GAME_DIR/games" -mindepth 1 -maxdepth 1 -type d | wc -l | tr -d ' ')
509+ echo "Found $SDD_COUNT .sdd directories"
510+ if [ "$SDD_COUNT" -lt 2 ]; then
511+ echo "::error::Expected at least 2 .sdd directories (game + lobby), found $SDD_COUNT"
512+ exit 1
513+ fi
514+ # Verify each .sdd has modinfo.lua and $VERSION was replaced.
515+ for sdd in "$GAME_DIR/games"/*/; do
516+ MODINFO="${sdd}modinfo.lua"
517+ if [ ! -f "$MODINFO" ]; then
518+ echo "::error::Missing modinfo.lua in $sdd"
519+ exit 1
520+ fi
521+ if grep -q '\$VERSION' "$MODINFO"; then
522+ echo "::error::\$VERSION placeholder not replaced in $MODINFO"
523+ exit 1
524+ fi
525+ NAME=$(grep -oP "(?<=name = ').*(?=')" "$MODINFO" || grep -o "name = '[^']*'" "$MODINFO" | head -1)
526+ VER=$(grep -oP "(?<=version = ').*(?=')" "$MODINFO" || grep -o "version = '[^']*'" "$MODINFO" | head -1)
527+ echo " .sdd OK: $NAME $VER"
528+ done
529+
530+ echo "--- Launcher script validation ---"
531+ if [ ! -x "$LAUNCHER" ]; then
532+ echo "::error::Launcher $LAUNCHER is not executable"
533+ exit 1
534+ fi
535+ # Check the launcher references --isolation-dir and --menu.
536+ if ! grep -q '\-\-isolation-dir' "$LAUNCHER"; then
537+ echo "::error::Launcher missing --isolation-dir flag"
538+ exit 1
539+ fi
540+ if ! grep -q '\-\-menu' "$LAUNCHER"; then
541+ echo "::error::Launcher missing --menu flag"
542+ exit 1
543+ fi
544+ # The --menu argument must reference a directory that exists
545+ # in the bundle's games/ directory.
546+ MENU_ARG=$(grep -oP '\-\-menu "[^"]*"' "$LAUNCHER" | head -1 || grep '\-\-menu' "$LAUNCHER" | head -1)
547+ echo " Launcher menu arg: $MENU_ARG"
548+ echo " Launcher syntactically valid (bash -n)"
549+ bash -n "$LAUNCHER"
550+
551+ echo "--- Bundle structure ---"
552+ echo " Engine: $(file "$ENGINE" | cut -d: -f2)"
553+ echo " Launcher: $(file "$LAUNCHER" | cut -d: -f2)"
554+ DYLIB_COUNT=$(find "$APP/Contents/Resources/lib" -name '*.dylib' 2>/dev/null | wc -l | tr -d ' ')
555+ echo " Bundled dylibs: $DYLIB_COUNT"
556+ echo "All smoke tests passed"
474557 - name : Install + .app + DMG
475558 working-directory : build
476559 run : |
0 commit comments