Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
9e46a65
bundle: add genie_spaces resource for direct deploy
janniklasrose Apr 21, 2026
517d22e
bundle: retry genie_space create on 400 INVALID_PARAMETER_VALUE missi…
janniklasrose Apr 30, 2026
fc4af0d
bundle: register genie_space file_path translation in unified path vi…
janniklasrose Apr 30, 2026
0145b87
bundle: normalize inline serialized_space to JSON string before plan
janniklasrose Apr 30, 2026
5535c46
bundle: reject genie_space permissions during plan
janniklasrose Apr 30, 2026
133a64c
bundle: warn on dual genie_space sources and clarify direct-only error
janniklasrose Apr 30, 2026
5decb00
bundle: round-trip parent_path through generate genie-space
janniklasrose Apr 30, 2026
786ded7
bundle: lint cleanups for genie_space changes
janniklasrose Apr 30, 2026
cd3f101
bundle: skip genie_space serialized_space in update when unchanged lo…
janniklasrose May 7, 2026
732641c
bundle: fix watch loop in generate genie-space
janniklasrose May 7, 2026
41f36a9
bundle: honor --key flag in generate genie-space
janniklasrose May 7, 2026
0b27cc4
bundle: guard empty serialized_space in generate genie-space
janniklasrose May 7, 2026
2ff9273
bundle: collapse DoRead into responseToGenieSpaceConfig for genie_space
janniklasrose May 7, 2026
04ec5fa
bundle: fill genie_space schema annotations
janniklasrose May 7, 2026
3303b8d
bundle: lint cleanups for genie_space review fixes
janniklasrose May 7, 2026
b1f7595
Regenerate test toml
janniklasrose May 18, 2026
9891229
Agent review
janniklasrose May 20, 2026
0a9f3cb
bundle: update genie_space test fixture to v2 export format
janniklasrose May 20, 2026
03350e8
bundle: align genie_space generate with new dstate.DB Open signature
janniklasrose May 20, 2026
e5d49dd
bundle: integrate genie_space after rebase onto main
janniklasrose Jun 4, 2026
2b186cb
bundle: address genie_space PR review comments
janniklasrose Jun 4, 2026
a595ca4
bundle: regenerate permissions analyze_requests output for genie_spaces
janniklasrose Jun 4, 2026
dcce42e
bundle: default genie_space testserver parent_path to home dir
janniklasrose Jun 4, 2026
9118a3b
bundle: testserver GetSpace returns etag only with serialized_space
janniklasrose Jun 4, 2026
1c1aa88
bundle: testserver returns 403 for missing genie space
janniklasrose Jun 4, 2026
b80768c
bundle: testserver bumps genie etag only on serialized_space change
janniklasrose Jun 4, 2026
c82791c
bundle: testserver does not register genie space as workspace file
janniklasrose Jun 4, 2026
fe19eb2
bundle: handle genie space 403-for-missing on read/delete/generate
janniklasrose Jun 4, 2026
6760708
bundle: clarify ConvertGenieSpaceToValue field-copy comment
janniklasrose Jun 4, 2026
55f1ed2
Add comment on IncludeSerializedSpace
janniklasrose Jun 4, 2026
6566ff1
bundle: acceptance test for genie serialized_space payload
janniklasrose Jun 4, 2026
4be04ae
bundle: don't send etag as If-Match on genie space update
janniklasrose Jun 4, 2026
cdf670c
Regenerate direct
janniklasrose Jun 4, 2026
d1487ea
bundle: error when a genie space sets both file_path and serialized_s…
janniklasrose Jun 4, 2026
7072a39
bundle: remove unusable by-path flow from generate genie-space
janniklasrose Jun 5, 2026
3911870
Autogenerate validation
janniklasrose Jun 5, 2026
23b0f68
Add gitattribute to force geniespace.json to eol=lf
janniklasrose Jun 5, 2026
cc53f04
bundle: add genie_space invariant and bind acceptance tests + changelog
janniklasrose Jun 5, 2026
ea9e983
Merge remote-tracking branch 'origin/main' into genie
janniklasrose Jun 5, 2026
4e18b60
bundle: regenerate invariant out.test.toml for genie_space matrix entry
janniklasrose Jun 5, 2026
e90597e
bundle: reject user-set etag on genie_space resources
janniklasrose Jun 5, 2026
c22a3fa
acceptance: exclude genie_space from migrate and continue_293 invaria…
janniklasrose Jun 5, 2026
df2e06b
bundle/direct: copy remote etag into bind state for genie spaces
janniklasrose Jun 5, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions NEXT_CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
### CLI

### Bundles
* Add the `genie_spaces` bundle resource for managing Databricks Genie spaces as code, plus `bundle generate genie-space` to import an existing space. Direct deployment engine only ([#5282](https://github.com/databricks/cli/pull/5282)).

### Dependency updates

Expand Down
1 change: 1 addition & 0 deletions acceptance/.gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
# uploading the file's content to a workspace.
*.txt text eol=lf
*.lvdash.json text eol=lf
*.geniespace.json text eol=lf

# The out.test.toml file is autogenerated based on the merged test.toml view.
out.test.toml linguist-generated=true
Expand Down
13 changes: 13 additions & 0 deletions acceptance/bundle/deployment/bind/genie_space/databricks.yml.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
bundle:
name: test-bundle-$UNIQUE_NAME

resources:
genie_spaces:
genie_space1:
title: $GENIE_SPACE_TITLE
warehouse_id: "test-warehouse-id"
parent_path: /Users/$CURRENT_USER_NAME
# Inline body matches the out-of-band-created space byte-for-byte, so the
# only possible post-bind drift signal is the etag.
serialized_space:
version: 1
3 changes: 3 additions & 0 deletions acceptance/bundle/deployment/bind/genie_space/out.test.toml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

37 changes: 37 additions & 0 deletions acceptance/bundle/deployment/bind/genie_space/output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@

>>> [CLI] bundle deployment bind genie_space1 [GENIE_SPACE_ID] --auto-approve
Updating deployment state...
Successfully bound genie_space with an id '[GENIE_SPACE_ID]'
Run 'bundle deploy' to deploy changes to your workspace

>>> [CLI] bundle plan
Plan: 0 to add, 0 to change, 0 to delete, 1 unchanged

>>> [CLI] bundle deploy
Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/test-bundle-[UNIQUE_NAME]/default/files...
Deploying resources...
Updating deployment state...
Deployment complete!

>>> [CLI] genie get-space [GENIE_SPACE_ID]
{
"parent_path": "/Users/[USERNAME]",
"title": "test genie space [UNIQUE_NAME]",
"warehouse_id": "test-warehouse-id"
}

>>> [CLI] bundle deployment unbind genie_space1
Updating deployment state...

>>> [CLI] bundle destroy --auto-approve
All files and directories at the following location will be deleted: /Workspace/Users/[USERNAME]/.bundle/test-bundle-[UNIQUE_NAME]/default

Deleting files...
Destroy complete!

>>> [CLI] genie get-space [GENIE_SPACE_ID]
{
"parent_path": "/Users/[USERNAME]",
"title": "test genie space [UNIQUE_NAME]",
"warehouse_id": "test-warehouse-id"
}
30 changes: 30 additions & 0 deletions acceptance/bundle/deployment/bind/genie_space/script
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
GENIE_SPACE_TITLE="test genie space $UNIQUE_NAME"

export GENIE_SPACE_TITLE
envsubst < databricks.yml.tmpl > databricks.yml

# Create a Genie space out of band, then bind the bundle resource to it.
GENIE_SPACE_ID=$($CLI genie create-space "test-warehouse-id" '{"version":1}' --title "${GENIE_SPACE_TITLE}" | jq -r '.space_id')

cleanupRemoveGenieSpace() {
$CLI genie trash-space "${GENIE_SPACE_ID}"
}
trap cleanupRemoveGenieSpace EXIT

trace $CLI bundle deployment bind genie_space1 "${GENIE_SPACE_ID}" --auto-approve

# Bind must copy the remote etag into state, so the first plan after bind is
# clean. Without that, the etag drift signal (empty stored vs remote) would
# produce a bogus update here.
trace $CLI bundle plan

trace $CLI bundle deploy

trace $CLI genie get-space "${GENIE_SPACE_ID}" | jq --sort-keys '{title, parent_path, warehouse_id}'

trace $CLI bundle deployment unbind genie_space1

trace $CLI bundle destroy --auto-approve

# Read the Genie space again (expecting it still exists and is not deleted):
trace $CLI genie get-space "${GENIE_SPACE_ID}" | jq --sort-keys '{title, parent_path, warehouse_id}'
13 changes: 13 additions & 0 deletions acceptance/bundle/deployment/bind/genie_space/test.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Local = true

# Genie spaces are only deployed via the direct deployment engine.
EnvMatrix.DATABRICKS_BUNDLE_ENGINE = ["direct"]

# Uses a literal warehouse id and a version-sensitive serialized_space, so this
# lifecycle test runs against the local mock server only (overrides the Cloud=true
# inherited from acceptance/bundle/deployment/test.toml).
Cloud = false
Copy link
Copy Markdown
Contributor Author

@janniklasrose janniklasrose Jun 5, 2026

Choose a reason for hiding this comment

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

Note to reviewers: All cloud tests are currently disabled, currently doing a couple of runs to spot obvious issues in advance but can be follow-up


[[Repls]]
Old = "[0-9a-f]{32}"
New = "[GENIE_SPACE_ID]"
2 changes: 2 additions & 0 deletions acceptance/bundle/generate/genie_space/databricks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
bundle:
name: genie-space-generate
7 changes: 7 additions & 0 deletions acceptance/bundle/generate/genie_space/genie_space.json.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"title": "test genie space",
"description": "test description",
"parent_path": "/Workspace/test-$UNIQUE_NAME",
"warehouse_id": "test-warehouse-id",
"serialized_space": "{\"tables\":[],\"questions\":[]}"
}
3 changes: 3 additions & 0 deletions acceptance/bundle/generate/genie_space/out.test.toml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"questions": [],
"tables": []
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
resources:
genie_spaces:
test_genie_space:
title: "test genie space"
warehouse_id: test-warehouse-id
file_path: ../genie_space/test_genie_space.geniespace.json
description: test description
parent_path: /Workspace/test-[UNIQUE_NAME]
6 changes: 6 additions & 0 deletions acceptance/bundle/generate/genie_space/output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

>>> [CLI] workspace mkdirs /Workspace/test-[UNIQUE_NAME]

>>> [CLI] bundle generate genie-space --existing-id [GENIE_SPACE_ID] --genie-space-dir out/genie_space --resource-dir out/resource
Writing genie space to out/genie_space/test_genie_space.geniespace.json
Writing configuration to out/resource/test_genie_space.genie_space.yml
8 changes: 8 additions & 0 deletions acceptance/bundle/generate/genie_space/script
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
trace $CLI workspace mkdirs /Workspace/test-$UNIQUE_NAME

# create a genie space to import
envsubst < genie_space.json.tmpl > genie_space.json
genie_space_id=$($CLI genie create-space --json @genie_space.json | jq -r '.space_id')
rm genie_space.json

trace $CLI bundle generate genie-space --existing-id $genie_space_id --genie-space-dir out/genie_space --resource-dir out/resource
10 changes: 10 additions & 0 deletions acceptance/bundle/generate/genie_space/test.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[[Repls]]
Old = '\\\\'
New = '/'

[[Repls]]
Old = "[0-9a-f]{32}"
New = "[GENIE_SPACE_ID]"

[Env]
MSYS_NO_PATHCONV = "1"
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
bundle:
name: test-bundle

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Error: genie space with ID f00dcafe not found


Exit code: 1
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Test that bundle generate genie-space fails when the existing ID is not found
exec $CLI bundle generate genie-space --existing-id f00dcafe
9 changes: 9 additions & 0 deletions acceptance/bundle/generate/genie_space_inplace/databricks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
bundle:
name: genie space update inplace

resources:
genie_spaces:
test_genie_space:
title: "test genie space"
warehouse_id: "my-warehouse-1234"
file_path: ./space.geniespace.json
3 changes: 3 additions & 0 deletions acceptance/bundle/generate/genie_space_inplace/out.test.toml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 30 additions & 0 deletions acceptance/bundle/generate/genie_space_inplace/output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@

>>> cat space.geniespace.json
{}

=== deploy initial genie space
>>> [CLI] bundle deploy
Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/genie space update inplace/default/files...
Deploying resources...
Updating deployment state...
Deployment complete!

=== update the genie space
>>> [CLI] genie update-space [GENIE_SPACE_ID] --serialized-space {"a":"b"}
{
"etag": "2",
"parent_path": "/Users/[USERNAME]/.bundle/genie space update inplace/default/resources",
"serialized_space": "{\"a\":\"b\"}",
"space_id": "[GENIE_SPACE_ID]",
"title": "test genie space",
"warehouse_id": "my-warehouse-1234"
}

=== update the genie space file using bundle generate
>>> [CLI] bundle generate genie-space --resource test_genie_space --force
Writing genie space to space.geniespace.json

>>> cat space.geniespace.json
{
"a": "b"
}
13 changes: 13 additions & 0 deletions acceptance/bundle/generate/genie_space_inplace/script
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
trace cat space.geniespace.json

title "deploy initial genie space"
trace $CLI bundle deploy
genie_space_id=$($CLI bundle summary --output json | jq -r '.resources.genie_spaces.test_genie_space.id')

title "update the genie space"
trace $CLI genie update-space $genie_space_id --serialized-space '{"a":"b"}'

title "update the genie space file using bundle generate"
trace $CLI bundle generate genie-space --resource test_genie_space --force

trace cat space.geniespace.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
6 changes: 6 additions & 0 deletions acceptance/bundle/generate/genie_space_inplace/test.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Genie spaces are only deployed via the direct deployment engine.
EnvMatrix.DATABRICKS_BUNDLE_ENGINE = ["direct"]

[[Repls]]
Old = "[0-9a-f]{32}"
New = "[GENIE_SPACE_ID]"
1 change: 1 addition & 0 deletions acceptance/bundle/help/bundle-generate/output.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ Available Commands:
alert Generate configuration for an alert
app Generate bundle configuration for a Databricks app
dashboard Generate configuration for a dashboard
genie-space Generate configuration for a Genie space
job Generate bundle configuration for a job
pipeline Generate bundle configuration for a pipeline

Expand Down
14 changes: 14 additions & 0 deletions acceptance/bundle/invariant/configs/genie_space.yml.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
bundle:
name: test-bundle-$UNIQUE_NAME

resources:
genie_spaces:
foo:
warehouse_id: $TEST_DEFAULT_WAREHOUSE_ID
title: test-genie-space-$UNIQUE_NAME
# Inline (structured) serialized_space is marshalled to a JSON string by
# ConfigureGenieSpaceSerializedSpace; this config doubles as a regression
# guard that the normalization produces a drift-free deploy.
serialized_space:
version: 1
display_name: test-genie-space-$UNIQUE_NAME
1 change: 1 addition & 0 deletions acceptance/bundle/invariant/continue_293/out.test.toml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions acceptance/bundle/invariant/continue_293/test.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ EnvMatrixExclude.no_model_with_permissions = ["INPUT_CONFIG=model_with_permissio
# vector_search_endpoints resource is not supported on v0.293.0
EnvMatrixExclude.no_vector_search_endpoint = ["INPUT_CONFIG=vector_search_endpoint.yml.tmpl"]

# genie_spaces resource is not supported on v0.293.0
EnvMatrixExclude.no_genie_space = ["INPUT_CONFIG=genie_space.yml.tmpl"]

# Dotted pipeline configuration keys are not supported on v0.293.0
EnvMatrixExclude.no_pipeline_config_dots = ["INPUT_CONFIG=pipeline_config_dots.yml.tmpl"]

Expand Down
1 change: 1 addition & 0 deletions acceptance/bundle/invariant/migrate/out.test.toml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions acceptance/bundle/invariant/migrate/test.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ EnvMatrixExclude.no_vector_search_index = ["INPUT_CONFIG=vector_search_index.yml
# Error: Catalog resources are only supported with direct deployment mode
EnvMatrixExclude.no_catalog = ["INPUT_CONFIG=catalog.yml.tmpl"]
EnvMatrixExclude.no_external_location = ["INPUT_CONFIG=external_location.yml.tmpl"]
# Genie spaces are direct-only too; the terraform deploy that seeds the migration fails for them.
EnvMatrixExclude.no_genie_space = ["INPUT_CONFIG=genie_space.yml.tmpl"]

# Cross-resource permission references (e.g. ${resources.jobs.job_b.permissions[0].level})
# don't work in terraform mode: the terraform interpolator converts the path to
Expand Down
1 change: 1 addition & 0 deletions acceptance/bundle/invariant/no_drift/out.test.toml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions acceptance/bundle/invariant/test.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ EnvMatrix.INPUT_CONFIG = [
"database_instance.yml.tmpl",
"experiment.yml.tmpl",
"external_location.yml.tmpl",
"genie_space.yml.tmpl",
"job.yml.tmpl",
"job_pydabs_10_tasks.yml.tmpl",
"job_pydabs_1000_tasks.yml.tmpl",
Expand Down Expand Up @@ -80,6 +81,10 @@ no_external_location_on_cloud = ["CONFIG_Cloud=true", "INPUT_CONFIG=external_loc
# External volumes reference external locations; excluded from cloud for the same reason
no_external_volume_on_cloud = ["CONFIG_Cloud=true", "INPUT_CONFIG=volume_external.yml.tmpl"]

# Genie space serialized_space schema is workspace-version-sensitive; we only
# exercise it against the local mock server, not a real cloud workspace.
no_genie_space_on_cloud = ["CONFIG_Cloud=true", "INPUT_CONFIG=genie_space.yml.tmpl"]

# Fake SQL endpoint for local tests
[[Server]]
Pattern = "POST /api/2.0/sql/statements/"
Expand Down
19 changes: 19 additions & 0 deletions acceptance/bundle/refschema/out.fields.txt
Original file line number Diff line number Diff line change
Expand Up @@ -734,6 +734,25 @@ resources.external_locations.*.grants[*] catalog.PrivilegeAssignment ALL
resources.external_locations.*.grants[*].principal string ALL
resources.external_locations.*.grants[*].privileges []catalog.Privilege ALL
resources.external_locations.*.grants[*].privileges[*] catalog.Privilege ALL
resources.genie_spaces.*.description string ALL
resources.genie_spaces.*.etag string ALL
resources.genie_spaces.*.file_path string INPUT
resources.genie_spaces.*.id string INPUT
resources.genie_spaces.*.lifecycle resources.Lifecycle INPUT
resources.genie_spaces.*.lifecycle.prevent_destroy bool INPUT
resources.genie_spaces.*.modified_status string INPUT
resources.genie_spaces.*.parent_path string ALL
resources.genie_spaces.*.serialized_space any ALL
resources.genie_spaces.*.space_id string ALL
resources.genie_spaces.*.title string ALL
resources.genie_spaces.*.url string INPUT
resources.genie_spaces.*.warehouse_id string ALL
resources.genie_spaces.*.permissions.object_id string ALL
resources.genie_spaces.*.permissions[*] dresources.StatePermission ALL
resources.genie_spaces.*.permissions[*].group_name string ALL
resources.genie_spaces.*.permissions[*].level iam.PermissionLevel ALL
resources.genie_spaces.*.permissions[*].service_principal_name string ALL
resources.genie_spaces.*.permissions[*].user_name string ALL
resources.jobs.*.budget_policy_id string ALL
resources.jobs.*.continuous *jobs.Continuous ALL
resources.jobs.*.continuous.pause_status jobs.PauseStatus ALL
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
bundle:
name: deploy-genie-space-inline-$UNIQUE_NAME

resources:
genie_spaces:
sales_analytics:
title: "Sales Analytics Inline Genie"
description: "Inline serialized_space test"
warehouse_id: "test-warehouse-id"
parent_path: /Users/$CURRENT_USER_NAME
serialized_space:
version: 1
config:
sample_questions:
- id: "sq-001"
question: ["What is the total revenue?"]
data_sources:
tables:
- identifier: "main.sales.orders"
column_configs:
- column_name: "amount"
get_example_values: true
Loading
Loading