mirror of
https://github.com/garrytan/gstack.git
synced 2026-09-12 16:08:59 +02:00
fix(browse): headed mode on macOS 26 — stop mutating the signed Chromium bundle, heal the ones we already broke (#2242, #2138, #2139)
The in-place rebrand rewrote the Chrome-for-Testing bundle's Info.plist (global name replace — which also renamed CFBundleExecutable to a binary that doesn't exist) and overwrote its Resources/*.icns, breaking the codesign seal: GPU process exit_code=5, headed mode dead on macOS 26. The mutation lived in the SHARED Playwright cache, so it also poisoned the user's other Playwright projects. Three layers land together: (1) the rebrand block is gone — branding lives in the GStack Browser.app wrapper via GSTACK_CHROMIUM_PATH, with a tombstone and a static tripwire (no plist/icns writes into the bundle; the tripwire allows the read-only probe below); (2) a launch-time self-heal detects an already-poisoned cache bundle, removes it, and errors with the exact re-fetch command — covering deploy paths that never run migrations; (3) migration v1.64.0.0 sweeps every cached bundle, removes poisoned ones, and re-fetches clean Chromium immediately (migrations run after ./setup, so without the re-fetch an upgrade would end with zero working browser). Functionally verified against fixture caches: poisoned removed, clean untouched, rerun no-op. Migration filename tracks the final VERSION at ship. The #2242 watchdog half is the absorbed PR #2565 (thanks @Screddyice). Tombstone/tripwire ported from time-attack/gstack (GStack 2); self-heal and migration are ours. Co-authored-by: Sina Matian <sina@time-attack.dev> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Sina Matian
Claude Fable 5
parent
01adcf8e8e
commit
a30ca53c1a
Executable
+75
@@ -0,0 +1,75 @@
|
||||
#!/usr/bin/env bash
|
||||
# Migration: v1.64.0.0 — repair Chrome-for-Testing bundles poisoned by the
|
||||
# old in-place rebrand (#2242).
|
||||
#
|
||||
# Why a migration: pre-v1.64 launchHeaded() rewrote the Chromium .app's
|
||||
# Info.plist ("Google Chrome for Testing" → "GStack Browser") and overwrote
|
||||
# its Resources/*.icns — inside the SHARED Playwright cache. That broke the
|
||||
# codesign seal (GPU process exit_code=5; headed mode dead on macOS 26) and
|
||||
# poisoned the cache for the user's OTHER Playwright projects too. Deleting
|
||||
# the rebrand code fixes fresh installs only; every existing macOS install
|
||||
# still has the mutated bundle on disk. This migration removes poisoned
|
||||
# bundles and re-fetches a clean one so the upgrade doesn't leave the user
|
||||
# with zero working browser (the browse launch path also self-heals, as the
|
||||
# belt to this suspenders, for installs that never run migrations).
|
||||
#
|
||||
# Affected: macOS installs that ever ran headed mode before v1.64.
|
||||
#
|
||||
# Idempotent: detection is content-based (plist contains "GStack Browser");
|
||||
# a clean cache is a no-op, and the .done touchfile gates re-runs. The
|
||||
# re-fetch is best-effort and non-fatal per the migration contract.
|
||||
|
||||
set -u
|
||||
|
||||
GSTACK_HOME="${GSTACK_HOME:-${HOME}/.gstack}"
|
||||
MIGRATION_DIR="${GSTACK_HOME}/.migrations"
|
||||
DONE="${MIGRATION_DIR}/v1.64.0.0.done"
|
||||
mkdir -p "${MIGRATION_DIR}" 2>/dev/null || true
|
||||
[ -f "${DONE}" ] && exit 0
|
||||
|
||||
# macOS only: the mutation targeted .app bundle plists.
|
||||
if [ "$(uname -s 2>/dev/null)" != "Darwin" ]; then
|
||||
touch "${DONE}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
PW_CACHE="${PLAYWRIGHT_BROWSERS_PATH:-${HOME}/Library/Caches/ms-playwright}"
|
||||
REMOVED=0
|
||||
|
||||
if [ -d "${PW_CACHE}" ]; then
|
||||
# Every Chrome-for-Testing bundle in the cache (one per pinned chromium build).
|
||||
while IFS= read -r plist; do
|
||||
if grep -q "GStack Browser" "${plist}" 2>/dev/null; then
|
||||
app_dir="$(dirname "$(dirname "${plist}")")"
|
||||
case "${app_dir}" in
|
||||
"${PW_CACHE}"/*.app|"${PW_CACHE}"/*/*.app|"${PW_CACHE}"/*/*/*.app)
|
||||
echo " [v1.64.0.0] removing rebrand-poisoned bundle: ${app_dir}" >&2
|
||||
rm -rf "${app_dir}"
|
||||
REMOVED=1
|
||||
;;
|
||||
*)
|
||||
echo " [v1.64.0.0] WARNING: poisoned plist outside the Playwright cache shape, skipping: ${plist}" >&2
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
done < <(find "${PW_CACHE}" -maxdepth 5 -name "Info.plist" -path "*.app/Contents/Info.plist" 2>/dev/null)
|
||||
fi
|
||||
|
||||
if [ "${REMOVED}" = "1" ]; then
|
||||
# Re-fetch immediately: migrations run AFTER ./setup, so without this the
|
||||
# user finishes the upgrade with no working browser at all (headless AND
|
||||
# headed use the same bundle). Best-effort — a failed download leaves the
|
||||
# actionable command printed and the launch-time self-heal message covers
|
||||
# the rest.
|
||||
echo " [v1.64.0.0] re-fetching a clean Chromium (bunx playwright install chromium)..." >&2
|
||||
if command -v bunx >/dev/null 2>&1 && bunx playwright install chromium >&2; then
|
||||
echo " [v1.64.0.0] clean Chromium installed." >&2
|
||||
else
|
||||
echo " [v1.64.0.0] WARNING: automatic re-fetch failed. Run manually: bunx playwright install chromium" >&2
|
||||
fi
|
||||
else
|
||||
echo " [v1.64.0.0] no rebrand-poisoned bundles found — no-op." >&2
|
||||
fi
|
||||
|
||||
touch "${DONE}"
|
||||
exit 0
|
||||
Reference in New Issue
Block a user