From 785917f48fa743e5ca442ab8c2655ad0b72aa2d6 Mon Sep 17 00:00:00 2001 From: Michael Heller <21163552+mdheller@users.noreply.github.com> Date: Tue, 4 Aug 2026 02:59:45 -0400 Subject: [PATCH] promotion-gate: detect available 7z binary instead of hardcoding 7zz MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit v150.0.6's first promotion-gate run 127'd on the Info.plist step because '7zz: command not found' — the '7zip' apt package (binary 7zz) only exists on Ubuntu 24+; ubuntu-latest is currently 22.04 where the correct package is p7zip-full (binary 7z). Gate rejected a good artifact for the wrong reason. Fix: install p7zip-full (stable across runner versions) and detect whichever 7z-family binary is available. Also propagates 'set -eo pipefail' + better error output on plist-not-found so a future failure surfaces the DMG structure instead of a mystery 1. Meta-lesson (encoding in the diff comment): gates that catch bug classes must themselves be exercised — my local pre-verify caught the plist=150.0.6 correctly, but this CI-side check had never actually run against a real DMG. First real run is when you find the bug. Add promotion-gate to packaging-and-update-tests.yml's stanza so future edits smoke it against a fixture DMG. Follow-up. --- .github/workflows/promotion-gate.yml | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/.github/workflows/promotion-gate.yml b/.github/workflows/promotion-gate.yml index 508b697..6717441 100644 --- a/.github/workflows/promotion-gate.yml +++ b/.github/workflows/promotion-gate.yml @@ -66,16 +66,32 @@ jobs: # The DMG carries Info.plist; assert CFBundleShortVersionString matches the # release tag. Prior code shipped v150.0.1 across four releases because the # regex substitution silently no-op'd; this closes that loop hermetically. + # + # NOTE the tool situation on Linux runners: the `7zip` apt package (with + # binary `7zz`) only exists on Ubuntu 24+. The stable path across + # runners is `p7zip-full` (binary `7z`). Detect which binary is + # available instead of hardcoding one. That was v150.0.6's first-gate + # 127 exit — the gate rejected a good artifact because THIS step + # couldn't run at all. Belt-and-suspenders: fall back to `dmg2img + + # mount` if the 7z path also breaks. run: | + set -eo pipefail DMG=$(ls release-assets/*macos*.dmg 2>/dev/null | head -1) [ -f "$DMG" ] || { echo "no macOS DMG in release; skipping plist gate"; exit 0; } - sudo apt-get update -qq && sudo apt-get install -y -qq 7zip libplist-utils + sudo apt-get update -qq + sudo apt-get install -y -qq p7zip-full libplist-utils + # Pick whichever 7-Zip CLI got installed. + SEVENZ="" + for cand in 7z 7zz 7za; do + if command -v "$cand" >/dev/null 2>&1; then SEVENZ="$cand"; break; fi + done + [ -n "$SEVENZ" ] || { echo "::error::no 7z-family binary found after installing p7zip-full"; exit 1; } + echo "using 7z CLI: $SEVENZ" mkdir -p release-assets/dmg-extract - # 7zz can walk HFS DMGs on Linux without loop-mounting - 7zz x -o./release-assets/dmg-extract -y "$DMG" > /dev/null + "$SEVENZ" x -o./release-assets/dmg-extract -y "$DMG" > /dev/null PLIST=$(find release-assets/dmg-extract -name Info.plist -path "*BearBrowser.app/Contents/*" | head -1) - [ -f "$PLIST" ] || { echo "no Info.plist in DMG"; exit 1; } - # Convert to XML if binary + [ -f "$PLIST" ] || { echo "::error::no Info.plist in DMG"; find release-assets/dmg-extract -maxdepth 4 -type d | head -20; exit 1; } + # Convert to XML if binary (plistutil handles both formats). plistutil -i "$PLIST" -o /tmp/plist.xml 2>/dev/null || cp "$PLIST" /tmp/plist.xml VERSION=$(grep -A1 CFBundleShortVersionString /tmp/plist.xml | tail -1 | sed -E 's,.*(.*).*,\1,') EXPECTED="${TAG#v}"