diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 311a2a8..5f2aaf2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -46,7 +46,7 @@ jobs: run: | BIN=.build/arm64-apple-macosx/release/yap "$BIN" --help - "$BIN" models list + "$BIN" --version "$BIN" bench --help # The embedded __TEXT,__info_plist is what lets TCC attribute the diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9dc3db1..18ef030 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -106,9 +106,12 @@ jobs: id: pkg working-directory: dist run: | - DMG="yap-${{ steps.v.outputs.version }}.dmg" - shasum -a 256 "$DMG" > "$DMG.sha256" - echo "sha256=$(shasum -a 256 "$DMG" | cut -d' ' -f1)" >> "$GITHUB_OUTPUT" + V="${{ steps.v.outputs.version }}" + shasum -a 256 "yap-$V.dmg" > "yap-$V.dmg.sha256" + # The in-app updater fetches this one and compares it against the zip + # before it unpacks anything. + shasum -a 256 "yap-$V.zip" > "yap-$V.zip.sha256" + echo "sha256=$(shasum -a 256 "yap-$V.dmg" | cut -d' ' -f1)" >> "$GITHUB_OUTPUT" - name: Publish release uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2 @@ -116,6 +119,8 @@ jobs: files: | dist/yap-${{ steps.v.outputs.version }}.dmg dist/yap-${{ steps.v.outputs.version }}.dmg.sha256 + dist/yap-${{ steps.v.outputs.version }}.zip + dist/yap-${{ steps.v.outputs.version }}.zip.sha256 generate_release_notes: true fail_on_unmatched_files: true @@ -151,10 +156,10 @@ jobs: depends_on macos: :sequoia app "yap.app" - # yap is a CLI first. The bundle exists so the build can be - # notarized and so TCC has something stable to hang grants on; this - # puts the command itself on PATH. - binary "#{appdir}/yap.app/Contents/MacOS/yap" + # No "binary" stanza. yap is a menu-bar app; the only subcommand + # left is "bench", which is a development tool, and putting a + # second path to the same executable on PATH is how the daemon + # ended up with two LaunchServices identities in the first place. # Homebrew replaces /Applications/yap.app, but a process keeps the # image it already mapped. Without this you stay on the old version @@ -162,23 +167,41 @@ jobs: # the new binary on disk and agrees with the version you just # installed — the worst shape for a bug, because it looks fixed. # - # "kickstart -k" rather than an uninstall stanza: it replaces the - # job launchd already owns, so the daemon stays inside launchd and - # the plist — the login item — is untouched. + # The rewrite first, and it is not cosmetic. yap 0.2's plist ran + # "yap run --skip-doctor", an argument 0.3 does not take: launchd + # would start it, ArgumentParser would exit 64, KeepAlive would + # relaunch it, and the login item would spin for ever. Nothing but + # this line and yap itself ever rewrites that file. + # + # bootout + bootstrap rather than "kickstart -k", because launchd + # reads a plist when the job is bootstrapped and not again — a + # kickstart would faithfully relaunch the arguments it already had + # in memory, rewritten file or not. # # Measured, because the alternative is losing someone's meeting: - # -k delivers SIGTERM, not SIGKILL, and yap catches SIGTERM and - # routes it through applicationWillTerminate. So a recording in + # bootout delivers SIGTERM, not SIGKILL, and yap catches SIGTERM + # and routes it through applicationWillTerminate. So a recording in # flight is finalized and transcribes on the next start instead of - # losing its meta.json. launchd brings the new image up about five - # seconds later. + # losing its meta.json. # - # must_succeed: false because an install with no login item has no - # job to restart, and launchctl exits 113 there. Not having asked - # for launch-at-login is not a reason to fail an upgrade. + # must_succeed: false throughout because an install with no login + # item has no job to restart, and launchctl exits 113 there. Not + # having asked for launch-at-login is not a reason to fail an + # upgrade. postflight do + agent = File.expand_path("~/Library/LaunchAgents/com.terrifiedbug.yap.plist") + next unless File.exist?(agent) + + system_command "/usr/bin/plutil", + args: ["-replace", "ProgramArguments", "-json", + %Q(["#{appdir}/yap.app/Contents/MacOS/yap", "run"]), + agent], + must_succeed: false + system_command "/bin/launchctl", + args: ["bootout", "gui/#{Process.uid}/com.terrifiedbug.yap"], + must_succeed: false system_command "/bin/launchctl", - args: ["kickstart", "-k", "gui/#{Process.uid}/com.terrifiedbug.yap"], + args: ["bootstrap", "gui/#{Process.uid}", agent], must_succeed: false end @@ -188,11 +211,11 @@ jobs: # ~/Library/LaunchAgents/