Skip to content

feat(auth): attempt browser login flow in non-TTY#1100

Draft
betegon wants to merge 1 commit into
mainfrom
feat/auth-non-tty-browser
Draft

feat(auth): attempt browser login flow in non-TTY#1100
betegon wants to merge 1 commit into
mainfrom
feat/auth-non-tty-browser

Conversation

@betegon

@betegon betegon commented Jun 12, 2026

Copy link
Copy Markdown
Member

Summary

When an unauthenticated command needed auth, the OAuth device flow (the bit that opens the browser) was gated on a stdin TTY check. So in a non-TTY — piped output, redirected stdin, CI — we'd skip it entirely and fail immediately with exit 10. This makes the CLI try to launch the browser in those cases too.

Changes

Dropped the TTY gate from autoAuthMiddleware so the device flow runs regardless of TTY. The flow is already TTY-agnostic: openBrowser is best-effort and falls back to printing the verification URL + QR code, and the copy-c key listener stays gated on process.stdin.isTTY inside runInteractiveLogin.

The recovery logic moved into a small recoverWithAutoAuth helper (keeps the middleware under the cognitive-complexity limit). On failure it branches on interactivity: an interactive terminal exits 1 (the flow already reported why), while a non-TTY re-throws the original AuthError so its standard message and exit code surface — exit 10 for not_authenticated, 11 for expired — matching the prior non-TTY behavior.

Heads up on the tradeoff: against live Sentry, an unauthenticated command in CI will now open a device-flow URL and poll until the timeout (~10 min) before failing, instead of failing instantly. That's intentional. If it ever becomes a problem, the natural follow-up is a --no-auto-auth / env opt-out.

auth status and the rc-import / scope-recovery prompts are unaffected — they opt out via skipAutoAuth or stay TTY-gated since they need interactive prompts.

Test Plan

  • New e2e test in test/e2e/auth.test.ts: a non-TTY unauth api organizations/ run now prints "Starting login flow…" yet still exits 10 with the not-authenticated message (the device-code request fails fast against the mock's 404).
  • All existing unauth e2e assertions (81 tests across trace/issue/project/api/log/event/bundle/auth) still pass — no hangs, since requestDeviceCode uses getSentryUrl() (= mock) and the mock 404s unknown routes.
  • biome check and tsc --noEmit clean.

@github-actions

github-actions Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor
PR Preview Action v1.8.1

QR code for preview link

🚀 View preview at
https://cli.sentry.dev/_preview/pr-1100/

Built to branch gh-pages at 2026-06-12 19:32 UTC.
Preview will be ready when the GitHub Pages deployment is complete.

@github-actions

github-actions Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Codecov Results 📊

❌ Patch coverage is 0.00%. Project has 5015 uncovered lines.
❌ Project coverage is 81.19%. Comparing base (base) to head (head).

Files with missing lines (1)
File Patch % Lines
src/cli.ts 0.00% ⚠️ 12 Missing
Coverage diff
@@            Coverage Diff             @@
##          main       #PR       +/-##
==========================================
- Coverage    81.20%    81.19%    -0.01%
==========================================
  Files          383       383         —
  Lines        26651     26656        +5
  Branches     17354     17355        +1
==========================================
+ Hits         21639     21641        +2
- Misses        5012      5015        +3
- Partials      1799      1798        -1

Generated by Codecov Action

The OAuth device flow (which opens the browser) was gated on a stdin
TTY check, so an unauthenticated command run in a non-TTY (piped
output, redirected stdin, CI) failed immediately instead of trying to
authenticate.

Attempt the device flow regardless of TTY. It's already TTY-agnostic:
openBrowser is best-effort and falls back to printing the verification
URL + QR code, and the copy-key listener stays gated on
process.stdin.isTTY. If login doesn't complete (e.g. nobody
authorizes), a non-TTY re-throws the original auth error so the
standard "Not authenticated" message and exit code still surface.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@betegon betegon force-pushed the feat/auth-non-tty-browser branch from 9bee57b to cb2c8cc Compare June 12, 2026 19:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant