fix: spinner consumes stdin causing double-Enter required in add-wizard#24523
fix: spinner consumes stdin causing double-Enter required in add-wizard#24523
Conversation
The SpinnerWrapper was creating a Bubble Tea program that started an input reader goroutine (via initInputReader) even though the spinner doesn't need keyboard input. In cooked mode this goroutine was consuming stdin events between interactive huh form prompts, leaving the terminal input in an inconsistent state. This caused the first Enter key press on each huh Select/Confirm field to be dropped, requiring users to press Enter twice to make selections in gh aw add-wizard. Fix: add tea.WithInput(nil) to the spinner's Bubble Tea program to disable stdin reading entirely. Ctrl+C is still handled via OS signal delivery (SIGINT) through bubbletea's signal handler, which operates independently of the input reader. Agent-Logs-Url: https://github.com/github/gh-aw/sessions/b2a6d3df-53fd-4885-b656-e014ef82bded Co-authored-by: dsyme <7204669+dsyme@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
|
Hey One thing missing before this can be marked If you'd like a hand, you can assign this prompt to your coding agent:
|
|
I tested this manually and it works OK now. It will hopefully explain some other glitches too when spinners were active |
There was a problem hiding this comment.
Pull request overview
Fixes an interactive UX bug where running spinners before gh aw add-wizard prompts caused the first Enter/key press to be dropped (requiring a second press), by preventing the spinner’s Bubble Tea program from reading stdin.
Changes:
- Disable stdin on the spinner Bubble Tea program via
tea.WithInput(nil)to avoid consuming key events meant for laterhuhprompts. - Add inline rationale explaining why stdin is disabled and how Ctrl+C remains handled.
Show a summary per file
| File | Description |
|---|---|
| pkg/console/spinner.go | Updates spinner program initialization to avoid stdin consumption during interactive flows. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 1/1 changed files
- Comments generated: 1
| // tea.WithInput(nil) disables stdin reading so the spinner does not consume key | ||
| // events that should be handled by subsequent interactive forms (e.g. huh.Select). | ||
| // Ctrl+C is still handled via OS signal delivery (SIGINT), which bubbletea | ||
| // processes independently of the input reader. | ||
| s.program = tea.NewProgram(model, tea.WithOutput(os.Stderr), tea.WithoutRenderer(), tea.WithInput(nil)) |
There was a problem hiding this comment.
This change fixes an interactive stdin issue but the enabled-spinner code path isn’t covered by the current spinner tests (they generally run with spinner disabled because stderr isn’t a TTY). Consider adding a regression test that simulates a TTY for stderr and verifies the spinner program does not consume bytes from os.Stdin while running (i.e., stdin remains readable for subsequent interactive prompts).
gh aw add-wizardrequired two Enter presses to confirm each interactive selection because theSpinnerWrapper's Bubble Tea program was reading from stdin between prompts.What was happening
SpinnerWrappercreates a Bubble Tea program withtea.WithoutRenderer()but without disabling input. Even with the renderer off, Bubble Tea still starts aninitInputReader()goroutine that attaches an epoll reader to stdin in cooked mode (sinceinitInput()/ raw mode is skipped). The add-wizard flow runs several spinners before each interactive form (auth, Actions enabled, permissions, secrets checks). Each spinner's input reader and handoff to the next program left stdin in an inconsistent state — the first key press received by the subsequenthuhform was silently dropped, requiring a second press.Fix
Disable stdin on the spinner program entirely with
tea.WithInput(nil):The spinner has no use for keyboard input. Ctrl+C remains functional via Bubble Tea's
handleSignals()goroutine (SIGINT), which is independent of the input reader.Warning
Firewall rules blocked me from connecting to one or more addresses (expand for details)
I tried to connect to the following addresses, but was blocked by firewall rules:
https://api.github.com/graphql/usr/bin/gh /usr/bin/gh api graphql -f query=query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } -f owner=github -f name=gh-aw 8930187/b100/vetrev-parse cfg git rev-�� --show-toplevel ache/go/1.25.8/x64/pkg/tool/linurev-parse /usr/bin/git prettier --write ache/go/1.25.8/x--show-toplevel git(http block)https://api.github.com/orgs/test-owner/actions/secrets/usr/bin/gh gh api /orgs/test-owner/actions/secrets --jq .secrets[].name go1.25.8 -c=4 -nolocalimports -importcfg /tmp/go-build603076144/b396/importcfg -pack /tmp/go-build603076144/b396/_testmain.go --no�� -issue git(http block)https://api.github.com/repos/actions/ai-inference/git/ref/tags/v1/usr/bin/gh gh api /repos/actions/ai-inference/git/ref/tags/v1 --jq .object.sha --show-toplevel x_amd64/vet /usr/bin/git --noprofile bash 64/pkg/tool/linu--show-toplevel git rev-�� --git-dir 64/pkg/tool/linu/tmp/file-tracker-test1924697553/test2.lock.yml /usr/bin/git te '**/*.cjs' '*git .cfg 64/pkg/tool/linu--show-toplevel /usr/bin/git(http block)https://api.github.com/repos/actions/checkout/git/ref/tags/v3/usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v3 --jq .object.sha --objects --stdin ache/node/24.14.1/x64/bin/node --exclude-hiddengit --all --quiet git t-12�� k/gh-aw/gh-aw/.github/workflows/agent-persona-explorer.md remote /opt/hostedtoolcache/node/24.14.1/x64/bin/node -issue git x_amd64/compile node(http block)https://api.github.com/repos/actions/checkout/git/ref/tags/v5/usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq .object.sha _.a 8930187/b191/vet.cfg cfg **/*.ts tants --ignore-path ache/go/1.25.8/xrepos/{owner}/{repo}/actions/runs/12346/artifacts(http block)/usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq .object.sha --paginate repos/{owner}/{repo}/actions/runs/3/artifacts /usr/bin/git .artifacts[].namgit .cfg 64/pkg/tool/linu--show-toplevel git rev-�� --show-toplevel 64/pkg/tool/linux_amd64/vet /usr/bin/git l.go l_test.go x_amd64/compile git(http block)/usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq .object.sha --show-toplevel 076144/b411/fileutil.test /usr/bin/git t0 /tmp/go-build393rev-parse 1/x64/bin/node git rev-�� /ref/tags/v8 /opt/hostedtoolcache/go/1.25.8/xREDACTED /usr/bin/gh ithub/workflows/git -buildtags 1/x64/bin/node gh(http block)https://api.github.com/repos/actions/checkout/git/ref/tags/v6/usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v6 --jq .object.sha run --auto /usr/bin/git --detach bash x_amd64/vet git conf�� user.name Test User 076144/b454/vet.cfg --noprofile bash 64/pkg/tool/linu--show-toplevel git(http block)/usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v6 --jq .object.sha test.txt x_amd64/vet /usr/bin/git 346 bash x_amd64/vet git rev-�� --show-toplevel UpQRbjo/bPQIwKXG^remote\..*\.gh-resolved$ /usr/bin/git(http block)/usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v6 --jq .object.sha -aw-actions/git/ref/tags/v1.0.0 ache/go/1.25.8/x64/pkg/tool/linux_amd64/vet /usr/bin/git /tmp/go-build393git -trimpath 1/x64/bin/node git rev-�� --show-toplevel ache/go/1.25.8/x64/pkg/tool/linux_amd64/vet /usr/bin/git vaScript21441814git -buildtags 076144/b357/vet.--show-toplevel git(http block)https://api.github.com/repos/actions/github-script/git/ref/tags/v8/usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v8 --jq .object.sha --noprofile git /usr/local/sbin/-importcfg uh.NewForm /generate-action-atomic nfig/composer/ve-bool bash --no�� --noprofile js/node_modules/-ifaceassert k/_temp/ghcca-no-nilfunc t_description_te/opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linux_amd64/vet _entry_test.go(http block)/usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v8 --jq .object.sha -issue git x_amd64/compile origin main 86_64/bash x_amd64/compile --no�� --noprofile bash x_amd64/vet(http block)/usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v8 --jq .object.sha ../pkg/workflow/-errorsas k/gh-aw/gh-aw/pk-ifaceassert /opt/hostedtoolc-nilfunc --objects --stdin p/bin/bash ls /hom�� /home/REDACTED/wor-p /home/REDACTED/worgithub.com/github/gh-aw/pkg/fileutil x_amd64/vet /home/REDACTED/worgh /home/REDACTED/worworkflow /home/REDACTED/worlist x_amd64/vet(http block)https://api.github.com/repos/actions/setup-go/git/ref/tags/v4/usr/bin/gh gh api /repos/actions/setup-go/git/ref/tags/v4 --jq .object.sha master IwtLslUObn8g /usr/bin/git Gitbranch_with_hgit Gitbranch_with_hrev-parse x_amd64/vet git rev-�� --show-toplevel x_amd64/vet /usr/bin/git --noprofile bash x_amd64/compile git(http block)https://api.github.com/repos/actions/setup-node/git/ref/tags/v4/usr/bin/gh gh api /repos/actions/setup-node/git/ref/tags/v4 --jq .object.sha -b epo}/actions/runs/12346/artifacts /usr/bin/git e head x_amd64/vet git rev-�� --git-dir x_amd64/vet(http block)https://api.github.com/repos/actions/upload-artifact/git/ref/tags/v4/usr/bin/gh gh api /repos/actions/upload-artifact/git/ref/tags/v4 --jq .object.sha runs/20260404-165429-14253/test-3178189586/.github/workflows -buildtags .git -errorsas -ifaceassert -nilfunc git push�� origin main 1/x64/bin/node json' --ignore-pgit git bash 1/x64/bin/node(http block)https://api.github.com/repos/github/gh-aw-actions/git/ref/tags/v0.1.2/usr/bin/gh gh api /repos/github/gh-aw-actions/git/ref/tags/v0.1.2 --jq .object.sha test.txt x_amd64/vet /usr/bin/git --noprofile bash x_amd64/asm git rev-�� --show-toplevel x_amd64/asm /usr/bin/git(http block)https://api.github.com/repos/github/gh-aw-actions/git/ref/tags/v1.0.0/usr/bin/gh gh api /repos/github/gh-aw-actions/git/ref/tags/v1.0.0 --jq .object.sha -bool -buildtags ache/node/24.14.1/x64/bin/node -errorsas -ifaceassert -nilfunc /opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linux_amd64/vet t-17�� sistency_GoAndJavaScript2144181472/001/test-inlined-imports-enabled-with-body-content.md -buildtags /usr/bin/git -errorsas -ifaceassert -nilfunc git(http block)https://api.github.com/repos/github/gh-aw-actions/git/ref/tags/v1.2.3/usr/bin/gh gh api /repos/github/gh-aw-actions/git/ref/tags/v1.2.3 --jq .object.sha ithub/workflows/archie.md -buildtags /tmp/go-build603076144/b414/gitutil.test -errorsas -ifaceassert -nilfunc /tmp/go-build603076144/b414/gitutil.test -tes�� -test.paniconexit0 -test.v=true /usr/bin/git -test.timeout=10git -test.run=^Test -test.short=true--show-toplevel git(http block)https://api.github.com/repos/github/gh-aw/actions/runs/1/artifacts/usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/1/artifacts --jq .artifacts[].name .cfg 64/pkg/tool/linux_amd64/vet usLost\|FocusMsggit pkg/mod/charm.larev-parse .go 64/pkg/tool/linux_amd64/vet --no�� til.go o 64/pkg/tool/linux_amd64/compile ./../.prettieriggit(http block)/usr/bin/gh gh run download 1 --dir test-logs/run-1 .cfg 64/pkg/tool/linux_amd64/vet --noprofile erignore 64/bin/bash 64/pkg/tool/linux_amd64/vet diff�� 7309325/b285/_pkg_.a go ache/go/1.25.8/x64/pkg/tool/linu-nilfunc ./../.prettieriggit b/gh-aw/pkg/parsrev-parse ndor/bin/bash ache/go/1.25.8/x64/pkg/tool/linu-tests(http block)https://api.github.com/repos/github/gh-aw/actions/runs/12345/artifacts/usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/12345/artifacts --jq .artifacts[].name .cfg 64/pkg/tool/linux_amd64/vet --noprofile r tnet/tools/bash 64/pkg/tool/linutest@example.com --no�� plorer.md sed x_amd64/compile 668,730p /home/REDACTED/go/remote bin/bash x_amd64/compile(http block)/usr/bin/gh gh run download 12345 --dir test-logs/run-12345 .cfg 64/pkg/tool/linux_amd64/vet --noprofile(http block)https://api.github.com/repos/github/gh-aw/actions/runs/12346/artifacts/usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/12346/artifacts --jq .artifacts[].name .cfg x_amd64/compile --noprofile r bash x_amd64/compile --no�� tants.go ne_constants.go 64/pkg/tool/linux_amd64/compile 27 --log-level ache/go/1.25.8/xuser.name 64/pkg/tool/linuTest User(http block)/usr/bin/gh gh run download 12346 --dir test-logs/run-12346 .cfg 64/pkg/tool/linux_amd64/vet --noprofile(http block)https://api.github.com/repos/github/gh-aw/actions/runs/2/artifacts/usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/2/artifacts --jq .artifacts[].name .cfg 64/pkg/tool/linux_amd64/vet --noprofile(http block)/usr/bin/gh gh run download 2 --dir test-logs/run-2 --others 64/pkg/tool/linux_amd64/vet --noprofile ed.go 86_64/bash 64/pkg/tool/linux_amd64/vet diff�� 354763491 cfg .cfg ./../.prettieriggit(http block)https://api.github.com/repos/github/gh-aw/actions/runs/3/artifacts/usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/3/artifacts --jq .artifacts[].name .cfg 64/pkg/tool/linux_amd64/vet --noprofile(http block)/usr/bin/gh gh run download 3 --dir test-logs/run-3 .cfg 64/pkg/tool/linux_amd64/vet --noprofile nd/huh/v2@v2.0.3rev-parse rgo/bin/bash 64/pkg/tool/linux_amd64/vet diff�� 7309325/b274/_pkg_.a HEAD ache/go/1.25.8/x64/pkg/tool/linu-buildmode=exe ./../.prettieriggit b/gh-aw/pkg/consrev-parse bin/bash ache/go/1.25.8/x64/pkg/tool/linu-trimpath(http block)https://api.github.com/repos/github/gh-aw/actions/runs/4/artifacts/usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/4/artifacts --jq .artifacts[].name .cfg 64/pkg/tool/linux_amd64/compile --noprofile(http block)/usr/bin/gh gh run download 4 --dir test-logs/run-4 --others 64/pkg/tool/linu-nolocalimports --noprofile ed.go nfig/composer/ve--show-toplevel 64/pkg/tool/linu/tmp/go-build603076144/b451/_testmain.go diff�� 7309325/b281/_pkg_.a HEAD 64/pkg/tool/linux_amd64/compile ./../.prettieriggit b/gh-aw/pkg/envurev-parse ache/go/1.25.8/x--show-toplevel 64/pkg/tool/linux_amd64/compile(http block)https://api.github.com/repos/github/gh-aw/actions/runs/5/artifacts/usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/5/artifacts --jq .artifacts[].name .cfg 64/pkg/tool/linux_amd64/vet --noprofile(http block)/usr/bin/gh gh run download 5 --dir test-logs/run-5 --others 64/pkg/tool/linux_amd64/vet ring\|filter pkg/mod/charm.larev-parse n-dir/bash 64/pkg/tool/linux_amd64/vet diff�� 354763491 HEAD .cfg ./../.prettieriggit(http block)https://api.github.com/repos/github/gh-aw/actions/workflows/usr/bin/gh gh workflow list --json name,state,path k/gh-aw/gh-aw/pkg/console/render_test.go k/gh-aw/gh-aw/pkg/console/list_wasm.go k/gh-aw/gh-aw/pkg/console/render_formatting_test.go k/gh-aw/gh-aw/pk/opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linux_amd64/vet k/gh-aw/gh-aw/pk-atomic k/gh-aw/gh-aw/pk-bool k/gh-aw/gh-aw/pk-buildtags k/gh�� -issue k/gh-aw/gh-aw/pk-ifaceassert ache/go/1.25.8/x-nilfunc origin /field_select.go-test.testlogfile=/tmp/go-build603076144/b402/testlog.txt sh ls(http block)/usr/bin/gh gh run list --json databaseId,number,url,status,conclusion,workflowName,createdAt,startedAt,updatedAt,event,headBranch,headSha,displayTitle --workflow nonexistent-workflow-12345 --limit 100(http block)/usr/bin/gh gh run list --json databaseId,number,url,status,conclusion,workflowName,createdAt,startedAt,updatedAt,event,headBranch,headSha,displayTitle --workflow nonexistent-workflow-12345 --limit 6(http block)https://api.github.com/repos/github/gh-aw/git/ref/tags/v0.47.4/usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v0.47.4 --jq .object.sha --show-toplevel bash /usr/bin/git 33627921/001 on x_amd64/compile git rev-�� --show-toplevel x_amd64/compile /usr/bin/git se 8930187/b040/vet-c ache/go/1.25.8/xgit-upload-pack 'origin' git(http block)https://api.github.com/repos/github/gh-aw/git/ref/tags/v1.0.0/usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v1.0.0 --jq .object.sha e-analyzer.md on 64/pkg/tool/linux_amd64/vet /../../.prettiergit erignore /eval.go 64/pkg/tool/linuTest User stlo�� y.md /field_multiselect.go ache/go/1.25.8/x64/pkg/tool/linux_amd64/vet /field_select.go/opt/hostedtoolcache/node/24.14.1/x64/bin/node chr/testify/requ/tmp/test-process-215554781.js /form.go ache/go/1.25.8/x64/pkg/tool/linurev-parse(http block)https://api.github.com/repos/github/gh-aw/git/ref/tags/v1.2.3/usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v1.2.3 --jq .object.sha --noprofile bash x_amd64/vet --noprofile(http block)https://api.github.com/repos/github/gh-aw/git/ref/tags/v2.0.0/usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v2.0.0 --jq .object.sha --noprofile bash x_amd64/vet --noprofile nd/huh/v2@v2.0.3rev-list(http block)/usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v2.0.0 --jq .object.sha --noprofile bash x_amd64/vet --noprofile(http block)/usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v2.0.0 --jq .object.sha /home/REDACTED/wor-test.timeout=10m0s /home/REDACTED/wor-test.run=^Test x_amd64/vet /home/REDACTED/wor/usr/bin/git /home/REDACTED/worremote /home/REDACTED/wor-v x_amd64/vet tion�� lGitmain_branch131227593/001' lGitmain_branch131227593/001' x_amd64/vet /home/REDACTED/worgit /home/REDACTED/wor-C /home/REDACTED/wor/tmp/compile-all-instructions-test-1529077875/.github/workflows x_amd64/vet(http block)https://api.github.com/repos/github/gh-aw/git/ref/tags/v3.0.0/usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v3.0.0 --jq .object.sha --noprofile bash x_amd64/vet --noprofile(http block)https://api.github.com/repos/nonexistent/action/git/ref/tags/v999.999.999/usr/bin/gh gh api /repos/nonexistent/action/git/ref/tags/v999.999.999 --jq .object.sha mpiledOutput4238723978/001 on 64/pkg/tool/linux_amd64/vet /../../.prettiergit erignore /home/REDACTED/go/--git-dir 64/pkg/tool/linux_amd64/vet(http block)https://api.github.com/repos/nonexistent/repo/actions/runs/12345/usr/bin/gh gh run view 12345 --repo nonexistent/repo --json status,conclusion --noprofile(http block)https://api.github.com/repos/owner/repo/actions/workflows/usr/bin/gh gh workflow list --json name,state,path --repo owner/repo -importcfg /tmp/go-build603076144/b410/importcfg -pack /home/REDACTED/work/gh-aw/gh-aw/pkg/fileutil/fileutil.go /home/REDACTED/work/gh-aw/gh-aw/pkg/fileutil/tar.go k/gh�� ../pkg/workflow/-errorsas k/gh-aw/gh-aw/pk-ifaceassert cal/bin/bash run --auto tnet/tools/bash ls(http block)/usr/bin/gh gh workflow list --json name,state,path --repo owner/repo sh k/gh-aw/gh-aw/pk/opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linux_amd64/vet k/gh-aw/gh-aw/pk-atomic k/gh-aw/gh-aw/pk-bool s not exist yet"-buildtags k/gh�� ../pkg/workflow/-errorsas k/gh-aw/gh-aw/pk-ifaceassert rgo/bin/bash |GroupIndex\|grogit pkg/mod/charm.larev-parse n-dir/bash ls(http block)https://api.github.com/repos/owner/repo/contents/file.md/tmp/go-build603076144/b396/cli.test /tmp/go-build603076144/b396/cli.test -test.testlogfile=/tmp/go-build603076144/b396/testlog.txt -test.paniconexit0 -test.v=true -test.parallel=4 -test.timeout=10m0s -test.run=^Test -test.short=true k/gh-aw/gh-aw/pk/opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linux_amd64/vet k/gh-aw/gh-aw/pk-unsafeptr=false k/gh-aw/gh-aw/pk-unreachable=false k/gh-aw/gh-aw/pk/tmp/go-build3938930187/b199/vet.cfg ode_�� k/gh-aw/gh-aw/pkg/console/render_test.go k/gh-aw/gh-aw/pkg/console/list_wasm.go k/gh-aw/gh-aw/pkg/console/render_formatting_test.go k/gh-aw/gh-aw/pk/opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linux_amd64/vet k/gh-aw/gh-aw/pk-atomic k/gh-aw/gh-aw/pk-bool k/gh-aw/gh-aw/pk-buildtags(http block)https://api.github.com/repos/test-owner/test-repo/actions/secrets/usr/bin/gh gh api /repos/test-owner/test-repo/actions/secrets --jq .secrets[].name on' --ignore-path ../../../.prettierignore git nfig/composer/vendor/bin/bash --local committer.email k/_temp/ghcca-no-bool cat /hom�� -issue git /usr/local/sbin/-nilfunc origin main de/node/bin/bash/tmp/go-build603076144/b405/constants.test bash(http block)If you need me to access, download, or install something from one of these locations, you can either: