Skip to content

feat(cli): open the browser on auth login - #1827

Open
sileht wants to merge 1 commit into
mainfrom
devs/sileht/mrgfy-9262-cli-login-ux/open-browser-auth-login--90e2ca4c
Open

feat(cli): open the browser on auth login#1827
sileht wants to merge 1 commit into
mainfrom
devs/sileht/mrgfy-9262-cli-login-ux/open-browser-auth-login--90e2ca4c

Conversation

@sileht

@sileht sileht commented Sep 11, 2026

Copy link
Copy Markdown
Member

auth login printed a URL and left the user to click it. It now opens
the approval page itself, which is the last bit of ceremony between
running the command and approving the grant.

Opening is a convenience and never a step in the flow:

  • The URL is still printed, always. A CI runner, a container and an
    SSH session have no browser to open, and a spawned opener is not a
    window on screen either — the terminal is the only place the user
    can be sure to find the address again. The instructions say
    "Opening your browser […] If nothing opens, go to:" only when an
    opener actually started, so the line never claims something that did
    not happen.
  • --no-browser skips it.
  • Every failure is a debug! line. The login proceeds either way.

No crate for it: each platform is one spawn (open, xdg-open,
cmd /C start), which is not worth a dependency under deny.toml.
Three things that are not obvious in those twenty lines:

  • Nothing is spawned when the screen the opener would use is not the
    one the user is looking at. On Linux that is an unset DISPLAY and
    WAYLAND_DISPLAY, where xdg-open falls through to a terminal
    browser (www-browser, w3m, lynx) and takes over the very
    terminal the code is being read from; on macOS, which has no
    DISPLAY to consult, it is SSH_CONNECTION / SSH_TTY, where
    open reaches the screen of whoever is sitting at the machine and
    hands them a page carrying somebody else's user code. The SSH
    session is one of the reasons the device grant exists, so it gets
    the printed URL and nothing else.
  • On Windows, start is a cmd builtin, so the URL goes through a
    shell that re-parses it, where & separates commands and %NAME%
    is expanded — after any check we run, inside quotes as well as out,
    with no escape available on a command line. The URL is quoted, and
    one holding a " or a % is refused rather than opened: the quote
    because it would close the quoting, the % because the value
    spliced in is not held to the rule the check just applied, and
    because a substituted URL would open a different page than the one
    printed. The host that writes that URL is whatever --api-url
    names, the same threat device::checked_uri already guards.
  • The opener's child is reaped on a thread. login then sits in the
    poll loop for minutes, and a child nobody waits on is a zombie for
    all of it. That thread is asked for fallibly, because
    thread::spawn panics when the OS refuses one and a panic is the
    one way this convenience could still take the login down. A zombie
    until the process exits is the cheaper of the two.

The browser is a trait so the suite can watch the URL go past without
opening a window on whoever ran cargo test.

Refs MRGFY-9262

Co-Authored-By: Claude Opus 5 (1M context) noreply@anthropic.com

Copilot AI lite review requested due to automatic review settings September 11, 2026 15:30
@mergify
mergify Bot had a problem deploying to Mergify Merge Protections September 11, 2026 15:30 Failure
@mergify

mergify Bot commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

Merge Protections

🔴 2 of 6 protections blocking · waiting on 👀 reviews

Protection Waiting on
🔴 👀 Review Requirements 👀 reviews
🔴 🔎 Reviews 👀 reviews
🟢 🤖 Continuous Integration
🟢 Enforce conventional commit
🟢 📕 PR description
🟢 🚦 Auto-queue

🔴 👀 Review Requirements

Waiting for

  • #approved-reviews-by>=2
This rule is failing.
  • any of:
    • #approved-reviews-by>=2
    • author = dependabot[bot]
    • author = mergify-ci-bot
    • author = renovate[bot]

🔴 🔎 Reviews

Waiting for

  • #review-requested = 0
This rule is failing.
  • #review-requested = 0
  • #changes-requested-reviews-by = 0
  • #review-threads-unresolved = 0

Show 4 satisfied protections

🟢 🤖 Continuous Integration

  • all of:
    • check-success=ci-gate

🟢 Enforce conventional commit

Make sure that we follow https://www.conventionalcommits.org/en/v1.0.0/

  • title ~= ^(fix|feat|internal|docs|style|refactor|perf|test|build|ci|chore|revert|ui)(?:\(.+\))?!?:

🟢 📕 PR description

  • body ~= (?ms:.{48,})

🟢 🚦 Auto-queue

When all merge protections are satisfied, this pull request will be queued automatically.

@sileht

sileht commented Sep 11, 2026

Copy link
Copy Markdown
Member Author

Revision history

# Type Changes Reason Date
1 initial cd108df 2026-09-11 15:32 UTC
2 rebase cd108df → bf111ea (rebase only) 2026-09-11 15:32 UTC
3 content bf111ea → 65c58ec 2026-09-11 15:49 UTC
4 content 65c58ec → 15ef21b 2026-09-11 16:00 UTC

@sileht
sileht force-pushed the devs/sileht/mrgfy-9262-cli-login-ux/open-browser-auth-login--90e2ca4c branch from cd108df to bf111ea Compare September 11, 2026 15:32
@mergify
mergify Bot had a problem deploying to Mergify Merge Protections September 11, 2026 15:33 Failure
@sileht
sileht deployed to func-tests-live September 11, 2026 15:33 — with GitHub Actions Active

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Resolve the clippy failure and add parser/dispatch regression coverage.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Adds automatic browser opening to auth login while preserving printed URLs and headless support.

Changes:

  • Adds --no-browser and updates CLI wiring.
  • Implements platform-specific browser launching.
  • Updates login messaging, documentation, and CLI schema.
File summaries
File Summary
README.md Documents browser-opening behavior.
crates/mergify-cli/src/snapshots/mergify__tests__cli_schema_golden.snap Updates the CLI schema snapshot.
crates/mergify-cli/src/main.rs Adds and dispatches --no-browser; missing parser/dispatch regression coverage (moderate, 2 votes).
crates/mergify-auth/src/login.rs Opens and reports the verification URL.
crates/mergify-auth/src/lib.rs Exposes the browser module.
crates/mergify-auth/src/browser.rs Implements platform-specific launchers; unused JoinHandle causes the clippy lint gate to fail (critical, 1 vote).
Review details

Suppressed comments (2)

crates/mergify-auth/src/browser.rs:143

  • std::thread::spawn panics if the OS cannot create the reaper thread. That turns this browser convenience into a fatal login crash under thread/resource exhaustion, contradicting the documented non-fatal behavior and the no-panics command-path rule. Use a fallible thread::Builder::spawn and define a fallback that still handles the child if the reaper cannot be created.
    std::thread::spawn(move || {
        let mut child = child;
        let _ = child.wait();
    });

crates/mergify-auth/src/browser.rs:143

  • The reaper discards the result of wait, so an opener that launches successfully but exits non-zero (or cannot be waited on) produces no debug! line and open is reported as successful. Log non-success statuses and wait errors here so the promised best-effort failure path remains observable without failing login.
        let mut child = child;
        let _ = child.wait();
    });
  • Files reviewed: 6/6 changed files
  • Comments generated: 2
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread crates/mergify-auth/src/browser.rs Outdated
Comment thread crates/mergify-cli/src/main.rs
@mergify
mergify Bot requested a review from a team September 11, 2026 15:40
@sileht
sileht force-pushed the devs/sileht/mrgfy-9262-cli-login-ux/open-browser-auth-login--90e2ca4c branch from bf111ea to 65c58ec Compare September 11, 2026 15:49
@sileht

sileht commented Sep 11, 2026

Copy link
Copy Markdown
Member Author

This pull request is part of a Mergify stack:

# Pull Request Link
1 feat(cli): open the browser on auth login #1827 👈
2 feat(cli): name the machine on the approval page #1828

@sileht
sileht deployed to func-tests-live September 11, 2026 15:49 — with GitHub Actions Active
@mergify
mergify Bot had a problem deploying to Mergify Merge Protections September 11, 2026 15:50 Failure
`auth login` printed a URL and left the user to click it. It now opens
the approval page itself, which is the last bit of ceremony between
running the command and approving the grant.

Opening is a convenience and never a step in the flow:

- The URL is still printed, always. A CI runner, a container and an
  SSH session have no browser to open, and a spawned opener is not a
  window on screen either — the terminal is the only place the user
  can be sure to find the address again. The instructions say
  "Opening your browser […] If nothing opens, go to:" only when an
  opener actually started, so the line never claims something that did
  not happen.
- `--no-browser` skips it.
- Every failure is a `debug!` line. The login proceeds either way.

No crate for it: each platform is one spawn (`open`, `xdg-open`,
`cmd /C start`), which is not worth a dependency under `deny.toml`.
Three things that are not obvious in those twenty lines:

- Nothing is spawned when the screen the opener would use is not the
  one the user is looking at. On Linux that is an unset `DISPLAY` and
  `WAYLAND_DISPLAY`, where `xdg-open` falls through to a terminal
  browser (`www-browser`, `w3m`, `lynx`) and takes over the very
  terminal the code is being read from; on macOS, which has no
  `DISPLAY` to consult, it is `SSH_CONNECTION` / `SSH_TTY`, where
  `open` reaches the screen of whoever is sitting at the machine and
  hands them a page carrying somebody else's user code. The SSH
  session is one of the reasons the device grant exists, so it gets
  the printed URL and nothing else.
- On Windows, `start` is a `cmd` builtin, so the URL goes through a
  shell that re-parses it, where `&` separates commands and `%NAME%`
  is expanded — after any check we run, inside quotes as well as out,
  with no escape available on a command line. The URL is quoted, and
  one holding a `"` or a `%` is refused rather than opened: the quote
  because it would close the quoting, the `%` because the value
  spliced in is not held to the rule the check just applied, and
  because a substituted URL would open a different page than the one
  printed. The host that writes that URL is whatever `--api-url`
  names, the same threat `device::checked_uri` already guards.
- The opener's child is reaped on a thread. `login` then sits in the
  poll loop for minutes, and a child nobody waits on is a zombie for
  all of it. That thread is asked for fallibly, because
  `thread::spawn` panics when the OS refuses one and a panic is the
  one way this convenience could still take the login down. A zombie
  until the process exits is the cheaper of the two.

The browser is a trait so the suite can watch the URL go past without
opening a window on whoever ran `cargo test`.

Refs MRGFY-9262

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Change-Id: I90e2ca4c0ce90afa95b3700a3c0acd35c1b0a135
@sileht
sileht force-pushed the devs/sileht/mrgfy-9262-cli-login-ux/open-browser-auth-login--90e2ca4c branch from 65c58ec to 15ef21b Compare September 11, 2026 16:00
@sileht
sileht deployed to func-tests-live September 11, 2026 16:00 — with GitHub Actions Active
@mergify
mergify Bot had a problem deploying to Mergify Merge Protections September 11, 2026 16:00 Failure
@sileht
sileht marked this pull request as ready for review September 11, 2026 22:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants