From d6104bd45bcfc62b686e605f84d6091cc5757461 Mon Sep 17 00:00:00 2001 From: Ryan Ward Date: Wed, 26 Aug 2026 12:36:05 -0500 Subject: [PATCH] Fix macOS distribution bundles --- script/build-and-deploy-hermes/src/index.tsx | 28 +++++++++----- .../src/index.tsx | 4 +- script/install-galaxy.sh | 37 +++++++++++++++---- 3 files changed, 50 insertions(+), 19 deletions(-) diff --git a/script/build-and-deploy-hermes/src/index.tsx b/script/build-and-deploy-hermes/src/index.tsx index 22e0662a..dd2aa62f 100644 --- a/script/build-and-deploy-hermes/src/index.tsx +++ b/script/build-and-deploy-hermes/src/index.tsx @@ -284,7 +284,7 @@ function App() { { label: "Pull current branch", status: "pending" }, { label: "Clean Cargo build artifacts", status: "pending" }, { label: "Bundle Galaxy", status: "pending" }, - { label: "Create Galaxy.zip", status: "pending" }, + { label: "Sign and create Galaxy.zip", status: "pending" }, { label: "Authenticate with Hermes", status: "pending" }, { label: "Start multipart upload", status: "pending" }, { label: "Upload parts", status: "pending" }, @@ -340,27 +340,37 @@ function App() { // ─── Step 3: Bundle ───────────────────────────────────────────── updateStep(3, { status: "running" }); await runCommandStreaming( - "cargo bundle --bin galaxy-oss --package galaxy", + "cargo bundle --release --bin galaxy-oss --package galaxy --features release_bundle,extern_plist", WORKSPACE_ROOT, (line) => appendLog(3, line) ); updateStep(3, { status: "done" }); - // ─── Step 4: Zip ──────────────────────────────────────────────── + // ─── Step 4: Sign and zip ─────────────────────────────────────── updateStep(4, { status: "running" }); - // Find the .app bundle — cargo bundle outputs to target/debug/bundle/osx/ - const appDir = path.join( - WORKSPACE_ROOT, - "target/debug/bundle/osx" - ); + // Distribution bundles must use a release profile so rust-embed includes assets in the + // executable instead of resolving them from the build machine's checkout at runtime. + const appDir = path.join(WORKSPACE_ROOT, "target/release/bundle/osx"); + const appPath = path.join(appDir, "Galaxy.app"); const zipPath = path.join(WORKSPACE_ROOT, "Galaxy.zip"); + await runCommandStreaming( + `/usr/bin/codesign --force --deep --sign - "${appPath}"`, + WORKSPACE_ROOT, + (line) => appendLog(4, line) + ); + await runCommandStreaming( + `/usr/bin/codesign --verify --deep --strict --verbose=2 "${appPath}"`, + WORKSPACE_ROOT, + (line) => appendLog(4, line) + ); + // Remove old zip if exists execSync(`rm -f "${zipPath}"`, { stdio: "pipe" }); // Preserve executable permissions, symlinks, and macOS bundle metadata. await runCommandStreaming( - `ditto -c -k --keepParent "${path.join(appDir, "Galaxy.app")}" "${zipPath}"`, + `ditto -c -k --keepParent "${appPath}" "${zipPath}"`, WORKSPACE_ROOT, (line) => appendLog(4, line) ); diff --git a/script/build-and-install-to-applications/src/index.tsx b/script/build-and-install-to-applications/src/index.tsx index c5f4057b..ad8f34ab 100644 --- a/script/build-and-install-to-applications/src/index.tsx +++ b/script/build-and-install-to-applications/src/index.tsx @@ -189,7 +189,7 @@ function App() { (async () => { try { const appName = "Galaxy.app"; - const bundleDir = path.join(WORKSPACE_ROOT, "target/debug/bundle/osx"); + const bundleDir = path.join(WORKSPACE_ROOT, "target/release/bundle/osx"); const appPath = path.join(bundleDir, appName); const destPath = path.join("/Applications", appName); @@ -224,7 +224,7 @@ function App() { // ─── Step 3: Bundle ───────────────────────────────────────────── updateStep(3, { status: "running" }); await runCommandStreaming( - "cargo bundle --bin galaxy-oss --package galaxy", + "cargo bundle --release --bin galaxy-oss --package galaxy --features release_bundle,extern_plist", WORKSPACE_ROOT, (line) => appendLog(3, line) ); diff --git a/script/install-galaxy.sh b/script/install-galaxy.sh index 5467996b..fc8c4136 100755 --- a/script/install-galaxy.sh +++ b/script/install-galaxy.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # -# install-galaxy.sh — Download and install Galaxy.app on macOS. +# install-galaxy.sh — Download, sign, and install Galaxy.app on macOS. # # Usage: # curl -fsSL https://mng-web-sharing.mini-games.tv/wst-data/ryan-share/galaxy/install-galaxy.sh | bash @@ -13,6 +13,7 @@ set -euo pipefail DOWNLOAD_URL="https://mng-web-sharing.mini-games.tv/wst-data/ryan-share/galaxy/Galaxy.zip" APP_NAME="Galaxy.app" +PROCESS_NAME="galaxy-oss" INSTALL_DIR="/Applications" # ---------- helpers ---------- @@ -44,14 +45,21 @@ if [[ ! -d "$TMP_DIR/$APP_NAME" ]]; then fail "$APP_NAME not found after extraction." fi -# ---------- 3. Clear quarantine ---------- -info "Removing the macOS quarantine attribute..." -/usr/bin/xattr -dr com.apple.quarantine "$TMP_DIR/$APP_NAME" 2>/dev/null || true +# ---------- 3. Clear quarantine & ad-hoc sign ---------- +info "Clearing quarantine attributes..." +/usr/bin/xattr -cr "$TMP_DIR/$APP_NAME" || fail "Failed to clear quarantine attributes." + +info "Applying an ad-hoc code signature..." +/usr/bin/codesign --force --deep --sign - "$TMP_DIR/$APP_NAME" || fail "Code signing failed." + +info "Verifying the code signature..." +/usr/bin/codesign --verify --deep --strict --verbose=2 "$TMP_DIR/$APP_NAME" || + fail "Code signature verification failed." # ---------- 4. Kill, remove, install, launch ---------- info "Stopping any running Galaxy processes..." -pkill -x "Galaxy" 2>/dev/null && sleep 1 || true -pkill -9 -x "Galaxy" 2>/dev/null || true +pkill -x "$PROCESS_NAME" 2>/dev/null && sleep 1 || true +pkill -9 -x "$PROCESS_NAME" 2>/dev/null || true INSTALLED_APP="$INSTALL_DIR/$APP_NAME" STAGED_APP="$INSTALL_DIR/.$APP_NAME.new" @@ -60,6 +68,9 @@ info "Staging $APP_NAME in $INSTALL_DIR..." rm -rf "$STAGED_APP" cp -R "$TMP_DIR/$APP_NAME" "$STAGED_APP" || fail "Failed to copy $APP_NAME to $INSTALL_DIR." +/usr/bin/codesign --verify --deep --strict --verbose=2 "$STAGED_APP" || + fail "Installed application signature verification failed." + if [[ -d "$INSTALLED_APP" ]]; then info "Removing existing $INSTALLED_APP..." rm -rf "$INSTALLED_APP" @@ -69,6 +80,16 @@ info "Installing $APP_NAME to $INSTALL_DIR..." mv "$STAGED_APP" "$INSTALLED_APP" || fail "Failed to install $APP_NAME." info "Launching Galaxy..." -open "$INSTALLED_APP" +/usr/bin/open "$INSTALLED_APP" || fail "macOS failed to launch Galaxy." -info "Done! Galaxy is running." +for _ in {1..50}; do + if pgrep -x "$PROCESS_NAME" >/dev/null; then + sleep 2 + pgrep -x "$PROCESS_NAME" >/dev/null || fail "Galaxy exited immediately after launch." + info "Done! Galaxy is running." + exit 0 + fi + sleep 0.1 +done + +fail "Galaxy did not start. Run $INSTALLED_APP/Contents/MacOS/$PROCESS_NAME to see the launch error."