Repository navigation
fix(git): stop the feature-branch fetch from blocking on a credential prompt - #5213
Open
xizhilanre wants to merge 3 commits into
Open
xizhilanre wants to merge 3 commits into
xizhilanre wants to merge 3 commits into
Conversation
… prompt (github#5199) check_existing_branches runs `git fetch --all --prune` for non-dry-run invocations without `GIT_TERMINAL_PROMPT=0`. When a remote is HTTPS and has no usable credential helper, git prompts on the tty, and because `speckit.git.feature` runs as the mandatory `before_specify` hook, `/speckit.specify` blocks instead of continuing. The dry-run path already passes the guard to `git ls-remote`; the real fetch path did not, in any of the three twins. Apply the same guard to bash, PowerShell and Python so the fetch fails fast and the script continues. Refs github#5199 Assisted-by: DeepSeek Harness (model: deepseek-v4.1-flash, autonomous)
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
A critical release-delivery issue remains because the bundled script changes are not accompanied by the required extension manifest and catalog version bump, so existing installations will not receive the fix.
1 open issue
What changed in this PR
This pull request prevents Git feature-branch fetches from blocking on HTTPS credential prompts by disabling terminal prompting across Bash, PowerShell, and Python implementations. It also adds regression tests for the guard.
Changes:
- Sets
GIT_TERMINAL_PROMPT=0for non-dry-run fetches in all three script variants. - Adds coverage verifying the environment variable during fetch operations.
- Requires a synchronized extension version bump in
extension.ymlandextensions/catalog.json. - Requires the PowerShell test to fall back to Windows PowerShell 5.1 when
pwshis unavailable.
This pull request requires changes.
| File | Description |
|---|---|
tests/test_git_fetch_prompt_guard.py |
Adds regression tests for Python, Bash, and PowerShell, but currently skips the PowerShell path on supported Windows hosts that only provide Windows PowerShell 5.1. |
extensions/git/scripts/python/create_new_feature_branch.py |
Passes GIT_TERMINAL_PROMPT=0 to the fetch subprocess. |
extensions/git/scripts/powershell/create-new-feature-branch.ps1 |
Temporarily disables terminal prompts around the PowerShell fetch. |
extensions/git/scripts/bash/create-new-feature-branch.sh |
Disables terminal prompts for the Bash fetch; the bundled extension version metadata must also be bumped for this content change to be released. |
Review effort: Lite (auto)
| # The dry-run path already sets this for `git ls-remote`. Without it, | ||
| # an HTTPS remote with no usable credential helper makes git prompt on | ||
| # the tty, and /speckit.specify hangs instead of continuing. | ||
| GIT_TERMINAL_PROMPT=0 git fetch --all --prune >/dev/null 2>&1 || true |
…rd (github#5199) The version-bump gate rejects content changes under `extensions/git/` without a manifest bump, because installed copies only receive updates when `extension.version` increases. Bump `extension.yml` and the matching `catalog.json` entry from 1.0.1 to 1.0.2, and drop the stray blank line at the end of the new regression test (`git diff --check`). Assisted-by: DeepSeek Harness (model: deepseek-v4.1-flash, autonomous)
The extension scripts resolve their project root from their own location, so the bash and PowerShell cases ran the checkout's copy and created feature branches in this repository while testing. Install the scripts into the temp project's `.specify/scripts` and run those copies instead, so the branch is created there. Verified: `git branch --list` is unchanged across the run (2 before, 2 after), 2 passed / 1 skipped on Windows (no native bash; the bash case runs on Linux CI). Assisted-by: DeepSeek Harness (model: deepseek-v4.1-flash, autonomous)
| id: git | ||
| name: "Git Branching Workflow" | ||
| version: "1.0.1" | ||
| version: "1.0.2" |
Collaborator
|
Please address Copilot feedback, resolve conflicts and address test & lint errors |
This branch has not been deployed
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.

Problem
speckit.git.featureruns as the mandatorybefore_specifyhook, and its feature-branch scripts rungit fetch --all --prunefor non-dry-run invocations. When a remote is HTTPS and has no usable credential helper, git writesUsername for 'https://…':to the tty — the output redirect does not hide it — and waits for input./speckit.specifythen appears to hang.The dry-run path already guards
git ls-remotewithGIT_TERMINAL_PROMPT=0; the real fetch path did not, in any of the three twins.Root cause
Each implementation called the fetch without the guard:
extensions/git/scripts/bash/create-new-feature-branch.shgit fetch --all --prune >/dev/null 2>&1 || trueextensions/git/scripts/powershell/create-new-feature-branch.ps1git fetch --all --prune 2>$null | Out-Nullextensions/git/scripts/python/create_new_feature_branch.pysubprocess.run(["git", "fetch", "--all", "--prune"], …)with noenvChange
Apply the same
GIT_TERMINAL_PROMPT=0guard the dry-run path uses, in all three twins, so the fetch fails fast and|| true/catch/ nothing-to-check continues:GIT_TERMINAL_PROMPT=0 git fetch --all --prune >/dev/null 2>&1 || true$env:GIT_TERMINAL_PROMPT = '0'around the fetch, restore to$nullafterwards (the same idiom already used forgit ls-remotein the same file)env={**os.environ, "GIT_TERMINAL_PROMPT": "0"}Verification
New
tests/test_git_fetch_prompt_guard.py(3 tests, one per implementation). Each registers agitshim that recordsGIT_TERMINAL_PROMPTwhenfetchis invoked and passes every other call through to the real git, then drives the real script and asserts the recorded value is0.The Python and PowerShell tests fail without the change with
AssertionError: assert '' == '0'— the guard was absent, which is the regression this pins. The bash test is skipped on this Windows host (only the WSLbashlauncher is installed, whichtests/conftest.requires_bashrejects); it runs on the Linux CI.Related suites, same command, before vs after (the 25 remaining failures/errors are pre-existing on this host — no native bash, no PS 5.1 harness setup — and are identical on the unmodified
maintree):The two-test delta is exactly the new regression tests flipping from fail to pass.
Windows PowerShell 5.1 evidence
The PowerShell twin was exercised under Windows PowerShell
5.1.22621.4391(dot-sourced with agitfunction shim, in an ASCII-path temp checkout):Only PS 5.1 constructs are used (
try/catch,$env:assignment).Lint
passes for the changed test file; the extension scripts are outside that CI gate.
AI disclosure
Implemented with DeepSeek Harness (agent) using model deepseek-v4.1-flash, running autonomously. Extent: code generation for the three guard lines and the regression tests, plus running the test evidence above. The submitting account holder reviewed the diff and is the one responding to review.
Closes #5199