Skip to content

Prompt for the host instead of failing when device code login has none - #7179

Merged
maksim-zuev-db merged 9 commits into
mainfrom
device-code-hide-create-profile
Oct 27, 2026
Merged

maksim-zuev-db merged 9 commits into
mainfrom
device-code-hide-create-profile

Conversation

@maksim-zuev-db

@maksim-zuev-db maksim-zuev-db commented Oct 26, 2026 •

Copy link
Copy Markdown
Member

Changes

databricks auth login --use-device-code now prompts for the workspace host when none is known, instead of failing. Device code login skips discovery, which opens a browser, and lets setHost prompt for the host instead. An empty answer still fails with --use-device-code requires a workspace host. This check only applies to device code login.

The picker also hides profiles that device code login always rejects: account-host profiles and profiles saved with resources. Unified-host profiles are still listed, because the profile doesn't store what identifies them. docs/device-code-login.md is updated.

Why

With no host known, device code login went into discovery and failed. That broke "Create a new profile" in the picker and auth login --use-device-code --profile <new-profile>. The picker also listed profiles that only failed after you picked them.

Tests

  • termtest tests check that the CLI prompts for the host, rejects an empty host (both after --profile and from the picker), and hides unsupported profiles. The picker empty-host test is skipped on Windows, because bubbletea can't cancel reads on piped stdin there.
  • TestMatchDeviceCodeProfiles and TestIsDeviceCodeSupportedForHost cover the filter and the host check.
  • The device-code/unsupported-host acceptance test now expects the non-interactive host error.

No changelog fragment: --use-device-code is still behind DATABRICKS_CLI_DEVICE_CODE.

This pull request and its description were written by Isaac.

@maksim-zuev-db
maksim-zuev-db marked this pull request as ready for review October 26, 2026 09:42
@maksim-zuev-db
maksim-zuev-db requested review from a team as code owners October 26, 2026 09:42
@maksim-zuev-db
maksim-zuev-db requested review from chrisst and simonfaltum and removed request for chrisst October 26, 2026 09:42
@eng-dev-ecosystem-bot

eng-dev-ecosystem-bot commented Oct 26, 2026 •

Copy link
Copy Markdown
Collaborator

Integration test report

Commit: 45f4673

Run: 40499272833

Env ✅​pass 🙈​skip Time
✅​ aws linux-2core-8gb 281 16 4:44
✅​ aws-windows-latest-4core-16gb 283 14 3:41
✅​ azure linux-2core-8gb 280 16 4:55
✅​ azure-windows-latest-4core-16gb 282 14 3:41
✅​ gcp linux-2core-8gb 281 16 5:26
✅​ gcp-windows-latest-4core-16gb 283 14 3:23
Top 6 slowest tests (at least 2 minutes):
duration env testname
3:54 gcp linux-2core-8gb TestAccept
3:36 azure-windows-latest-4core-16gb TestAccept
3:11 gcp-windows-latest-4core-16gb TestAccept
3:07 aws-windows-latest-4core-16gb TestAccept
2:52 azure linux-2core-8gb TestAccept
2:49 aws linux-2core-8gb TestAccept

@simonfaltum simonfaltum left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for picking this up! Left a few comments inline. The main ones:

  • The picker still lists profiles that device code login always rejects (L241).
  • The new test touches the real ~/.databricks/token-cache.json (L225).
  • I think skipping discovery for device code would fix this more generally and remove the need for the picker special case (L245).

The rest are small suggestions.

One more that can't go inline since the file isn't in this PR: step 1 in docs/device-code-login.md says the host comes from an argument, --host, or an existing profile. It doesn't mention the picker, so someone running databricks auth login --use-device-code with no arguments won't find out why "Create a new profile" is missing. Might be worth a line there.

Comment thread cmd/auth/login.go Resolved
Comment thread cmd/auth/login.go Resolved
Comment thread cmd/auth/login.go Resolved
Comment thread cmd/auth/login_device_code_test.go Resolved
Comment thread cmd/auth/login_device_code_test.go Resolved
Comment thread cmd/auth/login_device_code_test.go Resolved
Comment thread cmd/auth/login_device_code_test.go Resolved
Comment thread cmd/auth/profile_picker_test.go Resolved
Comment thread cmd/auth/profile_picker.go Resolved
Comment thread cmd/auth/switch.go Resolved
@maksim-zuev-db
maksim-zuev-db force-pushed the device-code-hide-create-profile branch from f142176 to 7d59c27 Compare October 26, 2026 11:58
Discovery login opens a browser on this machine and learns the workspace
host only after sign-in. Device code login is meant for machines without
a browser, but when no host was known it still went into the discovery
branch and failed with "--use-device-code requires a workspace host".
This broke "Create a new profile" in the login picker and "auth login
--use-device-code --profile <new-profile>".

Skip discovery for device code login so setHost resolves the host. It
prompts for it when interactive and asks for --host otherwise.

Co-authored-by: Isaac <no-reply@databricks.com>
@maksim-zuev-db
maksim-zuev-db force-pushed the device-code-hide-create-profile branch from 7d59c27 to 12f1366 Compare October 26, 2026 12:03
@maksim-zuev-db maksim-zuev-db changed the title Hide "Create a new profile" from the login picker with --use-device-code Prompt for the host instead of failing when device code login has none Oct 26, 2026
@github-actions

github-actions Bot commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Commit: 45f467380 | Workflow run

Regression test report

Selected 1 changed tests (limit=20, 0 not selected)

1 tests: regression=1 unreleased=0 coverage=0 failing=0

test branch main (accb3df) latest (v1.22.1)
TestAccept/cmd/auth/login/device-code/unsupported-host ✅ ❌ ❌
TestAccept/cmd/auth/login/device-code/unsupported-host: branch ✅ | main (accb3df) ❌ | latest (v1.22.1) ❌

main (accb3df):

acceptance_test.go:1311: Diff:
        --- cmd/auth/login/device-code/unsupported-host/output.txt
        +++ /tmp/TestAcceptcmdauthlogindevice-codeunsupported-host2550042976/002/output.txt
        @@ -2,7 +2,7 @@
         === No host
         
         >>> musterr [CLI] auth login --profile new-profile --use-device-code
        -Error: the command is being run in a non-interactive environment, please specify a host using --host
        +Error: --use-device-code requires a workspace host. Pass it as an argument or with --host
         
         === Account host
         
        
FAIL

latest (v1.22.1):

acceptance_test.go:1311: Diff:
        --- cmd/auth/login/device-code/unsupported-host/output.txt
        +++ /tmp/TestAcceptcmdauthlogindevice-codeunsupported-host2937810046/002/output.txt
        @@ -2,30 +2,170 @@
         === No host
         
         >>> musterr [CLI] auth login --profile new-profile --use-device-code
        -Error: the command is being run in a non-interactive environment, please specify a host using --host
        +Error: unknown flag: --use-device-code
         
        +Usage:
        +  databricks auth login [PROFILE] [flags]
        +
        +Flags:
        +      --client-id string       OAuth client ID to use for U2M authentication
        +      --configure-cluster      Prompts to configure cluster
        +      --configure-serverless   Prompts to configure serverless
        +  -h, --help                   help for login
        +      --resource stringArray   RFC 8707 resource indicator to scope the login to (repeatable). Requires --host.
        +      --scopes string          Comma-separated list of OAuth scopes to request (defaults to 'all-apis')
        +      --skip-workspace         Skip workspace selection for account-level access
        +      --timeout duration       Timeout for completing login challenge in the browser (default 1h0m0s)
        +
        +Global Flags:
        +      --account-id string     Databricks Account ID
        +      --debug                 enable debug logging
        +      --host string           Databricks Host
        +  -o, --output type           output type: text or json (default text)
        +  -p, --profile string        ~/.databrickscfg profile
        +  -t, --target string         bundle target to use (if applicable)
        +      --workspace-id string   Databricks Workspace ID
        +
        +
         === Account host
         
         >>> musterr [CLI] auth login --host https://accounts.cloud.databricks.test --profile test --use-device-code
        -Warn: [hostmetadata] failed to fetch host metadata for https://accounts.cloud.databricks.test, will skip for 1m0s
        -Error: --use-device-code is only supported for workspace hosts
        +Error: unknown flag: --use-device-code
         
        +Usage:
        +  databricks auth login [PROFILE] [flags]
        +
        +Flags:
        +      --client-id string       OAuth client ID to use for U2M authentication
        +      --configure-cluster      Prompts to configure cluster
        +      --configure-serverless   Prompts to configure serverless
        +  -h, --help                   help for login
        +      --resource stringArray   RFC 8707 resource indicator to scope the login to (repeatable). Requires --host.
        +      --scopes string          Comma-separated list of OAuth scopes to request (defaults to 'all-apis')
        +      --skip-workspace         Skip workspace selection for account-level access
        +      --timeout duration       Timeout for completing login challenge in the browser (default 1h0m0s)
        +
        +Global Flags:
        +      --account-id string     Databricks Account ID
        +      --debug                 enable debug logging
        +      --host string           Databricks Host
        +  -o, --output type           output type: text or json (default text)
        +  -p, --profile string        ~/.databrickscfg profile
        +  -t, --target string         bundle target to use (if applicable)
        +      --workspace-id string   Databricks Workspace ID
        +
        +
         >>> musterr [CLI] auth login --profile account --use-device-code
        -Error: --use-device-code is only supported for workspace hosts
        +Error: unknown flag: --use-device-code
         
        +Usage:
        +  databricks auth login [PROFILE] [flags]
        +
        +Flags:
        +      --client-id string       OAuth client ID to use for U2M authentication
        +      --configure-cluster      Prompts to configure cluster
        +      --configure-serverless   Prompts to configure serverless
        +  -h, --help                   help for login
        +      --resource stringArray   RFC 8707 resource indicator to scope the login to (repeatable). Requires --host.
        +      --scopes string          Comma-separated list of OAuth scopes to request (defaults to 'all-apis')
        +      --skip-workspace         Skip workspace selection for account-level access
        +      --timeout duration       Timeout for completing login challenge in the browser (default 1h0m0s)
        +
        +Global Flags:
        +      --account-id string     Databricks Account ID
        +      --debug                 enable debug logging
        +      --host string           Databricks Host
        +  -o, --output type           output type: text or json (default text)
        +  -p, --profile string        ~/.databrickscfg profile
        +  -t, --target string         bundle target to use (if applicable)
        +      --workspace-id string   Databricks Workspace ID
        +
        +
         === Unified host
         
         >>> DATABRICKS_DISCOVERY_URL=[DATABRICKS_URL]/oidc/accounts/spog-acct-123/.well-known/oauth-authorization-server musterr [CLI] auth login --host [DATABRICKS_URL] --use-device-code
        -Error: --use-device-code is only supported for workspace hosts
        +Error: unknown flag: --use-device-code
         
        +Usage:
        +  databricks auth login [PROFILE] [flags]
        +
        +Flags:
        +      --client-id string       OAuth client ID to use for U2M authentication
        +      --configure-cluster      Prompts to configure cluster
        +      --configure-serverless   Prompts to configure serverless
        +  -h, --help                   help for login
        +      --resource stringArray   RFC 8707 resource indicator to scope the login to (repeatable). Requires --host.
        +      --scopes string          Comma-separated list of OAuth scopes to request (defaults to 'all-apis')
        +      --skip-workspace         Skip workspace selection for account-level access
        +      --timeout duration       Timeout for completing login challenge in the browser (default 1h0m0s)
        +
        +Global Flags:
        +      --account-id string     Databricks Account ID
        +      --debug                 enable debug logging
        +      --host string           Databricks Host
        +  -o, --output type           output type: text or json (default text)
        +  -p, --profile string        ~/.databrickscfg profile
        +  -t, --target string         bundle target to use (if applicable)
        +      --workspace-id string   Databricks Workspace ID
        +
        +
         === Workspace without device code login
         
         >>> musterr [CLI] auth login --host [DATABRICKS_URL] --profile test --use-device-code
        -Error: device code login is not enabled for this workspace
        +Error: unknown flag: --use-device-code
         
        +Usage:
        +  databricks auth login [PROFILE] [flags]
        +
        +Flags:
        +      --client-id string       OAuth client ID to use for U2M authentication
        +      --configure-cluster      Prompts to configure cluster
        +      --configure-serverless   Prompts to configure serverless
        +  -h, --help                   help for login
        +      --resource stringArray   RFC 8707 resource indicator to scope the login to (repeatable). Requires --host.
        +      --scopes string          Comma-separated list of OAuth scopes to request (defaults to 'all-apis')
        +      --skip-workspace         Skip workspace selection for account-level access
        +      --timeout duration       Timeout for completing login challenge in the browser (default 1h0m0s)
        +
        +Global Flags:
        +      --account-id string     Databricks Account ID
        +      --debug                 enable debug logging
        +      --host string           Databricks Host
        +  -o, --output type           output type: text or json (default text)
        +  -p, --profile string        ~/.databrickscfg profile
        +  -t, --target string         bundle target to use (if applicable)
        +      --workspace-id string   Databricks Workspace ID
        +
        +
         >>> musterr [CLI] auth login --profile workspace --use-device-code
        -Error: device code login is not enabled for this workspace
        +Error: unknown flag: --use-device-code
         
        +Usage:
        +  databricks auth login [PROFILE] [flags]
        +
        +Flags:
        +      --client-id string       OAuth client ID to use for U2M authentication
        +      --configure-cluster      Prompts to configure cluster
        +      --configure-serverless   Prompts to configure serverless
        +  -h, --help                   help for login
        +      --resource stringArray   RFC 8707 resource indicator to scope the login to (repeatable). Requires --host.
        +      --scopes string          Comma-separated list of OAuth scopes to request (defaults to 'all-apis')
        +      --skip-workspace         Skip workspace selection for account-level access
        +      --timeout duration       Timeout for completing login challenge in the browser (default 1h0m0s)
        +
        +Global Flags:
        +      --account-id string     Databricks Account ID
        +      --debug                 enable debug logging
        +      --host string           Databricks Host
        +  -o, --output type           output type: text or json (default text)
        +  -p, --profile string        ~/.databrickscfg profile
        +  -t, --target string         bundle target to use (if applicable)
        +      --workspace-id string   Databricks Workspace ID
        +
        +
         === Device authorization requests
         
         >>> print_requests.py //oidc/v1/device/auth
        +File [OUTPUT_DIR]/out.requests.txt not found
        +
        +Exit code: 1
        
FAIL

maksim-zuev-db and others added 4 commits October 26, 2026 12:31
On Windows, bubbletea cannot cancel its read from the test's stdin pipe,
so after the profile picker quits its reader swallows the input typed for
the profile name prompt, and the test timed out waiting for the host
prompt. Passing --profile makes the host prompt the only prompt while
still covering the skipped discovery branch.

Co-authored-by: Isaac <no-reply@databricks.com>
With --use-device-code, the login picker leaves out profiles on a classic
account host and profiles saved with resources, which device code login
always rejects. Profiles on unified hosts are still listed, because the
discovery URL that identifies them is not saved on the profile.

isDeviceCodeSupportedForHost replaces validateDeviceCodeHost so the
picker and the check after setHost share the host check.

Co-authored-by: Isaac <no-reply@databricks.com>
Share the setup of the two termtest tests in startDeviceCodeLogin.

Co-authored-by: Isaac <no-reply@databricks.com>
Co-authored-by: Isaac <no-reply@databricks.com>

@simonfaltum simonfaltum left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks, the discovery change looks good and the earlier comments are all covered. One issue with an empty host answer below, plus an optional suggestion.

Comment thread cmd/auth/login.go Outdated
}
// an account ID for account and unified hosts. A workspace without
// device code login enabled is rejected later by DeviceCodeChallenge.
if useDeviceCode && !isDeviceCodeSupportedForHost(authArguments.Host, authArguments.DiscoveryURL) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

With discovery skipped, setHost now prompts for the host, but promptForHost accepts an empty answer. If the user presses Enter at "Databricks host", Host stays "" and isDeviceCodeSupportedForHost("", "") returns true, so login continues:

  • ToOAuthArgument resolves the config with the ConfigAttributes loader, which reads env vars. With DATABRICKS_HOST set, login runs against that host (this workspace-only check never sees it), and the profile is saved without a host key.
  • Without DATABRICKS_HOST, it fails later with host must start with 'https://': .

Picker → "Enter a host URL manually" → empty input hits the same path, and the user gets the profile name prompt followed by a second host prompt. Before this PR, errDeviceCodeNeedsHost caught both cases.

I think the simplest fix is to reject empty input in promptForHost (cmdio.PromptOptions has Validate), or an empty host check here for device code.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I kept the fix to device code login so other flows don't change in this PR. An empty host now fails with --use-device-code requires a workspace host, both at the setHost prompt and right after "Enter a host URL manually", without asking for the host again. Rejecting empty input in promptForHost would also change browser login and auth token, so I'd do that in a separate PR.

Comment thread cmd/auth/login.go Outdated
Comment on lines +228 to +230
// (Create a new profile) and a manual host URL. Device code login skips
// discovery, so for it "Create a new profile" prompts for the host after
// the profile name.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Optional, and mostly unrelated to this PR: after "Create a new profile" no host is known yet, so the name prompt suggests DEFAULT, and pressing Enter loads the existing DEFAULT profile if there is one. If that's an account profile the picker just hid, the user gets --use-device-code is only supported for workspace hosts for a profile they didn't pick. If it's a workspace profile, login reuses its host instead of prompting as this comment describes. Browser login reuses DEFAULT the same way, so fine to leave for a follow-up.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Thanks, I updated the comment to mention that an existing profile's host is reused. I'll leave the fix for a follow-up PR.

maksim-zuev-db and others added 4 commits October 27, 2026 10:38
Co-authored-by: Isaac <no-reply@databricks.com>
Co-authored-by: Isaac <no-reply@databricks.com>
Co-authored-by: Isaac <no-reply@databricks.com>
Co-authored-by: Isaac <no-reply@databricks.com>

@simonfaltum simonfaltum left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for addressing everything, LGTM.

@maksim-zuev-db
maksim-zuev-db added this pull request to the merge queue Oct 27, 2026
Merged via the queue into main with commit e773191 Oct 27, 2026
27 checks passed
@maksim-zuev-db
maksim-zuev-db deleted the device-code-hide-create-profile branch October 27, 2026 13:42
@eng-dev-ecosystem-bot

Copy link
Copy Markdown
Collaborator

Integration test report

Commit: e773191

Run: 40514450698

Env ❌​FAIL 🔄​flaky ✅​pass 🙈​skip Time
❌​ aws linux-2core-8gb 4 1463 1212 152:47
❌​ aws-windows-latest-4core-16gb 4 2 1386 1237 167:31
✅​ azure linux-2core-8gb 1316 1264 124:55
🔄​ azure-windows-latest-4core-16gb 3 1238 1289 135:00
✅​ gcp linux-2core-8gb 1303 1269 141:01
✅​ gcp-windows-latest-4core-16gb 1228 1294 149:47
8 interesting tests: 4 FAIL, 4 flaky
Test Name aws linux-2core-8gb aws-windows-latest-4core-16gb azure-windows-latest-4core-16gb
❌​ TestAccept ❌​F ❌​F 🔄​f
🔄​ TestAccept/bundle/invariant/no_drift ✅​p ✅​p 🔄​f
🔄​ TestAccept/bundle/invariant/no_drift/DMS=/INPUT_CONFIG=genie_space.yml.tmpl/READPLAN= ✅​p ✅​p 🔄​f
❌​ TestAccept/bundle/resources/postgres_databases/live_errors/bad_role_ref ❌​F ❌​F 🙈​s
❌​ TestAccept/bundle/resources/postgres_databases/live_errors/bad_role_ref/DMS= ❌​F ❌​F
❌​ TestAccept/bundle/resources/postgres_databases/live_errors/bad_role_ref/DMS=true ❌​F ❌​F
🔄​ TestAccept/bundle/resources/postgres_synced_tables/recreate ✅​p 🔄​f 🙈​s
🔄​ TestAccept/bundle/resources/postgres_synced_tables/recreate/DMS=true ✅​p 🔄​f
Top 50 slowest tests (at least 2 minutes):
duration env testname
13:05 gcp-windows-latest-4core-16gb TestAccept/bundle/resources/apps/lifecycle-started/DMS=true
11:37 gcp linux-2core-8gb TestAccept/bundle/resources/apps/lifecycle-started/DMS=true
10:44 gcp-windows-latest-4core-16gb TestAccept/bundle/resources/apps/lifecycle-started/DMS=
10:35 gcp linux-2core-8gb TestAccept/bundle/resources/apps/lifecycle-started/DMS=
9:21 aws-windows-latest-4core-16gb TestAccept/bundle/resources/clusters/lifecycle-started/DMS=true
8:55 aws linux-2core-8gb TestAccept/bundle/resources/clusters/lifecycle-started/DMS=
8:45 gcp linux-2core-8gb TestAccept/bundle/resources/clusters/lifecycle-started/DMS=true
8:34 azure-windows-latest-4core-16gb TestAccept/bundle/resources/clusters/lifecycle-started/DMS=
8:14 aws-windows-latest-4core-16gb TestAccept/bundle/resources/apps/lifecycle-started/DMS=
8:13 aws-windows-latest-4core-16gb TestAccept/bundle/resources/apps/lifecycle-started/DMS=true
8:13 gcp-windows-latest-4core-16gb TestAccept/bundle/resources/clusters/lifecycle-started/DMS=true
8:00 aws linux-2core-8gb TestAccept/bundle/resources/apps/lifecycle-started/DMS=true
7:45 gcp linux-2core-8gb TestAccept/bundle/resources/clusters/lifecycle-started-toggle/DMS=true
7:38 aws linux-2core-8gb TestAccept/bundle/resources/clusters/lifecycle-started/DMS=true
7:29 gcp-windows-latest-4core-16gb TestAccept/bundle/resources/clusters/deploy/local_ssd_count/DMS=
7:28 aws linux-2core-8gb TestAccept/bundle/resources/apps/lifecycle-started/DMS=
7:27 aws-windows-latest-4core-16gb TestAccept/bundle/resources/clusters/lifecycle-started-toggle/DMS=true
7:26 aws-windows-latest-4core-16gb TestAccept/bundle/resources/clusters/lifecycle-started/DMS=
7:21 gcp linux-2core-8gb TestAccept/bundle/invariant/delete_idempotent/DMS=/INPUT_CONFIG=cluster.yml.tmpl/READPLAN=
7:20 gcp linux-2core-8gb TestAccept/bundle/resources/clusters/lifecycle-started-toggle/DMS=
7:19 azure-windows-latest-4core-16gb TestAccept/bundle/resources/apps/lifecycle-started/DMS=true
7:17 gcp linux-2core-8gb TestAccept/bundle/resources/clusters/lifecycle-started/DMS=
7:15 gcp linux-2core-8gb TestAccept/bundle/invariant/no_drift/DMS=/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=
7:15 gcp linux-2core-8gb TestAccept/bundle/resources/clusters/deploy/local_ssd_count/DMS=
7:13 gcp-windows-latest-4core-16gb TestAccept/bundle/resources/clusters/deploy/local_ssd_count/DMS=true
7:11 aws linux-2core-8gb TestAccept/bundle/resources/clusters/lifecycle-started-toggle/DMS=
7:10 aws-windows-latest-4core-16gb TestAccept/bundle/resources/clusters/lifecycle-started-toggle/DMS=
7:03 azure linux-2core-8gb TestAccept/bundle/resources/apps/lifecycle-started/DMS=true
7:03 aws linux-2core-8gb TestAccept/bundle/invariant/no_drift/DMS=/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=
6:58 gcp linux-2core-8gb TestAccept/bundle/resources/clusters/deploy/local_ssd_count/DMS=true
6:58 azure-windows-latest-4core-16gb TestAccept/bundle/resources/apps/lifecycle-started/DMS=
6:53 gcp-windows-latest-4core-16gb TestAccept/bundle/resources/clusters/lifecycle-started/DMS=
6:52 azure linux-2core-8gb TestAccept/bundle/resources/apps/lifecycle-started/DMS=
6:49 gcp linux-2core-8gb TestAccept/bundle/invariant/no_drift/DMS=/INPUT_CONFIG=cluster_apply_policy_default_values.yml.tmpl/READPLAN=1
6:40 gcp linux-2core-8gb TestAccept/bundle/config-remote-sync/multiple_resources/DMS=true
6:40 aws linux-2core-8gb TestAccept/bundle/invariant/no_drift/DMS=/INPUT_CONFIG=cluster_apply_policy_default_values.yml.tmpl/READPLAN=1
6:31 aws linux-2core-8gb TestAccept/bundle/config-remote-sync/multiple_resources/DMS=true
6:24 aws linux-2core-8gb TestAccept/bundle/invariant/no_drift/DMS=true/INPUT_CONFIG=cluster_apply_policy_default_values.yml.tmpl/READPLAN=
6:24 azure linux-2core-8gb TestAccept/bundle/config-remote-sync/multiple_resources/DMS=
6:22 aws linux-2core-8gb TestAccept/bundle/invariant/no_drift/DMS=true/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=
6:20 aws linux-2core-8gb TestAccept/bundle/config-remote-sync/multiple_resources/DMS=
6:16 azure linux-2core-8gb TestAccept/bundle/resources/clusters/lifecycle-started/DMS=true
6:12 azure linux-2core-8gb TestAccept/bundle/config-remote-sync/multiple_resources/DMS=true
6:03 aws linux-2core-8gb TestAccept/bundle/resources/clusters/resize-terminated-fallback/DMS=
6:01 azure-windows-latest-4core-16gb TestAccept/bundle/resources/clusters/lifecycle-started/DMS=true
5:58 gcp linux-2core-8gb TestAccept/bundle/config-remote-sync/multiple_resources/DMS=
5:56 gcp linux-2core-8gb TestAccept/bundle/deploy/spark-jar-task/DMS=
5:56 gcp-windows-latest-4core-16gb TestAccept/bundle/resources/clusters/lifecycle-started-toggle/DMS=
5:51 aws linux-2core-8gb TestAccept/bundle/resources/clusters/lifecycle-started-toggle/DMS=true
5:50 gcp linux-2core-8gb TestAccept/bundle/resources/apps/lifecycle-started-omitted/DMS=

idelafuente-oc pushed a commit to idelafuente-oc/cli that referenced this pull request Nov 11, 2026
…s#7196)

## Changes
After "Create a new profile" in the `databricks auth login` and
`databricks auth token` pickers, the profile name prompt rejects the
name of any existing config section with `profile X already exists.
Choose a different name`. This includes the profiles the device code
picker hides and sections without a `host`. A taken `DEFAULT` is no
longer suggested: the prompt then has no default and requires a name.

All profile name prompts now also trim spaces and pasted newlines, and
reject the reserved `__settings__` name before the OAuth flow rather
than after it.

Saving a profile now rejects names that contain line breaks, for example
a pasted `foo\nbar`. go-ini writes section headers unescaped, so such a
name produced a config file that no longer parses. This applies to every
command that saves a profile or sets the default profile, such as `auth
login`, `auth token`, `auth switch` and `configure`.

The `auth token` inline login can no longer target an existing profile,
so its code for keeping that profile's scopes, client ID and resources
is removed.

## Why
Follow-up to a review comment on databricks#7179. With no host known yet, the
prompt suggested `DEFAULT`, and pressing Enter logged in to the existing
`DEFAULT` profile and reused its host. With `--use-device-code`, if that
was an account profile the picker hid, login failed with
`--use-device-code is only supported for workspace hosts`.

A generated name like `DEFAULT-1` is not offered instead: the host is
not known yet, so the name would not say which workspace the profile is
for.

## Tests
- `TestPromptForProfile*` cover the prompt: free and taken defaults, and
empty, taken, reserved and pasted names.
- `TestLoginCreateNewProfileRejectsTakenName`,
`TestLoginDeviceCodeCreateNewProfileRejectsHiddenProfileName` and
`TestResolveNoArgsTokenCreateNewProfileRejectsTakenName` cover the
browser login, device code login and `auth token` flows. Like the other
picker tests, they are skipped on Windows.
- `TestGetSectionNames` covers sections without a host and empty
sections.
- `TestValidateProfileName` and
`TestSaveToProfile_SquareBracketsRoundTrip` cover line breaks, and check
that names with square brackets are still accepted and parse back.
- `cmd/auth` unit tests and `TestAccept/cmd/auth` pass.

This pull request and its description were written by Isaac.

---------

Co-authored-by: Isaac <no-reply@databricks.com>
idelafuente-oc pushed a commit to idelafuente-oc/cli that referenced this pull request Nov 11, 2026
## Changes
`databricks auth login` and `databricks auth token` reject a host that
is not an http(s) URL with a hostname,
e.g. `/`, `?o=123`, `https://` or `ftp://x.test`, with
`invalid host "<input>". Expected a URL like
https://<databricks-instance>.cloud.databricks.com`.

The check covers `--host`, the positional argument, profile hosts and
the host prompt, which shows the error
and asks again. `auth login` runs it before the keyring probe and the
profile name prompt.

Behavior changes:
- An empty host after "Enter a host URL manually" in the login profile
picker no longer starts discovery login.
- `auth login --skip-workspace --host '?a=123'` fails. On main this
started discovery login.
- Spaces around a host are trimmed, so `" https://x.test/?o=1 "` works
and keeps the workspace ID.

## Why
Follow-up to a review comment on databricks#7179. An invalid host made login and
token resolve the host from
`DATABRICKS_HOST`, save a profile without a `host` key, connect to a
host named `https`, or fail later
with `host must start with 'https://': `.

## Tests
Unit tests cover host validation for each host source, the host prompt,
and the early rejection in browser,
device code and `--skip-workspace` login. New acceptance tests check the
error output of `auth login` and
`auth token`.

This pull request and its description were written by Isaac.

---------

Co-authored-by: Isaac <no-reply@databricks.com>
tedjt pushed a commit to tedjt/cli that referenced this pull request Nov 12, 2026
…tabricks#7506)

## Changes
In `termtest.Run`, the goroutine running the cmdio call now sends
`(value, err)` on `done` before it closes the stdin pipe's read end.
Before this change it closed the pipe first.

## Why
On Windows, bubbletea wraps a non-console input in cancelreader's
fallback reader, and that reader cannot cancel a read in progress
(`Cancel()` returns false). After the prompt quits, bubbletea's read
loop can still be blocked in `ReadFile` on the pipe. Go's
`(*os.File).Close` on Windows calls `CancelIoEx` on pipes, but it does
nothing when the read loop hasn't entered `ReadFile` yet. Close then
waits for the outstanding read, which only ends when `Term.Close` (run
in `t.Cleanup`) closes the write end. That happens only after `Result()`
has given up, so the test fails with `cmdio call did not finish in 5s`,
even though the raw output shows bubbletea already restored the
terminal. Whether it fails depends on goroutine scheduling, so on a
retry it usually passes.

Sending the result first lets `Result()` return as soon as the call
finishes. `Close` still closes the write end and waits for the
goroutine, so nothing leaks.

Background:
- databricks#5248 introduced the harness with this ordering.
- databricks#7071 and later auth PRs (e.g. databricks#7093, databricks#7179) moved many more
`cmd/auth` tests onto `termtest.Run`, which is why the flake rate rose.
- Tests that start more than one bubbletea program are already skipped
on Windows for the same root cause (`bubbletea cannot cancel reads on
non-console input on Windows`). This PR does not change that.

I decided not to raise `defaultTimeout`, because the wait isn't caused
by load: it lasts until cleanup, however long the timeout is.

## Tests
- `go test ./libs/cmdio/... ./cmd/auth/` (Linux, also `-race -count=5`
for cmdiotest); `GOOS=windows go vet` on the same packages.
- Windows unit tests in this PR's CI.

Dashboard:

| error | key failure lines |
|---|---|
|
[error/2065](http://go/cli/dashboard/error/2065?main=1&pr=1&end=2026-11-11T19:40:00Z&last=30d)
| `select_baseline_wrap_around_test.go:39: cmdio call did not finish in
5s; raw output:` …
`\u001b[?2004l\u001b[?25h\u001b[?1002l\u001b[?1003l\u001b[?1006l` / `---
FAIL: TestSelectBaseline_WrapAround (5.05s)` |

Affected (flaky on Windows, 59 tests), e.g.
[cmdiotest.TestSelectBaseline_Scroll](http://go/cli/dashboard/test/libs/cmdio/cmdiotest.TestSelectBaseline_Scroll?main=1&pr=1&end=2026-11-11T19:40:00Z&last=30d),
[cmdiotest.TestPromptBaseline_AltKeyNoop](http://go/cli/dashboard/test/libs/cmdio/cmdiotest.TestPromptBaseline_AltKeyNoop?main=1&pr=1&end=2026-11-11T19:40:00Z&last=30d),
[auth.TestPromptForWorkspaceSelection/id_beyond_first_fifty](http://go/cli/dashboard/test/cmd/auth.TestPromptForWorkspaceSelection/id_beyond_first_fifty?main=1&pr=1&end=2026-11-11T19:40:00Z&last=30d),
[auth.TestLoginDeviceCodeNewProfilePromptsForHost](http://go/cli/dashboard/test/cmd/auth.TestLoginDeviceCodeNewProfilePromptsForHost?main=1&pr=1&end=2026-11-11T19:40:00Z&last=30d).

This PR was opened by an AI agent (harness_auto).

This pull request and its description were written by Isaac.

Co-authored-by: Isaac <no-reply@databricks.com>
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.

3 participants