Keep background remote refreshes from prompting for credentials - #2738
Open
noih wants to merge 1 commit into
Open
Keep background remote refreshes from prompting for credentials#2738noih wants to merge 1 commit into
noih wants to merge 1 commit into
Conversation
Opening the new-thread composer starts a throttled background `git fetch --all --prune` through `host.inspect_git_source`. For a passphrase-protected key that is not loaded in an agent, that fetch cannot succeed and its result is already discarded, but how it failed depended on how the daemon was launched: silently from the desktop app, blocking on the terminal's `/dev/tty` until the 5s timeout when run from a shell, or with a GUI passphrase dialog on every composer visit when `SSH_ASKPASS` is set. None of those had a user action behind them. Background refreshes now run non-interactively: `GIT_TERMINAL_PROMPT=0` and the resolved ssh command (`GIT_SSH_COMMAND`, `core.sshCommand`, or `ssh`) with `-o BatchMode=yes` appended. Blocking refreshes, which only happen when the user opens the branch picker or passes `bb project branches --refresh`, stay interactive. When a background refresh fails non-interactively, the next blocking refresh bypasses the 30-second throttle so the picker can still fetch with a prompt instead of serving stale refs.
3 tasks
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.
Human comments
What was wrong
Opening the new-thread composer mounts
useProjectSourceBranches, which requestsGET /projects/:id/branches?refresh=background. The server turns that intohost.inspect_git_source { remoteRefresh: "background" }, and the daemon starts the throttledgit fetch --all --prunefrom #2616.That fetch inherits whatever interactive git and ssh behaviour the daemon process happens to have. For a passphrase-protected key that is not loaded in an agent (or an https remote whose credential helper prompts), the background refresh cannot succeed, and upstream already treats it as best effort: the result is discarded and errors are swallowed. What varies is how it fails, and that depends on how the daemon was launched:
SSH_ASKPASS(no controlling tty; stdin isignore)/dev/tty, fails silentlybbin the foreground)/dev/tty, git blocks until the 5s refresh timeout kills itSSH_ASKPASSin the daemon's environment (Linux desktops with an askpass helper, or a user-configured system-wide one)ssh-agent/ macOS Keychain (UseKeychain,AddKeysToAgent)The third row is the reported case. The same principle #1608 applied to the browser's local-network prompt applies here: a background request must never surface a prompt; prompts belong to explicit user actions. A refresh that can pop a dialog is not a background refresh.
What changed
fetchRemoteBranchestakes an explicitinteractiveflag. Non-interactive fetches run withGIT_TERMINAL_PROMPT=0and the resolved ssh command (GIT_SSH_COMMAND, thencore.sshCommand, thenssh) with-o BatchMode=yesappended, so user-configured keys, ports, and wrappers keep working.refreshRemoteBranchesrunsremoteRefresh: "background"non-interactively andremoteRefresh: "blocking"(branch picker open,bb project branches --refresh) interactively.host.inspect_git_source/host.list_branch_optionscontracts are untouched, soHOST_DAEMON_PROTOCOL_VERSIONstays at 174. No CLI, guide, or app changes.Users whose keys are loaded in an agent or Keychain see no behaviour change: the background fetch still succeeds silently, and the picker still opens against fresh refs.
Known limit
BatchModeonly silences the ssh client. An agent that prompts on its own (a locked gnome-keyring key,ssh-add -cconfirmation) still prompts, before and after this change. Silencing that would mean not contacting the agent at all, which would also break the common agent-backed case, so it is left as is.Possible follow-up
The background attempt's failure is currently invisible. If that matters, the picker could show that remote refs may be stale until the user refreshes. Not included here to keep the change a behaviour fix.
How you verified
New tests use a recording
core.sshCommandscript against anssh://remote, so the assertions see exactly what git passes to ssh rather than a mock:packages/host-workspace/test/git.test.ts: a non-interactive fetch passes-o BatchMode=yesandGIT_TERMINAL_PROMPT=0; an interactive fetch passes neither. The first case fails onmain(expected '-G\n-o\nSendEnv=GIT_PROTOCOL\n…' to contain '-o\nBatchMode=yes\n').apps/host-daemon/test/command/host-branches-dispatch.test.ts:remoteRefresh: "background"runs ssh withBatchMode=yes;remoteRefresh: "blocking"runs it without; a blocking refresh right after a failed background refresh performs a second, interactive fetch instead of being throttled.pnpm exec turbo run test --filter=@bb/host-workspace --filter=@bb/host-daemon --force— host-workspace 230 passed, host-daemon passed. One pre-existing macOS failure (provisioning.test.ts› "runs teardown scripts before it removes managed worktrees",/private/tmpvs/tmppath comparison) fails identically onmain.pnpm exec turbo run typecheck lint --filter=@bb/host-workspace --filter=@bb/host-daemon— passed.Fixes #2737