From 6a81425fda6060efab057af45dae12ce60f740b6 Mon Sep 17 00:00:00 2001 From: Shreyas Goenka Date: Wed, 28 Oct 2026 14:26:31 +0000 Subject: [PATCH 1/3] Test regeneration and binding of deployed jobs and pipelines --- .../generate/auto-bind/databricks.yml.tmpl | 4 ++ .../bundle/generate/auto-bind/output.txt | 34 ++++++++++ acceptance/bundle/generate/auto-bind/script | 17 +++++ .../pipeline_and_deploy/databricks.yml.tmpl | 7 ++ .../generate/pipeline_and_deploy/output.txt | 66 ++++++++++++++++--- .../generate/pipeline_and_deploy/script | 35 ++++++++-- 6 files changed, 146 insertions(+), 17 deletions(-) diff --git a/acceptance/bundle/generate/auto-bind/databricks.yml.tmpl b/acceptance/bundle/generate/auto-bind/databricks.yml.tmpl index 49ff482e7f0..59005adb6fc 100644 --- a/acceptance/bundle/generate/auto-bind/databricks.yml.tmpl +++ b/acceptance/bundle/generate/auto-bind/databricks.yml.tmpl @@ -6,3 +6,7 @@ workspace: include: - resources/*.yml + +sync: + exclude: + - LOG.* diff --git a/acceptance/bundle/generate/auto-bind/output.txt b/acceptance/bundle/generate/auto-bind/output.txt index e7a43c9c50e..93bfd646779 100644 --- a/acceptance/bundle/generate/auto-bind/output.txt +++ b/acceptance/bundle/generate/auto-bind/output.txt @@ -25,6 +25,40 @@ Updated jobs.test_job Files: 5 uploaded, 0 deleted Resources: 0 created, 1 changed, 0 deleted, 0 unchanged +=== Regenerate the already-bound job: +>>> musterr [CLI] bundle generate job --key test_job --existing-job-id [JOB_ID] --config-dir resources --source-dir src --bind --force +File successfully saved to src/test.py +Job configuration successfully saved to resources/test_job.job.yml +Error: Resource already managed + +The bundle is already managing resource for resources.jobs.test_job and it is bound to the requested ID [JOB_ID]. + + +>>> [CLI] bundle validate +Name: auto-bind-test +Target: default +Workspace: + User: [USERNAME] + Path: /Workspace/Users/[USERNAME]/.bundle/auto-bind-test-[UNIQUE_NAME] + +Validation OK! + +=== Unbind and regenerate the deployed job: +>>> [CLI] bundle deployment unbind test_job + +>>> [CLI] bundle generate job --key test_job --existing-job-id [JOB_ID] --config-dir resources --source-dir src --bind --force +File successfully saved to src/test.py +Job configuration successfully saved to resources/test_job.job.yml +Successfully bound job with an id '[JOB_ID]' + +=== Redeploy the regenerated job: +>>> [CLI] bundle deploy +Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/auto-bind-test-[UNIQUE_NAME]/files... +Files: 2 uploaded, 0 deleted +Resources: 0 created, 0 changed, 0 deleted, 1 unchanged + +>>> test [JOB_ID] = [JOB_ID] + === Destroy the bundle: >>> [CLI] bundle destroy --auto-approve The following resources will be deleted: diff --git a/acceptance/bundle/generate/auto-bind/script b/acceptance/bundle/generate/auto-bind/script index 542dc0b96d6..ae546f8e1ed 100755 --- a/acceptance/bundle/generate/auto-bind/script +++ b/acceptance/bundle/generate/auto-bind/script @@ -45,6 +45,23 @@ trace cat resources/test_job.job.yml | grep "name: auto-bind-job-${UNIQUE_NAME}" title "Deploy the bound job:" trace $CLI bundle deploy +if [ "${DATABRICKS_BUNDLE_DEPLOYMENT_HISTORY:-}" = true ]; then + $CLI jobs get "$JOB_ID" | jq -e '.settings.deployment | (.deployment_id | length > 0) and (.version_id | length > 0)' > LOG.deployment +fi + +title "Regenerate the already-bound job:" +trace musterr $CLI bundle generate job --key test_job --existing-job-id $JOB_ID --config-dir resources --source-dir src --bind --force 2>&1 | contains.py 'Resource already managed' +cat resources/test_job.job.yml | contains.py '!deployment:' '!deployment_id:' '!version_id:' > LOG.generated +trace $CLI bundle validate + +title "Unbind and regenerate the deployed job:" +trace $CLI bundle deployment unbind test_job +trace $CLI bundle generate job --key test_job --existing-job-id $JOB_ID --config-dir resources --source-dir src --bind --force + +title "Redeploy the regenerated job:" +trace $CLI bundle deploy +trace test "$(read_id.py test_job)" = "$JOB_ID" + title "Destroy the bundle:" trace $CLI bundle destroy --auto-approve diff --git a/acceptance/bundle/generate/pipeline_and_deploy/databricks.yml.tmpl b/acceptance/bundle/generate/pipeline_and_deploy/databricks.yml.tmpl index 487b54402f8..26c46a3466d 100644 --- a/acceptance/bundle/generate/pipeline_and_deploy/databricks.yml.tmpl +++ b/acceptance/bundle/generate/pipeline_and_deploy/databricks.yml.tmpl @@ -1,2 +1,9 @@ bundle: name: pipeline_and_deploy-$UNIQUE_NAME + +include: + - resources/*.yml + +sync: + exclude: + - LOG.* diff --git a/acceptance/bundle/generate/pipeline_and_deploy/output.txt b/acceptance/bundle/generate/pipeline_and_deploy/output.txt index c63cfee74d5..06e1274e3db 100644 --- a/acceptance/bundle/generate/pipeline_and_deploy/output.txt +++ b/acceptance/bundle/generate/pipeline_and_deploy/output.txt @@ -8,31 +8,77 @@ === Generate bundle config from the pipelineFile successfully saved to src/notebook-[UNIQUE_NAME].py File successfully saved to src/test-[UNIQUE_NAME].py -Pipeline configuration successfully saved to resources/out.pipeline.yml -Warning: Generated configuration is not included in the bundle - -The file resources/out.pipeline.yml is not matched by any pattern in the 'include' section of databricks.yml, -so it will not be deployed. Add a matching entry to the 'include' section, for example: - -include: - - resources/*.yml +>>> [CLI] bundle generate pipeline --existing-pipeline-id [PIPELINE_ID] --key out --config-dir resources --source-dir src --bind --force +Pipeline configuration successfully saved to resources/out.pipeline.yml +Successfully bound pipeline with an id '[PIPELINE_ID]' === Verify generated yaml has expected fields === Deploy the generated bundle >>> [CLI] bundle deploy Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/pipeline_and_deploy-[UNIQUE_NAME]/default/files... +Updated pipelines.out Files: 7 uploaded, 0 deleted -Resources: 0 created, 0 changed, 0 deleted, 0 unchanged +Resources: 0 created, 1 changed, 0 deleted, 0 unchanged + +=== Regenerate the already-bound pipelineFile successfully saved to src/notebook-[UNIQUE_NAME].py +File successfully saved to src/test-[UNIQUE_NAME].py + +>>> musterr [CLI] bundle generate pipeline --existing-pipeline-id [PIPELINE_ID] --key out --config-dir resources --source-dir src --bind --force +Pipeline configuration successfully saved to resources/out.pipeline.yml +Error: Resource already managed + +The bundle is already managing resource for resources.pipelines.out and it is bound to the requested ID [PIPELINE_ID]. + + +>>> [CLI] bundle validate +Name: pipeline_and_deploy-[UNIQUE_NAME] +Target: default +Workspace: + User: [USERNAME] + Path: /Workspace/Users/[USERNAME]/.bundle/pipeline_and_deploy-[UNIQUE_NAME]/default + +Validation OK! + +=== Unbind and regenerate the deployed pipeline +>>> [CLI] bundle deployment unbind out +File successfully saved to src/notebook-[UNIQUE_NAME].py +File successfully saved to src/test-[UNIQUE_NAME].py + +>>> [CLI] bundle generate pipeline --existing-pipeline-id [PIPELINE_ID] --key out --config-dir resources --source-dir src --bind --force +Pipeline configuration successfully saved to resources/out.pipeline.yml +Successfully bound pipeline with an id '[PIPELINE_ID]' + +=== Redeploy the regenerated pipeline +>>> [CLI] bundle deploy +Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/pipeline_and_deploy-[UNIQUE_NAME]/default/files... +Files: 3 uploaded, 0 deleted +Resources: 0 created, 0 changed, 0 deleted, 1 unchanged + +>>> test [PIPELINE_ID] = [PIPELINE_ID] === Destroy the deployed bundle >>> [CLI] bundle destroy --auto-approve +The following resources will be deleted: + delete resources.pipelines.out + +This action will result in the deletion of the following Lakeflow Spark Declarative Pipelines along with the +Streaming Tables (STs) and Materialized Views (MVs) managed by them. Set 'cascade_on_destroy: false' on a pipeline to retain datasets on pipeline deletion: + delete resources.pipelines.out + All files and directories at the following location will be deleted: /Workspace/Users/[USERNAME]/.bundle/pipeline_and_deploy-[UNIQUE_NAME]/default -Destroy: 0 deleted +Destroy: 1 deleted + +=== Check that the bound pipeline was destroyed +>>> musterr [CLI] pipelines get [PIPELINE_ID] +Error: The specified pipeline [PIPELINE_ID] was not found. === Cleanup: delete the original pipeline and files >>> errcode [CLI] pipelines delete [PIPELINE_ID] +Error: Not Found + +Exit code: 1 >>> errcode [CLI] workspace delete /Workspace/Users/[USERNAME]/notebook-[UNIQUE_NAME] diff --git a/acceptance/bundle/generate/pipeline_and_deploy/script b/acceptance/bundle/generate/pipeline_and_deploy/script index 32d4cbcbc4a..214e25b8324 100644 --- a/acceptance/bundle/generate/pipeline_and_deploy/script +++ b/acceptance/bundle/generate/pipeline_and_deploy/script @@ -1,7 +1,7 @@ envsubst < databricks.yml.tmpl > databricks.yml title "Upload files to workspace" -# The terraform and direct engine variants run concurrently against the same workspace user, +# The history-enabled and history-disabled variants run concurrently against the same workspace user, # so embed $UNIQUE_NAME in the remote paths: otherwise one variant's cleanup deletes the shared # files out from under the other variant's bundle generate read. trace $CLI workspace import "/Workspace/Users/${CURRENT_USER_NAME}/notebook-${UNIQUE_NAME}.py" --file notebook.py --format AUTO --overwrite @@ -36,12 +36,13 @@ trap cleanup EXIT title "Generate bundle config from the pipeline" # The concurrent downloader emits the "File successfully saved" lines in -# nondeterministic order, so sort just those; the remaining lines (including the -# multi-line include warning) are deterministic and kept in their natural order. -$CLI bundle generate pipeline --existing-pipeline-id "$PIPELINE_ID" --key out --config-dir resources --source-dir src --force > out.gen.txt 2>&1 -grep '^File successfully saved to' out.gen.txt | sort -grep -v '^File successfully saved to' out.gen.txt -rm out.gen.txt +# nondeterministic order, so sort just those. +generate_pipeline() { + trace "$@" $CLI bundle generate pipeline --existing-pipeline-id "$PIPELINE_ID" --key out --config-dir resources --source-dir src --bind --force &> LOG.generate + grep '^File successfully saved to' LOG.generate | sort + grep -v '^File successfully saved to' LOG.generate +} +generate_pipeline title "Verify generated yaml has expected fields" cat resources/out.pipeline.yml | env -u MSYS_NO_PATHCONV contains.py "libraries:" "- notebook:" "path: ../src/notebook-${UNIQUE_NAME}.py" "- file:" "path: ../src/test-${UNIQUE_NAME}.py" > /dev/null @@ -49,5 +50,25 @@ cat resources/out.pipeline.yml | env -u MSYS_NO_PATHCONV contains.py "libraries: title "Deploy the generated bundle" trace $CLI bundle deploy +if [ "${DATABRICKS_BUNDLE_DEPLOYMENT_HISTORY:-}" = true ]; then + $CLI pipelines get "$PIPELINE_ID" | jq -e '.spec.deployment | (.deployment_id | length > 0) and (.version_id | length > 0)' > LOG.deployment +fi + +title "Regenerate the already-bound pipeline" +generate_pipeline musterr | contains.py 'Resource already managed' +cat resources/out.pipeline.yml | contains.py '!deployment:' '!deployment_id:' '!version_id:' > LOG.generated +trace $CLI bundle validate + +title "Unbind and regenerate the deployed pipeline" +trace $CLI bundle deployment unbind out +generate_pipeline + +title "Redeploy the regenerated pipeline" +trace $CLI bundle deploy +trace test "$(read_id.py out)" = "$PIPELINE_ID" + title "Destroy the deployed bundle" trace $CLI bundle destroy --auto-approve + +title "Check that the bound pipeline was destroyed" +trace musterr $CLI pipelines get "$PIPELINE_ID" From a00297284eeff3c3e1001296db679e17e53c3a27 Mon Sep 17 00:00:00 2001 From: Shreyas Goenka Date: Wed, 28 Oct 2026 14:37:27 +0000 Subject: [PATCH 2/3] Keep generate bind regression coverage minimal --- .../generate/auto-bind/databricks.yml.tmpl | 4 -- .../bundle/generate/auto-bind/output.txt | 28 +------------ acceptance/bundle/generate/auto-bind/script | 15 +------ .../pipeline_and_deploy/databricks.yml.tmpl | 4 -- .../generate/pipeline_and_deploy/output.txt | 39 ++----------------- .../generate/pipeline_and_deploy/script | 32 ++++----------- 6 files changed, 12 insertions(+), 110 deletions(-) diff --git a/acceptance/bundle/generate/auto-bind/databricks.yml.tmpl b/acceptance/bundle/generate/auto-bind/databricks.yml.tmpl index 59005adb6fc..49ff482e7f0 100644 --- a/acceptance/bundle/generate/auto-bind/databricks.yml.tmpl +++ b/acceptance/bundle/generate/auto-bind/databricks.yml.tmpl @@ -6,7 +6,3 @@ workspace: include: - resources/*.yml - -sync: - exclude: - - LOG.* diff --git a/acceptance/bundle/generate/auto-bind/output.txt b/acceptance/bundle/generate/auto-bind/output.txt index 93bfd646779..f2e7837c2a8 100644 --- a/acceptance/bundle/generate/auto-bind/output.txt +++ b/acceptance/bundle/generate/auto-bind/output.txt @@ -25,25 +25,7 @@ Updated jobs.test_job Files: 5 uploaded, 0 deleted Resources: 0 created, 1 changed, 0 deleted, 0 unchanged -=== Regenerate the already-bound job: ->>> musterr [CLI] bundle generate job --key test_job --existing-job-id [JOB_ID] --config-dir resources --source-dir src --bind --force -File successfully saved to src/test.py -Job configuration successfully saved to resources/test_job.job.yml -Error: Resource already managed - -The bundle is already managing resource for resources.jobs.test_job and it is bound to the requested ID [JOB_ID]. - - ->>> [CLI] bundle validate -Name: auto-bind-test -Target: default -Workspace: - User: [USERNAME] - Path: /Workspace/Users/[USERNAME]/.bundle/auto-bind-test-[UNIQUE_NAME] - -Validation OK! - -=== Unbind and regenerate the deployed job: +=== Regenerate and bind the deployed job: >>> [CLI] bundle deployment unbind test_job >>> [CLI] bundle generate job --key test_job --existing-job-id [JOB_ID] --config-dir resources --source-dir src --bind --force @@ -51,14 +33,6 @@ File successfully saved to src/test.py Job configuration successfully saved to resources/test_job.job.yml Successfully bound job with an id '[JOB_ID]' -=== Redeploy the regenerated job: ->>> [CLI] bundle deploy -Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/auto-bind-test-[UNIQUE_NAME]/files... -Files: 2 uploaded, 0 deleted -Resources: 0 created, 0 changed, 0 deleted, 1 unchanged - ->>> test [JOB_ID] = [JOB_ID] - === Destroy the bundle: >>> [CLI] bundle destroy --auto-approve The following resources will be deleted: diff --git a/acceptance/bundle/generate/auto-bind/script b/acceptance/bundle/generate/auto-bind/script index ae546f8e1ed..0bd6c6cc02f 100755 --- a/acceptance/bundle/generate/auto-bind/script +++ b/acceptance/bundle/generate/auto-bind/script @@ -45,23 +45,10 @@ trace cat resources/test_job.job.yml | grep "name: auto-bind-job-${UNIQUE_NAME}" title "Deploy the bound job:" trace $CLI bundle deploy -if [ "${DATABRICKS_BUNDLE_DEPLOYMENT_HISTORY:-}" = true ]; then - $CLI jobs get "$JOB_ID" | jq -e '.settings.deployment | (.deployment_id | length > 0) and (.version_id | length > 0)' > LOG.deployment -fi - -title "Regenerate the already-bound job:" -trace musterr $CLI bundle generate job --key test_job --existing-job-id $JOB_ID --config-dir resources --source-dir src --bind --force 2>&1 | contains.py 'Resource already managed' -cat resources/test_job.job.yml | contains.py '!deployment:' '!deployment_id:' '!version_id:' > LOG.generated -trace $CLI bundle validate - -title "Unbind and regenerate the deployed job:" +title "Regenerate and bind the deployed job:" trace $CLI bundle deployment unbind test_job trace $CLI bundle generate job --key test_job --existing-job-id $JOB_ID --config-dir resources --source-dir src --bind --force -title "Redeploy the regenerated job:" -trace $CLI bundle deploy -trace test "$(read_id.py test_job)" = "$JOB_ID" - title "Destroy the bundle:" trace $CLI bundle destroy --auto-approve diff --git a/acceptance/bundle/generate/pipeline_and_deploy/databricks.yml.tmpl b/acceptance/bundle/generate/pipeline_and_deploy/databricks.yml.tmpl index 26c46a3466d..0e0dcbfb4aa 100644 --- a/acceptance/bundle/generate/pipeline_and_deploy/databricks.yml.tmpl +++ b/acceptance/bundle/generate/pipeline_and_deploy/databricks.yml.tmpl @@ -3,7 +3,3 @@ bundle: include: - resources/*.yml - -sync: - exclude: - - LOG.* diff --git a/acceptance/bundle/generate/pipeline_and_deploy/output.txt b/acceptance/bundle/generate/pipeline_and_deploy/output.txt index 06e1274e3db..a2808f37ebf 100644 --- a/acceptance/bundle/generate/pipeline_and_deploy/output.txt +++ b/acceptance/bundle/generate/pipeline_and_deploy/output.txt @@ -8,8 +8,6 @@ === Generate bundle config from the pipelineFile successfully saved to src/notebook-[UNIQUE_NAME].py File successfully saved to src/test-[UNIQUE_NAME].py - ->>> [CLI] bundle generate pipeline --existing-pipeline-id [PIPELINE_ID] --key out --config-dir resources --source-dir src --bind --force Pipeline configuration successfully saved to resources/out.pipeline.yml Successfully bound pipeline with an id '[PIPELINE_ID]' @@ -21,42 +19,15 @@ Updated pipelines.out Files: 7 uploaded, 0 deleted Resources: 0 created, 1 changed, 0 deleted, 0 unchanged -=== Regenerate the already-bound pipelineFile successfully saved to src/notebook-[UNIQUE_NAME].py -File successfully saved to src/test-[UNIQUE_NAME].py - ->>> musterr [CLI] bundle generate pipeline --existing-pipeline-id [PIPELINE_ID] --key out --config-dir resources --source-dir src --bind --force -Pipeline configuration successfully saved to resources/out.pipeline.yml -Error: Resource already managed - -The bundle is already managing resource for resources.pipelines.out and it is bound to the requested ID [PIPELINE_ID]. - - ->>> [CLI] bundle validate -Name: pipeline_and_deploy-[UNIQUE_NAME] -Target: default -Workspace: - User: [USERNAME] - Path: /Workspace/Users/[USERNAME]/.bundle/pipeline_and_deploy-[UNIQUE_NAME]/default - -Validation OK! - -=== Unbind and regenerate the deployed pipeline +=== Regenerate and bind the deployed pipeline >>> [CLI] bundle deployment unbind out -File successfully saved to src/notebook-[UNIQUE_NAME].py -File successfully saved to src/test-[UNIQUE_NAME].py >>> [CLI] bundle generate pipeline --existing-pipeline-id [PIPELINE_ID] --key out --config-dir resources --source-dir src --bind --force +File successfully saved to src/notebook-[UNIQUE_NAME].py +File successfully saved to src/test-[UNIQUE_NAME].py Pipeline configuration successfully saved to resources/out.pipeline.yml Successfully bound pipeline with an id '[PIPELINE_ID]' -=== Redeploy the regenerated pipeline ->>> [CLI] bundle deploy -Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/pipeline_and_deploy-[UNIQUE_NAME]/default/files... -Files: 3 uploaded, 0 deleted -Resources: 0 created, 0 changed, 0 deleted, 1 unchanged - ->>> test [PIPELINE_ID] = [PIPELINE_ID] - === Destroy the deployed bundle >>> [CLI] bundle destroy --auto-approve The following resources will be deleted: @@ -70,10 +41,6 @@ All files and directories at the following location will be deleted: /Workspace/ Destroy: 1 deleted -=== Check that the bound pipeline was destroyed ->>> musterr [CLI] pipelines get [PIPELINE_ID] -Error: The specified pipeline [PIPELINE_ID] was not found. - === Cleanup: delete the original pipeline and files >>> errcode [CLI] pipelines delete [PIPELINE_ID] Error: Not Found diff --git a/acceptance/bundle/generate/pipeline_and_deploy/script b/acceptance/bundle/generate/pipeline_and_deploy/script index 214e25b8324..8f27ba7b04b 100644 --- a/acceptance/bundle/generate/pipeline_and_deploy/script +++ b/acceptance/bundle/generate/pipeline_and_deploy/script @@ -1,7 +1,7 @@ envsubst < databricks.yml.tmpl > databricks.yml title "Upload files to workspace" -# The history-enabled and history-disabled variants run concurrently against the same workspace user, +# The terraform and direct engine variants run concurrently against the same workspace user, # so embed $UNIQUE_NAME in the remote paths: otherwise one variant's cleanup deletes the shared # files out from under the other variant's bundle generate read. trace $CLI workspace import "/Workspace/Users/${CURRENT_USER_NAME}/notebook-${UNIQUE_NAME}.py" --file notebook.py --format AUTO --overwrite @@ -37,12 +37,10 @@ trap cleanup EXIT title "Generate bundle config from the pipeline" # The concurrent downloader emits the "File successfully saved" lines in # nondeterministic order, so sort just those. -generate_pipeline() { - trace "$@" $CLI bundle generate pipeline --existing-pipeline-id "$PIPELINE_ID" --key out --config-dir resources --source-dir src --bind --force &> LOG.generate - grep '^File successfully saved to' LOG.generate | sort - grep -v '^File successfully saved to' LOG.generate -} -generate_pipeline +$CLI bundle generate pipeline --existing-pipeline-id "$PIPELINE_ID" --key out --config-dir resources --source-dir src --bind --force > out.gen.txt 2>&1 +grep '^File successfully saved to' out.gen.txt | sort +grep -v '^File successfully saved to' out.gen.txt +rm out.gen.txt title "Verify generated yaml has expected fields" cat resources/out.pipeline.yml | env -u MSYS_NO_PATHCONV contains.py "libraries:" "- notebook:" "path: ../src/notebook-${UNIQUE_NAME}.py" "- file:" "path: ../src/test-${UNIQUE_NAME}.py" > /dev/null @@ -50,25 +48,9 @@ cat resources/out.pipeline.yml | env -u MSYS_NO_PATHCONV contains.py "libraries: title "Deploy the generated bundle" trace $CLI bundle deploy -if [ "${DATABRICKS_BUNDLE_DEPLOYMENT_HISTORY:-}" = true ]; then - $CLI pipelines get "$PIPELINE_ID" | jq -e '.spec.deployment | (.deployment_id | length > 0) and (.version_id | length > 0)' > LOG.deployment -fi - -title "Regenerate the already-bound pipeline" -generate_pipeline musterr | contains.py 'Resource already managed' -cat resources/out.pipeline.yml | contains.py '!deployment:' '!deployment_id:' '!version_id:' > LOG.generated -trace $CLI bundle validate - -title "Unbind and regenerate the deployed pipeline" +title "Regenerate and bind the deployed pipeline" trace $CLI bundle deployment unbind out -generate_pipeline - -title "Redeploy the regenerated pipeline" -trace $CLI bundle deploy -trace test "$(read_id.py out)" = "$PIPELINE_ID" +trace $CLI bundle generate pipeline --existing-pipeline-id "$PIPELINE_ID" --key out --config-dir resources --source-dir src --bind --force 2>&1 | sort title "Destroy the deployed bundle" trace $CLI bundle destroy --auto-approve - -title "Check that the bound pipeline was destroyed" -trace musterr $CLI pipelines get "$PIPELINE_ID" From 5e7a8cab78d0b1e99b3bb4670a08ae0869121bea Mon Sep 17 00:00:00 2001 From: Shreyas Goenka Date: Wed, 28 Oct 2026 14:59:30 +0000 Subject: [PATCH 3/3] Cover jobs and pipelines in the existing auto-bind test --- .../bundle/generate/auto-bind/output.txt | 39 ++++++++++++++++--- acceptance/bundle/generate/auto-bind/script | 19 +++++++-- .../pipeline_and_deploy/databricks.yml.tmpl | 3 -- .../generate/pipeline_and_deploy/output.txt | 33 +++++----------- .../generate/pipeline_and_deploy/script | 9 ++--- 5 files changed, 62 insertions(+), 41 deletions(-) diff --git a/acceptance/bundle/generate/auto-bind/output.txt b/acceptance/bundle/generate/auto-bind/output.txt index f2e7837c2a8..c5fe2edfc36 100644 --- a/acceptance/bundle/generate/auto-bind/output.txt +++ b/acceptance/bundle/generate/auto-bind/output.txt @@ -6,26 +6,38 @@ Created job with ID: [JOB_ID] >>> [CLI] workspace import /Workspace/Users/[USERNAME]/python-[UNIQUE_NAME]/test --file test.py --language PYTHON +=== Create a pre-defined pipeline: +Created pipeline with ID: [PIPELINE_ID] + === Generate and bind in one step: >>> [CLI] bundle generate job --key test_job --existing-job-id [JOB_ID] --config-dir resources --source-dir src --bind File successfully saved to src/test.py Job configuration successfully saved to resources/test_job.job.yml Successfully bound job with an id '[JOB_ID]' +>>> [CLI] bundle generate pipeline --key test_pipeline --existing-pipeline-id [PIPELINE_ID] --config-dir resources --source-dir src --bind --force +File successfully saved to src/test.py +Pipeline configuration successfully saved to resources/test_pipeline.pipeline.yml +Successfully bound pipeline with an id '[PIPELINE_ID]' + >>> ls src/ test.py >>> cat resources/test_job.job.yml name: auto-bind-job-[UNIQUE_NAME] -=== Deploy the bound job: +>>> cat resources/test_pipeline.pipeline.yml + name: auto-bind-pipeline-[UNIQUE_NAME] + +=== Deploy the bound resources: >>> [CLI] bundle deploy Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/auto-bind-test-[UNIQUE_NAME]/files... Updated jobs.test_job -Files: 5 uploaded, 0 deleted -Resources: 0 created, 1 changed, 0 deleted, 0 unchanged +Updated pipelines.test_pipeline +Files: 6 uploaded, 0 deleted +Resources: 0 created, 2 changed, 0 deleted, 0 unchanged -=== Regenerate and bind the deployed job: +=== Regenerate and bind the deployed resources: >>> [CLI] bundle deployment unbind test_job >>> [CLI] bundle generate job --key test_job --existing-job-id [JOB_ID] --config-dir resources --source-dir src --bind --force @@ -33,21 +45,36 @@ File successfully saved to src/test.py Job configuration successfully saved to resources/test_job.job.yml Successfully bound job with an id '[JOB_ID]' +>>> [CLI] bundle deployment unbind test_pipeline + +>>> [CLI] bundle generate pipeline --key test_pipeline --existing-pipeline-id [PIPELINE_ID] --config-dir resources --source-dir src --bind --force +File successfully saved to src/test.py +Pipeline configuration successfully saved to resources/test_pipeline.pipeline.yml +Successfully bound pipeline with an id '[PIPELINE_ID]' + === Destroy the bundle: >>> [CLI] bundle destroy --auto-approve The following resources will be deleted: delete resources.jobs.test_job + delete resources.pipelines.test_pipeline + +This action will result in the deletion of the following Lakeflow Spark Declarative Pipelines along with the +Streaming Tables (STs) and Materialized Views (MVs) managed by them. Set 'cascade_on_destroy: false' on a pipeline to retain datasets on pipeline deletion: + delete resources.pipelines.test_pipeline All files and directories at the following location will be deleted: /Workspace/Users/[USERNAME]/.bundle/auto-bind-test-[UNIQUE_NAME] -Destroy: 1 deleted +Destroy: 2 deleted -=== Check that job is bound and does not exist after bundle is destroyed: +=== Check that resources are bound and do not exist after bundle is destroyed: >>> errcode [CLI] jobs get [JOB_ID] --output json Error: Job [JOB_ID] does not exist. Exit code: 1 +>>> musterr [CLI] pipelines get [PIPELINE_ID] --output json +Error: The specified pipeline [PIPELINE_ID] was not found. + === Delete the tmp folder: >>> [CLI] workspace delete /Workspace/Users/[USERNAME]/python-[UNIQUE_NAME]/test diff --git a/acceptance/bundle/generate/auto-bind/script b/acceptance/bundle/generate/auto-bind/script index 0bd6c6cc02f..72e688a6318 100755 --- a/acceptance/bundle/generate/auto-bind/script +++ b/acceptance/bundle/generate/auto-bind/script @@ -36,21 +36,34 @@ trap cleanup EXIT trace $CLI workspace mkdirs "${PYTHON_NOTEBOOK_DIR}" trace $CLI workspace import "${PYTHON_NOTEBOOK}" --file test.py --language PYTHON +title "Create a pre-defined pipeline:\n" +PIPELINE_ID=$($CLI pipelines create --json '{ + "name": "auto-bind-pipeline-'${UNIQUE_NAME}'", + "libraries": [{"notebook": {"path": "'${PYTHON_NOTEBOOK}'"}}] +}' | jq -r '.pipeline_id') +add_repl "$PIPELINE_ID" PIPELINE_ID +echo "Created pipeline with ID: $PIPELINE_ID" + title "Generate and bind in one step:" trace $CLI bundle generate job --key test_job --existing-job-id $JOB_ID --config-dir resources --source-dir src --bind +trace $CLI bundle generate pipeline --key test_pipeline --existing-pipeline-id $PIPELINE_ID --config-dir resources --source-dir src --bind --force trace ls src/ # The output of the job is difference per cloud so we only check the name. trace cat resources/test_job.job.yml | grep "name: auto-bind-job-${UNIQUE_NAME}" +trace cat resources/test_pipeline.pipeline.yml | grep "name: auto-bind-pipeline-${UNIQUE_NAME}" -title "Deploy the bound job:" +title "Deploy the bound resources:" trace $CLI bundle deploy -title "Regenerate and bind the deployed job:" +title "Regenerate and bind the deployed resources:" trace $CLI bundle deployment unbind test_job trace $CLI bundle generate job --key test_job --existing-job-id $JOB_ID --config-dir resources --source-dir src --bind --force +trace $CLI bundle deployment unbind test_pipeline +trace $CLI bundle generate pipeline --key test_pipeline --existing-pipeline-id $PIPELINE_ID --config-dir resources --source-dir src --bind --force title "Destroy the bundle:" trace $CLI bundle destroy --auto-approve -title "Check that job is bound and does not exist after bundle is destroyed:" +title "Check that resources are bound and do not exist after bundle is destroyed:" trace errcode $CLI jobs get "${JOB_ID}" --output json +trace musterr $CLI pipelines get "${PIPELINE_ID}" --output json diff --git a/acceptance/bundle/generate/pipeline_and_deploy/databricks.yml.tmpl b/acceptance/bundle/generate/pipeline_and_deploy/databricks.yml.tmpl index 0e0dcbfb4aa..487b54402f8 100644 --- a/acceptance/bundle/generate/pipeline_and_deploy/databricks.yml.tmpl +++ b/acceptance/bundle/generate/pipeline_and_deploy/databricks.yml.tmpl @@ -1,5 +1,2 @@ bundle: name: pipeline_and_deploy-$UNIQUE_NAME - -include: - - resources/*.yml diff --git a/acceptance/bundle/generate/pipeline_and_deploy/output.txt b/acceptance/bundle/generate/pipeline_and_deploy/output.txt index a2808f37ebf..c63cfee74d5 100644 --- a/acceptance/bundle/generate/pipeline_and_deploy/output.txt +++ b/acceptance/bundle/generate/pipeline_and_deploy/output.txt @@ -9,43 +9,30 @@ === Generate bundle config from the pipelineFile successfully saved to src/notebook-[UNIQUE_NAME].py File successfully saved to src/test-[UNIQUE_NAME].py Pipeline configuration successfully saved to resources/out.pipeline.yml -Successfully bound pipeline with an id '[PIPELINE_ID]' +Warning: Generated configuration is not included in the bundle + +The file resources/out.pipeline.yml is not matched by any pattern in the 'include' section of databricks.yml, +so it will not be deployed. Add a matching entry to the 'include' section, for example: + +include: + - resources/*.yml + === Verify generated yaml has expected fields === Deploy the generated bundle >>> [CLI] bundle deploy Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/pipeline_and_deploy-[UNIQUE_NAME]/default/files... -Updated pipelines.out Files: 7 uploaded, 0 deleted -Resources: 0 created, 1 changed, 0 deleted, 0 unchanged - -=== Regenerate and bind the deployed pipeline ->>> [CLI] bundle deployment unbind out - ->>> [CLI] bundle generate pipeline --existing-pipeline-id [PIPELINE_ID] --key out --config-dir resources --source-dir src --bind --force -File successfully saved to src/notebook-[UNIQUE_NAME].py -File successfully saved to src/test-[UNIQUE_NAME].py -Pipeline configuration successfully saved to resources/out.pipeline.yml -Successfully bound pipeline with an id '[PIPELINE_ID]' +Resources: 0 created, 0 changed, 0 deleted, 0 unchanged === Destroy the deployed bundle >>> [CLI] bundle destroy --auto-approve -The following resources will be deleted: - delete resources.pipelines.out - -This action will result in the deletion of the following Lakeflow Spark Declarative Pipelines along with the -Streaming Tables (STs) and Materialized Views (MVs) managed by them. Set 'cascade_on_destroy: false' on a pipeline to retain datasets on pipeline deletion: - delete resources.pipelines.out - All files and directories at the following location will be deleted: /Workspace/Users/[USERNAME]/.bundle/pipeline_and_deploy-[UNIQUE_NAME]/default -Destroy: 1 deleted +Destroy: 0 deleted === Cleanup: delete the original pipeline and files >>> errcode [CLI] pipelines delete [PIPELINE_ID] -Error: Not Found - -Exit code: 1 >>> errcode [CLI] workspace delete /Workspace/Users/[USERNAME]/notebook-[UNIQUE_NAME] diff --git a/acceptance/bundle/generate/pipeline_and_deploy/script b/acceptance/bundle/generate/pipeline_and_deploy/script index 8f27ba7b04b..32d4cbcbc4a 100644 --- a/acceptance/bundle/generate/pipeline_and_deploy/script +++ b/acceptance/bundle/generate/pipeline_and_deploy/script @@ -36,8 +36,9 @@ trap cleanup EXIT title "Generate bundle config from the pipeline" # The concurrent downloader emits the "File successfully saved" lines in -# nondeterministic order, so sort just those. -$CLI bundle generate pipeline --existing-pipeline-id "$PIPELINE_ID" --key out --config-dir resources --source-dir src --bind --force > out.gen.txt 2>&1 +# nondeterministic order, so sort just those; the remaining lines (including the +# multi-line include warning) are deterministic and kept in their natural order. +$CLI bundle generate pipeline --existing-pipeline-id "$PIPELINE_ID" --key out --config-dir resources --source-dir src --force > out.gen.txt 2>&1 grep '^File successfully saved to' out.gen.txt | sort grep -v '^File successfully saved to' out.gen.txt rm out.gen.txt @@ -48,9 +49,5 @@ cat resources/out.pipeline.yml | env -u MSYS_NO_PATHCONV contains.py "libraries: title "Deploy the generated bundle" trace $CLI bundle deploy -title "Regenerate and bind the deployed pipeline" -trace $CLI bundle deployment unbind out -trace $CLI bundle generate pipeline --existing-pipeline-id "$PIPELINE_ID" --key out --config-dir resources --source-dir src --bind --force 2>&1 | sort - title "Destroy the deployed bundle" trace $CLI bundle destroy --auto-approve