Skip to content

Add experimental workspace open command#4727

Open
simonfaltum wants to merge 11 commits intomainfrom
simonfaltum/workspace-open
Open

Add experimental workspace open command#4727
simonfaltum wants to merge 11 commits intomainfrom
simonfaltum/workspace-open

Conversation

@simonfaltum
Copy link
Member

@simonfaltum simonfaltum commented Mar 12, 2026

Why

Opening workspace resources in the browser requires manually constructing URLs. A quick command to open jobs, notebooks, clusters, etc. by type and ID saves time during development.

Changes

Before: Users had to manually construct workspace URLs to open resources in the browser. URL patterns were duplicated between bundle open (via per-resource InitializeURL methods) and would need to be hardcoded again here.
Now: databricks experimental open RESOURCE_TYPE ID_OR_PATH opens any supported resource directly.

Resource types use plural names matching CLI command groups: jobs, clusters, notebooks, pipelines, dashboards, warehouses, queries, apps, experiments.

URL pattern construction is shared with bundle open via a new libs/workspaceurls package. This package provides:

  • A canonical map of resource type to URL pattern (e.g., jobs -> jobs/%s, notebooks -> #notebook/%s)
  • Workspace base URL construction with ?o=<workspace-id> handling
  • Fragment vs path URL formatting

Both experimental open and bundle/config/mutator/initialize_urls.go now use this shared helper instead of duplicating patterns. The stricter adb-<id> hostname check for workspace ID detection is also shared, fixing a loose strings.Contains match that existed in the bundle code.

A --url flag prints the URL to stdout without opening the browser, useful for scripting and SSH sessions. Browser opening respects the BROWSER env var (including BROWSER=none) via a shared libs/browser helper.

Test plan

  • Unit tests for URL construction for all resource types (including experiments)
  • Unit test for fragment vs path URL handling
  • Unit test for unknown resource type error
  • Unit test for shell completion
  • Unit tests for --url flag (prints URL, no browser)
  • Unit tests for BROWSER=none contract
  • Unit test for vanity hostname workspace ID detection
  • Bundle mutator tests still pass after refactor
  • make lintfull passes
  • make checks passes

@eng-dev-ecosystem-bot
Copy link
Collaborator

eng-dev-ecosystem-bot commented Mar 12, 2026

Commit: 14ba838

Run: 23070566223

Env 🔄​flaky 💚​RECOVERED 🙈​SKIP ✅​pass 🙈​skip Time
💚​ aws linux 8 7 268 788 6:15
💚​ aws windows 8 7 270 786 5:20
🔄​ aws-ucws linux 2 7 7 364 703 7:03
🔄​ aws-ucws windows 2 7 7 366 701 6:23
💚​ azure linux 2 9 271 786 5:12
💚​ azure windows 2 9 273 784 5:22
🔄​ azure-ucws linux 2 1 9 369 699 7:57
🔄​ azure-ucws windows 2 1 9 371 697 6:16
💚​ gcp linux 2 9 267 789 5:59
💚​ gcp windows 2 9 269 787 5:09
16 interesting tests: 7 SKIP, 6 RECOVERED, 3 flaky
Test Name aws linux aws windows aws-ucws linux aws-ucws windows azure linux azure windows azure-ucws linux azure-ucws windows gcp linux gcp windows
🔄​ TestAccept 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 🔄​f 💚​R 💚​R 💚​R
🙈​ TestAccept/bundle/resources/permissions 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
💚​ TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/with_permissions 💚​R 💚​R 💚​R 💚​R 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
💚​ TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/with_permissions/DATABRICKS_BUNDLE_ENGINE=direct 💚​R 💚​R 💚​R 💚​R
💚​ TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/with_permissions/DATABRICKS_BUNDLE_ENGINE=terraform 💚​R 💚​R 💚​R 💚​R
💚​ TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/without_permissions 💚​R 💚​R 💚​R 💚​R 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
💚​ TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/without_permissions/DATABRICKS_BUNDLE_ENGINE=direct 💚​R 💚​R 💚​R 💚​R
💚​ TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/without_permissions/DATABRICKS_BUNDLE_ENGINE=terraform 💚​R 💚​R 💚​R 💚​R
🙈​ TestAccept/bundle/resources/postgres_branches/basic 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/postgres_branches/recreate 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/postgres_branches/update_protected 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/postgres_branches/without_branch_id 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/postgres_endpoints/recreate 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/synced_database_tables/basic 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🔄​ TestAccept/ssh/connect-serverless-gpu 🙈​s 🙈​s 🔄​f 🔄​f 🙈​s 🙈​s 🔄​f 🔄​f 🙈​s 🙈​s
🔄​ TestAccept/ssh/connection 💚​R 💚​R 🔄​f 🔄​f 💚​R 💚​R 💚​R 🔄​f 💚​R 💚​R
Top 20 slowest tests (at least 2 minutes):
duration env testname
3:46 azure windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
3:45 gcp windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
3:39 gcp linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
3:19 azure linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
3:09 azure-ucws windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
3:06 gcp windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
3:00 aws-ucws windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
2:54 aws-ucws windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
2:48 aws linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
2:46 azure-ucws windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
2:44 aws windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
2:41 aws linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
2:39 gcp linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
2:38 aws windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
2:35 aws-ucws linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
2:34 aws-ucws linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
2:14 azure windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
2:12 azure-ucws linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
2:09 azure-ucws linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
2:03 azure linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct

Adds `databricks experimental open RESOURCE_TYPE ID_OR_PATH` to open
workspace resources (jobs, notebooks, clusters, pipelines, dashboards,
warehouses, queries, apps) in the default browser.

Handles both path-based and fragment-based URL patterns correctly.
Includes shell completion for resource types.

Co-authored-by: Isaac
- Fix fragment URLs to include `/` before `#` (host/#notebook vs host#notebook)
- Update cluster pattern to `compute/clusters/%s` (matching bundle code)
- Update dashboard pattern to `dashboardsv3/%s/published` (matching bundle code)
- Add leading `/` to all path-based URL patterns
- Add `?o=<workspace-id>` via CurrentWorkspaceID for shared-domain workspaces
- Add tests for notebook path-style IDs, workspace ID parameter
- Add doc comment for openURLSuppressingBrowserStderr

Co-authored-by: Isaac
Move shared workspace UI routes and base URL synthesis into libs/workspaceurls so experimental open and bundle resource URLs stay aligned, including vanity hosts that still require the ?o workspace suffix.
@simonfaltum simonfaltum force-pushed the simonfaltum/workspace-open branch from cb07ae7 to 59d2959 Compare March 13, 2026 10:18
The shared workspaceurls lib uses a stricter adb- hostname check for
workspace ID detection. This is correct but changes bundle summary URL
output on non-Azure workspaces (adds ?o= where it was previously
omitted due to a loose strings.Contains match). That behavior change
should be a separate PR with its own integration test updates.

experimental open still uses the shared lib with the strict check.
@simonfaltum simonfaltum force-pushed the simonfaltum/workspace-open branch from c672536 to c5ae950 Compare March 13, 2026 11:23

// buildWorkspaceURL constructs a full workspace URL for a given resource type and ID.
func buildWorkspaceURL(host, resourceType, id string, workspaceID int64) (string, error) {
if !slices.Contains(supportedOpenResourceTypes, resourceType) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why have this check, should not LookupPattern below handle the case or unsupported resource type?

workspaceurls.ResourcePipelines,
workspaceurls.ResourceQueries,
workspaceurls.ResourceWarehouses,
}
Copy link
Contributor

@denik denik Mar 13, 2026

Choose a reason for hiding this comment

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

question - Why is there less resource types than supported in libs/workspaceurls?


cmd.Flags().BoolVar(&printURL, "url", false, "Print the workspace URL instead of opening the browser")

return cmd
Copy link
Contributor

Choose a reason for hiding this comment

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

We have acceptance test for bundle open + completion (as it was otherwise easy to break in the past). Would it make sense to add such test here as well? See acceptance/bundle/open

Copy link
Contributor

@shreyas-goenka shreyas-goenka left a comment

Choose a reason for hiding this comment

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

Note: This review was posted by Claude (AI assistant). Shreyas will do a separate, more thorough review pass.

Priority: MEDIUM — Redundant checks and missing tests

MEDIUM: Redundant double-check pattern

The code checks for the workspace client / configuration validity in multiple places redundantly. One check should be sufficient.

MEDIUM: Missing test coverage

The workspace open command lacks tests for error paths (invalid URLs, missing workspace client, browser launch failures).

LOW: Partial bundle refactor revert

Some changes appear to partially revert or duplicate work from a related bundle refactoring effort. Worth confirming this is intentional.

What looks good

  • The command itself is a useful addition for the experimental feature set
  • Clean integration with the existing command structure
  • Proper use of the experimental command group

…cceptance test

Remove the redundant slices.Contains check in buildWorkspaceURL since
LookupPattern already handles unknown resource types.

Add missing resource types (alerts, models, model_serving_endpoints,
registered_models) so the command supports all types from
libs/workspaceurls.

Add acceptance test for the experimental open command covering URL
generation, error handling, and tab completion.
Fix three issues in workspace open and browser opener:

1. Convert dot-separated registered_models names (catalog.schema.model)
   to slash-separated URL paths automatically. Add help text and example.

2. Handle quoted BROWSER env values (e.g. open -a "Google Chrome") by
   delegating to sh -c instead of naive whitespace splitting.

3. Make the BROWSER=none fallback message configurable via
   WithDisabledMessage option. Auth callers keep the auth-specific
   message, workspace open uses a generic resource message.
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.

4 participants