Skip to content

Commit 7da602c

Browse files
sean-robertsSean Roberts
andauthored
fix: have login attempt to use browser and fallback to ticket instead of forcing tickets (#8167)
Try browser-based auth first in non-interactive environments before falling back to the agent copy/paste flow. Previously, non-interactive sessions (CI, piped input, etc.) skipped the browser entirely and went straight to the ticket/URL output. Now we attempt to open the browser and only fall back to the agent-friendly flow if it fails. This should help agents that allow a graceful timeout situation to have a good experience <!-- Explain the **motivation** for making this change. What existing problem does the pull request solve and how? --> --- For us to review and ship your PR efficiently, please perform the following steps: - [ ] Open a [bug/issue](https://github.com/netlify/cli/issues/new/choose) before writing your code 🧑‍💻. This ensures we can discuss the changes and get feedback from everyone that should be involved. If you\`re fixing a typo or something that\`s on fire 🔥 (e.g. incident related), you can skip this step. - [ ] Read the [contribution guidelines](../CONTRIBUTING.md) 📖. This ensures your code follows our style guide and passes our tests. - [ ] Update or add tests (if any source code was changed or added) 🧪 - [ ] Update or add documentation (if features were changed or added) 📝 - [ ] Make sure the status checks below are successful ✅ **A picture of a cute animal (not mandatory, but encouraged)** --------- Co-authored-by: Sean Roberts <sean.roberts@netlify.com>
1 parent 8976f0b commit 7da602c

File tree

3 files changed

+26
-11
lines changed

3 files changed

+26
-11
lines changed

src/commands/base-command.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import {
2323
USER_AGENT,
2424
chalk,
2525
logAndThrowError,
26+
logJson,
2627
exit,
2728
getToken,
2829
log,
@@ -516,7 +517,26 @@ export default class BaseCommand extends Command {
516517
const authLink = `${webUI}/authorize?response_type=ticket&ticket=${ticket.id}`
517518

518519
log(`Opening ${authLink}`)
519-
await openBrowser({ url: authLink })
520+
const browserOpened = await openBrowser({ url: authLink })
521+
522+
if (!browserOpened && !isInteractive() && ticket.id) {
523+
const ticketId = ticket.id
524+
logJson({
525+
ticket_id: ticketId,
526+
url: authLink,
527+
check_command: `netlify login --check ${ticketId}`,
528+
agent_next_steps:
529+
'Give the URL to the user so they can authorize. Then poll the check_command for up to ten minutes to see if the user has logged in, or wait for them to tell you and then use check_command after.',
530+
})
531+
log(`Ticket ID: ${ticketId}`)
532+
log(`Authorize URL: ${authLink}`)
533+
log()
534+
log(`After authorizing, run: netlify login --check ${ticketId}`)
535+
log()
536+
log('After user opens the authorization URL and approves, the login will be complete.')
537+
return exit()
538+
}
539+
520540
log()
521541
log(`To request authorization from a human, run: ${chalk.cyanBright('netlify login --request "<msg>"')}`)
522542
log()

src/commands/login/login.ts

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { OptionValues } from 'commander'
22

33
import { chalk, exit, getToken, log, logAndThrowError } from '../../utils/command-helpers.js'
4-
import { isInteractive } from '../../utils/scripted-commands.js'
54
import { TokenLocation } from '../../utils/types.js'
65
import BaseCommand from '../base-command.js'
76

@@ -51,11 +50,5 @@ export const login = async (options: OptionValues, command: BaseCommand) => {
5150
return exit()
5251
}
5352

54-
if (!isInteractive()) {
55-
const { loginRequest } = await import('./login-request.js')
56-
await loginRequest('CLI session', command.netlify.apiOpts)
57-
return
58-
}
59-
6053
await command.expensivelyAuthenticate()
6154
}

src/utils/open-browser.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,24 +23,26 @@ type OpenBrowsrProps = {
2323
url: string
2424
}
2525

26-
const openBrowser = async function ({ silentBrowserNoneError, url }: OpenBrowsrProps) {
26+
const openBrowser = async function ({ silentBrowserNoneError, url }: OpenBrowsrProps): Promise<boolean> {
2727
if (isDockerContainer()) {
2828
unableToOpenBrowserMessage({ url, message: 'Running inside a docker container' })
29-
return
29+
return false
3030
}
3131
if (process.env.BROWSER === 'none') {
3232
if (!silentBrowserNoneError) {
3333
unableToOpenBrowserMessage({ url, message: "BROWSER environment variable is set to 'none'" })
3434
}
35-
return
35+
return false
3636
}
3737

3838
try {
3939
await open(url)
40+
return true
4041
} catch (error) {
4142
if (error instanceof Error) {
4243
unableToOpenBrowserMessage({ url, message: error.message })
4344
}
45+
return false
4446
}
4547
}
4648

0 commit comments

Comments
 (0)