resolve: authenticate clones via gh CLI / token — never fall into git's interactive prompt #13

Closed
opened 2026-07-13 15:35:40 +00:00 by dan-claude-bot · 0 comments
dan-claude-bot commented 2026-07-13 15:35:40 +00:00 (Migrated from github.com)

Repro

$ cast diff heavy-duty/incubator --env prod --state .
Username for 'https://github.com': danmt
Password for 'https://danmt@github.com':
Command failed: git clone --depth 1 https://github.com/heavy-duty/incubator.git /tmp/infra-checkout-2r6XiC
remote: Invalid username or token. Password authentication is not supported for Git operations.
fatal: Authentication failed for 'https://github.com/heavy-duty/incubator.git/'

The operator was logged into gh at the time. cast still failed.

Root cause

resolveCheckout (src/resolve.ts) shells out to a bare clone and relies
entirely on the ambient git credential helper:

execFileSync("git", ["clone", "--depth", "1", `https://github.com/${orgRepo}.git`, dir], { stdio: "pipe" })

On a workstation with no helper configured, git falls through to its
interactive username/password prompt — which GitHub no longer accepts — and the
resulting error talks about the repository rather than about cast's missing
credentials. Being logged into gh does not help: gh auth login alone does
not wire git's credential helper (that is gh auth setup-git, a separate act
most people never run).

This is not routable around for prod: resolveCheckout refuses --path when
--env prod, by design ("prod always reads the default branch"), so the clone
is the only path and its auth is mandatory.

Proposal

Resolve credentials in this order, inside cast:

  1. gh as a per-invocation credential helper — no mutation of the user's
    global git config:
    git -c credential.helper='!gh auth git-credential' clone --depth 1 …
  2. GITHUB_TOKEN / GH_TOKEN from the environment, if set (the CI path).
  3. The ambient helper, as today.

And regardless of which path is taken, set GIT_TERMINAL_PROMPT=0 so cast
can never hang on or fall into an interactive prompt. When all three fail, exit
with an actionable error rather than git's:

cannot clone heavy-duty/incubator: no GitHub credentials.
run `gh auth login`, or `gh auth setup-git`, or set GITHUB_TOKEN.

Please do not embed the token in the clone URL or in http.extraheader
both leak it into ps output and, for the latter, into the clone's git config.

Acceptance

  • With gh logged in and no git credential helper configured,
    cast diff <private-slug> --env prod clones successfully.
  • With no credentials at all, cast fails fast with the actionable message and
    never prompts.
  • The token never appears in process arguments or on disk.
## Repro ``` $ cast diff heavy-duty/incubator --env prod --state . Username for 'https://github.com': danmt Password for 'https://danmt@github.com': Command failed: git clone --depth 1 https://github.com/heavy-duty/incubator.git /tmp/infra-checkout-2r6XiC remote: Invalid username or token. Password authentication is not supported for Git operations. fatal: Authentication failed for 'https://github.com/heavy-duty/incubator.git/' ``` The operator was logged into `gh` at the time. cast still failed. ## Root cause `resolveCheckout` (`src/resolve.ts`) shells out to a bare clone and relies entirely on the **ambient git credential helper**: ```ts execFileSync("git", ["clone", "--depth", "1", `https://github.com/${orgRepo}.git`, dir], { stdio: "pipe" }) ``` On a workstation with no helper configured, git falls through to its interactive username/password prompt — which GitHub no longer accepts — and the resulting error talks about *the repository* rather than about cast's missing credentials. Being logged into `gh` does not help: `gh auth login` alone does not wire git's credential helper (that is `gh auth setup-git`, a separate act most people never run). This is not routable around for prod: `resolveCheckout` refuses `--path` when `--env prod`, by design ("prod always reads the default branch"), so the clone is the only path and its auth is mandatory. ## Proposal Resolve credentials in this order, inside cast: 1. **`gh` as a per-invocation credential helper** — no mutation of the user's global git config: `git -c credential.helper='!gh auth git-credential' clone --depth 1 …` 2. **`GITHUB_TOKEN` / `GH_TOKEN`** from the environment, if set (the CI path). 3. The ambient helper, as today. And regardless of which path is taken, set **`GIT_TERMINAL_PROMPT=0`** so cast can never hang on or fall into an interactive prompt. When all three fail, exit with an actionable error rather than git's: ``` cannot clone heavy-duty/incubator: no GitHub credentials. run `gh auth login`, or `gh auth setup-git`, or set GITHUB_TOKEN. ``` Please do **not** embed the token in the clone URL or in `http.extraheader` — both leak it into `ps` output and, for the latter, into the clone's git config. ## Acceptance - With `gh` logged in and **no** git credential helper configured, `cast diff <private-slug> --env prod` clones successfully. - With no credentials at all, cast fails fast with the actionable message and never prompts. - The token never appears in process arguments or on disk.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: heavy-duty/cast#13
No description provided.