Skip to content

Avoid syncing cluster policy values into shared bundle config - #7170

Merged
ilyakuz-db merged 12 commits into
mainfrom
ilyakuz-db/fix-policy-values-in-remote-sync
Nov 4, 2026
Merged

ilyakuz-db merged 12 commits into
mainfrom
ilyakuz-db/fix-policy-values-in-remote-sync

Conversation

@ilyakuz-db

@ilyakuz-db ilyakuz-db commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Changes

config-remote-sync no longer copies cluster policy values into bundle YAML. After changes are extracted and selected, job and cluster specs whose remote policy_id is set are checked against that policy (read lazily, once per sync):

  • Fields under fixed rules, including * wildcards, are never synced. The backend rejects any other value for them, so the remote value always comes from the policy.
  • Fields under other rules are dropped only when they equal the policy defaultValue and apply_policy_default_values is set; any other value is a user edit and syncs.
  • Values authored in YAML are kept, and policy values never remove them.
  • If the policy no longer exists, policy-dependent fields are listed in skippedChanges with the new partial status, and other edits still sync.

Clusters without a policy are not filtered. The blanket custom_tags/cluster_log_conf skip is removed, so tags added in the UI now sync.

Why

Syncing a UI edit could copy one target's policy values into shared YAML, and deploying that YAML to a target with a different policy then failed validation.

Tests

Unit tests for rule matching, plus acceptance tests for cross-target deploys, missing policies and deploy-and-plan after sync.

This PR was written with assistance from Codex.

This pull request and its description were written by Isaac.

@github-actions github-actions Bot added the DABs DABs related issues label Oct 23, 2026
@github-actions

github-actions Bot commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Commit: 614f1e23a | Workflow run

Regression test report

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

12 tests: regression=10 unreleased=0 coverage=2 failing=0

test branch main (aae07ca) latest (v1.23.0)
TestAccept/bundle/config-remote-sync/cluster_policy_cross_target/DMS= ✅ ❌ ❌
TestAccept/bundle/config-remote-sync/cluster_policy_cross_target/DMS=true ✅ ❌ ❌
TestAccept/bundle/config-remote-sync/cluster_policy_remote_addition/DMS= ✅ ❌ ❌
TestAccept/bundle/config-remote-sync/cluster_policy_remote_addition/DMS=true ✅ ❌ ❌
TestAccept/bundle/config-remote-sync/cluster_policy_replaces_array/DMS= ✅ ❌ ❌
TestAccept/bundle/config-remote-sync/cluster_policy_replaces_array/DMS=true ✅ ❌ ❌
TestAccept/bundle/config-remote-sync/external_cluster_policy_cross_target/DMS= ✅ ❌ ❌
TestAccept/bundle/config-remote-sync/external_cluster_policy_cross_target/DMS=true ✅ ❌ ❌
TestAccept/bundle/config-remote-sync/missing_cluster_policy/DMS= ✅ ❌ ❌
TestAccept/bundle/config-remote-sync/missing_cluster_policy/DMS=true ✅ ❌ ❌
TestAccept/bundle/config-remote-sync/policy_injected_cluster_fields/DMS= ✅ ✅ ✅
TestAccept/bundle/config-remote-sync/policy_injected_cluster_fields/DMS=true ✅ ✅ ✅
TestAccept/bundle/config-remote-sync/cluster_policy_cross_target/DMS=: branch ✅ | main (aae07ca) ❌ | latest (v1.23.0) ❌

main (aae07ca):

acceptance_test.go:1342: Diff:
        --- bundle/config-remote-sync/cluster_policy_cross_target/output.txt
        +++ /tmp/TestAcceptbundleconfig-remote-synccluster_policy_cross_target3688756387/002/output.txt
        @@ -13,6 +13,9 @@
         
         Resource: resources.jobs.policy_sync
           description: replace
        +  job_clusters[job_cluster_key='main'].new_cluster.custom_tags['workspace']: add
        +  job_clusters[job_cluster_key='main'].new_cluster.spark_env_vars: add
        +  job_clusters[job_cluster_key='main'].new_cluster.workload_type: add
         
         
         
        @@ -26,56 +29,39 @@
         +      description: Edited in the UI
                job_clusters:
                  - job_cluster_key: main
        -
        -=== Deploy shared YAML with the prod policy
        ->>> [CLI] bundle deploy -t prod
        -Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/[UNIQUE_NAME]/prod/files...
        -Created cluster_policies.policy
        -Created jobs.policy_sync
        -Files: 4 uploaded, 0 deleted
        -Resources: 2 created, 0 changed, 0 deleted, 0 unchanged
        -
        -=== Add a user tag beside the policy tag in the UI
        ->>> [CLI] bundle config-remote-sync -t dev --save
        -Detected changes in 1 resource(s):
        -
        -Resource: resources.jobs.policy_sync
        -  job_clusters[job_cluster_key='main'].new_cluster.custom_tags['UserTag']: add
        -
        -
        -
        ->>> diff.py databricks.yml.backup databricks.yml
        ---- databricks.yml.backup
        -+++ databricks.yml
        -@@ -39,4 +39,5 @@
        +@@ -39,4 +39,11 @@
                      custom_tags:
                        owner: bundle-author
        -+              UserTag: edited-in-ui
        ++              workspace: dev
        ++            spark_env_vars:
        ++              ENVIRONMENT: dev
        ++            workload_type:
        ++              clients:
        ++                jobs: true
        ++                notebooks: false
                tasks:
                  - task_key: main
         
        -=== Deploy the user tag with the prod policy
        +=== Deploy shared YAML with the prod policy
         >>> [CLI] bundle deploy -t prod
         Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/[UNIQUE_NAME]/prod/files...
        -Updated jobs.policy_sync
        -Files: 2 uploaded, 0 deleted
        -Resources: 0 created, 1 changed, 0 deleted, 1 unchanged
        +Created cluster_policies.policy
        +Error: cannot create resources.jobs.policy_sync: Cluster validation error: Validation failed for custom_tags, workspace must be prod (is "dev") (400 INVALID_PARAMETER_VALUE)
         
        ->>> [CLI] jobs get [POLICY_SYNC_ID_2] -o json
        -{
        -  "UserTag": "edited-in-ui",
        -  "owner": "bundle-author",
        -  "workspace": "prod"
        -}
        +Endpoint: POST [DATABRICKS_URL]/api/2.2/jobs/create
        +HTTP Status: 400 Bad Request
        +API error_code: INVALID_PARAMETER_VALUE
        +API message: Cluster validation error: Validation failed for custom_tags, workspace must be prod (is "dev")
         
        +Files: 4 uploaded, 0 deleted
        +
         >>> [CLI] bundle destroy -t prod --auto-approve
         The following resources will be deleted:
           delete resources.cluster_policies.policy
        -  delete resources.jobs.policy_sync
         
         All files and directories at the following location will be deleted: /Workspace/Users/[USERNAME]/.bundle/[UNIQUE_NAME]/prod
         
        -Destroy: 2 deleted
        +Destroy: 1 deleted
         
         >>> [CLI] bundle destroy -t dev --auto-approve
         The following resources will be deleted:
        @@ -85,3 +56,5 @@
         All files and directories at the following location will be deleted: /Workspace/Users/[USERNAME]/.bundle/[UNIQUE_NAME]/dev
         
         Destroy: 2 deleted
        +
        +Exit code: 1

latest (v1.23.0): same output as main (aae07ca)

TestAccept/bundle/config-remote-sync/cluster_policy_cross_target/DMS=true: branch ✅ | main (aae07ca) ❌ | latest (v1.23.0) ❌

main (aae07ca):

acceptance_test.go:1342: Diff:
        --- bundle/config-remote-sync/cluster_policy_cross_target/output.txt
        +++ /tmp/TestAcceptbundleconfig-remote-synccluster_policy_cross_target552116436/002/output.txt
        @@ -13,6 +13,9 @@
         
         Resource: resources.jobs.policy_sync
           description: replace
        +  job_clusters[job_cluster_key='main'].new_cluster.custom_tags['workspace']: add
        +  job_clusters[job_cluster_key='main'].new_cluster.spark_env_vars: add
        +  job_clusters[job_cluster_key='main'].new_cluster.workload_type: add
         
         
         
        @@ -26,56 +29,39 @@
         +      description: Edited in the UI
                job_clusters:
                  - job_cluster_key: main
        -
        -=== Deploy shared YAML with the prod policy
        ->>> [CLI] bundle deploy -t prod
        -Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/[UNIQUE_NAME]/prod/files...
        -Created cluster_policies.policy
        -Created jobs.policy_sync
        -Files: 4 uploaded, 0 deleted
        -Resources: 2 created, 0 changed, 0 deleted, 0 unchanged
        -
        -=== Add a user tag beside the policy tag in the UI
        ->>> [CLI] bundle config-remote-sync -t dev --save
        -Detected changes in 1 resource(s):
        -
        -Resource: resources.jobs.policy_sync
        -  job_clusters[job_cluster_key='main'].new_cluster.custom_tags['UserTag']: add
        -
        -
        -
        ->>> diff.py databricks.yml.backup databricks.yml
        ---- databricks.yml.backup
        -+++ databricks.yml
        -@@ -39,4 +39,5 @@
        +@@ -39,4 +39,11 @@
                      custom_tags:
                        owner: bundle-author
        -+              UserTag: edited-in-ui
        ++              workspace: dev
        ++            spark_env_vars:
        ++              ENVIRONMENT: dev
        ++            workload_type:
        ++              clients:
        ++                jobs: true
        ++                notebooks: false
                tasks:
                  - task_key: main
         
        -=== Deploy the user tag with the prod policy
        +=== Deploy shared YAML with the prod policy
         >>> [CLI] bundle deploy -t prod
         Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/[UNIQUE_NAME]/prod/files...
        -Updated jobs.policy_sync
        -Files: 2 uploaded, 0 deleted
        -Resources: 0 created, 1 changed, 0 deleted, 1 unchanged
        +Created cluster_policies.policy
        +Error: cannot create resources.jobs.policy_sync: Cluster validation error: Validation failed for custom_tags, workspace must be prod (is "dev") (400 INVALID_PARAMETER_VALUE)
         
        ->>> [CLI] jobs get [POLICY_SYNC_ID_2] -o json
        -{
        -  "UserTag": "edited-in-ui",
        -  "owner": "bundle-author",
        -  "workspace": "prod"
        -}
        +Endpoint: POST [DATABRICKS_URL]/api/2.2/jobs/create
        +HTTP Status: 400 Bad Request
        +API error_code: INVALID_PARAMETER_VALUE
        +API message: Cluster validation error: Validation failed for custom_tags, workspace must be prod (is "dev")
         
        +Files: 4 uploaded, 0 deleted
        +
         >>> [CLI] bundle destroy -t prod --auto-approve
         The following resources will be deleted:
           delete resources.cluster_policies.policy
        -  delete resources.jobs.policy_sync
         
         All files and directories at the following location will be deleted: /Workspace/Users/[USERNAME]/.bundle/[UNIQUE_NAME]/prod
         
        -Destroy: 2 deleted
        +Destroy: 1 deleted
         
         >>> [CLI] bundle destroy -t dev --auto-approve
         The following resources will be deleted:
        @@ -85,3 +56,5 @@
         All files and directories at the following location will be deleted: /Workspace/Users/[USERNAME]/.bundle/[UNIQUE_NAME]/dev
         
         Destroy: 2 deleted
        +
        +Exit code: 1

latest (v1.23.0): same output as main (aae07ca)

TestAccept/bundle/config-remote-sync/cluster_policy_remote_addition/DMS=: branch ✅ | main (aae07ca) ❌ | latest (v1.23.0) ❌

main (aae07ca):

acceptance_test.go:1342: Diff:
        --- bundle/config-remote-sync/cluster_policy_remote_addition/output.txt
        +++ /tmp/TestAcceptbundleconfig-remote-synccluster_policy_remote_addit4086630105/002/output.txt
        @@ -10,7 +10,6 @@
         Detected changes in 1 resource(s):
         
         Resource: resources.jobs.test_job
        -  tasks[task_key='test'].new_cluster.custom_tags: add
           tasks[task_key='test'].new_cluster.spark_conf: add
         
         
        @@ -18,11 +17,9 @@
         >>> diff.py databricks.yml.backup databricks.yml
         --- databricks.yml.backup
         +++ databricks.yml
        -@@ -24,4 +24,8 @@
        +@@ -24,4 +24,6 @@
                      node_type_id: [NODE_TYPE_ID]
                      num_workers: 1
        -+            custom_tags:
        -+              UserTag: edited-in-ui
         +            spark_conf:
         +              spark.sql.shuffle.partitions: "7"
                    spark_python_task:
        @@ -31,9 +26,8 @@
         === Synced config deploys and converges under the policy
         >>> [CLI] bundle deploy
         Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/[UNIQUE_NAME]/files...
        -Updated jobs.test_job
         Files: 1 uploaded, 0 deleted
        -Resources: 0 created, 1 changed, 0 deleted, 1 unchanged
        +Resources: 0 created, 0 changed, 0 deleted, 2 unchanged
         
         >>> [CLI] bundle plan
         Plan: 0 to add, 0 to change, 0 to delete, 2 unchanged
        @@ -50,12 +43,10 @@
         >>> diff.py databricks.yml.backup databricks.yml
         --- databricks.yml.backup
         +++ databricks.yml
        -@@ -30,2 +30,14 @@
        +@@ -28,2 +28,12 @@
                    spark_python_task:
                      python_file: ./hello.py
         +        - new_cluster:
        -+            custom_tags:
        -+              UserTag: new-task
         +            node_type_id: [NODE_TYPE_ID]
         +            num_workers: 1
         +            policy_id: ${resources.cluster_policies.policy.id}

latest (v1.23.0): same output as main (aae07ca)

TestAccept/bundle/config-remote-sync/cluster_policy_remote_addition/DMS=true: branch ✅ | main (aae07ca) ❌ | latest (v1.23.0) ❌

main (aae07ca):

acceptance_test.go:1342: Diff:
        --- bundle/config-remote-sync/cluster_policy_remote_addition/output.txt
        +++ /tmp/TestAcceptbundleconfig-remote-synccluster_policy_remote_addit2306557786/002/output.txt
        @@ -10,7 +10,6 @@
         Detected changes in 1 resource(s):
         
         Resource: resources.jobs.test_job
        -  tasks[task_key='test'].new_cluster.custom_tags: add
           tasks[task_key='test'].new_cluster.spark_conf: add
         
         
        @@ -18,11 +17,9 @@
         >>> diff.py databricks.yml.backup databricks.yml
         --- databricks.yml.backup
         +++ databricks.yml
        -@@ -24,4 +24,8 @@
        +@@ -24,4 +24,6 @@
                      node_type_id: [NODE_TYPE_ID]
                      num_workers: 1
        -+            custom_tags:
        -+              UserTag: edited-in-ui
         +            spark_conf:
         +              spark.sql.shuffle.partitions: "7"
                    spark_python_task:
        @@ -31,9 +26,8 @@
         === Synced config deploys and converges under the policy
         >>> [CLI] bundle deploy
         Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/[UNIQUE_NAME]/files...
        -Updated jobs.test_job
         Files: 1 uploaded, 0 deleted
        -Resources: 0 created, 1 changed, 0 deleted, 1 unchanged
        +Resources: 0 created, 0 changed, 0 deleted, 2 unchanged
         
         >>> [CLI] bundle plan
         Plan: 0 to add, 0 to change, 0 to delete, 2 unchanged
        @@ -50,12 +43,10 @@
         >>> diff.py databricks.yml.backup databricks.yml
         --- databricks.yml.backup
         +++ databricks.yml
        -@@ -30,2 +30,14 @@
        +@@ -28,2 +28,12 @@
                    spark_python_task:
                      python_file: ./hello.py
         +        - new_cluster:
        -+            custom_tags:
        -+              UserTag: new-task
         +            node_type_id: [NODE_TYPE_ID]
         +            num_workers: 1
         +            policy_id: ${resources.cluster_policies.policy.id}

latest (v1.23.0): same output as main (aae07ca)

TestAccept/bundle/config-remote-sync/cluster_policy_replaces_array/DMS=: branch ✅ | main (aae07ca) ❌ | latest (v1.23.0) ❌

main (aae07ca):

acceptance_test.go:1342: Diff:
        --- bundle/config-remote-sync/cluster_policy_replaces_array/output.txt
        +++ /tmp/TestAcceptbundleconfig-remote-synccluster_policy_replaces_arr1980248462/002/output.txt
        @@ -13,14 +13,31 @@
         }
         
         >>> [CLI] bundle config-remote-sync --save
        -No changes detected.
        +Detected changes in 1 resource(s):
         
        +Resource: resources.jobs.test_job
        +  tasks[task_key='main'].new_cluster.init_scripts: replace
         
        +
        +
         >>> diff.py databricks.yml.backup databricks.yml
        +--- databricks.yml.backup
        ++++ databricks.yml
        +@@ -17,8 +17,6 @@
        +             num_workers: 1
        +             init_scripts:
        +-              - workspace:
        +-                  destination: /Workspace/init-a.sh
        +-              - workspace:
        +-                  destination: /Workspace/init-b.sh
        ++              - volumes:
        ++                  destination: /Volumes/catalog/schema/volume/policy.sh
        +           spark_python_task:
        +             python_file: ./hello.py
         
         === Authored scripts are kept without copying the policy script
         >>> [CLI] bundle validate -o json
        -true
        +false
         
         >>> [CLI] bundle destroy --auto-approve
         The following resources will be deleted:
        @@ -31,3 +42,5 @@
         Destroy: 1 deleted
         
         >>> [CLI] cluster-policies delete [POLICY_ID]
        +
        +Exit code: 1

latest (v1.23.0): same output as main (aae07ca)

TestAccept/bundle/config-remote-sync/cluster_policy_replaces_array/DMS=true: branch ✅ | main (aae07ca) ❌ | latest (v1.23.0) ❌

main (aae07ca):

acceptance_test.go:1342: Diff:
        --- bundle/config-remote-sync/cluster_policy_replaces_array/output.txt
        +++ /tmp/TestAcceptbundleconfig-remote-synccluster_policy_replaces_arr3475303200/002/output.txt
        @@ -13,14 +13,31 @@
         }
         
         >>> [CLI] bundle config-remote-sync --save
        -No changes detected.
        +Detected changes in 1 resource(s):
         
        +Resource: resources.jobs.test_job
        +  tasks[task_key='main'].new_cluster.init_scripts: replace
         
        +
        +
         >>> diff.py databricks.yml.backup databricks.yml
        +--- databricks.yml.backup
        ++++ databricks.yml
        +@@ -17,8 +17,6 @@
        +             num_workers: 1
        +             init_scripts:
        +-              - workspace:
        +-                  destination: /Workspace/init-a.sh
        +-              - workspace:
        +-                  destination: /Workspace/init-b.sh
        ++              - volumes:
        ++                  destination: /Volumes/catalog/schema/volume/policy.sh
        +           spark_python_task:
        +             python_file: ./hello.py
         
         === Authored scripts are kept without copying the policy script
         >>> [CLI] bundle validate -o json
        -true
        +false
         
         >>> [CLI] bundle destroy --auto-approve
         The following resources will be deleted:
        @@ -31,3 +42,5 @@
         Destroy: 1 deleted
         
         >>> [CLI] cluster-policies delete [POLICY_ID]
        +
        +Exit code: 1
        
FAIL

latest (v1.23.0): same output as main (aae07ca)

TestAccept/bundle/config-remote-sync/external_cluster_policy_cross_target/DMS=: branch ✅ | main (aae07ca) ❌ | latest (v1.23.0) ❌

main (aae07ca):

acceptance_test.go:1342: Diff:
        --- bundle/config-remote-sync/external_cluster_policy_cross_target/output.txt
        +++ /tmp/TestAcceptbundleconfig-remote-syncexternal_cluster_policy_cro1742982392/002/output.txt
        @@ -13,6 +13,8 @@
         
         Resource: resources.jobs.policy_sync
           description: replace
        +  job_clusters[job_cluster_key='main'].new_cluster.custom_tags['workspace']: add
        +  job_clusters[job_cluster_key='main'].new_cluster.spark_env_vars: add
         
         
         
        @@ -26,59 +28,31 @@
         +      description: Edited in the UI
                job_clusters:
                  - job_cluster_key: main
        +@@ -23,4 +23,7 @@
        +             custom_tags:
        +               owner: bundle-author
        ++              workspace: dev
        ++            spark_env_vars:
        ++              ENVIRONMENT: dev
        +       tasks:
        +         - task_key: main
         
         === Deploy shared YAML with the prod policy
         >>> [CLI] bundle deploy -t prod
         Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/[UNIQUE_NAME]/prod/files...
        -Created jobs.policy_sync
        -Files: 5 uploaded, 0 deleted
        -Resources: 1 created, 0 changed, 0 deleted, 0 unchanged
        +Error: cannot create resources.jobs.policy_sync: Cluster validation error: Validation failed for custom_tags, workspace must be prod (is "dev") (400 INVALID_PARAMETER_VALUE)
         
        -=== A deleted policy leaves the job unchanged, including its unrelated edits
        ->>> [CLI] cluster-policies delete [DEV_POLICY_ID]
        +Endpoint: POST [DATABRICKS_URL]/api/2.2/jobs/create
        +HTTP Status: 400 Bad Request
        +API error_code: INVALID_PARAMETER_VALUE
        +API message: Cluster validation error: Validation failed for custom_tags, workspace must be prod (is "dev")
         
        ->>> [CLI] bundle config-remote-sync -t dev --save -o json
        -{
        -  "status": "partial",
        -  "changes": {},
        -  "skippedChanges": [
        -    {
        -      "resourceKey": "resources.jobs.policy_sync",
        -      "reason": "cluster_policy_not_found",
        -      "policyId": "[DEV_POLICY_ID]"
        -    }
        -  ]
        -}
        +Files: 5 uploaded, 0 deleted
         
        ->>> diff.py databricks.yml.backup databricks.yml
        -
        -=== The job stays skipped on the next sync
        ->>> [CLI] bundle config-remote-sync -t dev -o json
        -{
        -  "status": "partial",
        -  "changes": {},
        -  "skippedChanges": [
        -    {
        -      "resourceKey": "resources.jobs.policy_sync",
        -      "reason": "cluster_policy_not_found",
        -      "policyId": "[DEV_POLICY_ID]"
        -    }
        -  ]
        -}
        -
        -=== Text output reports the incomplete sync
        ->>> [CLI] bundle config-remote-sync -t dev
        -Sync is incomplete: some remote changes were skipped.
        -Left resources.jobs.policy_sync unchanged: cluster policy [DEV_POLICY_ID] was not found.
        -No changes could be synced.
        -
         >>> [CLI] bundle destroy -t prod --auto-approve
        -The following resources will be deleted:
        -  delete resources.jobs.policy_sync
        -
         All files and directories at the following location will be deleted: /Workspace/Users/[USERNAME]/.bundle/[UNIQUE_NAME]/prod
         
        -Destroy: 1 deleted
        +Destroy: 0 deleted
         
         >>> [CLI] bundle destroy -t dev --auto-approve
         The following resources will be deleted:
        @@ -88,4 +52,8 @@
         
         Destroy: 1 deleted
         
        +>>> [CLI] cluster-policies delete [DEV_POLICY_ID]
        +
         >>> [CLI] cluster-policies delete [PROD_POLICY_ID]
        +
        +Exit code: 1

latest (v1.23.0): same output as main (aae07ca)

TestAccept/bundle/config-remote-sync/external_cluster_policy_cross_target/DMS=true: branch ✅ | main (aae07ca) ❌ | latest (v1.23.0) ❌

main (aae07ca):

acceptance_test.go:1342: Diff:
        --- bundle/config-remote-sync/external_cluster_policy_cross_target/output.txt
        +++ /tmp/TestAcceptbundleconfig-remote-syncexternal_cluster_policy_cro712681/002/output.txt
        @@ -13,6 +13,8 @@
         
         Resource: resources.jobs.policy_sync
           description: replace
        +  job_clusters[job_cluster_key='main'].new_cluster.custom_tags['workspace']: add
        +  job_clusters[job_cluster_key='main'].new_cluster.spark_env_vars: add
         
         
         
        @@ -26,59 +28,31 @@
         +      description: Edited in the UI
                job_clusters:
                  - job_cluster_key: main
        +@@ -23,4 +23,7 @@
        +             custom_tags:
        +               owner: bundle-author
        ++              workspace: dev
        ++            spark_env_vars:
        ++              ENVIRONMENT: dev
        +       tasks:
        +         - task_key: main
         
         === Deploy shared YAML with the prod policy
         >>> [CLI] bundle deploy -t prod
         Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/[UNIQUE_NAME]/prod/files...
        -Created jobs.policy_sync
        -Files: 5 uploaded, 0 deleted
        -Resources: 1 created, 0 changed, 0 deleted, 0 unchanged
        +Error: cannot create resources.jobs.policy_sync: Cluster validation error: Validation failed for custom_tags, workspace must be prod (is "dev") (400 INVALID_PARAMETER_VALUE)
         
        -=== A deleted policy leaves the job unchanged, including its unrelated edits
        ->>> [CLI] cluster-policies delete [DEV_POLICY_ID]
        +Endpoint: POST [DATABRICKS_URL]/api/2.2/jobs/create
        +HTTP Status: 400 Bad Request
        +API error_code: INVALID_PARAMETER_VALUE
        +API message: Cluster validation error: Validation failed for custom_tags, workspace must be prod (is "dev")
         
        ->>> [CLI] bundle config-remote-sync -t dev --save -o json
        -{
        -  "status": "partial",
        -  "changes": {},
        -  "skippedChanges": [
        -    {
        -      "resourceKey": "resources.jobs.policy_sync",
        -      "reason": "cluster_policy_not_found",
        -      "policyId": "[DEV_POLICY_ID]"
        -    }
        -  ]
        -}
        +Files: 5 uploaded, 0 deleted
         
        ->>> diff.py databricks.yml.backup databricks.yml
        -
        -=== The job stays skipped on the next sync
        ->>> [CLI] bundle config-remote-sync -t dev -o json
        -{
        -  "status": "partial",
        -  "changes": {},
        -  "skippedChanges": [
        -    {
        -      "resourceKey": "resources.jobs.policy_sync",
        -      "reason": "cluster_policy_not_found",
        -      "policyId": "[DEV_POLICY_ID]"
        -    }
        -  ]
        -}
        -
        -=== Text output reports the incomplete sync
        ->>> [CLI] bundle config-remote-sync -t dev
        -Sync is incomplete: some remote changes were skipped.
        -Left resources.jobs.policy_sync unchanged: cluster policy [DEV_POLICY_ID] was not found.
        -No changes could be synced.
        -
         >>> [CLI] bundle destroy -t prod --auto-approve
        -The following resources will be deleted:
        -  delete resources.jobs.policy_sync
        -
         All files and directories at the following location will be deleted: /Workspace/Users/[USERNAME]/.bundle/[UNIQUE_NAME]/prod
         
        -Destroy: 1 deleted
        +Destroy: 0 deleted
         
         >>> [CLI] bundle destroy -t dev --auto-approve
         The following resources will be deleted:
        @@ -88,4 +52,8 @@
         
         Destroy: 1 deleted
         
        +>>> [CLI] cluster-policies delete [DEV_POLICY_ID]
        +
         >>> [CLI] cluster-policies delete [PROD_POLICY_ID]
        +
        +Exit code: 1

latest (v1.23.0): same output as main (aae07ca)

TestAccept/bundle/config-remote-sync/missing_cluster_policy/DMS=: branch ✅ | main (aae07ca) ❌ | latest (v1.23.0) ❌

main (aae07ca):

acceptance_test.go:1342: Diff:
        --- bundle/config-remote-sync/missing_cluster_policy/output.txt
        +++ /tmp/TestAcceptbundleconfig-remote-syncmissing_cluster_policyDMS=1464912715/002/output.txt
        @@ -31,117 +31,50 @@
         === A selected job's policy read error leaves the job unchanged without saving
         >>> [CLI] bundle config-remote-sync --select-ids jobs:[ARRAY_CHANGE_ID] --save -o json
         {
        -  "status": "partial",
        -  "changes": {},
        -  "skippedChanges": [
        -    {
        -      "resourceKey": "resources.jobs.array_change",
        -      "reason": "cluster_policy_permission_denied",
        -      "policyId": "[POLICY_ID]",
        -      "error": "Fault injected by test."
        -    }
        -  ]
        -}
        -
        ->>> diff.py databricks.yml.backup databricks.yml
        -
        ->>> print_requests.py //policies/clusters/get --get --oneline
        -{"method": "GET", "path": "/api/2.0/policies/clusters/get", "q": {"policy_id": "[POLICY_ID]"}}
        -
        -=== An array replacement leaves the selected job unchanged
        ->>> [CLI] bundle config-remote-sync --select-ids jobs:[ARRAY_CHANGE_ID] --save -o json
        -{
        -  "status": "partial",
        -  "changes": {},
        -  "skippedChanges": [
        -    {
        -      "resourceKey": "resources.jobs.array_change",
        -      "reason": "cluster_policy_not_found",
        -      "policyId": "[POLICY_ID]"
        -    }
        -  ]
        -}
        -
        ->>> diff.py databricks.yml.backup databricks.yml
        -
        -=== A log-storage switch leaves the selected job unchanged
        ->>> [CLI] bundle config-remote-sync --select-ids jobs:[LOG_STORAGE_CHANGE_ID] --save -o json
        -{
        -  "status": "partial",
        -  "changes": {},
        -  "skippedChanges": [
        -    {
        -      "resourceKey": "resources.jobs.log_storage_change",
        -      "reason": "cluster_policy_not_found",
        -      "policyId": "[POLICY_ID]"
        -    }
        -  ]
        -}
        -
        ->>> diff.py databricks.yml.backup databricks.yml
        -
        -=== Switching autoscale to a fixed worker count leaves the selected job unchanged
        ->>> [CLI] bundle config-remote-sync --select-ids jobs:[WORKER_COUNT_CHANGE_ID] --save -o json
        -{
        -  "status": "partial",
        -  "changes": {},
        -  "skippedChanges": [
        -    {
        -      "resourceKey": "resources.jobs.worker_count_change",
        -      "reason": "cluster_policy_not_found",
        -      "policyId": "[POLICY_ID]"
        -    }
        -  ]
        -}
        -
        ->>> diff.py databricks.yml.backup databricks.yml
        -
        -=== Unrelated jobs still sync when other jobs depend on the missing policy
        ->>> [CLI] bundle config-remote-sync --save -o json
        -{
        -  "status": "partial",
        +  "status": "success",
           "changes": {
        -    "resources.jobs.unaffected": {
        +    "resources.jobs.array_change": {
               "description": {
                 "operation": "replace",
        -        "value": "Unrelated UI edit"
        +        "value": "Array changed in the UI"
        +      },
        +      "tasks[task_key='main'].new_cluster.init_scripts": {
        +        "operation": "replace",
        +        "value": [
        +          {
        +            "volumes": {
        +              "destination": "/Volumes/catalog/schema/volume/policy.sh"
        +            }
        +          }
        +        ]
               }
             }
           },
        -  "skippedChanges": [
        -    {
        -      "resourceKey": "resources.jobs.array_change",
        -      "reason": "cluster_policy_not_found",
        -      "policyId": "[POLICY_ID]"
        -    },
        -    {
        -      "resourceKey": "resources.jobs.log_storage_change",
        -      "reason": "cluster_policy_not_found",
        -      "policyId": "[POLICY_ID]"
        -    },
        -    {
        -      "resourceKey": "resources.jobs.new_task",
        -      "reason": "cluster_policy_not_found",
        -      "policyId": "[POLICY_ID]"
        -    },
        -    {
        -      "resourceKey": "resources.jobs.worker_count_change",
        -      "reason": "cluster_policy_not_found",
        -      "policyId": "[POLICY_ID]"
        -    }
        -  ]
        +  "skippedChanges": null
         }
         
         >>> diff.py databricks.yml.backup databricks.yml
         --- databricks.yml.backup
         +++ databricks.yml
        -@@ -67,5 +67,5 @@
        -     unaffected:
        -       name: test-unaffected-[UNIQUE_NAME]
        +@@ -9,5 +9,5 @@
        +     array_change:
        +       name: test-array_change-[UNIQUE_NAME]
         -      description: Before UI edit
        -+      description: Unrelated UI edit
        ++      description: Array changed in the UI
                tasks:
                  - task_key: main
        +@@ -18,8 +18,6 @@
        +             num_workers: 1
        +             init_scripts:
        +-              - workspace:
        +-                  destination: /Workspace/init-a.sh
        +-              - workspace:
        +-                  destination: /Workspace/init-b.sh
        ++              - volumes:
        ++                  destination: /Volumes/catalog/schema/volume/policy.sh
        +           spark_python_task:
        +             python_file: ./hello.py
        +databricks.yml.backup databricks.yml differ: char 232, line 11
         
         >>> [CLI] bundle destroy --auto-approve
         The following resources will be deleted:
        @@ -154,3 +73,5 @@
         All files and directories at the following location will be deleted: /Workspace/Users/[USERNAME]/.bundle/[UNIQUE_NAME]
         
         Destroy: 5 deleted
        +
        +Exit code: 1
        
    acceptance_test.go:1120: LOG.cleanup-requests: 
    acceptance_test.go:1120: LOG.setup-requests:

latest (v1.23.0): same output as main (aae07ca)

TestAccept/bundle/config-remote-sync/missing_cluster_policy/DMS=true: branch ✅ | main (aae07ca) ❌ | latest (v1.23.0) ❌

main (aae07ca):

acceptance_test.go:1342: Diff:
        --- bundle/config-remote-sync/missing_cluster_policy/output.txt
        +++ /tmp/TestAcceptbundleconfig-remote-syncmissing_cluster_policyDMS=618638911/002/output.txt
        @@ -31,117 +31,50 @@
         === A selected job's policy read error leaves the job unchanged without saving
         >>> [CLI] bundle config-remote-sync --select-ids jobs:[ARRAY_CHANGE_ID] --save -o json
         {
        -  "status": "partial",
        -  "changes": {},
        -  "skippedChanges": [
        -    {
        -      "resourceKey": "resources.jobs.array_change",
        -      "reason": "cluster_policy_permission_denied",
        -      "policyId": "[POLICY_ID]",
        -      "error": "Fault injected by test."
        -    }
        -  ]
        -}
        -
        ->>> diff.py databricks.yml.backup databricks.yml
        -
        ->>> print_requests.py //policies/clusters/get --get --oneline
        -{"method": "GET", "path": "/api/2.0/policies/clusters/get", "q": {"policy_id": "[POLICY_ID]"}}
        -
        -=== An array replacement leaves the selected job unchanged
        ->>> [CLI] bundle config-remote-sync --select-ids jobs:[ARRAY_CHANGE_ID] --save -o json
        -{
        -  "status": "partial",
        -  "changes": {},
        -  "skippedChanges": [
        -    {
        -      "resourceKey": "resources.jobs.array_change",
        -      "reason": "cluster_policy_not_found",
        -      "policyId": "[POLICY_ID]"
        -    }
        -  ]
        -}
        -
        ->>> diff.py databricks.yml.backup databricks.yml
        -
        -=== A log-storage switch leaves the selected job unchanged
        ->>> [CLI] bundle config-remote-sync --select-ids jobs:[LOG_STORAGE_CHANGE_ID] --save -o json
        -{
        -  "status": "partial",
        -  "changes": {},
        -  "skippedChanges": [
        -    {
        -      "resourceKey": "resources.jobs.log_storage_change",
        -      "reason": "cluster_policy_not_found",
        -      "policyId": "[POLICY_ID]"
        -    }
        -  ]
        -}
        -
        ->>> diff.py databricks.yml.backup databricks.yml
        -
        -=== Switching autoscale to a fixed worker count leaves the selected job unchanged
        ->>> [CLI] bundle config-remote-sync --select-ids jobs:[WORKER_COUNT_CHANGE_ID] --save -o json
        -{
        -  "status": "partial",
        -  "changes": {},
        -  "skippedChanges": [
        -    {
        -      "resourceKey": "resources.jobs.worker_count_change",
        -      "reason": "cluster_policy_not_found",
        -      "policyId": "[POLICY_ID]"
        -    }
        -  ]
        -}
        -
        ->>> diff.py databricks.yml.backup databricks.yml
        -
        -=== Unrelated jobs still sync when other jobs depend on the missing policy
        ->>> [CLI] bundle config-remote-sync --save -o json
        -{
        -  "status": "partial",
        +  "status": "success",
           "changes": {
        -    "resources.jobs.unaffected": {
        +    "resources.jobs.array_change": {
               "description": {
                 "operation": "replace",
        -        "value": "Unrelated UI edit"
        +        "value": "Array changed in the UI"
        +      },
        +      "tasks[task_key='main'].new_cluster.init_scripts": {
        +        "operation": "replace",
        +        "value": [
        +          {
        +            "volumes": {
        +              "destination": "/Volumes/catalog/schema/volume/policy.sh"
        +            }
        +          }
        +        ]
               }
             }
           },
        -  "skippedChanges": [
        -    {
        -      "resourceKey": "resources.jobs.array_change",
        -      "reason": "cluster_policy_not_found",
        -      "policyId": "[POLICY_ID]"
        -    },
        -    {
        -      "resourceKey": "resources.jobs.log_storage_change",
        -      "reason": "cluster_policy_not_found",
        -      "policyId": "[POLICY_ID]"
        -    },
        -    {
        -      "resourceKey": "resources.jobs.new_task",
        -      "reason": "cluster_policy_not_found",
        -      "policyId": "[POLICY_ID]"
        -    },
        -    {
        -      "resourceKey": "resources.jobs.worker_count_change",
        -      "reason": "cluster_policy_not_found",
        -      "policyId": "[POLICY_ID]"
        -    }
        -  ]
        +  "skippedChanges": null
         }
         
         >>> diff.py databricks.yml.backup databricks.yml
         --- databricks.yml.backup
         +++ databricks.yml
        -@@ -67,5 +67,5 @@
        -     unaffected:
        -       name: test-unaffected-[UNIQUE_NAME]
        +@@ -9,5 +9,5 @@
        +     array_change:
        +       name: test-array_change-[UNIQUE_NAME]
         -      description: Before UI edit
        -+      description: Unrelated UI edit
        ++      description: Array changed in the UI
                tasks:
                  - task_key: main
        +@@ -18,8 +18,6 @@
        +             num_workers: 1
        +             init_scripts:
        +-              - workspace:
        +-                  destination: /Workspace/init-a.sh
        +-              - workspace:
        +-                  destination: /Workspace/init-b.sh
        ++              - volumes:
        ++                  destination: /Volumes/catalog/schema/volume/policy.sh
        +           spark_python_task:
        +             python_file: ./hello.py
        +databricks.yml.backup databricks.yml differ: char 232, line 11
         
         >>> [CLI] bundle destroy --auto-approve
         The following resources will be deleted:
        @@ -154,3 +73,5 @@
         All files and directories at the following location will be deleted: /Workspace/Users/[USERNAME]/.bundle/[UNIQUE_NAME]
         
         Destroy: 5 deleted
        +
        +Exit code: 1
        
    acceptance_test.go:1120: LOG.cleanup-requests: 
    acceptance_test.go:1120: LOG.setup-requests:

latest (v1.23.0): same output as main (aae07ca)

@eng-dev-ecosystem-bot

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

Copy link
Copy Markdown
Collaborator

Integration test report

Commit: 614f1e2

Run: 41643131234

Env ✅​pass 🙈​skip Time
✅​ aws linux-2core-8gb 283 17 9:17
✅​ aws-windows-latest-4core-16gb 273 19 4:50
✅​ azure linux-2core-8gb 282 17 8:58
✅​ azure-windows-latest-4core-16gb 272 19 4:49
✅​ gcp linux-2core-8gb 283 17 10:32
✅​ gcp-windows-latest-4core-16gb 273 19 5:57
Top 8 slowest tests (at least 2 minutes):
duration env testname
4:19 gcp linux-2core-8gb TestAccept
4:11 azure linux-2core-8gb TestAccept
4:10 aws linux-2core-8gb TestAccept
3:15 gcp-windows-latest-4core-16gb TestAccept
3:08 azure-windows-latest-4core-16gb TestAccept
3:00 aws-windows-latest-4core-16gb TestAccept
2:15 azure linux-2core-8gb TestAccept/bundle/config-remote-sync/cluster_policy_cross_target/DMS=
2:12 gcp-windows-latest-4core-16gb TestFilerWorkspaceFilesExtensionsStat

@ilyakuz-db
ilyakuz-db marked this pull request as ready for review November 3, 2026 13:17
@ilyakuz-db
ilyakuz-db requested review from a team as code owners November 3, 2026 13:17
@ilyakuz-db
ilyakuz-db requested a review from denik November 3, 2026 14:03
// one environment's policy values into (often shared) config and breaks deploys in
// other environments. TODO: move to backend_defaults in jobs.yml once
// configsync filtering is migrated to the direct engine lifecycle metadata.
"resources.jobs.*.tasks[*].new_cluster.custom_tags": backendDefault,

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Context for removing the custom_tags / cluster_log_conf blanket skip (originally added in #5610 as a quick fix for policy-injected values leaking into shared YAML).

The new policy-aware filter covers the cases that skip was protecting, and the skip itself turned out to be incomplete: it only applied when the field was entirely absent from config. A cluster with a single authored tag still got the policy's tags synced in beside it.

Verified against a real AWS workspace with two policies (dev/prod) fixing custom_tags.*, spark_env_vars.*, workload_type.clients.* and an S3 cluster_log_conf (type/path/region), a shared job with one authored tag, and a UI edit (description + user-added tag) applied via jobs reset:

Scenario v1.23.0 (blanket skip) this PR
Policy-fixed tags next to an authored tag synced, prod deploy fails filtered
Policy-fixed spark_env_vars, workload_type synced, prod deploy fails filtered
Policy-fixed S3 cluster_log_conf skipped filtered
User tag added in UI synced synced
Description edited in UI synced synced
Shared YAML deployed to prod Cluster validation error: ... must be prod (is "dev") succeeds, next sync and plan report no changes

The backend materialized the S3 log conf as exactly s3.destination + s3.region, both mapped back to the policy's path / region rules, so nothing is left to leak. With that, these entries are safe to drop.

@ilyakuz-db
ilyakuz-db added this pull request to the merge queue Nov 4, 2026
Merged via the queue into main with commit 5bda5d4 Nov 4, 2026
28 checks passed
@ilyakuz-db
ilyakuz-db deleted the ilyakuz-db/fix-policy-values-in-remote-sync branch November 4, 2026 12:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

DABs DABs related issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants