From 700921b37e21933f70cbb591f3b2f7a69fe3c929 Mon Sep 17 00:00:00 2001 From: Dustin Hilgaertner Date: Fri, 24 Apr 2026 19:20:04 -0500 Subject: [PATCH] Run glab from HOME to avoid GITLAB_HOST repo-mismatch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit glab refuses to start when invoked from a git repo whose remote doesn't correspond to GITLAB_HOST ("None of the git remotes configured for this repository correspond to the GITLAB_HOST environment variable"). The Crow app's inherited CWD is typically a GitHub repo, so every glab call aborted and the entire GitLab fetch failed — assigned GitLab issues never rendered. Add an optional `cwd:` parameter to the shell helpers in IssueTracker and ProviderManager, and pass NSHomeDirectory() at the four glab call sites (issue list, api reconcile, mr view, issue view). HOME is not a git repo, so glab's auto-detection finds no conflicting remotes. Closes #195 Co-Authored-By: Claude Opus 4.7 (1M context) --- .../Sources/CrowProvider/ProviderManager.swift | 7 ++++--- Sources/Crow/App/IssueTracker.swift | 11 +++++++---- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/Packages/CrowProvider/Sources/CrowProvider/ProviderManager.swift b/Packages/CrowProvider/Sources/CrowProvider/ProviderManager.swift index bba374b..17c8970 100644 --- a/Packages/CrowProvider/Sources/CrowProvider/ProviderManager.swift +++ b/Packages/CrowProvider/Sources/CrowProvider/ProviderManager.swift @@ -91,9 +91,9 @@ public actor ProviderManager { } let repoSlug = "\(parsed.org)/\(parsed.repo)" if parsed.isMR { - output = try await shell(env: env, "glab", "mr", "view", "\(parsed.number)", "--repo", repoSlug) + output = try await shell(env: env, cwd: NSHomeDirectory(), "glab", "mr", "view", "\(parsed.number)", "--repo", repoSlug) } else { - output = try await shell(env: env, "glab", "issue", "view", "\(parsed.number)", "--repo", repoSlug) + output = try await shell(env: env, cwd: NSHomeDirectory(), "glab", "issue", "view", "\(parsed.number)", "--repo", repoSlug) } } @@ -122,7 +122,7 @@ public actor ProviderManager { return output.components(separatedBy: .newlines).first } - private func shell(env: [String: String] = [:], _ args: String...) async throws -> String { + private func shell(env: [String: String] = [:], cwd: String? = nil, _ args: String...) async throws -> String { let process = Process() let pipe = Pipe() process.executableURL = URL(fileURLWithPath: "/usr/bin/env") @@ -130,6 +130,7 @@ public actor ProviderManager { process.environment = env.isEmpty ? ShellEnvironment.shared.env : ShellEnvironment.shared.merging(env) + if let cwd { process.currentDirectoryURL = URL(fileURLWithPath: cwd) } process.standardOutput = pipe process.standardError = pipe try process.run() diff --git a/Sources/Crow/App/IssueTracker.swift b/Sources/Crow/App/IssueTracker.swift index 4d459c0..305f2b8 100644 --- a/Sources/Crow/App/IssueTracker.swift +++ b/Sources/Crow/App/IssueTracker.swift @@ -1144,7 +1144,7 @@ final class IssueTracker { let output: String do { - output = try await shell(env: ["GITLAB_HOST": host], "glab", "api", endpoint) + output = try await shell(env: ["GITLAB_HOST": host], cwd: NSHomeDirectory(), "glab", "api", endpoint) } catch { print("[IssueTracker] Reconcile glab api failed for \(candidate.repoSlug)#\(candidate.branch) on \(host): \(error.localizedDescription.prefix(200))") continue @@ -1553,6 +1553,7 @@ final class IssueTracker { do { output = try await shell( env: ["GITLAB_HOST": host], + cwd: NSHomeDirectory(), "glab", "issue", "list", "-a", "@me", "--output-format", "json" ) } catch { @@ -1736,14 +1737,15 @@ final class IssueTracker { // MARK: - Shell - private func shell(env: [String: String] = [:], _ args: String...) async throws -> String { - return try await shell(env: env, args: args) + private func shell(env: [String: String] = [:], cwd: String? = nil, _ args: String...) async throws -> String { + return try await shell(env: env, cwd: cwd, args: args) } - private func shell(env: [String: String] = [:], args: [String]) async throws -> String { + private func shell(env: [String: String] = [:], cwd: String? = nil, args: [String]) async throws -> String { currentRefreshGhCalls += 1 let args = args let env = env + let cwd = cwd return try await Task.detached { let process = Process() let outPipe = Pipe() @@ -1753,6 +1755,7 @@ final class IssueTracker { process.environment = env.isEmpty ? ShellEnvironment.shared.env : ShellEnvironment.shared.merging(env) + if let cwd { process.currentDirectoryURL = URL(fileURLWithPath: cwd) } process.standardOutput = outPipe process.standardError = errPipe try process.run()