From 54ef2462d1416236ced954a2afc029f0adf97b04 Mon Sep 17 00:00:00 2001 From: Jan Rose Date: Wed, 19 Aug 2026 19:05:47 +0200 Subject: [PATCH 1/2] acc: Reproduce that file syncs are done despite failed resource deployments --- .../move-during-failed-deploy/databricks.yml | 15 ++++++ .../move-during-failed-deploy/out.test.toml | 2 + .../move-during-failed-deploy/output.txt | 46 +++++++++++++++++++ .../files/move-during-failed-deploy/script | 23 ++++++++++ .../move-during-failed-deploy/src/main.py | 1 + .../files/move-during-failed-deploy/test.toml | 17 +++++++ 6 files changed, 104 insertions(+) create mode 100644 acceptance/bundle/deploy/files/move-during-failed-deploy/databricks.yml create mode 100644 acceptance/bundle/deploy/files/move-during-failed-deploy/out.test.toml create mode 100644 acceptance/bundle/deploy/files/move-during-failed-deploy/output.txt create mode 100644 acceptance/bundle/deploy/files/move-during-failed-deploy/script create mode 100644 acceptance/bundle/deploy/files/move-during-failed-deploy/src/main.py create mode 100644 acceptance/bundle/deploy/files/move-during-failed-deploy/test.toml diff --git a/acceptance/bundle/deploy/files/move-during-failed-deploy/databricks.yml b/acceptance/bundle/deploy/files/move-during-failed-deploy/databricks.yml new file mode 100644 index 00000000000..f5fd21fc732 --- /dev/null +++ b/acceptance/bundle/deploy/files/move-during-failed-deploy/databricks.yml @@ -0,0 +1,15 @@ +bundle: + name: move-during-failed-deploy + +resources: + jobs: + foo: + name: test-job + tasks: + - task_key: my_task + spark_python_task: + python_file: ./src/main.py + new_cluster: + num_workers: 1 + spark_version: 13.3.x-scala2.12 + node_type_id: i3.xlarge diff --git a/acceptance/bundle/deploy/files/move-during-failed-deploy/out.test.toml b/acceptance/bundle/deploy/files/move-during-failed-deploy/out.test.toml new file mode 100644 index 00000000000..0938e678987 --- /dev/null +++ b/acceptance/bundle/deploy/files/move-during-failed-deploy/out.test.toml @@ -0,0 +1,2 @@ +Cloud = false +EnvMatrix.DATABRICKS_BUNDLE_ENGINE = ["direct"] diff --git a/acceptance/bundle/deploy/files/move-during-failed-deploy/output.txt b/acceptance/bundle/deploy/files/move-during-failed-deploy/output.txt new file mode 100644 index 00000000000..b60f3a98c4e --- /dev/null +++ b/acceptance/bundle/deploy/files/move-during-failed-deploy/output.txt @@ -0,0 +1,46 @@ + +=== Deploy 1: the job references src/main.py, which is uploaded to the workspace +>>> [CLI] bundle deploy +Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/move-during-failed-deploy/default/files... +Created jobs.foo +Files: 5 uploaded, 0 deleted +Resources: 1 created, 0 changed, 0 deleted, 0 unchanged + +>>> [CLI] workspace get-status /Workspace/Users/[USERNAME]/.bundle/move-during-failed-deploy/default/files/src/main.py +{ + "object_type": "FILE", + "path": "/Workspace/Users/[USERNAME]/.bundle/move-during-failed-deploy/default/files/src/main.py" +} + +=== Move the referenced file and point the job at the new location +>>> mv src/main.py src/renamed.py + +>>> update_file.py databricks.yml src/main.py src/renamed.py + +=== Fail the job update. Files are still synced first, so main.py is deleted and +renamed.py uploaded before the failing jobs/reset. +>>> musterr [CLI] bundle deploy +Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/move-during-failed-deploy/default/files... +Error: cannot update resources.jobs.foo: updating id=[FOO_ID]: Fault injected by test. (403 INJECTED) + +Endpoint: POST [DATABRICKS_URL]/api/2.2/jobs/reset +HTTP Status: 403 Forbidden +API error_code: INJECTED +API message: Fault injected by test. + +Files: 3 uploaded, 1 deleted + +=== Broken state: the failed deploy already deleted the old file from the workspace +>>> musterr [CLI] workspace get-status /Workspace/Users/[USERNAME]/.bundle/move-during-failed-deploy/default/files/src/main.py +Error: Path (/Workspace/Users/[USERNAME]/.bundle/move-during-failed-deploy/default/files/src/main.py) doesn't exist. + +=== The new file was uploaded +>>> [CLI] workspace get-status /Workspace/Users/[USERNAME]/.bundle/move-during-failed-deploy/default/files/src/renamed.py +{ + "object_type": "FILE", + "path": "/Workspace/Users/[USERNAME]/.bundle/move-during-failed-deploy/default/files/src/renamed.py" +} + +=== But the deployed job still points at the deleted file, so a run fails file-not-found +>>> [CLI] jobs get [FOO_ID] +"/Workspace/Users/[USERNAME]/.bundle/move-during-failed-deploy/default/files/src/main.py" diff --git a/acceptance/bundle/deploy/files/move-during-failed-deploy/script b/acceptance/bundle/deploy/files/move-during-failed-deploy/script new file mode 100644 index 00000000000..5ea88233b27 --- /dev/null +++ b/acceptance/bundle/deploy/files/move-during-failed-deploy/script @@ -0,0 +1,23 @@ +BUNDLE_FILES="/Workspace/Users/${CURRENT_USER_NAME}/.bundle/move-during-failed-deploy/default/files" + +title "Deploy 1: the job references src/main.py, which is uploaded to the workspace" +trace $CLI bundle deploy +trace $CLI workspace get-status "$BUNDLE_FILES/src/main.py" | jq '{object_type,path}' + +title "Move the referenced file and point the job at the new location" +trace mv src/main.py src/renamed.py +trace update_file.py databricks.yml src/main.py src/renamed.py + +title "Fail the job update. Files are still synced first, so main.py is deleted and\nrenamed.py uploaded before the failing jobs/reset." +fault.py "POST /api/2.2/jobs/reset" 403 0 1 +trace musterr $CLI bundle deploy + +title "Broken state: the failed deploy already deleted the old file from the workspace" +trace musterr $CLI workspace get-status "$BUNDLE_FILES/src/main.py" + +title "The new file was uploaded" +trace $CLI workspace get-status "$BUNDLE_FILES/src/renamed.py" | jq '{object_type,path}' + +title "But the deployed job still points at the deleted file, so a run fails file-not-found" +job_id=$(read_id.py foo) +trace $CLI jobs get "$job_id" | jq '.settings.tasks[0].spark_python_task.python_file' diff --git a/acceptance/bundle/deploy/files/move-during-failed-deploy/src/main.py b/acceptance/bundle/deploy/files/move-during-failed-deploy/src/main.py new file mode 100644 index 00000000000..11b15b1a458 --- /dev/null +++ b/acceptance/bundle/deploy/files/move-during-failed-deploy/src/main.py @@ -0,0 +1 @@ +print("hello") diff --git a/acceptance/bundle/deploy/files/move-during-failed-deploy/test.toml b/acceptance/bundle/deploy/files/move-during-failed-deploy/test.toml new file mode 100644 index 00000000000..8b2068637c9 --- /dev/null +++ b/acceptance/bundle/deploy/files/move-during-failed-deploy/test.toml @@ -0,0 +1,17 @@ +Badness = "A deploy uploads and deletes bundle files before it applies resources, so a resource-update failure after a file move leaves the job pointing at a file that no longer exists in the workspace." + +# The injected fault (POST /api/2.2/jobs/reset) and the state inspection differ in +# output between the terraform and direct engines, so pin the direct engine (same +# precedent as ../partial-summary-on-push-fail). The ordering bug being demonstrated +# is engine-independent: files.Upload runs before deployCore for both engines. +EnvMatrix.DATABRICKS_BUNDLE_ENGINE = ["direct"] + +# The script moves src/main.py to src/renamed.py, so the renamed file is not a +# committed input and would otherwise be flagged as an unexpected leftover. +Ignore = ["src/renamed.py"] + +[Env] +# The script passes absolute workspace paths like /Workspace/Users/.../src/main.py as +# CLI arguments. On Windows the script runs under MSYS2, which rewrites such +# leading-slash arguments to Windows paths before the CLI sees them. Disable that. +MSYS_NO_PATHCONV = "1" From dbdb3850c4e610ad2333bc244a87b907c9945ea9 Mon Sep 17 00:00:00 2001 From: Jan Rose Date: Wed, 19 Aug 2026 23:33:01 +0200 Subject: [PATCH 2/2] acc: scope MSYS_NO_PATHCONV to the workspace-path CLI calls Setting MSYS_NO_PATHCONV=1 globally in [Env] fixed the leading-slash /Workspace/... arguments passed to `workspace get-status`, but it also disabled Git Bash path conversion for the shebang-resolved .py helpers (update_file.py, read_id.py). On Windows the native python.exe then received the unconverted POSIX path (/c/a/cli/cli/.../update_file.py -> C:\c\a\cli\cli\...), which does not exist, so the test failed only on the windows/direct runner. Scope the env var to the three get-status calls that actually pass a workspace path, leaving the .py helpers with normal path conversion. Co-authored-by: Isaac --- .../deploy/files/move-during-failed-deploy/output.txt | 6 +++--- .../bundle/deploy/files/move-during-failed-deploy/script | 9 ++++++--- .../deploy/files/move-during-failed-deploy/test.toml | 6 ------ 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/acceptance/bundle/deploy/files/move-during-failed-deploy/output.txt b/acceptance/bundle/deploy/files/move-during-failed-deploy/output.txt index b60f3a98c4e..7e189f31af6 100644 --- a/acceptance/bundle/deploy/files/move-during-failed-deploy/output.txt +++ b/acceptance/bundle/deploy/files/move-during-failed-deploy/output.txt @@ -6,7 +6,7 @@ Created jobs.foo Files: 5 uploaded, 0 deleted Resources: 1 created, 0 changed, 0 deleted, 0 unchanged ->>> [CLI] workspace get-status /Workspace/Users/[USERNAME]/.bundle/move-during-failed-deploy/default/files/src/main.py +>>> MSYS_NO_PATHCONV=1 [CLI] workspace get-status /Workspace/Users/[USERNAME]/.bundle/move-during-failed-deploy/default/files/src/main.py { "object_type": "FILE", "path": "/Workspace/Users/[USERNAME]/.bundle/move-during-failed-deploy/default/files/src/main.py" @@ -31,11 +31,11 @@ API message: Fault injected by test. Files: 3 uploaded, 1 deleted === Broken state: the failed deploy already deleted the old file from the workspace ->>> musterr [CLI] workspace get-status /Workspace/Users/[USERNAME]/.bundle/move-during-failed-deploy/default/files/src/main.py +>>> MSYS_NO_PATHCONV=1 musterr [CLI] workspace get-status /Workspace/Users/[USERNAME]/.bundle/move-during-failed-deploy/default/files/src/main.py Error: Path (/Workspace/Users/[USERNAME]/.bundle/move-during-failed-deploy/default/files/src/main.py) doesn't exist. === The new file was uploaded ->>> [CLI] workspace get-status /Workspace/Users/[USERNAME]/.bundle/move-during-failed-deploy/default/files/src/renamed.py +>>> MSYS_NO_PATHCONV=1 [CLI] workspace get-status /Workspace/Users/[USERNAME]/.bundle/move-during-failed-deploy/default/files/src/renamed.py { "object_type": "FILE", "path": "/Workspace/Users/[USERNAME]/.bundle/move-during-failed-deploy/default/files/src/renamed.py" diff --git a/acceptance/bundle/deploy/files/move-during-failed-deploy/script b/acceptance/bundle/deploy/files/move-during-failed-deploy/script index 5ea88233b27..a00da6aea3b 100644 --- a/acceptance/bundle/deploy/files/move-during-failed-deploy/script +++ b/acceptance/bundle/deploy/files/move-during-failed-deploy/script @@ -2,7 +2,10 @@ BUNDLE_FILES="/Workspace/Users/${CURRENT_USER_NAME}/.bundle/move-during-failed-d title "Deploy 1: the job references src/main.py, which is uploaded to the workspace" trace $CLI bundle deploy -trace $CLI workspace get-status "$BUNDLE_FILES/src/main.py" | jq '{object_type,path}' +# MSYS_NO_PATHCONV=1 keeps Git Bash from rewriting the leading-slash workspace path +# into a Windows path before the CLI sees it. Scoped per-command so it does not also +# break the shebang-resolved .py helpers (update_file.py, read_id.py) on Windows. +trace MSYS_NO_PATHCONV=1 $CLI workspace get-status "$BUNDLE_FILES/src/main.py" | jq '{object_type,path}' title "Move the referenced file and point the job at the new location" trace mv src/main.py src/renamed.py @@ -13,10 +16,10 @@ fault.py "POST /api/2.2/jobs/reset" 403 0 1 trace musterr $CLI bundle deploy title "Broken state: the failed deploy already deleted the old file from the workspace" -trace musterr $CLI workspace get-status "$BUNDLE_FILES/src/main.py" +trace MSYS_NO_PATHCONV=1 musterr $CLI workspace get-status "$BUNDLE_FILES/src/main.py" title "The new file was uploaded" -trace $CLI workspace get-status "$BUNDLE_FILES/src/renamed.py" | jq '{object_type,path}' +trace MSYS_NO_PATHCONV=1 $CLI workspace get-status "$BUNDLE_FILES/src/renamed.py" | jq '{object_type,path}' title "But the deployed job still points at the deleted file, so a run fails file-not-found" job_id=$(read_id.py foo) diff --git a/acceptance/bundle/deploy/files/move-during-failed-deploy/test.toml b/acceptance/bundle/deploy/files/move-during-failed-deploy/test.toml index 8b2068637c9..0f194c5ae50 100644 --- a/acceptance/bundle/deploy/files/move-during-failed-deploy/test.toml +++ b/acceptance/bundle/deploy/files/move-during-failed-deploy/test.toml @@ -9,9 +9,3 @@ EnvMatrix.DATABRICKS_BUNDLE_ENGINE = ["direct"] # The script moves src/main.py to src/renamed.py, so the renamed file is not a # committed input and would otherwise be flagged as an unexpected leftover. Ignore = ["src/renamed.py"] - -[Env] -# The script passes absolute workspace paths like /Workspace/Users/.../src/main.py as -# CLI arguments. On Windows the script runs under MSYS2, which rewrites such -# leading-slash arguments to Windows paths before the CLI sees them. Disable that. -MSYS_NO_PATHCONV = "1"