fix: keep the Homebrew symlink in the launchd plist - #37
Merged
Conversation
setup resolved symlinks before recording the driver's path, so a cask install wrote Caskroom/openshell-driver-applecontainer/<version>/… into the launchd plist. `brew upgrade` deletes that directory, so the service would point at a path that no longer exists and the driver would stay down until setup ran again — silently, since nothing fails until a sandbox is created. Keep Homebrew's <prefix>/bin symlink, which outlives every upgrade. Other symlinks are still resolved, so the plist does not depend on one staying put. Found on the machine right after installing 0.2.8 from the tap: setup logged binary=/opt/homebrew/Caskroom/openshell-driver-applecontainer/0.2.8/… The cask detection now lives in internal/hostsetup and is shared with update, which needs the same answer for the opposite reason. Signed-off-by: Vyncint Ng <vyncint@users.noreply.github.com>
setup resolved symlinks before recording the driver's path, so a cask install wrote Caskroom/openshell-driver-applecontainer/<version>/… into the launchd plist — a path tied to one version. Keep Homebrew's <prefix>/bin symlink, which is stable across versions; other symlinks are still resolved, so the plist does not depend on one staying put. Also document what testing the upgrade path turned up: `brew upgrade` REMOVES the driver's launchd service. Homebrew replaces a cask by uninstalling the old version first, and that runs the cask's `uninstall launchctl:` directive — UPGRADE_REINSTALL_SKIP_DIRECTIVES skips only `signal`. Keeping the directive is deliberate: without it a real `brew uninstall` leaves a loaded agent respawning a binary that no longer exists. So `setup` after an upgrade is mandatory, not advisory, and the README and caveats now say so plainly. The cask detection now lives in internal/hostsetup and is shared with update, which needs the same answer for the opposite reason. Signed-off-by: Vyncint Ng <vyncint@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Found while verifying the v0.2.8 cask install end to end on the reference machine.
The plist pinned a version directory
setupresolves symlinks before recording the driver's path, which on a Homebrew install produced:That path belongs to one version. The plist now keeps Homebrew's
<prefix>/binsymlink, which is stable across versions; every other symlink is still resolved, so the plist does not depend on one staying put. Verified live —setupon a cask install now records/opt/homebrew/bin/openshell-driver-applecontainer.The Caskroom detection moved to
internal/hostsetupand is shared withupdate, which needs the same answer for the opposite reason (it must not write into the Caskroom).What testing the upgrade path actually revealed
I first added a
postflightlaunchctl kickstartso a barebrew upgradewould restart the driver on the new binary. Testing it showed the hook can never fire, and why:brew upgraderemoves the driver's launchd service. Homebrew replaces a cask by uninstalling the old version first, and that runs the cask'suninstall launchctl:directive. Fromcask/artifact/uninstall.rb:Only
signalis skipped on upgrade/reinstall —launchctlalways runs. Confirmed on the machine: afterbrew reinstall --cask, the agent was gone and~/Library/LaunchAgents/local.openshell-driver-applecontainer.plistwas deleted. The postflight kickstart then had nothing to restart, so it is dropped rather than shipped as dead code.Keeping the
uninstall launchctl:directive is deliberate: dropping it would preserve the service across upgrades, but leave a realbrew uninstallwith a loaded agent respawning a binary that no longer exists.So
setupafter an upgrade is mandatory, not advisory. The README and the cask caveats now say that plainly instead of the weaker "re-run setup so the service restarts on the new binary".Verification
On the reference machine, through a local tap serving a snapshot build:
setupon a cask install records the<prefix>/binsymlink (was: the Caskroom path)brew reinstall --cask→ agent unloaded and plist deleted, confirming the upgrade behaviour abovesetupafterwardsgo test ./...,make lint,goreleaser check, andruby -con the generated cask all clean. Unit tests cover the cask symlink, an ordinary symlink, and an unresolvable path.Note: the earlier
test (ubuntu-latest)failure on this branch wasTestPollerTracksExitininternal/grpcsvc— a timing-sensitive poller test untouched by this change. It passed on rerun and 8 local-raceruns; tracked separately.