diff --git a/acceptance/acceptance_test.go b/acceptance/acceptance_test.go index 65c5776978c..59f9e66be70 100644 --- a/acceptance/acceptance_test.go +++ b/acceptance/acceptance_test.go @@ -333,6 +333,12 @@ func testAccept(t *testing.T, inprocessMode bool, singleTest string) int { cli293Path := DownloadCLI(t, buildDir, "0.293.0") t.Setenv("CLI_293", cli293Path) repls.SetPath(cli293Path, "[CLI_293]") + + prevVersion := resolveLatestVersion(t, buildDir) + cliPrevPath := DownloadCLI(t, buildDir, prevVersion) + t.Setenv("CLI_PREV", cliPrevPath) + repls.SetPath(cliPrevPath, "[CLI_PREV]") + repls.Set(prevVersion, "[CLI_PREV_VERSION]") } paths := []string{ diff --git a/acceptance/bundle/invariant/continue_prev/out.test.toml b/acceptance/bundle/invariant/continue_prev/out.test.toml new file mode 100644 index 00000000000..ac81d200496 --- /dev/null +++ b/acceptance/bundle/invariant/continue_prev/out.test.toml @@ -0,0 +1,52 @@ +Local = true +Cloud = true +RequiresUnityCatalog = true +EnvMatrix.DATABRICKS_BUNDLE_ENGINE = ["direct"] +EnvMatrix.INPUT_CONFIG = [ + "alert.yml.tmpl", + "app.yml.tmpl", + "catalog.yml.tmpl", + "cluster.yml.tmpl", + "cluster_apply_policy_default_values.yml.tmpl", + "dashboard.yml.tmpl", + "job_apply_policy_default_values_job_cluster.yml.tmpl", + "job_apply_policy_default_values_task_cluster.yml.tmpl", + "job_apply_policy_default_values_for_each_task.yml.tmpl", + "database_catalog.yml.tmpl", + "database_instance.yml.tmpl", + "experiment.yml.tmpl", + "external_location.yml.tmpl", + "genie_space.yml.tmpl", + "job.yml.tmpl", + "job_pydabs_10_tasks.yml.tmpl", + "job_cross_resource_ref.yml.tmpl", + "job_permission_ref.yml.tmpl", + "job_run_job_ref.yml.tmpl", + "job_with_depends_on.yml.tmpl", + "job_with_task.yml.tmpl", + "model.yml.tmpl", + "model_with_permissions.yml.tmpl", + "model_serving_endpoint.yml.tmpl", + "pipeline.yml.tmpl", + "pipeline_apply_policy_default_values.yml.tmpl", + "pipeline_config_dots.yml.tmpl", + "postgres_branch.yml.tmpl", + "postgres_catalog.yml.tmpl", + "postgres_database.yml.tmpl", + "postgres_endpoint.yml.tmpl", + "postgres_role.yml.tmpl", + "postgres_synced_table.yml.tmpl", + "registered_model.yml.tmpl", + "schema.yml.tmpl", + "schema_grant_ref.yml.tmpl", + "schema_uppercase_name.yml.tmpl", + "secret_scope.yml.tmpl", + "secret_scope_default_backend_type.yml.tmpl", + "sql_warehouse.yml.tmpl", + "synced_database_table.yml.tmpl", + "vector_search_endpoint.yml.tmpl", + "vector_search_index.yml.tmpl", + "volume.yml.tmpl", + "volume_external.yml.tmpl", + "volume_uppercase_name.yml.tmpl" +] diff --git a/acceptance/bundle/invariant/continue_prev/output.txt b/acceptance/bundle/invariant/continue_prev/output.txt new file mode 100644 index 00000000000..20e01313be6 --- /dev/null +++ b/acceptance/bundle/invariant/continue_prev/output.txt @@ -0,0 +1,4 @@ + +>>> [CLI_PREV] --version +Databricks CLI v[CLI_PREV_VERSION] +INPUT_CONFIG_OK diff --git a/acceptance/bundle/invariant/continue_prev/script b/acceptance/bundle/invariant/continue_prev/script new file mode 100644 index 00000000000..908792643b8 --- /dev/null +++ b/acceptance/bundle/invariant/continue_prev/script @@ -0,0 +1,41 @@ +# Invariant to test: current CLI can deploy on top of state produced by the previous release + +cp -r "$TESTDIR/../data/." . &> LOG.cp + +INIT_SCRIPT="$TESTDIR/../configs/$INPUT_CONFIG-init.sh" +if [ -f "$INIT_SCRIPT" ]; then + source "$INIT_SCRIPT" &> LOG.init +fi + +envsubst < "$TESTDIR/../configs/$INPUT_CONFIG" > databricks.yml + +cleanup() { + $CLI bundle destroy --auto-approve &> LOG.destroy + cat LOG.destroy | contains.py '!panic' '!internal error' > /dev/null + + CLEANUP_SCRIPT="$TESTDIR/../configs/$INPUT_CONFIG-cleanup.sh" + if [ -f "$CLEANUP_SCRIPT" ]; then + source "$CLEANUP_SCRIPT" &> LOG.cleanup + fi +} + +trap cleanup EXIT + +# Deploy with previous released CLI to produce previous-version state +trace $CLI_PREV --version +$CLI_PREV bundle deploy &> LOG.deploy.prev +cat LOG.deploy.prev | contains.py '!panic' '!internal error' > /dev/null + +echo INPUT_CONFIG_OK + +# Deploy with current CLI on top of previous state +$CLI bundle deploy &> LOG.deploy +cat LOG.deploy | contains.py '!panic' '!internal error' > /dev/null + +# Verify no drift after current CLI deploy +$CLI bundle plan -o json > LOG.planjson 2>LOG.planjson.err +cat LOG.planjson.err | contains.py '!panic' '!internal error' > /dev/null +verify_no_drift.py LOG.planjson + +$CLI bundle plan 2>LOG.plan.err | contains.py '!panic' '!internal error' 'Plan: 0 to add, 0 to change, 0 to delete' > LOG.plan +cat LOG.plan.err | contains.py '!panic' '!internal error' > /dev/null diff --git a/acceptance/bundle/invariant/continue_prev/test.toml b/acceptance/bundle/invariant/continue_prev/test.toml new file mode 100644 index 00000000000..5a92f4f5ba9 --- /dev/null +++ b/acceptance/bundle/invariant/continue_prev/test.toml @@ -0,0 +1,13 @@ +# Computed volume_path was added after the previous release (#5550), so the +# seed deploy with the previous CLI cannot resolve ${resources.volumes.*.volume_path}. +# Covered by no_drift on direct. +EnvMatrixExclude.no_volume_path_job_ref = ["INPUT_CONFIG=volume_path_job_ref.yml.tmpl"] + +# postgres_project.yml.tmpl sets enable_pg_native_login: false, which triggers a +# state serialization bug on the previous CLI (fixed by #5782). +# Broken on CLI_PREV=1.6.0; remove after the next release. +EnvMatrixExclude.no_postgres_project = ["INPUT_CONFIG=postgres_project.yml.tmpl"] + +# The 1000-task scale case is covered by no_drift. Running it here adds ~1.5 min +# per variant (two full deploys at 1000 tasks) without incremental coverage. +EnvMatrixExclude.no_pydabs_1000_tasks = ["INPUT_CONFIG=job_pydabs_1000_tasks.yml.tmpl"]