Skip to content

stash impl and two stash init prompts hang on CI runners that allocate a TTY #727

Description

@tobyhede

Three commands can hang forever on a CI runner that allocates a TTY, because each reimplements the interactivity check inline instead of using config/tty.ts, and each gets a different subset wrong.

The shared helper is isInteractive() = Boolean(process.stdin.isTTY) && !isCiEnv(), where isCiEnv() matches /^(1|true)$/i against a trimmed CI.

Site Was Failure
commands/impl/index.ts process.stdin.isTTY && process.env.CI !== 'true' CI=1 / CI=TRUE pass → blocks on p.confirm or the agent-target picker
commands/init/index.ts process.stdout.isTTY no CI check → blocks on the "chain into stash plan?" confirm
commands/init/steps/resolve-proxy-choice.ts process.stdout.isTTY no CI check → blocks on the proxy-vs-SDK select

Two distinct bugs: impl had the right stream and the wrong CI test; both init sites had the wrong stream (stdout where prompts read stdin) and no CI test — strictly more exposed, since neither caught even CI=true.

It hangs rather than errors because clack's prompts open /dev/tty directly rather than reading process.stdin, so there is nothing to fail — the prompt waits until the job hits its wall-clock limit. That is also why it survived: invisible on a dev machine, invisible on GitHub Actions (CI=true), and on the CI systems where it fires it looks like a hung runner, not a CLI defect.

Fix

PR #704 routes all three through isInteractive(). Both init sites already had correct non-interactive branches in their else — only the gate selecting them was wrong. resolve-proxy-choice defaults to SDK-only under CI (unchanged behaviour: it is the prompt's own initialValue).

Regression tests cover CI=1, CI=TRUE, CI=true and CI-unset across all three sites, forcing both stdin and stdout as TTYs (a real CI runner has both — an earlier test version that stubbed only stdin passed against the broken code for an unrelated reason).

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions