Skip to content

Commit f025f14

Browse files
authored
Merge pull request #27 from codeGROOVE-dev/rob_pike
Prefer PATH for gh discovery, hard-coded paths as a fallback
2 parents de82396 + efd9f87 commit f025f14

File tree

1 file changed

+59
-47
lines changed

1 file changed

+59
-47
lines changed

cmd/goose/github.go

Lines changed: 59 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -59,61 +59,73 @@ func (*App) token(ctx context.Context) (string, error) {
5959
log.Println("Using GitHub token from GITHUB_TOKEN environment variable")
6060
return token, nil
6161
}
62-
// Only check absolute paths for security - never use PATH
63-
var trustedPaths []string
64-
switch runtime.GOOS {
65-
case "windows":
66-
trustedPaths = []string{
67-
`C:\Program Files\GitHub CLI\gh.exe`,
68-
`C:\Program Files (x86)\GitHub CLI\gh.exe`,
69-
filepath.Join(os.Getenv("LOCALAPPDATA"), "Programs", "gh", "gh.exe"),
70-
filepath.Join(os.Getenv("LOCALAPPDATA"), "GitHub CLI", "gh.exe"),
62+
// Try to find gh in PATH first
63+
ghPath, err := exec.LookPath("gh")
64+
if err == nil {
65+
log.Printf("Found gh in PATH at: %s", ghPath)
66+
// Resolve any symlinks to get the real path
67+
if realPath, err := filepath.EvalSymlinks(ghPath); err == nil {
68+
ghPath = realPath
69+
log.Printf("Resolved to: %s", ghPath)
7170
}
72-
case "darwin":
73-
trustedPaths = []string{
74-
"/opt/homebrew/bin/gh", // Homebrew on Apple Silicon
75-
"/usr/local/bin/gh", // Homebrew on Intel / manual install
76-
"/usr/bin/gh", // System package managers
77-
}
78-
case "linux":
79-
trustedPaths = []string{
80-
"/usr/local/bin/gh", // Manual install
81-
"/usr/bin/gh", // System package managers
82-
"/home/linuxbrew/.linuxbrew/bin/gh", // Linuxbrew
83-
"/snap/bin/gh", // Snap package
84-
}
85-
default:
86-
// BSD and other Unix-like systems
87-
trustedPaths = []string{
88-
"/usr/local/bin/gh",
89-
"/usr/bin/gh",
71+
} else {
72+
// Fall back to checking common installation paths
73+
log.Print("gh not found in PATH, checking common locations...")
74+
var commonPaths []string
75+
switch runtime.GOOS {
76+
case "windows":
77+
commonPaths = []string{
78+
`C:\Program Files\GitHub CLI\gh.exe`,
79+
`C:\Program Files (x86)\GitHub CLI\gh.exe`,
80+
filepath.Join(os.Getenv("LOCALAPPDATA"), "Programs", "gh", "gh.exe"),
81+
filepath.Join(os.Getenv("LOCALAPPDATA"), "GitHub CLI", "gh.exe"),
82+
}
83+
case "darwin":
84+
commonPaths = []string{
85+
"/opt/homebrew/bin/gh", // Homebrew on Apple Silicon
86+
"/usr/local/bin/gh", // Homebrew on Intel / manual install
87+
"/usr/bin/gh", // System package managers
88+
"/opt/local/bin/gh", // MacPorts
89+
"/run/current-system/sw/bin/gh", // Nix
90+
"/nix/var/nix/profiles/default/bin/gh", // Nix fallback
91+
}
92+
case "linux":
93+
homeDir := os.Getenv("HOME")
94+
commonPaths = []string{
95+
"/usr/local/bin/gh", // Manual install
96+
"/usr/bin/gh", // System package managers (apt, dnf, etc)
97+
"/home/linuxbrew/.linuxbrew/bin/gh", // Linuxbrew
98+
"/snap/bin/gh", // Snap package
99+
"/run/current-system/sw/bin/gh", // NixOS
100+
"/var/lib/flatpak/exports/bin/gh", // Flatpak system
101+
"/usr/local/go/bin/gh", // Go install
102+
filepath.Join(homeDir, "go", "bin", "gh"), // Go install user
103+
"/opt/gh/bin/gh", // Custom installs
104+
}
105+
default:
106+
// BSD and other Unix-like systems
107+
commonPaths = []string{
108+
"/usr/local/bin/gh",
109+
"/usr/bin/gh",
110+
"/usr/pkg/bin/gh", // NetBSD pkgsrc
111+
"/opt/local/bin/gh", // OpenBSD ports
112+
}
90113
}
91-
}
92114

93-
var ghPath string
94-
for _, path := range trustedPaths {
95-
// Verify the file exists and is executable
96-
if info, err := os.Stat(path); err == nil {
97-
// Check if it's a regular file and executable
98-
const executableMask = 0o111
99-
if info.Mode().IsRegular() && info.Mode()&executableMask != 0 {
100-
// Verify it's actually the gh binary by running version command
101-
// Use timeout to prevent hanging
102-
versionCtx, cancel := context.WithTimeout(ctx, 2*time.Second)
103-
cmd := exec.CommandContext(versionCtx, path, "version")
104-
output, err := cmd.Output()
105-
cancel() // Call cancel immediately after command execution
106-
if err == nil && strings.Contains(string(output), "gh version") {
107-
log.Printf("Found and verified gh at: %s", path)
108-
ghPath = path
109-
break
110-
}
115+
for _, path := range commonPaths {
116+
if path == "" {
117+
continue // Skip empty paths from unset env vars
118+
}
119+
if _, err := os.Stat(path); err == nil {
120+
log.Printf("Found gh at common location: %s", path)
121+
ghPath = path
122+
break
111123
}
112124
}
113125
}
114126

115127
if ghPath == "" {
116-
return "", errors.New("gh cli not found in trusted locations and GITHUB_TOKEN not set")
128+
return "", errors.New("gh CLI not found in PATH or common locations, and GITHUB_TOKEN not set")
117129
}
118130

119131
log.Printf("Executing command: %s auth token", ghPath)

0 commit comments

Comments
 (0)