fix(brew): detect Homebrew installed outside PATH#172
Merged
ashishkurmi merged 3 commits intoJul 20, 2026
Merged
Conversation
Resolve the brew executable from standard install locations (/opt/homebrew, /usr/local, /home/linuxbrew) when it is not on PATH, and read the version from the Homebrew git repo metadata (describe-cache / packed-refs) instead of shelling out to `brew --version`. Detection and formula/cask listing now work for scans run without the user's interactive PATH.
There was a problem hiding this comment.
Pull request overview
Improves Homebrew (brew) detection so scans running in non-interactive environments can still find Homebrew even when brew is not on PATH, and derives the Homebrew version from local git metadata instead of invoking brew --version.
Changes:
- Add
resolveBrewExecutableto locatebrewviaLookPathor common install paths, and use the resolved executable for brew invocations. - Add git-metadata-based version resolution (
HEAD+describe-cache/packed-refs) with an"unknown"fallback. - Add unit tests covering outside-PATH detection and git-based version resolution scenarios.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| internal/detector/brew.go | Implements outside-PATH brew executable resolution and git-based version derivation. |
| internal/detector/brew_test.go | Adds tests for standard-path discovery and version-from-git/packed-refs fallbacks. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+235
to
+238
| func resolveBrewExecutable(exec executor.Executor) (brewExecutable, error) { | ||
| if path, err := exec.LookPath("brew"); err == nil { | ||
| return brewExecutable{path: path, command: "brew"}, nil | ||
| } |
Comment on lines
+306
to
+311
| if data, err := exec.ReadFile(filepath.Join(gitDir, "describe-cache", revision)); err == nil { | ||
| version := strings.TrimSpace(string(data)) | ||
| if version != "" && !strings.Contains(version, "-dirty") { | ||
| return version | ||
| } | ||
| } |
- resolveBrewExecutable now uses the resolved absolute path as the command even when found via PATH, so all invocations are PATH-independent. - describe-cache version is reduced to its base tag and validated against brewVersionTagPattern, so strings like "4.3.5-17-g<sha>" no longer leak into PkgManager.Version.
ashishkurmi
approved these changes
Jul 20, 2026
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.
What
Homebrew detection previously relied on
brewbeing on the processPATH(
exec.LookPath("brew")) and shelled out tobrew --version. Scans that runwithout the user's interactive shell environment (e.g. scheduled/agent runs)
often have no
brewonPATH, so Homebrew went undetected even when installed.Changes
brewoutside PATH. NewresolveBrewExecutablefalls back to thestandard install locations when
LookPathfails:/opt/homebrew/bin/brew,/usr/local/bin/brew,/home/linuxbrew/.linuxbrew/bin/brew. All invocations(
DetectBrew,ListFormulae,ListCasks,ListFormulaeRich,ListCasksRich) use the resolved command.brew --version.readBrewVersionderives the version from the Homebrew git repo (
HEAD→describe-cache/packed-refsexact tag), avoiding a subprocess and working when brew isn't onPATH. Falls back to
"unknown"when metadata is unavailable.Tests
Added coverage for detection at a standard path outside PATH, the
<prefix>/Homebrewrepository layout, version-from-packed-tag, and theunknown-version fallback. Full detector suite passes.
Notes
Rebased onto latest
upstream/main. The prior branch also touchedbrewscan.go, but upstream has since refactoredBrewScannerto synthesizescan output from rich
brew info --json=v2data rather than shelling out tobrew list— so those scanner changes are obsolete and were dropped. Theoutside-PATH fix now flows entirely through
brew.go, which feeds the scanner.