cast/test
claude-hdb 79834369b1 fix: authenticate clones via gh / token, never fall into git's prompt (#13)
resolveCheckout shelled out to a bare `git clone` and relied entirely on the
ambient credential helper. On a workstation with none 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 helper (that is `gh auth setup-git`,
a separate act most people never run).

Not routable around for prod: resolveCheckout refuses --path with --env prod,
so the clone is the only path and its auth is mandatory.

cast now resolves credentials itself, in order: `gh` borrowed as a
per-invocation credential helper (no mutation of the user's global git
config), then GITHUB_TOKEN / GH_TOKEN, then the ambient helper. The token is
never embedded in the clone URL or in http.extraheader — both leak it into
`ps`, and the latter persists it into the clone's git config. The helper
reads it from the environment at run time, so what lands in argv is the
literal text `$CAST_GIT_TOKEN`, never its value.

GIT_TERMINAL_PROMPT=0 on every path: whichever credential was used, git may
never fall through to a prompt it cannot satisfy — it can only hang, or hide
the real fault. When there were no credentials at all, cast now says so, and
names the fix.

Note that the empty `credential.helper=` reset clears URL-scoped helpers
(`credential.https://github.com.helper`, what `gh auth setup-git` writes) as
well as generic ones — verified against a live private clone, along with all
three acceptance criteria.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 16:30:04 +00:00
..
fixtures feat: assert the token's team before touching Coolify (fail-closed) 2026-07-12 20:55:04 +00:00
apply.test.ts feat: cast — the Coolify executor, extracted from the infra state repo 2026-07-11 12:25:44 +00:00
bindings.test.ts fix: diff refuses an absent target instead of reporting it as empty (#11, #6) 2026-07-13 14:52:38 +00:00
cli.test.ts feat: assert the token's team before touching Coolify (fail-closed) 2026-07-12 20:55:04 +00:00
coolify.test.ts feat: assert the token's team before touching Coolify (fail-closed) 2026-07-12 20:55:04 +00:00
diff.test.ts feat: cast — the Coolify executor, extracted from the infra state repo 2026-07-11 12:25:44 +00:00
envtemplate.test.ts feat: cast — the Coolify executor, extracted from the infra state repo 2026-07-11 12:25:44 +00:00
live-lookup.test.ts fix: diff refuses an absent target instead of reporting it as empty (#11, #6) 2026-07-13 14:52:38 +00:00
manifest.test.ts feat: assert the token's team before touching Coolify (fail-closed) 2026-07-12 20:55:04 +00:00
resolve.test.ts fix: authenticate clones via gh / token, never fall into git's prompt (#13) 2026-07-13 16:30:04 +00:00
secrets.test.ts feat: cast — the Coolify executor, extracted from the infra state repo 2026-07-11 12:25:44 +00:00
smoke.test.ts feat: cast — the Coolify executor, extracted from the infra state repo 2026-07-11 12:25:44 +00:00
team.test.ts feat: assert the token's team before touching Coolify (fail-closed) 2026-07-12 20:55:04 +00:00
wire.test.ts feat: cast — the Coolify executor, extracted from the infra state repo 2026-07-11 12:25:44 +00:00