Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
d1c3445
bundle: add --select flag to validate/plan/summary/deploy
denik Jun 1, 2026
5cb793e
bundle: add tests for repeated --select and resource dependency
denik Jun 1, 2026
76fdaca
bundle: auto-include transitive dependencies in --select
denik Jun 1, 2026
6506b1c
bundle: use plan DependsOn graph for --select dependency expansion
denik Jun 1, 2026
699d778
update outputs + newlines
denik Jun 1, 2026
34a70db
bundle: use StringSlice for --select to match --var convention
denik Jun 1, 2026
47eb09a
update
denik Jun 2, 2026
52e84b9
bundle: reject --select on terraform engine with actionable error
denik Jun 2, 2026
dc519fa
bundle: limit --select to plan/deploy only
denik Jun 2, 2026
203ea84
bundle: run --select tests on both engines, link docs in error
denik Jun 2, 2026
124ebdd
bundle: move --select tests to acceptance/bundle/select, cover deploy
denik Jun 2, 2026
5dc2c35
bundle: cover serialized-plan deploy variant in --select test
denik Jun 2, 2026
2129404
bundle: consolidate --select tests into a single acceptance test
denik Jun 2, 2026
1b2e8da
bundle: rename SelectResources->ResolveSelect, split error test, trim…
denik Jun 2, 2026
36fc9d1
bundle: fold plan InitFunc into ProcessOptions literal
denik Jun 2, 2026
cb1e467
bundle: check --select engine after state pull; add ambiguous accept …
denik Jun 2, 2026
cb85374
bundle: regroup --select acceptance tests under select/{ok,missing,am…
denik Jun 2, 2026
849814c
update
denik Jun 2, 2026
606505a
update
denik Jun 2, 2026
bba4341
Add NEXT_CHANGELOG entry for bundle --select
denik Jun 2, 2026
c2b30d5
Fix select/missing test: script out of sync with output
denik Jun 2, 2026
d718aa4
bundle: run select/basic on cloud; test full deploy after partial deploy
denik Jun 2, 2026
b0153ab
bundle: serialize full plan via readplanarg in select/basic
denik Jun 2, 2026
576ba6e
bundle: emit select_used telemetry metric when --select is used
denik Jun 2, 2026
820dc0e
bundle: assert select telemetry and summary in select/basic
denik Jun 2, 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 @@ -11,5 +11,6 @@
* Retry transient HTTP 5xx and 408 errors in direct deployment engine ([#5349](https://github.com/databricks/cli/pull/5349), [#5364](https://github.com/databricks/cli/pull/5364)).
* Preserve `.designer.ipynb` suffix when translating notebook task paths so Lakeflow Designer files referenced from a `notebook_task` resolve correctly in the workspace ([#5370](https://github.com/databricks/cli/pull/5370)).
* Fix script output dropping last line without trailing newline ([#4995](https://github.com/databricks/cli/pull/4995)).
* Add `--select` flag to `bundle plan` and `bundle deploy` to plan/deploy a subset of resources (e.g. `--select my_job` or `--select jobs.my_job`); resources referenced by the selection are included transitively. Direct engine only ([#5413](https://github.com/databricks/cli/pull/5413)).

### Dependency updates
1 change: 1 addition & 0 deletions acceptance/bundle/help/bundle-deploy/output.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Flags:
--force-lock Force acquisition of deployment lock.
-h, --help help for deploy
--plan string Path to a JSON plan file to apply instead of planning (direct engine only).
--select strings Deploy only the specified resource (e.g. 'my_job' or 'jobs.my_job'). Can be repeated or comma-separated.

Global Flags:
--debug enable debug logging
Expand Down
13 changes: 13 additions & 0 deletions acceptance/bundle/select/ambiguous/databricks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
bundle:
name: select-ambiguous

# "thing" is defined as both a job and a pipeline. This is what an ambiguous
# --select selector would resolve to, but UniqueResourceKeys rejects it at load
# time, so the bundle never reaches selector resolution.
resources:
jobs:
thing:
name: job-thing
pipelines:
thing:
name: pipeline-thing
3 changes: 3 additions & 0 deletions acceptance/bundle/select/ambiguous/out.test.toml

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

16 changes: 16 additions & 0 deletions acceptance/bundle/select/ambiguous/output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@

>>> musterr [CLI] bundle plan --select thing
Error: multiple resources or scripts have been defined with the same key: thing
at resources.jobs.thing
resources.pipelines.thing
in databricks.yml:10:7
databricks.yml:13:7


>>> musterr [CLI] bundle deploy --select thing
Error: multiple resources or scripts have been defined with the same key: thing
at resources.jobs.thing
resources.pipelines.thing
in databricks.yml:10:7
databricks.yml:13:7

2 changes: 2 additions & 0 deletions acceptance/bundle/select/ambiguous/script
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
trace musterr $CLI bundle plan --select thing
trace musterr $CLI bundle deploy --select thing
17 changes: 17 additions & 0 deletions acceptance/bundle/select/basic/databricks.yml.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
bundle:
name: select-$UNIQUE_NAME

resources:
jobs:
bar:
name: bar-$UNIQUE_NAME

foo:
name: foo-$UNIQUE_NAME
tasks:
- task_key: run_bar
run_job_task:
job_id: ${resources.jobs.bar.id}

baz:
name: baz-$UNIQUE_NAME
4 changes: 4 additions & 0 deletions acceptance/bundle/select/basic/out.test.toml

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

141 changes: 141 additions & 0 deletions acceptance/bundle/select/basic/output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@

>>> [CLI] bundle plan --select bar
create jobs.bar

Plan: 1 to add, 0 to change, 0 to delete, 0 unchanged

>>> [CLI] bundle plan --select jobs.bar --select jobs.baz
create jobs.bar
create jobs.baz

Plan: 2 to add, 0 to change, 0 to delete, 0 unchanged

>>> [CLI] bundle plan --select jobs.bar,jobs.baz
create jobs.bar
create jobs.baz

Plan: 2 to add, 0 to change, 0 to delete, 0 unchanged

>>> [CLI] bundle plan --select jobs.foo
create jobs.bar
create jobs.foo

Plan: 2 to add, 0 to change, 0 to delete, 0 unchanged

=== bundle deploy --select jobs.foo
Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/select-[UNIQUE_NAME]/default/files...
Deploying resources...
Updating deployment state...
Deployment complete!

=== Telemetry:
select_used true

>>> print_requests.py --sort //jobs
Comment thread
denik marked this conversation as resolved.
{
"method": "POST",
"path": "/api/2.2/jobs/create",
"body": {
"deployment": {
"kind": "BUNDLE",
"metadata_file_path": "/Workspace/Users/[USERNAME]/.bundle/select-[UNIQUE_NAME]/default/state/metadata.json"
},
"edit_mode": "UI_LOCKED",
"format": "MULTI_TASK",
"max_concurrent_runs": 1,
"name": "bar-[UNIQUE_NAME]",
"queue": {
"enabled": true
}
}
}
{
"method": "POST",
"path": "/api/2.2/jobs/create",
"body": {
"deployment": {
"kind": "BUNDLE",
"metadata_file_path": "/Workspace/Users/[USERNAME]/.bundle/select-[UNIQUE_NAME]/default/state/metadata.json"
},
"edit_mode": "UI_LOCKED",
"format": "MULTI_TASK",
"max_concurrent_runs": 1,
"name": "foo-[UNIQUE_NAME]",
"queue": {
"enabled": true
},
"tasks": [
{
"run_job_task": {
"job_id": [NUMID]
},
"task_key": "run_bar"
}
]
}
}

>>> [CLI] bundle summary
Name: select-[UNIQUE_NAME]
Target: default
Workspace:
User: [USERNAME]
Path: /Workspace/Users/[USERNAME]/.bundle/select-[UNIQUE_NAME]/default
Resources:
Jobs:
bar:
Name: bar-[UNIQUE_NAME]
URL: [DATABRICKS_URL]/jobs/[NUMID]?w=[NUMID]
baz:
Name: baz-[UNIQUE_NAME]
URL: (not deployed)
foo:
Name: foo-[UNIQUE_NAME]
URL: [DATABRICKS_URL]/jobs/[NUMID]?w=[NUMID]

=== Full plan after partial deploy
>>> [CLI] bundle plan
create jobs.baz

Plan: 1 to add, 0 to change, 0 to delete, 2 unchanged

=== Full deploy
Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/select-[UNIQUE_NAME]/default/files...
Deploying resources...
Updating deployment state...
Deployment complete!

>>> print_requests.py --sort //jobs
{
"method": "POST",
"path": "/api/2.2/jobs/create",
"body": {
"deployment": {
"kind": "BUNDLE",
"metadata_file_path": "/Workspace/Users/[USERNAME]/.bundle/select-[UNIQUE_NAME]/default/state/metadata.json"
},
"edit_mode": "UI_LOCKED",
"format": "MULTI_TASK",
"max_concurrent_runs": 1,
"name": "baz-[UNIQUE_NAME]",
"queue": {
"enabled": true
}
}
}

=== Full plan again
>>> [CLI] bundle plan
Plan: 0 to add, 0 to change, 0 to delete, 3 unchanged

=== Destroy
>>> [CLI] bundle destroy --auto-approve
The following resources will be deleted:
delete resources.jobs.bar
delete resources.jobs.baz
delete resources.jobs.foo

All files and directories at the following location will be deleted: /Workspace/Users/[USERNAME]/.bundle/select-[UNIQUE_NAME]/default

Deleting files...
Destroy complete!
47 changes: 47 additions & 0 deletions acceptance/bundle/select/basic/script
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
envsubst '$UNIQUE_NAME' < databricks.yml.tmpl > databricks.yml

cleanup() {
title "Destroy"
trace $CLI bundle destroy --auto-approve
rm -f out.requests.txt
}
trap cleanup EXIT

# --- selector resolution ---
# Unqualified name, unique across resource types.
trace $CLI bundle plan --select bar
# Repeated --select.
trace $CLI bundle plan --select jobs.bar --select jobs.baz
# Comma-separated --select (equivalent to repeating the flag).
trace $CLI bundle plan --select jobs.bar,jobs.baz
# Qualified name; foo pulls in its dependency bar but not the independent baz.
trace $CLI bundle plan --select jobs.foo

# --- partial deploy ---
# Serialize the filtered plan to a temp file (kept out of the recorded output: the
# JSON embeds remote state that differs between local and cloud), then deploy it:
# inline, or via --plan (READPLAN=1). The deploy is not traced because readplanarg
# varies the command line between READPLAN variants, which must produce identical output.
$CLI bundle plan --select jobs.foo -o json > plan.json
title "bundle deploy --select jobs.foo\n"
$CLI bundle deploy --select jobs.foo $(readplanarg plan.json)
# The deploy reports that --select was used via telemetry.
title "Telemetry:\n"
print_telemetry_bool_values | grep '^select_used '
# Only bar and foo were created, never baz.
trace print_requests.py --sort //jobs
# Summary after the partial deploy: foo and bar are deployed, baz is not.
trace $CLI bundle summary

# --- full plan/deploy after the partial deploy ---
# foo and bar are already deployed, so only baz remains to create.
title "Full plan after partial deploy"
trace $CLI bundle plan
$CLI bundle plan -o json > plan-full.json
title "Full deploy\n"
$CLI bundle deploy $(readplanarg plan-full.json)
# Only baz is created this time.
trace print_requests.py --sort //jobs
# Everything is deployed now: no changes.
title "Full plan again"
trace $CLI bundle plan
11 changes: 11 additions & 0 deletions acceptance/bundle/select/basic/test.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Local = true
Cloud = true
RecordRequests = true
# --select is only supported by the direct engine, so this happy-path test runs on
# direct only (the rejection on terraform is covered by bundle/select/rejected).
EnvMatrix.DATABRICKS_BUNDLE_ENGINE = ["direct"]
# Also run a variant that deploys a serialized (already filtered) plan via --plan.
EnvMatrix.READPLAN = ["", "1"]
# databricks.yml and the serialized plans are generated at runtime; the plan JSON
# is kept out of the recorded output because it embeds local/cloud-specific state.
Ignore = [".databricks", ".gitignore", "databricks.yml", "plan.json", "plan-full.json"]
7 changes: 7 additions & 0 deletions acceptance/bundle/select/missing/databricks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
bundle:
name: select-errors

resources:
jobs:
my_job:
name: my-job
3 changes: 3 additions & 0 deletions acceptance/bundle/select/missing/out.test.toml

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

12 changes: 12 additions & 0 deletions acceptance/bundle/select/missing/output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

>>> [CLI] bundle plan --select no_such_resource
Error: no such resource: no_such_resource


Exit code: 1

>>> [CLI] bundle plan --select jobs.no_such_job
Error: no such resource: jobs.no_such_job


Exit code: 1
8 changes: 8 additions & 0 deletions acceptance/bundle/select/missing/script
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Selectors are resolved by the ResolveSelect mutator during initialize, before the
# engine is known, so these errors are identical on both engines.

# Unqualified name that matches no resource.
errcode trace $CLI bundle plan --select no_such_resource

# Qualified name whose resource does not exist.
errcode trace $CLI bundle plan --select jobs.no_such_job
7 changes: 7 additions & 0 deletions acceptance/bundle/select/rejected/databricks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
bundle:
name: select-rejected

resources:
jobs:
my_job:
name: my-job
3 changes: 3 additions & 0 deletions acceptance/bundle/select/rejected/out.test.toml

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

12 changes: 12 additions & 0 deletions acceptance/bundle/select/rejected/output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

>>> [CLI] bundle plan --select my_job
Error: --select is only supported with the direct engine. See https://docs.databricks.com/aws/en/dev-tools/bundles/direct


Exit code: 1

>>> [CLI] bundle deploy --select my_job
Error: --select is only supported with the direct engine. See https://docs.databricks.com/aws/en/dev-tools/bundles/direct


Exit code: 1
3 changes: 3 additions & 0 deletions acceptance/bundle/select/rejected/script
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# --select is only supported by the direct engine; both plan and deploy reject it.
errcode trace $CLI bundle plan --select my_job
errcode trace $CLI bundle deploy --select my_job
2 changes: 2 additions & 0 deletions acceptance/bundle/select/rejected/test.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# --select is rejected on the terraform engine with an actionable error.
EnvMatrix.DATABRICKS_BUNDLE_ENGINE = ["terraform"]
3 changes: 3 additions & 0 deletions acceptance/bundle/select/test.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Local = true
Cloud = false
Ignore = [".databricks", ".gitignore"]
4 changes: 4 additions & 0 deletions bundle/bundle.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,10 @@ type Bundle struct {
// files
AutoApprove bool

// Select contains resource selectors passed via --select flag.
// When non-empty, only the specified resources are included in deployment.
Select []string
Comment thread
denik marked this conversation as resolved.

// SkipLocalFileValidation makes path translation tolerant of missing local files.
// When set, TranslatePaths computes workspace paths without verifying files exist.
// Used by config-remote-sync: a user may modify resource paths remotely (e.g.,
Expand Down
Loading
Loading