Skip to content

fix: keep the service running the current binary after a Homebrew upgrade - #59

Merged
krisiasty merged 1 commit into
mainfrom
fix/stable-executable-path
Oct 15, 2026
Merged

krisiasty merged 1 commit into
mainfrom
fix/stable-executable-path

Conversation

@krisiasty

Copy link
Copy Markdown
Owner

Pull request

Summary

-install saved the symlink-resolved path of the running binary in the service definition. This project ships a Homebrew cask, which installs each version under <prefix>/Caskroom/ssh-agent-proxy/<version>/, links it into <prefix>/bin, and removes the old version on upgrade. After the first brew upgrade, the service therefore pointed at a binary that no longer existed and could not start until it was reinstalled. Formulas behave the same way under <prefix>/Cellar.

  • When the resolved binary is inside a Homebrew Caskroom or Cellar directory, the service records the <prefix>/bin/<name> link instead, which Homebrew repoints on upgrade. The link is used only when it is verifiably the same file; otherwise the resolved path is kept as before.
  • -start and -restart fail with a -reinstall hint when the recorded binary no longer exists, and print a warning when it differs from the binary being run. The installed definition, config path, and cache arguments are never rewritten implicitly; -reinstall remains the way to change them.
  • -diag reports a missing installed binary as a failure with the same hint, and now shares the path comparison (service.SamePath, service.CurrentExecutable) with the lifecycle commands instead of keeping its own copy.
  • README: documents which binary the service records, that brew upgrade takes effect at the next -restart, and the one-time -reinstall for services installed by earlier versions.

Closes #50.

User impact

New installs from Homebrew record /opt/homebrew/bin/ssh-agent-proxy (or the equivalent prefix), so upgrades take effect at the next restart without reinstalling. Existing installs still record the versioned Caskroom path and need one ssh-agent-proxy -reinstall from a build that includes this change. When the recorded binary is missing, -start and -restart now explain how to fix it instead of failing inside launchd or systemd.

Installations outside Homebrew are unchanged: they record the resolved binary path and need -reinstall after the binary is moved or replaced.

Validation

  • Unit tests: cask and formula layouts map to the bin link; a missing link, a link to a different version, and a non-Homebrew path keep the resolved path; the program check accepts present, uninstalled, and unknown programs and rejects a removed one with a -reinstall hint; path comparison follows the Homebrew link and distinguishes versions; -diag fails on a missing installed binary; the -start/-restart check rejects a removed binary.
  • Mutation checks in scratch copies: disabling the link mapping and removing the start/restart check each fail the corresponding tests.
  • Read-only probe against the real local cask layout: the installed /opt/homebrew/Caskroom/ssh-agent-proxy/0.99.2/ssh-agent-proxy maps to /opt/homebrew/bin/ssh-agent-proxy, and a removed version path yields the reinstall error. A real brew upgrade was not run.
  • SSH_AGENT_PROXY_REQUIRE_OPENSSH=1 go test -race ./....
  • Native and Linux golangci-lint (0 issues), go vet ./... (also GOOS=linux), formatting, git diff --check, and CGO-disabled builds for darwin/linux × amd64/arm64.

Checklist

  • Tests cover changed behavior.
  • Documentation is updated when behavior or design changed.
  • No credentials, private configuration, or identifying key metadata are included.
  • go test -race ./... passes locally, or the reason it was not run is documented.

🤖 Generated with Claude Code

…rade

Install saved the symlink-resolved path of the running binary. Homebrew
keeps each version in its own directory under Caskroom (casks, which this
project ships) or Cellar (formulas) and removes the old one on upgrade,
so after the first upgrade the service definition pointed at a binary
that no longer existed.

- When the resolved binary is in a Homebrew Caskroom or Cellar
  directory, the service records the <prefix>/bin link instead, which
  Homebrew repoints on upgrade, and only if it is the same file.
- -start and -restart fail with a -reinstall hint when the recorded
  binary no longer exists and warn when it differs from the running
  binary; the installed definition is never rewritten implicitly.
- -diag reports a missing installed binary as a failure and shares the
  path comparison with the lifecycle commands.
- README documents the recorded path and the one-time reinstall for
  services installed by earlier versions.

Closes #50.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@krisiasty
krisiasty merged commit e9d354f into main Oct 15, 2026
11 checks passed
@krisiasty
krisiasty deleted the fix/stable-executable-path branch October 15, 2026 20:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: saved executable path can become stale after a Homebrew upgrade

1 participant