From 3253ed6f32ac3e8e5cd931fcbeaa4cad3c49a775 Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Thu, 2 Apr 2026 11:44:58 +0200 Subject: [PATCH 1/8] Add acceptance test reproducing bind stale state bug Bind uses ReadState (not AlwaysPull) when pulling deployment state, so it operates on stale local state instead of fetching the latest remote state. This test demonstrates the issue: after a second deploy bumps the remote serial, restoring an old local state and running bind causes the stale state to be pushed back, corrupting the remote state. Co-authored-by: Isaac --- .../bind/job/stale-state/databricks.yml | 7 +++++ .../bind/job/stale-state/databricks_v2.yml | 10 ++++++ .../bind/job/stale-state/out.test.toml | 5 +++ .../bind/job/stale-state/output.txt | 31 +++++++++++++++++++ .../deployment/bind/job/stale-state/script | 27 ++++++++++++++++ .../deployment/bind/job/stale-state/test.toml | 9 ++++++ 6 files changed, 89 insertions(+) create mode 100644 acceptance/bundle/deployment/bind/job/stale-state/databricks.yml create mode 100644 acceptance/bundle/deployment/bind/job/stale-state/databricks_v2.yml create mode 100644 acceptance/bundle/deployment/bind/job/stale-state/out.test.toml create mode 100644 acceptance/bundle/deployment/bind/job/stale-state/output.txt create mode 100755 acceptance/bundle/deployment/bind/job/stale-state/script create mode 100644 acceptance/bundle/deployment/bind/job/stale-state/test.toml diff --git a/acceptance/bundle/deployment/bind/job/stale-state/databricks.yml b/acceptance/bundle/deployment/bind/job/stale-state/databricks.yml new file mode 100644 index 0000000000..cb97b5ce96 --- /dev/null +++ b/acceptance/bundle/deployment/bind/job/stale-state/databricks.yml @@ -0,0 +1,7 @@ +bundle: + name: stale_state_test + +resources: + jobs: + job_1: + name: Job 1 diff --git a/acceptance/bundle/deployment/bind/job/stale-state/databricks_v2.yml b/acceptance/bundle/deployment/bind/job/stale-state/databricks_v2.yml new file mode 100644 index 0000000000..54a898ce3d --- /dev/null +++ b/acceptance/bundle/deployment/bind/job/stale-state/databricks_v2.yml @@ -0,0 +1,10 @@ +bundle: + name: stale_state_test + +resources: + jobs: + job_1: + name: Job 1 + + job_2: + name: Job 2 diff --git a/acceptance/bundle/deployment/bind/job/stale-state/out.test.toml b/acceptance/bundle/deployment/bind/job/stale-state/out.test.toml new file mode 100644 index 0000000000..54146af564 --- /dev/null +++ b/acceptance/bundle/deployment/bind/job/stale-state/out.test.toml @@ -0,0 +1,5 @@ +Local = true +Cloud = false + +[EnvMatrix] + DATABRICKS_BUNDLE_ENGINE = ["direct"] diff --git a/acceptance/bundle/deployment/bind/job/stale-state/output.txt b/acceptance/bundle/deployment/bind/job/stale-state/output.txt new file mode 100644 index 0000000000..c6c2a659c8 --- /dev/null +++ b/acceptance/bundle/deployment/bind/job/stale-state/output.txt @@ -0,0 +1,31 @@ + +=== Step 1: Deploy with job_1 only +>>> [CLI] bundle deploy +Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/stale_state_test/default/files... +Deploying resources... +Updating deployment state... +Deployment complete! + +=== Step 2: Save stale local state (has only job_1, serial=1) +=== Step 3: Add job_2 to config and deploy again +>>> [CLI] bundle deploy +Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/stale_state_test/default/files... +Deploying resources... +Updating deployment state... +Deployment complete! + +=== Step 4: Record deployed job_2 ID from stateDeployed job_2 ID: [DEPLOYED_JOB2_ID] + +=== Step 5: Restore stale local state (only job_1, serial=1) +=== Step 6: Create external job and bindExternal job ID: [EXTERNAL_JOB_ID] + +>>> [CLI] bundle deployment bind job_2 [EXTERNAL_JOB_ID] --auto-approve +Updating deployment state... +Successfully bound job with an id '[EXTERNAL_JOB_ID]' +Run 'bundle deploy' to deploy changes to your workspace + +=== Step 7: Remove local state and run plan to see remote state effect +>>> [CLI] bundle plan +update jobs.job_2 + +Plan: 0 to add, 1 to change, 0 to delete, 1 unchanged diff --git a/acceptance/bundle/deployment/bind/job/stale-state/script b/acceptance/bundle/deployment/bind/job/stale-state/script new file mode 100755 index 0000000000..c1b11c7017 --- /dev/null +++ b/acceptance/bundle/deployment/bind/job/stale-state/script @@ -0,0 +1,27 @@ +title "Step 1: Deploy with job_1 only" +trace $CLI bundle deploy + +title "Step 2: Save stale local state (has only job_1, serial=1)" +cp .databricks/bundle/default/resources.json stale_state.json + +title "Step 3: Add job_2 to config and deploy again" +cp databricks_v2.yml databricks.yml +trace $CLI bundle deploy + +title "Step 4: Record deployed job_2 ID from state" +deployed_job2_id=$(cat .databricks/bundle/default/resources.json | jq -r '.state["resources.jobs.job_2"].__id__') +add_repl.py "$deployed_job2_id" DEPLOYED_JOB2_ID +echo "Deployed job_2 ID: $deployed_job2_id" + +title "Step 5: Restore stale local state (only job_1, serial=1)" +cp stale_state.json .databricks/bundle/default/resources.json + +title "Step 6: Create external job and bind" +job_id=$($CLI jobs create --json '{"name": "External Job"}' | jq -r '.job_id') +add_repl.py "$job_id" EXTERNAL_JOB_ID +echo "External job ID: $job_id" +trace $CLI bundle deployment bind job_2 $job_id --auto-approve + +title "Step 7: Remove local state and run plan to see remote state effect" +rm -rf .databricks +trace $CLI bundle plan diff --git a/acceptance/bundle/deployment/bind/job/stale-state/test.toml b/acceptance/bundle/deployment/bind/job/stale-state/test.toml new file mode 100644 index 0000000000..de2e06c452 --- /dev/null +++ b/acceptance/bundle/deployment/bind/job/stale-state/test.toml @@ -0,0 +1,9 @@ +Cloud = false + +Ignore = [ + "databricks_v2.yml", + "stale_state.json", +] + +[EnvMatrix] +DATABRICKS_BUNDLE_ENGINE = ["direct"] From bf2fae40ea762a07e8244f126cdd6ebdabafcbbb Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Thu, 2 Apr 2026 11:49:37 +0200 Subject: [PATCH 2/8] Extend bind stale state test to cover both terraform and direct engines Use read_id.py and engine-conditional state file paths so the same test script and output work for both deployment engines. Co-authored-by: Isaac --- .../deployment/bind/job/stale-state/out.test.toml | 2 +- .../deployment/bind/job/stale-state/output.txt | 2 +- .../bundle/deployment/bind/job/stale-state/script | 14 +++++++++----- .../deployment/bind/job/stale-state/test.toml | 2 +- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/acceptance/bundle/deployment/bind/job/stale-state/out.test.toml b/acceptance/bundle/deployment/bind/job/stale-state/out.test.toml index 54146af564..d560f1de04 100644 --- a/acceptance/bundle/deployment/bind/job/stale-state/out.test.toml +++ b/acceptance/bundle/deployment/bind/job/stale-state/out.test.toml @@ -2,4 +2,4 @@ Local = true Cloud = false [EnvMatrix] - DATABRICKS_BUNDLE_ENGINE = ["direct"] + DATABRICKS_BUNDLE_ENGINE = ["terraform", "direct"] diff --git a/acceptance/bundle/deployment/bind/job/stale-state/output.txt b/acceptance/bundle/deployment/bind/job/stale-state/output.txt index c6c2a659c8..ba20db0f7e 100644 --- a/acceptance/bundle/deployment/bind/job/stale-state/output.txt +++ b/acceptance/bundle/deployment/bind/job/stale-state/output.txt @@ -14,7 +14,7 @@ Deploying resources... Updating deployment state... Deployment complete! -=== Step 4: Record deployed job_2 ID from stateDeployed job_2 ID: [DEPLOYED_JOB2_ID] +=== Step 4: Record deployed job_2 ID from stateDeployed job_2 ID: [JOB_2_ID] === Step 5: Restore stale local state (only job_1, serial=1) === Step 6: Create external job and bindExternal job ID: [EXTERNAL_JOB_ID] diff --git a/acceptance/bundle/deployment/bind/job/stale-state/script b/acceptance/bundle/deployment/bind/job/stale-state/script index c1b11c7017..7d1a6cbb74 100755 --- a/acceptance/bundle/deployment/bind/job/stale-state/script +++ b/acceptance/bundle/deployment/bind/job/stale-state/script @@ -1,20 +1,24 @@ +if [ "$DATABRICKS_BUNDLE_ENGINE" = "direct" ]; then + state_file=".databricks/bundle/default/resources.json" +else + state_file=".databricks/bundle/default/terraform/terraform.tfstate" +fi + title "Step 1: Deploy with job_1 only" trace $CLI bundle deploy title "Step 2: Save stale local state (has only job_1, serial=1)" -cp .databricks/bundle/default/resources.json stale_state.json +cp "$state_file" stale_state.json title "Step 3: Add job_2 to config and deploy again" cp databricks_v2.yml databricks.yml trace $CLI bundle deploy title "Step 4: Record deployed job_2 ID from state" -deployed_job2_id=$(cat .databricks/bundle/default/resources.json | jq -r '.state["resources.jobs.job_2"].__id__') -add_repl.py "$deployed_job2_id" DEPLOYED_JOB2_ID -echo "Deployed job_2 ID: $deployed_job2_id" +echo "Deployed job_2 ID: $(read_id.py job_2)" title "Step 5: Restore stale local state (only job_1, serial=1)" -cp stale_state.json .databricks/bundle/default/resources.json +cp stale_state.json "$state_file" title "Step 6: Create external job and bind" job_id=$($CLI jobs create --json '{"name": "External Job"}' | jq -r '.job_id') diff --git a/acceptance/bundle/deployment/bind/job/stale-state/test.toml b/acceptance/bundle/deployment/bind/job/stale-state/test.toml index de2e06c452..df072247ba 100644 --- a/acceptance/bundle/deployment/bind/job/stale-state/test.toml +++ b/acceptance/bundle/deployment/bind/job/stale-state/test.toml @@ -6,4 +6,4 @@ Ignore = [ ] [EnvMatrix] -DATABRICKS_BUNDLE_ENGINE = ["direct"] +DATABRICKS_BUNDLE_ENGINE = ["terraform", "direct"] From 2f444e5baf5e73e5baed7fc496ec6ed894e06452 Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Thu, 2 Apr 2026 11:54:43 +0200 Subject: [PATCH 3/8] Add acceptance test for bind cross-engine lineage mismatch Deploy with terraform, bind a pipeline, remove local state, then bind another pipeline with direct engine. The direct bind creates a new state with a different lineage instead of using the existing terraform state, causing bundle summary to fail with lineage mismatch. Co-authored-by: Isaac --- .../bind/cross-engine/databricks.yml | 10 ++++++ .../bind/cross-engine/databricks_empty.yml | 2 ++ .../bind/cross-engine/databricks_p1.yml | 7 ++++ .../bind/cross-engine/out.test.toml | 5 +++ .../deployment/bind/cross-engine/output.txt | 32 +++++++++++++++++++ .../deployment/bind/cross-engine/script | 25 +++++++++++++++ .../deployment/bind/cross-engine/test.toml | 11 +++++++ 7 files changed, 92 insertions(+) create mode 100644 acceptance/bundle/deployment/bind/cross-engine/databricks.yml create mode 100644 acceptance/bundle/deployment/bind/cross-engine/databricks_empty.yml create mode 100644 acceptance/bundle/deployment/bind/cross-engine/databricks_p1.yml create mode 100644 acceptance/bundle/deployment/bind/cross-engine/out.test.toml create mode 100644 acceptance/bundle/deployment/bind/cross-engine/output.txt create mode 100755 acceptance/bundle/deployment/bind/cross-engine/script create mode 100644 acceptance/bundle/deployment/bind/cross-engine/test.toml diff --git a/acceptance/bundle/deployment/bind/cross-engine/databricks.yml b/acceptance/bundle/deployment/bind/cross-engine/databricks.yml new file mode 100644 index 0000000000..9deddbdf30 --- /dev/null +++ b/acceptance/bundle/deployment/bind/cross-engine/databricks.yml @@ -0,0 +1,10 @@ +bundle: + name: cross-engine-bind + +resources: + pipelines: + pipeline_1: + name: Pipeline 1 + + pipeline_2: + name: Pipeline 2 diff --git a/acceptance/bundle/deployment/bind/cross-engine/databricks_empty.yml b/acceptance/bundle/deployment/bind/cross-engine/databricks_empty.yml new file mode 100644 index 0000000000..87dfce028e --- /dev/null +++ b/acceptance/bundle/deployment/bind/cross-engine/databricks_empty.yml @@ -0,0 +1,2 @@ +bundle: + name: cross-engine-bind diff --git a/acceptance/bundle/deployment/bind/cross-engine/databricks_p1.yml b/acceptance/bundle/deployment/bind/cross-engine/databricks_p1.yml new file mode 100644 index 0000000000..8d99284161 --- /dev/null +++ b/acceptance/bundle/deployment/bind/cross-engine/databricks_p1.yml @@ -0,0 +1,7 @@ +bundle: + name: cross-engine-bind + +resources: + pipelines: + pipeline_1: + name: Pipeline 1 diff --git a/acceptance/bundle/deployment/bind/cross-engine/out.test.toml b/acceptance/bundle/deployment/bind/cross-engine/out.test.toml new file mode 100644 index 0000000000..54146af564 --- /dev/null +++ b/acceptance/bundle/deployment/bind/cross-engine/out.test.toml @@ -0,0 +1,5 @@ +Local = true +Cloud = false + +[EnvMatrix] + DATABRICKS_BUNDLE_ENGINE = ["direct"] diff --git a/acceptance/bundle/deployment/bind/cross-engine/output.txt b/acceptance/bundle/deployment/bind/cross-engine/output.txt new file mode 100644 index 0000000000..bee49be1ad --- /dev/null +++ b/acceptance/bundle/deployment/bind/cross-engine/output.txt @@ -0,0 +1,32 @@ + +=== Step 1: Deploy empty bundle with terraform engine +>>> [CLI] bundle deploy +Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/cross-engine-bind/default/files... +Deploying resources... +Deployment complete! + +=== Step 2: Add pipeline_1 and bind with terraform engine +>>> [CLI] bundle deployment bind pipeline_1 [PIPELINE_1_ID] --auto-approve +Updating deployment state... +Successfully bound pipeline with an id '[PIPELINE_1_ID]' +Run 'bundle deploy' to deploy changes to your workspace + +=== Step 3: Remove local state +>>> rm -rf .databricks + +=== Step 4: Add pipeline_2 config and bind with direct engine +>>> [CLI] bundle deployment bind pipeline_2 [PIPELINE_2_ID] --auto-approve +Updating deployment state... +Successfully bound pipeline with an id '[PIPELINE_2_ID]' +Run 'bundle deploy' to deploy changes to your workspace + +=== Step 5: Run summary +>>> errcode [CLI] bundle summary +Error: lineage mismatch in state files + +Available state files: +- [TEST_TMP_DIR]/.databricks/bundle/default/terraform/terraform.tfstate: local terraform state serial=1 lineage="[UUID]" +- [TEST_TMP_DIR]/.databricks/bundle/default/resources.json: local direct state serial=2 lineage="[UUID]" + + +Exit code: 1 diff --git a/acceptance/bundle/deployment/bind/cross-engine/script b/acceptance/bundle/deployment/bind/cross-engine/script new file mode 100755 index 0000000000..f08ebd0278 --- /dev/null +++ b/acceptance/bundle/deployment/bind/cross-engine/script @@ -0,0 +1,25 @@ +title "Step 1: Deploy empty bundle with terraform engine" +cp databricks_empty.yml databricks.yml +DATABRICKS_BUNDLE_ENGINE=terraform trace $CLI bundle deploy + +title "Step 2: Add pipeline_1 and bind with terraform engine" +cp databricks_p1.yml databricks.yml +p1_id=$($CLI pipelines create --json '{"name": "External Pipeline 1"}' | jq -r '.pipeline_id') +add_repl.py "$p1_id" PIPELINE_1_ID +DATABRICKS_BUNDLE_ENGINE=terraform trace $CLI bundle deployment bind pipeline_1 $p1_id --auto-approve + +title "Step 3: Remove local state" +trace rm -rf .databricks + +title "Step 4: Add pipeline_2 config and bind with direct engine" +cat >> databricks.yml < Date: Thu, 2 Apr 2026 12:00:04 +0200 Subject: [PATCH 4/8] Fix bind to always pull remote state before modifying Bind used ReadState (local-only when a local file exists) instead of AlwaysPull, so it could operate on stale local state and push it back to remote, overwriting newer state from other deployments. Change bind_resource.go and apps/import.go to use AlwaysPull, matching what unbind already does. Update the stale-state acceptance test to verify bind now correctly detects the already-managed resource. Co-authored-by: Isaac --- .../bind/job/stale-state/out.bind.direct.txt | 9 +++++++++ .../bind/job/stale-state/out.bind.terraform.txt | 14 ++++++++++++++ .../deployment/bind/job/stale-state/output.txt | 13 +------------ .../bundle/deployment/bind/job/stale-state/script | 8 ++------ cmd/apps/import.go | 2 +- cmd/bundle/deployment/bind_resource.go | 2 +- 6 files changed, 28 insertions(+), 20 deletions(-) create mode 100644 acceptance/bundle/deployment/bind/job/stale-state/out.bind.direct.txt create mode 100644 acceptance/bundle/deployment/bind/job/stale-state/out.bind.terraform.txt diff --git a/acceptance/bundle/deployment/bind/job/stale-state/out.bind.direct.txt b/acceptance/bundle/deployment/bind/job/stale-state/out.bind.direct.txt new file mode 100644 index 0000000000..b03475c6c2 --- /dev/null +++ b/acceptance/bundle/deployment/bind/job/stale-state/out.bind.direct.txt @@ -0,0 +1,9 @@ + +>>> errcode [CLI] bundle deployment bind job_2 [EXTERNAL_JOB_ID] --auto-approve +Error: Resource already managed + +The bundle is already managing a resource for resources.jobs.job_2 with ID '[JOB_2_ID]'. +To bind to a different resource with ID '[EXTERNAL_JOB_ID]', you must first unbind the existing resource. + + +Exit code: 1 diff --git a/acceptance/bundle/deployment/bind/job/stale-state/out.bind.terraform.txt b/acceptance/bundle/deployment/bind/job/stale-state/out.bind.terraform.txt new file mode 100644 index 0000000000..88dabf9f20 --- /dev/null +++ b/acceptance/bundle/deployment/bind/job/stale-state/out.bind.terraform.txt @@ -0,0 +1,14 @@ + +>>> errcode [CLI] bundle deployment bind job_2 [EXTERNAL_JOB_ID] --auto-approve +Error: terraform import: exit status 1 + +Error: Resource already managed by Terraform + +Terraform is already managing a remote object for databricks_job.job_2. To +import to this address you must first remove the existing object from the +state. + + + + +Exit code: 1 diff --git a/acceptance/bundle/deployment/bind/job/stale-state/output.txt b/acceptance/bundle/deployment/bind/job/stale-state/output.txt index ba20db0f7e..446f34de7f 100644 --- a/acceptance/bundle/deployment/bind/job/stale-state/output.txt +++ b/acceptance/bundle/deployment/bind/job/stale-state/output.txt @@ -17,15 +17,4 @@ Deployment complete! === Step 4: Record deployed job_2 ID from stateDeployed job_2 ID: [JOB_2_ID] === Step 5: Restore stale local state (only job_1, serial=1) -=== Step 6: Create external job and bindExternal job ID: [EXTERNAL_JOB_ID] - ->>> [CLI] bundle deployment bind job_2 [EXTERNAL_JOB_ID] --auto-approve -Updating deployment state... -Successfully bound job with an id '[EXTERNAL_JOB_ID]' -Run 'bundle deploy' to deploy changes to your workspace - -=== Step 7: Remove local state and run plan to see remote state effect ->>> [CLI] bundle plan -update jobs.job_2 - -Plan: 0 to add, 1 to change, 0 to delete, 1 unchanged +=== Step 6: Create external job and try to bind (should fail: remote state already has job_2)External job ID: [EXTERNAL_JOB_ID] diff --git a/acceptance/bundle/deployment/bind/job/stale-state/script b/acceptance/bundle/deployment/bind/job/stale-state/script index 7d1a6cbb74..0e05b38a8a 100755 --- a/acceptance/bundle/deployment/bind/job/stale-state/script +++ b/acceptance/bundle/deployment/bind/job/stale-state/script @@ -20,12 +20,8 @@ echo "Deployed job_2 ID: $(read_id.py job_2)" title "Step 5: Restore stale local state (only job_1, serial=1)" cp stale_state.json "$state_file" -title "Step 6: Create external job and bind" +title "Step 6: Create external job and try to bind (should fail: remote state already has job_2)" job_id=$($CLI jobs create --json '{"name": "External Job"}' | jq -r '.job_id') add_repl.py "$job_id" EXTERNAL_JOB_ID echo "External job ID: $job_id" -trace $CLI bundle deployment bind job_2 $job_id --auto-approve - -title "Step 7: Remove local state and run plan to see remote state effect" -rm -rf .databricks -trace $CLI bundle plan +trace errcode $CLI bundle deployment bind job_2 $job_id --auto-approve &> out.bind.$DATABRICKS_BUNDLE_ENGINE.txt diff --git a/cmd/apps/import.go b/cmd/apps/import.go index de6529cf3c..7aae1fe43a 100644 --- a/cmd/apps/import.go +++ b/cmd/apps/import.go @@ -298,7 +298,7 @@ func runImport(ctx context.Context, w *databricks.WorkspaceClient, appName, outp var err error b, err = bundleutils.ProcessBundle(bindCmd, bundleutils.ProcessOptions{ SkipInitContext: true, - ReadState: true, + AlwaysPull: true, InitFunc: func(b *bundle.Bundle) { b.Config.Bundle.Deployment.Lock.Force = false }, diff --git a/cmd/bundle/deployment/bind_resource.go b/cmd/bundle/deployment/bind_resource.go index 4fcee8b07f..8a766f240c 100644 --- a/cmd/bundle/deployment/bind_resource.go +++ b/cmd/bundle/deployment/bind_resource.go @@ -18,7 +18,7 @@ import ( func BindResource(cmd *cobra.Command, resourceKey, resourceId string, autoApprove, forceLock, skipInitContext bool) error { b, err := utils.ProcessBundle(cmd, utils.ProcessOptions{ SkipInitContext: skipInitContext, - ReadState: true, + AlwaysPull: true, InitFunc: func(b *bundle.Bundle) { b.Config.Bundle.Deployment.Lock.Force = forceLock }, From 99b9cf3c6d6397fc5a1f530c0791460d179fd40f Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Thu, 2 Apr 2026 12:57:34 +0200 Subject: [PATCH 5/8] update --- acceptance/bundle/deployment/bind/job/stale-state/output.txt | 3 ++- acceptance/bundle/deployment/bind/job/stale-state/script | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/acceptance/bundle/deployment/bind/job/stale-state/output.txt b/acceptance/bundle/deployment/bind/job/stale-state/output.txt index 446f34de7f..815586e6d4 100644 --- a/acceptance/bundle/deployment/bind/job/stale-state/output.txt +++ b/acceptance/bundle/deployment/bind/job/stale-state/output.txt @@ -17,4 +17,5 @@ Deployment complete! === Step 4: Record deployed job_2 ID from stateDeployed job_2 ID: [JOB_2_ID] === Step 5: Restore stale local state (only job_1, serial=1) -=== Step 6: Create external job and try to bind (should fail: remote state already has job_2)External job ID: [EXTERNAL_JOB_ID] +=== Step 6: Create external job and try to bind (should fail: remote state already has job_2) +External job ID: [EXTERNAL_JOB_ID] diff --git a/acceptance/bundle/deployment/bind/job/stale-state/script b/acceptance/bundle/deployment/bind/job/stale-state/script index 0e05b38a8a..32a2d3fb47 100755 --- a/acceptance/bundle/deployment/bind/job/stale-state/script +++ b/acceptance/bundle/deployment/bind/job/stale-state/script @@ -20,7 +20,7 @@ echo "Deployed job_2 ID: $(read_id.py job_2)" title "Step 5: Restore stale local state (only job_1, serial=1)" cp stale_state.json "$state_file" -title "Step 6: Create external job and try to bind (should fail: remote state already has job_2)" +title "Step 6: Create external job and try to bind (should fail: remote state already has job_2)\n" job_id=$($CLI jobs create --json '{"name": "External Job"}' | jq -r '.job_id') add_repl.py "$job_id" EXTERNAL_JOB_ID echo "External job ID: $job_id" From d1a244dbde27ff125d98efc77fba1e5840c6646b Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Thu, 2 Apr 2026 15:04:50 +0200 Subject: [PATCH 6/8] Update NEXT_CHANGELOG with bind remote state fix entry Co-authored-by: Isaac --- NEXT_CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/NEXT_CHANGELOG.md b/NEXT_CHANGELOG.md index 2c13750d4b..4e7203d2bd 100644 --- a/NEXT_CHANGELOG.md +++ b/NEXT_CHANGELOG.md @@ -13,6 +13,7 @@ * Deduplicate grant entries with duplicate principals or privileges during initialization ([#4801](https://github.com/databricks/cli/pull/4801)) * engine/direct: Fix unwanted recreation of secret scopes when scope_backend_type is not set ([#4834](https://github.com/databricks/cli/pull/4834)) * engine/direct: Fix bind and unbind for non-Terraform resources ([#4850](https://github.com/databricks/cli/pull/4850)) +* Fix `bundle deployment bind` to always pull remote state before modifying (denik/investigate-dir) * engine/direct: Fix deploying removed principals ([#4824](https://github.com/databricks/cli/pull/4824)) * engine/direct: Fix secret scope permissions migration from Terraform to Direct engine ([#4866](https://github.com/databricks/cli/pull/4866)) From 89eddb4b45fe38522688cb4ecad5908c39c1a336 Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Thu, 2 Apr 2026 15:59:30 +0200 Subject: [PATCH 7/8] Update NEXT_CHANGELOG.md with PR #4892 --- NEXT_CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEXT_CHANGELOG.md b/NEXT_CHANGELOG.md index 4e7203d2bd..db84656673 100644 --- a/NEXT_CHANGELOG.md +++ b/NEXT_CHANGELOG.md @@ -13,7 +13,7 @@ * Deduplicate grant entries with duplicate principals or privileges during initialization ([#4801](https://github.com/databricks/cli/pull/4801)) * engine/direct: Fix unwanted recreation of secret scopes when scope_backend_type is not set ([#4834](https://github.com/databricks/cli/pull/4834)) * engine/direct: Fix bind and unbind for non-Terraform resources ([#4850](https://github.com/databricks/cli/pull/4850)) -* Fix `bundle deployment bind` to always pull remote state before modifying (denik/investigate-dir) +* Fix `bundle deployment bind` to always pull remote state before modifying ([#4892](https://github.com/databricks/cli/pull/4892)) * engine/direct: Fix deploying removed principals ([#4824](https://github.com/databricks/cli/pull/4824)) * engine/direct: Fix secret scope permissions migration from Terraform to Direct engine ([#4866](https://github.com/databricks/cli/pull/4866)) From 7c2aabe2efbd2c83fb21a4d5d7ec9ffc245e7c42 Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Thu, 2 Apr 2026 16:01:40 +0200 Subject: [PATCH 8/8] changelog entry last --- NEXT_CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEXT_CHANGELOG.md b/NEXT_CHANGELOG.md index db84656673..578e2f5708 100644 --- a/NEXT_CHANGELOG.md +++ b/NEXT_CHANGELOG.md @@ -13,9 +13,9 @@ * Deduplicate grant entries with duplicate principals or privileges during initialization ([#4801](https://github.com/databricks/cli/pull/4801)) * engine/direct: Fix unwanted recreation of secret scopes when scope_backend_type is not set ([#4834](https://github.com/databricks/cli/pull/4834)) * engine/direct: Fix bind and unbind for non-Terraform resources ([#4850](https://github.com/databricks/cli/pull/4850)) -* Fix `bundle deployment bind` to always pull remote state before modifying ([#4892](https://github.com/databricks/cli/pull/4892)) * engine/direct: Fix deploying removed principals ([#4824](https://github.com/databricks/cli/pull/4824)) * engine/direct: Fix secret scope permissions migration from Terraform to Direct engine ([#4866](https://github.com/databricks/cli/pull/4866)) +* Fix `bundle deployment bind` to always pull remote state before modifying ([#4892](https://github.com/databricks/cli/pull/4892)) ### Dependency updates