Skip to content

Commit e05adcb

Browse files
authored
direct: Fix phantom diffs from depends_on reordering in job tasks (#4990)
## Changes Fix phantom diffs in `bundle plan` caused by the Jobs API returning `depends_on` arrays in a different order than submitted. Both `tasks[*].depends_on` and `tasks[*].for_each_task.task.depends_on` are handled. ## Why After a deploy with the direct engine, every subsequent `bundle plan` showed spurious `depends_on` updates even though nothing changed, creating a perpetual deploy-plan-update cycle. ## Tests - Unit tests for nested `depends_on` keyed-slice diffing (reorder, field change, add, remove). - Testserver sorts `depends_on` by `task_key` to simulate real API reordering. - Acceptance test (`depends-on-reorder`, direct-only) verifies deploy followed by plan reports no changes.
1 parent e126356 commit e05adcb

13 files changed

Lines changed: 134 additions & 23 deletions

File tree

NEXT_CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
* Remove `experimental-jobs-as-code` template, superseded by `pydabs` ([#4999](https://github.com/databricks/cli/pull/4999)).
1515
* engine/direct: Added support for Vector Search Endpoints ([#4887](https://github.com/databricks/cli/pull/4887))
1616
* engine/direct: Exclude deploy-only fields (e.g. `lifecycle`) from the Apps update mask so requests that change both `description` and `lifecycle.started` in the same deploy no longer fail with `INVALID_PARAMETER_VALUE`.
17+
* engine/direct: Fix phantom diffs from `depends_on` reordering in job tasks ([#4990](https://github.com/databricks/cli/pull/4990))
1718

1819
### Dependency updates
1920

acceptance/bundle/config-remote-sync/job_multiple_tasks/output.txt

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ Deployment complete!
88
Detected changes in 2 resource(s):
99

1010
Resource: resources.jobs.my_job
11-
tasks[task_key='c_task'].depends_on[0].task_key: replace
11+
tasks[task_key='c_task'].depends_on[task_key='b_task']: add
12+
tasks[task_key='c_task'].depends_on[task_key='d_task']: remove
1213
tasks[task_key='c_task'].new_cluster.num_workers: replace
1314
tasks[task_key='c_task'].timeout_seconds: add
1415
tasks[task_key='d_task']: remove
@@ -83,8 +84,10 @@ Resource: resources.jobs.rename_task_job
8384
tasks[task_key='a_task'].notebook_task.notebook_path: replace
8485
tasks[task_key='b_task']: remove
8586
tasks[task_key='b_task_renamed']: add
86-
tasks[task_key='c_task'].depends_on[0].task_key: replace
87-
tasks[task_key='d_task'].depends_on[0].task_key: replace
87+
tasks[task_key='c_task'].depends_on[task_key='b_task']: remove
88+
tasks[task_key='c_task'].depends_on[task_key='b_task_renamed']: add
89+
tasks[task_key='d_task'].depends_on[task_key='b_task']: remove
90+
tasks[task_key='d_task'].depends_on[task_key='b_task_renamed']: add
8891
tasks[task_key='synced_task']: add
8992

9093

acceptance/bundle/config-remote-sync/multiple_files/output.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ Detected changes in 2 resource(s):
1212

1313
Resource: resources.jobs.job_one
1414
max_concurrent_runs: replace
15-
tasks[task_key='a_task'].depends_on[0].task_key: replace
15+
tasks[task_key='a_task'].depends_on[task_key='c_task']: remove
16+
tasks[task_key='a_task'].depends_on[task_key='c_task_renamed']: add
1617
tasks[task_key='c_task']: remove
1718
tasks[task_key='c_task_renamed']: add
1819
tasks[task_key='synced_task']: add
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
bundle:
2+
name: test-bundle-$UNIQUE_NAME
3+
4+
resources:
5+
jobs:
6+
foo:
7+
name: test-job-$UNIQUE_NAME
8+
tasks:
9+
- task_key: main
10+
notebook_task:
11+
notebook_path: /Shared/notebook
12+
- task_key: process
13+
depends_on:
14+
- task_key: main
15+
notebook_task:
16+
notebook_path: /Shared/notebook
17+
- task_key: finalize
18+
depends_on:
19+
- task_key: process
20+
- task_key: main
21+
notebook_task:
22+
notebook_path: /Shared/notebook

acceptance/bundle/invariant/continue_293/out.test.toml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

acceptance/bundle/invariant/migrate/out.test.toml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

acceptance/bundle/invariant/migrate/script

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,17 @@ cat LOG.deploy | contains.py '!panic:' '!internal error' > /dev/null
3434

3535
echo INPUT_CONFIG_OK
3636

37-
trace $CLI bundle deployment migrate &> LOG.migrate
37+
MIGRATE_ARGS=""
38+
# The terraform provider sorts depends_on entries alphabetically by task_key on Read
39+
# (see terraform-provider-databricks PR #3000). Since depends_on uses TypeList
40+
# (order-sensitive), terraform plan reports positional drift when the bundle config
41+
# specifies depends_on in a different order than the provider's sorted state.
42+
# This is a false positive -- the logical dependencies are identical.
43+
if [[ "$INPUT_CONFIG" == "job_with_depends_on.yml.tmpl" ]]; then
44+
MIGRATE_ARGS="--noplancheck"
45+
fi
46+
47+
trace $CLI bundle deployment migrate $MIGRATE_ARGS &> LOG.migrate
3848

3949
cat LOG.migrate | contains.py '!panic:' '!internal error' > /dev/null
4050

acceptance/bundle/invariant/no_drift/out.test.toml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

acceptance/bundle/invariant/test.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ EnvMatrix.INPUT_CONFIG = [
3535
"job_pydabs_1000_tasks.yml.tmpl",
3636
"job_cross_resource_ref.yml.tmpl",
3737
"job_permission_ref.yml.tmpl",
38+
"job_with_depends_on.yml.tmpl",
3839
"job_with_permissions.yml.tmpl",
3940
"job_with_task.yml.tmpl",
4041
"model.yml.tmpl",

bundle/direct/dresources/job.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,18 @@ func getEnvironmentKey(x jobs.JobEnvironment) (string, string) {
7171
return "environment_key", x.EnvironmentKey
7272
}
7373

74+
func getDependsOnTaskKey(x jobs.TaskDependency) (string, string) {
75+
return "task_key", x.TaskKey
76+
}
77+
7478
func (*ResourceJob) KeyedSlices() map[string]any {
7579
return map[string]any{
76-
"tasks": getTaskKey,
77-
"parameters": getParameterName,
78-
"job_clusters": getJobClusterKey,
79-
"environments": getEnvironmentKey,
80+
"tasks": getTaskKey,
81+
"parameters": getParameterName,
82+
"job_clusters": getJobClusterKey,
83+
"environments": getEnvironmentKey,
84+
"tasks[*].depends_on": getDependsOnTaskKey,
85+
"tasks[*].for_each_task.task.depends_on": getDependsOnTaskKey,
8086
}
8187
}
8288

0 commit comments

Comments
 (0)