Skip to content

Revert bundle file uploads to import-file and replace nodes of the other type - #7218

Merged
Sankalp-Mittal merged 18 commits into
mainfrom
sankalp-mittal/acc-7216-notebook-detection
Oct 29, 2026
Merged

Sankalp-Mittal merged 18 commits into
mainfrom
sankalp-mittal/acc-7216-notebook-detection

Conversation

@Sankalp-Mittal

@Sankalp-Mittal Sankalp-Mittal commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

Changes

Fixes #7216.

Forward-fixes for changes on main since #6149: the upload-504 tests (#7014) and upload/internal_server_error inject faults on the import-file URL again, the multipart request recorder stays (snapshot uploads use it), and the testserver keeps the improvements from #6149/#7034 (its /workspace/import model, fault.py --body-contains, JUPYTER imports). libs/notebook is left as on main.

The testserver now also extracts a .zip sent to import-file into the parent folder, like the real endpoint (importZipFile in universe), instead of storing it as a file. The ssh tests therefore upload valid placeholder archives instead of empty files.

Upload errors no longer carry the failed to upload <path>: prefix #6149 added; the path is still in the Endpoint: line, as in v1.20.

Why

Discussed in Slack: revert until the backend fixes /workspace/import, and clean up mismatched nodes client-side, since a deploy's goal is for the remote to match the local files.

Tests

  • New bundle/sync/replace-node-type (Cloud = true): a file where the upload is a notebook and a notebook where the upload is a file are both replaced. Passes locally and on aws-cli.
  • New bundle/sync/zip-extract (Cloud = true): a synced .zip is extracted into the file path and overwritten on the next sync. Passes locally and on aws-cli.
  • Compared against v1.20.0: the reverted production files match v1.20.0 except the new deleteNodeOfOtherType. Deploying the same 32-file bundle (notebook header variants, .zip, reserved asset names, a dashboard) twice with released v1.20.0 and with this branch on dogfood gives identical object types and byte-identical contents, and a deploy lock held by someone else is rejected the same way and left in place.
  • Replayed on dogfood: deploy with released v1.21.0 (leaves FILE bom.sql), then this branch (replaced by NOTEBOOK bom), then v1.20.0 and this branch again; no errors.
  • Full acceptance suite passes locally, except the Python template/wheel tests, which fail in my environment because uv can't resolve hatchling.
  • Merged main in. I couldn't build the merged tree locally because the internal Go proxy still blocks golang.org/x/net v0.62.0 (from Bump dependencies with known vulnerabilities #7213); the merge only touched two bind/pipelines tests, resolved by combining --nostamp with the import-file exclusion. Everything above ran on the commit before the merge.

This pull request and its description were written by Isaac.

Since v1.21 the CLI decides itself whether a source file is a notebook
(exact first-line header). The legacy import-file endpoint used up to
v1.20 imports a file as a notebook if its first line contains
"Databricks notebook source", and always imports .Rmd as an R notebook.
Files where the two disagree break deployments that switch between CLI
versions, which is the error reported in #7216.

Add acceptance tests, with Badness, for the CLI side:
- near-miss headers (BOM, trailing space, ...) are uploaded as files
- .Rmd is uploaded as a file
- syncing over a legacy-created notebook fails with "file already exists"
- the legacy endpoint fails over a file synced by this CLI with
  RESOURCE_ALREADY_EXISTS: Node named '...' already exists

and a Cloud test documenting /workspace/import: AUTO's 200-byte, any-line
marker rule, R_MARKDOWN, and that overwrite never changes an object's type.

The testserver now mirrors the legacy and AUTO classification rules, the
R_MARKDOWN format and the collision responses observed on a real
workspace.

Co-authored-by: Isaac <no-reply@databricks.com>
@github-actions github-actions Bot added the DABs DABs related issues label Oct 28, 2026
@github-actions

github-actions Bot commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

Commit: 640e02f4c | Workflow run

Regression test report

Selected 20 changed tests (limit=20, 37 not selected)

64 tests: regression=58 unreleased=0 coverage=6 failing=0

test branch main (e9687c1) latest (v1.22.1)
TestAccept/air/run-submit-deps ✅ ❌ ❌
TestAccept/air/run-submit-overrides ✅ ❌ ❌
TestAccept/bundle/apps/app_yaml/DMS= ✅ ❌ ❌
TestAccept/bundle/apps/app_yaml/DMS=true ✅ ❌ ❌
TestAccept/bundle/artifacts/ai_runtime_code_source/DMS=/READPLAN= ✅ ❌ ❌
TestAccept/bundle/artifacts/ai_runtime_code_source/DMS=/READPLAN=1 ✅ ❌ ❌
TestAccept/bundle/artifacts/ai_runtime_code_source/DMS=true/READPLAN= ✅ ❌ ❌
TestAccept/bundle/artifacts/ai_runtime_code_source/DMS=true/READPLAN=1 ✅ ❌ ❌
TestAccept/bundle/artifacts/artifact_upload_for_workspace/DMS=/READPLAN= ✅ ❌ ❌
TestAccept/bundle/artifacts/artifact_upload_for_workspace/DMS=/READPLAN=1 ✅ ❌ ❌
TestAccept/bundle/artifacts/artifact_upload_for_workspace/DMS=true/READPLAN= ✅ ❌ ❌
TestAccept/bundle/artifacts/artifact_upload_for_workspace/DMS=true/READPLAN=1 ✅ ❌ ❌
TestAccept/bundle/artifacts/artifact_upload_with_no_library_reference/DMS=/READPLAN= ✅ ❌ ❌
TestAccept/bundle/artifacts/artifact_upload_with_no_library_reference/DMS=/READPLAN=1 ✅ ❌ ❌
TestAccept/bundle/artifacts/artifact_upload_with_no_library_reference/DMS=true/READPLAN= ✅ ❌ ❌
TestAccept/bundle/artifacts/artifact_upload_with_no_library_reference/DMS=true/READPLAN=1 ✅ ❌ ❌
TestAccept/bundle/artifacts/upload_multiple_libraries/DMS=/READPLAN= ✅ ❌ ❌
TestAccept/bundle/artifacts/upload_multiple_libraries/DMS=/READPLAN=1 ✅ ❌ ❌
TestAccept/bundle/artifacts/upload_multiple_libraries/DMS=true/READPLAN= ✅ ❌ ❌
TestAccept/bundle/artifacts/upload_multiple_libraries/DMS=true/READPLAN=1 ✅ ❌ ❌
TestAccept/bundle/artifacts/whl_change_version/DMS= ✅ ❌ ❌
TestAccept/bundle/artifacts/whl_change_version/DMS=true ✅ ❌ ❌
TestAccept/bundle/artifacts/whl_dbfs/DMS=/READPLAN= ✅ ✅ ✅
TestAccept/bundle/artifacts/whl_dbfs/DMS=/READPLAN=1 ✅ ✅ ✅
TestAccept/bundle/artifacts/whl_dbfs/DMS=true/READPLAN= ✅ ✅ ✅
TestAccept/bundle/artifacts/whl_dbfs/DMS=true/READPLAN=1 ✅ ✅ ✅
TestAccept/bundle/artifacts/whl_dynamic/DMS=/READPLAN= ✅ ❌ ❌
TestAccept/bundle/artifacts/whl_dynamic/DMS=/READPLAN=1 ✅ ❌ ❌
TestAccept/bundle/artifacts/whl_dynamic/DMS=true/READPLAN= ✅ ❌ ❌
TestAccept/bundle/artifacts/whl_dynamic/DMS=true/READPLAN=1 ✅ ❌ ❌
TestAccept/bundle/artifacts/whl_explicit/DMS=/READPLAN= ✅ ❌ ❌
TestAccept/bundle/artifacts/whl_explicit/DMS=/READPLAN=1 ✅ ❌ ❌
TestAccept/bundle/artifacts/whl_explicit/DMS=true/READPLAN= ✅ ❌ ❌
TestAccept/bundle/artifacts/whl_explicit/DMS=true/READPLAN=1 ✅ ❌ ❌
TestAccept/bundle/artifacts/whl_implicit/DMS=/READPLAN= ✅ ❌ ❌
TestAccept/bundle/artifacts/whl_implicit/DMS=/READPLAN=1 ✅ ❌ ❌
TestAccept/bundle/artifacts/whl_implicit/DMS=true/READPLAN= ✅ ❌ ❌
TestAccept/bundle/artifacts/whl_implicit/DMS=true/READPLAN=1 ✅ ❌ ❌
TestAccept/bundle/artifacts/whl_implicit_custom_path/DMS=/READPLAN= ✅ ❌ ❌
TestAccept/bundle/artifacts/whl_implicit_custom_path/DMS=/READPLAN=1 ✅ ❌ ❌
TestAccept/bundle/artifacts/whl_implicit_custom_path/DMS=true/READPLAN= ✅ ❌ ❌
TestAccept/bundle/artifacts/whl_implicit_custom_path/DMS=true/READPLAN=1 ✅ ❌ ❌
TestAccept/bundle/artifacts/whl_implicit_notebook/DMS=/READPLAN= ✅ ❌ ❌
TestAccept/bundle/artifacts/whl_implicit_notebook/DMS=/READPLAN=1 ✅ ❌ ❌
TestAccept/bundle/artifacts/whl_implicit_notebook/DMS=true/READPLAN= ✅ ❌ ❌
TestAccept/bundle/artifacts/whl_implicit_notebook/DMS=true/READPLAN=1 ✅ ❌ ❌
TestAccept/bundle/artifacts/whl_multiple/DMS=/READPLAN= ✅ ❌ ❌
TestAccept/bundle/artifacts/whl_multiple/DMS=/READPLAN=1 ✅ ❌ ❌
TestAccept/bundle/artifacts/whl_multiple/DMS=true/READPLAN= ✅ ❌ ❌
TestAccept/bundle/artifacts/whl_multiple/DMS=true/READPLAN=1 ✅ ❌ ❌
TestAccept/bundle/artifacts/whl_no_cleanup/DMS=/READPLAN= ✅ ❌ ❌
TestAccept/bundle/artifacts/whl_no_cleanup/DMS=/READPLAN=1 ✅ ❌ ❌
TestAccept/bundle/artifacts/whl_no_cleanup/DMS=true/READPLAN= ✅ ❌ ❌
TestAccept/bundle/artifacts/whl_no_cleanup/DMS=true/READPLAN=1 ✅ ❌ ❌
TestAccept/bundle/artifacts/whl_prebuilt_multiple/DMS=/READPLAN= ✅ ❌ ❌
TestAccept/bundle/artifacts/whl_prebuilt_multiple/DMS=/READPLAN=1 ✅ ❌ ❌
TestAccept/bundle/artifacts/whl_prebuilt_multiple/DMS=true/READPLAN= ✅ ❌ ❌
TestAccept/bundle/artifacts/whl_prebuilt_multiple/DMS=true/READPLAN=1 ✅ ❌ ❌
TestAccept/bundle/artifacts/whl_prebuilt_outside/DMS= ✅ ❌ ❌
TestAccept/bundle/artifacts/whl_prebuilt_outside/DMS=true ✅ ❌ ❌
TestAccept/bundle/sync/replace-node-type/DMS= ✅ ❌ ❌
TestAccept/bundle/sync/replace-node-type/DMS=true ✅ ❌ ❌
TestAccept/bundle/sync/zip-extract/DMS= ✅ ✅ ✅
TestAccept/bundle/sync/zip-extract/DMS=true ✅ ✅ ✅
TestAccept/air/run-submit-deps: branch ✅ | main (e9687c1) ❌ | latest (v1.22.1) ❌

main (e9687c1):

acceptance_test.go:1341: Diff:
        --- air/run-submit-deps/output.txt
        +++ /tmp/TestAcceptairrun-submit-deps4137224171/002/output.txt
        @@ -11,8 +11,6 @@
         
         === only config + command are uploaded; no requirements.yaml
         >>> print_requests.py //api/2.0/workspace-files/import-file --oneline --sort --unique --keep
        -{"method": "POST", "path": "/api/2.0/workspace-files/import-file/Workspace/Users/[USERNAME]/.air/cli_launch/deps-smoke/deps-smoke_[RUN_ID]/command.sh", "q": {"overwrite": "true"}, "raw_body": "python train.py"}
        -{"method": "POST", "path": "/api/2.0/workspace-files/import-file/Workspace/Users/[USERNAME]/.air/cli_launch/deps-smoke/deps-smoke_[RUN_ID]/training_config.yaml", "q": {"overwrite": "true"}, "raw_body": "experiment_name: deps-smoke\ncommand: python train.py\ncompute:\n    accelerator_type: GPU_1xH100\n    num_accelerators: 1\n    pool_id: capacity-123\nenvironment:\n    version: 5\n    dependencies:\n        - numpy\n        - torch==2.3.0\nmlflow_artifact_location: /Volumes/main/default/air-artifacts\n"}
         
         === inline deps, artifact location, and capacity id reach the submit payload
         >>> print_requests.py //api/2.2/jobs/runs/submit

latest (v1.22.1): same output as main (e9687c1)

TestAccept/air/run-submit-overrides: branch ✅ | main (e9687c1) ❌ | latest (v1.22.1) ❌

main (e9687c1):

acceptance_test.go:1341: Diff:
        --- air/run-submit-overrides/output.txt
        +++ /tmp/TestAcceptairrun-submit-overrides3714348470/002/output.txt
        @@ -14,6 +14,3 @@
         
         === the uploaded config preserves source order and contains overrides
         >>> print_requests.py //api/2.0/workspace-files/import-file --oneline --sort --unique
        -{"method": "POST", "path": "/api/2.0/workspace-files/import-file/Workspace/Users/[USERNAME]/.air/cli_launch/overrides-smoke/overrides-smoke_[RUN_ID]/command.sh", "q": {"overwrite": "true"}, "raw_body": "python train.py"}
        -{"method": "POST", "path": "/api/2.0/workspace-files/import-file/Workspace/Users/[USERNAME]/.air/cli_launch/overrides-smoke/overrides-smoke_[RUN_ID]/hyperparameters.yaml", "q": {"overwrite": "true"}, "raw_body": "model:\n    hidden_size: 2048\noptimizer:\n    learning_rate: 0.001\n    name: adamw\n"}
        -{"method": "POST", "path": "/api/2.0/workspace-files/import-file/Workspace/Users/[USERNAME]/.air/cli_launch/overrides-smoke/overrides-smoke_[RUN_ID]/training_config.yaml", "q": {"overwrite": "true"}, "raw_body": "experiment_name: overrides-smoke\ncommand: python train.py\ncompute:\n    accelerator_type: GPU_1xH100\n    num_accelerators: 2\nparameters:\n    model:\n        hidden_size: 2048\n    optimizer:\n        name: adamw\n        learning_rate: 0.001\nmlflow_artifact_location: /Volumes/main/default/air-artifacts\n"}

latest (v1.22.1): same output as main (e9687c1)

TestAccept/bundle/apps/app_yaml/DMS=: branch ✅ | main (e9687c1) ❌ | latest (v1.22.1) ❌

main (e9687c1):

acceptance_test.go:1341: 
        	Error Trace:	/home/runner/work/cli/cli/libs/testdiff/testdiff.go:22
        	            				/home/runner/work/cli/cli/acceptance/acceptance_test.go:1341
        	            				/home/runner/work/cli/cli/acceptance/acceptance_test.go:1094
        	            				/home/runner/work/cli/cli/acceptance/acceptance_test.go:659
        	Error:      	Not equal: 
        	            	expected: "{\n  \"method\": \"POST\",\n  \"path\": \"/api/2.0/workspace-files/import-file/Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files/app/app.yml\",\n  \"q\": {\n    \"overwrite\": \"true\"\n  },\n  \"raw_body\": \"command:\\n  - python\\n  - app.py\\n\"\n}\n"
        	            	actual  : ""
        	            	
        	            	Diff:
        	            	--- Expected
        	            	+++ Actual
        	            	@@ -1,9 +1 @@
        	            	-{
        	            	-  "method": "POST",
        	            	-  "path": "/api/2.0/workspace-files/import-file/Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files/app/app.yml",
        	            	-  "q": {
        	            	-    "overwrite": "true"
        	            	-  },
        	            	-  "raw_body": "command:\n  - python\n  - app.py\n"
        	            	-}
        	            	 
        	Test:       	TestAccept/bundle/apps/app_yaml/DMS=
        	Messages:   	bundle/apps/app_yaml/out.app.yml.txt vs /tmp/TestAcceptbundleappsapp_yamlDMS=2369539817/001/out.app.yml.txt

latest (v1.22.1): same output as main (e9687c1)

TestAccept/bundle/apps/app_yaml/DMS=true: branch ✅ | main (e9687c1) ❌ | latest (v1.22.1) ❌

main (e9687c1):

acceptance_test.go:1341: 
        	Error Trace:	/home/runner/work/cli/cli/libs/testdiff/testdiff.go:22
        	            				/home/runner/work/cli/cli/acceptance/acceptance_test.go:1341
        	            				/home/runner/work/cli/cli/acceptance/acceptance_test.go:1094
        	            				/home/runner/work/cli/cli/acceptance/acceptance_test.go:659
        	Error:      	Not equal: 
        	            	expected: "{\n  \"method\": \"POST\",\n  \"path\": \"/api/2.0/workspace-files/import-file/Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files/app/app.yml\",\n  \"q\": {\n    \"overwrite\": \"true\"\n  },\n  \"raw_body\": \"command:\\n  - python\\n  - app.py\\n\"\n}\n"
        	            	actual  : ""
        	            	
        	            	Diff:
        	            	--- Expected
        	            	+++ Actual
        	            	@@ -1,9 +1 @@
        	            	-{
        	            	-  "method": "POST",
        	            	-  "path": "/api/2.0/workspace-files/import-file/Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files/app/app.yml",
        	            	-  "q": {
        	            	-    "overwrite": "true"
        	            	-  },
        	            	-  "raw_body": "command:\n  - python\n  - app.py\n"
        	            	-}
        	            	 
        	Test:       	TestAccept/bundle/apps/app_yaml/DMS=true
        	Messages:   	bundle/apps/app_yaml/out.app.yml.txt vs /tmp/TestAcceptbundleappsapp_yamlDMS=true306927183/001/out.app.yml.txt

latest (v1.22.1): same output as main (e9687c1)

TestAccept/bundle/artifacts/ai_runtime_code_source/DMS=/READPLAN=: branch ✅ | main (e9687c1) ❌ | latest (v1.22.1) ❌

main (e9687c1):

acceptance_test.go:1341: 
        	Error Trace:	/home/runner/work/cli/cli/libs/testdiff/testdiff.go:22
        	            				/home/runner/work/cli/cli/acceptance/acceptance_test.go:1341
        	            				/home/runner/work/cli/cli/acceptance/acceptance_test.go:1082
        	            				/home/runner/work/cli/cli/acceptance/acceptance_test.go:659
        	Error:      	Not equal: 
        	            	expected: "\n=== Expecting code_source_path rewritten to the uploaded artifact remote path\n>>> jq -s .[] | select(.path==\"/api/2.2/jobs/create\") | .body.tasks[].ai_runtime_task [OUTPUT_DIR]/out.requests.txt\n{\n  \"code_source_path\": \"/Workspace/foo/bar/artifacts/.internal/code.tgz\",\n  \"deployments\": [\n    {\n      \"command_path\": \"/Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files/command.sh\",\n      \"compute\": {\n        \"accelerator_count\": 1,\n        \"accelerator_type\": \"GPU_1xA10\"\n      }\n    }\n  ],\n  \"experiment\": \"my-experiment\"\n}\n\n=== Expecting the code_source tarball to be uploaded\n>>> jq .path\n\"/api/2.0/workspace-files/import-file/Workspace/foo/bar/artifacts/.internal/code.tgz\"\n"
        	            	actual  : "\n=== Expecting code_source_path rewritten to the uploaded artifact remote path\n>>> jq -s .[] | select(.path==\"/api/2.2/jobs/create\") | .body.tasks[].ai_runtime_task [OUTPUT_DIR]/out.requests.txt\n{\n  \"code_source_path\": \"/Workspace/foo/bar/artifacts/.internal/code.tgz\",\n  \"deployments\": [\n    {\n      \"command_path\": \"/Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files/command.sh\",\n      \"compute\": {\n        \"accelerator_count\": 1,\n        \"accelerator_type\": \"GPU_1xA10\"\n      }\n    }\n  ],\n  \"experiment\": \"my-experiment\"\n}\n\n=== Expecting the code_source tarball to be uploaded\n>>> jq .path\n\nExit code: 1\n"
        	            	
        	            	Diff:
        	            	--- Expected
        	            	+++ Actual
        	            	@@ -19,3 +19,4 @@
        	            	 >>> jq .path
        	            	-"/api/2.0/workspace-files/import-file/Workspace/foo/bar/artifacts/.internal/code.tgz"
        	            	 
        	            	+Exit code: 1
        	            	+
        	Test:       	TestAccept/bundle/artifacts/ai_runtime_code_source/DMS=/READPLAN=
        	Messages:   	bundle/artifacts/ai_runtime_code_source/output.txt vs /tmp/TestAcceptbundleartifactsai_runtime_code_sourceDMS=READPLAN1299159620/002/output.txt
    acceptance_test.go:1119: 
        LOG.deploy: Building code_source...
        LOG.deploy: Uploading code.tgz...
        LOG.deploy: Uploading bundle files to /Workspace/Users/tester@databricks.com/.bundle/test-bundle/default/files...
        LOG.deploy: Created jobs.job
        LOG.deploy: Files: 5 uploaded, 0 deleted
        LOG.deploy: Resources: 1 created, 0 changed, 0 deleted, 0 unchanged
    acceptance_test.go:1119: LOG.plan: Building code_source...

latest (v1.22.1): same output as main (e9687c1)

TestAccept/bundle/artifacts/ai_runtime_code_source/DMS=/READPLAN=1: branch ✅ | main (e9687c1) ❌ | latest (v1.22.1) ❌

main (e9687c1):

acceptance_test.go:1341: 
        	Error Trace:	/home/runner/work/cli/cli/libs/testdiff/testdiff.go:22
        	            				/home/runner/work/cli/cli/acceptance/acceptance_test.go:1341
        	            				/home/runner/work/cli/cli/acceptance/acceptance_test.go:1082
        	            				/home/runner/work/cli/cli/acceptance/acceptance_test.go:659
        	Error:      	Not equal: 
        	            	expected: "\n=== Expecting code_source_path rewritten to the uploaded artifact remote path\n>>> jq -s .[] | select(.path==\"/api/2.2/jobs/create\") | .body.tasks[].ai_runtime_task [OUTPUT_DIR]/out.requests.txt\n{\n  \"code_source_path\": \"/Workspace/foo/bar/artifacts/.internal/code.tgz\",\n  \"deployments\": [\n    {\n      \"command_path\": \"/Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files/command.sh\",\n      \"compute\": {\n        \"accelerator_count\": 1,\n        \"accelerator_type\": \"GPU_1xA10\"\n      }\n    }\n  ],\n  \"experiment\": \"my-experiment\"\n}\n\n=== Expecting the code_source tarball to be uploaded\n>>> jq .path\n\"/api/2.0/workspace-files/import-file/Workspace/foo/bar/artifacts/.internal/code.tgz\"\n"
        	            	actual  : "\n=== Expecting code_source_path rewritten to the uploaded artifact remote path\n>>> jq -s .[] | select(.path==\"/api/2.2/jobs/create\") | .body.tasks[].ai_runtime_task [OUTPUT_DIR]/out.requests.txt\n{\n  \"code_source_path\": \"/Workspace/foo/bar/artifacts/.internal/code.tgz\",\n  \"deployments\": [\n    {\n      \"command_path\": \"/Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files/command.sh\",\n      \"compute\": {\n        \"accelerator_count\": 1,\n        \"accelerator_type\": \"GPU_1xA10\"\n      }\n    }\n  ],\n  \"experiment\": \"my-experiment\"\n}\n\n=== Expecting the code_source tarball to be uploaded\n>>> jq .path\n\nExit code: 1\n"
        	            	
        	            	Diff:
        	            	--- Expected
        	            	+++ Actual
        	            	@@ -19,3 +19,4 @@
        	            	 >>> jq .path
        	            	-"/api/2.0/workspace-files/import-file/Workspace/foo/bar/artifacts/.internal/code.tgz"
        	            	 
        	            	+Exit code: 1
        	            	+
        	Test:       	TestAccept/bundle/artifacts/ai_runtime_code_source/DMS=/READPLAN=1
        	Messages:   	bundle/artifacts/ai_runtime_code_source/output.txt vs /tmp/TestAcceptbundleartifactsai_runtime_code_sourceDMS=READPLAN2860772256/002/output.txt
    acceptance_test.go:1119: 
        LOG.deploy: Uploading code.tgz...
        LOG.deploy: Uploading bundle files to /Workspace/Users/tester@databricks.com/.bundle/test-bundle/default/files...
        LOG.deploy: Created jobs.job
        LOG.deploy: Files: 5 uploaded, 0 deleted
        LOG.deploy: Resources: 1 created, 0 changed, 0 deleted, 0 unchanged
    acceptance_test.go:1119: LOG.plan: Building code_source...

latest (v1.22.1):

acceptance_test.go:1341: 
        	Error Trace:	/home/runner/work/cli/cli/libs/testdiff/testdiff.go:22
        	            				/home/runner/work/cli/cli/acceptance/acceptance_test.go:1341
        	            				/home/runner/work/cli/cli/acceptance/acceptance_test.go:1082
        	            				/home/runner/work/cli/cli/acceptance/acceptance_test.go:659
        	Error:      	Not equal: 
        	            	expected: "\n=== Expecting code_source_path rewritten to the uploaded artifact remote path\n>>> jq -s .[] | select(.path==\"/api/2.2/jobs/create\") | .body.tasks[].ai_runtime_task [OUTPUT_DIR]/out.requests.txt\n{\n  \"code_source_path\": \"/Workspace/foo/bar/artifacts/.internal/code.tgz\",\n  \"deployments\": [\n    {\n      \"command_path\": \"/Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files/command.sh\",\n      \"compute\": {\n        \"accelerator_count\": 1,\n        \"accelerator_type\": \"GPU_1xA10\"\n      }\n    }\n  ],\n  \"experiment\": \"my-experiment\"\n}\n\n=== Expecting the code_source tarball to be uploaded\n>>> jq .path\n\"/api/2.0/workspace-files/import-file/Workspace/foo/bar/artifacts/.internal/code.tgz\"\n"
        	            	actual  : "\n=== Expecting code_source_path rewritten to the uploaded artifact remote path\n>>> jq -s .[] | select(.path==\"/api/2.2/jobs/create\") | .body.tasks[].ai_runtime_task [OUTPUT_DIR]/out.requests.txt\n{\n  \"code_source_path\": \"/Workspace/foo/bar/artifacts/.internal/code.tgz\",\n  \"deployments\": [\n    {\n      \"command_path\": \"/Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files/command.sh\",\n      \"compute\": {\n        \"accelerator_count\": 1,\n        \"accelerator_type\": \"GPU_1xA10\"\n      }\n    }\n  ],\n  \"experiment\": \"my-experiment\"\n}\n\n=== Expecting the code_source tarball to be uploaded\n>>> jq .path\n\nExit code: 1\n"
        	            	
        	            	Diff:
        	            	--- Expected
        	            	+++ Actual
        	            	@@ -19,3 +19,4 @@
        	            	 >>> jq .path
        	            	-"/api/2.0/workspace-files/import-file/Workspace/foo/bar/artifacts/.internal/code.tgz"
        	            	 
        	            	+Exit code: 1
        	            	+
        	Test:       	TestAccept/bundle/artifacts/ai_runtime_code_source/DMS=/READPLAN=1
        	Messages:   	bundle/artifacts/ai_runtime_code_source/output.txt vs /tmp/TestAcceptbundleartifactsai_runtime_code_sourceDMS=READPLAN1517234044/002/output.txt
    acceptance_test.go:1119: 
        LOG.deploy: Uploading code.tgz...
        LOG.deploy: Uploading bundle files to /Workspace/Users/tester@databricks.com/.bundle/test-bundle/default/files...
        LOG.deploy: Created jobs.job
        LOG.deploy: Files: 5 uploaded, 0 deleted
        LOG.deploy: Resources: 1 created, 0 changed, 0 deleted, 0 unchanged
    acceptance_test.go:1119: LOG.plan: Building code_source...
FAIL
TestAccept/bundle/artifacts/ai_runtime_code_source/DMS=true/READPLAN=: branch ✅ | main (e9687c1) ❌ | latest (v1.22.1) ❌

main (e9687c1):

acceptance_test.go:1341: 
        	Error Trace:	/home/runner/work/cli/cli/libs/testdiff/testdiff.go:22
        	            				/home/runner/work/cli/cli/acceptance/acceptance_test.go:1341
        	            				/home/runner/work/cli/cli/acceptance/acceptance_test.go:1082
        	            				/home/runner/work/cli/cli/acceptance/acceptance_test.go:659
        	Error:      	Not equal: 
        	            	expected: "\n=== Expecting code_source_path rewritten to the uploaded artifact remote path\n>>> jq -s .[] | select(.path==\"/api/2.2/jobs/create\") | .body.tasks[].ai_runtime_task [OUTPUT_DIR]/out.requests.txt\n{\n  \"code_source_path\": \"/Workspace/foo/bar/artifacts/.internal/code.tgz\",\n  \"deployments\": [\n    {\n      \"command_path\": \"/Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files/command.sh\",\n      \"compute\": {\n        \"accelerator_count\": 1,\n        \"accelerator_type\": \"GPU_1xA10\"\n      }\n    }\n  ],\n  \"experiment\": \"my-experiment\"\n}\n\n=== Expecting the code_source tarball to be uploaded\n>>> jq .path\n\"/api/2.0/workspace-files/import-file/Workspace/foo/bar/artifacts/.internal/code.tgz\"\n"
        	            	actual  : "\n=== Expecting code_source_path rewritten to the uploaded artifact remote path\n>>> jq -s .[] | select(.path==\"/api/2.2/jobs/create\") | .body.tasks[].ai_runtime_task [OUTPUT_DIR]/out.requests.txt\n{\n  \"code_source_path\": \"/Workspace/foo/bar/artifacts/.internal/code.tgz\",\n  \"deployments\": [\n    {\n      \"command_path\": \"/Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files/command.sh\",\n      \"compute\": {\n        \"accelerator_count\": 1,\n        \"accelerator_type\": \"GPU_1xA10\"\n      }\n    }\n  ],\n  \"experiment\": \"my-experiment\"\n}\n\n=== Expecting the code_source tarball to be uploaded\n>>> jq .path\n\nExit code: 1\n"
        	            	
        	            	Diff:
        	            	--- Expected
        	            	+++ Actual
        	            	@@ -19,3 +19,4 @@
        	            	 >>> jq .path
        	            	-"/api/2.0/workspace-files/import-file/Workspace/foo/bar/artifacts/.internal/code.tgz"
        	            	 
        	            	+Exit code: 1
        	            	+
        	Test:       	TestAccept/bundle/artifacts/ai_runtime_code_source/DMS=true/READPLAN=
        	Messages:   	bundle/artifacts/ai_runtime_code_source/output.txt vs /tmp/TestAcceptbundleartifactsai_runtime_code_sourceDMS=trueREAD3591721836/002/output.txt
    acceptance_test.go:1119: 
        LOG.deploy: Building code_source...
        LOG.deploy: Uploading code.tgz...
        LOG.deploy: Uploading bundle files to /Workspace/Users/tester@databricks.com/.bundle/test-bundle/default/files...
        LOG.deploy: Current Deployment Version: http://127.0.0.1:46523/deployments/1905?version=1
        LOG.deploy: Created jobs.job
        LOG.deploy: Files: 5 uploaded, 0 deleted
        LOG.deploy: Resources: 1 created, 0 changed, 0 deleted, 0 unchanged
    acceptance_test.go:1119: LOG.plan: Building code_source...

latest (v1.22.1):

acceptance_test.go:1341: 
        	Error Trace:	/home/runner/work/cli/cli/libs/testdiff/testdiff.go:22
        	            				/home/runner/work/cli/cli/acceptance/acceptance_test.go:1341
        	            				/home/runner/work/cli/cli/acceptance/acceptance_test.go:1082
        	            				/home/runner/work/cli/cli/acceptance/acceptance_test.go:659
        	Error:      	Not equal: 
        	            	expected: "\n=== Expecting code_source_path rewritten to the uploaded artifact remote path\n>>> jq -s .[] | select(.path==\"/api/2.2/jobs/create\") | .body.tasks[].ai_runtime_task [OUTPUT_DIR]/out.requests.txt\n{\n  \"code_source_path\": \"/Workspace/foo/bar/artifacts/.internal/code.tgz\",\n  \"deployments\": [\n    {\n      \"command_path\": \"/Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files/command.sh\",\n      \"compute\": {\n        \"accelerator_count\": 1,\n        \"accelerator_type\": \"GPU_1xA10\"\n      }\n    }\n  ],\n  \"experiment\": \"my-experiment\"\n}\n\n=== Expecting the code_source tarball to be uploaded\n>>> jq .path\n\"/api/2.0/workspace-files/import-file/Workspace/foo/bar/artifacts/.internal/code.tgz\"\n"
        	            	actual  : "\n=== Expecting code_source_path rewritten to the uploaded artifact remote path\n>>> jq -s .[] | select(.path==\"/api/2.2/jobs/create\") | .body.tasks[].ai_runtime_task [OUTPUT_DIR]/out.requests.txt\n{\n  \"code_source_path\": \"/Workspace/foo/bar/artifacts/.internal/code.tgz\",\n  \"deployments\": [\n    {\n      \"command_path\": \"/Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files/command.sh\",\n      \"compute\": {\n        \"accelerator_count\": 1,\n        \"accelerator_type\": \"GPU_1xA10\"\n      }\n    }\n  ],\n  \"experiment\": \"my-experiment\"\n}\n\n=== Expecting the code_source tarball to be uploaded\n>>> jq .path\n\nExit code: 1\n"
        	            	
        	            	Diff:
        	            	--- Expected
        	            	+++ Actual
        	            	@@ -19,3 +19,4 @@
        	            	 >>> jq .path
        	            	-"/api/2.0/workspace-files/import-file/Workspace/foo/bar/artifacts/.internal/code.tgz"
        	            	 
        	            	+Exit code: 1
        	            	+
        	Test:       	TestAccept/bundle/artifacts/ai_runtime_code_source/DMS=true/READPLAN=
        	Messages:   	bundle/artifacts/ai_runtime_code_source/output.txt vs /tmp/TestAcceptbundleartifactsai_runtime_code_sourceDMS=trueREAD4132240679/002/output.txt
    acceptance_test.go:1119: 
        LOG.deploy: Building code_source...
        LOG.deploy: Uploading code.tgz...
        LOG.deploy: Uploading bundle files to /Workspace/Users/tester@databricks.com/.bundle/test-bundle/default/files...
        LOG.deploy: Current Deployment Version: http://127.0.0.1:42037/deployments/2783?version=1
        LOG.deploy: Created jobs.job
        LOG.deploy: Files: 5 uploaded, 0 deleted
        LOG.deploy: Resources: 1 created, 0 changed, 0 deleted, 0 unchanged
    acceptance_test.go:1119: LOG.plan: Building code_source...
TestAccept/bundle/artifacts/ai_runtime_code_source/DMS=true/READPLAN=1: branch ✅ | main (e9687c1) ❌ | latest (v1.22.1) ❌

main (e9687c1):

acceptance_test.go:1341: 
        	Error Trace:	/home/runner/work/cli/cli/libs/testdiff/testdiff.go:22
        	            				/home/runner/work/cli/cli/acceptance/acceptance_test.go:1341
        	            				/home/runner/work/cli/cli/acceptance/acceptance_test.go:1082
        	            				/home/runner/work/cli/cli/acceptance/acceptance_test.go:659
        	Error:      	Not equal: 
        	            	expected: "\n=== Expecting code_source_path rewritten to the uploaded artifact remote path\n>>> jq -s .[] | select(.path==\"/api/2.2/jobs/create\") | .body.tasks[].ai_runtime_task [OUTPUT_DIR]/out.requests.txt\n{\n  \"code_source_path\": \"/Workspace/foo/bar/artifacts/.internal/code.tgz\",\n  \"deployments\": [\n    {\n      \"command_path\": \"/Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files/command.sh\",\n      \"compute\": {\n        \"accelerator_count\": 1,\n        \"accelerator_type\": \"GPU_1xA10\"\n      }\n    }\n  ],\n  \"experiment\": \"my-experiment\"\n}\n\n=== Expecting the code_source tarball to be uploaded\n>>> jq .path\n\"/api/2.0/workspace-files/import-file/Workspace/foo/bar/artifacts/.internal/code.tgz\"\n"
        	            	actual  : "\n=== Expecting code_source_path rewritten to the uploaded artifact remote path\n>>> jq -s .[] | select(.path==\"/api/2.2/jobs/create\") | .body.tasks[].ai_runtime_task [OUTPUT_DIR]/out.requests.txt\n{\n  \"code_source_path\": \"/Workspace/foo/bar/artifacts/.internal/code.tgz\",\n  \"deployments\": [\n    {\n      \"command_path\": \"/Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files/command.sh\",\n      \"compute\": {\n        \"accelerator_count\": 1,\n        \"accelerator_type\": \"GPU_1xA10\"\n      }\n    }\n  ],\n  \"experiment\": \"my-experiment\"\n}\n\n=== Expecting the code_source tarball to be uploaded\n>>> jq .path\n\nExit code: 1\n"
        	            	
        	            	Diff:
        	            	--- Expected
        	            	+++ Actual
        	            	@@ -19,3 +19,4 @@
        	            	 >>> jq .path
        	            	-"/api/2.0/workspace-files/import-file/Workspace/foo/bar/artifacts/.internal/code.tgz"
        	            	 
        	            	+Exit code: 1
        	            	+
        	Test:       	TestAccept/bundle/artifacts/ai_runtime_code_source/DMS=true/READPLAN=1
        	Messages:   	bundle/artifacts/ai_runtime_code_source/output.txt vs /tmp/TestAcceptbundleartifactsai_runtime_code_sourceDMS=trueREAD3182373521/002/output.txt
    acceptance_test.go:1119: 
        LOG.deploy: Uploading code.tgz...
        LOG.deploy: Uploading bundle files to /Workspace/Users/tester@databricks.com/.bundle/test-bundle/default/files...
        LOG.deploy: Current Deployment Version: http://127.0.0.1:37727/deployments/1932?version=1
        LOG.deploy: Created jobs.job
        LOG.deploy: Files: 5 uploaded, 0 deleted
        LOG.deploy: Resources: 1 created, 0 changed, 0 deleted, 0 unchanged
    acceptance_test.go:1119: LOG.plan: Building code_source...

latest (v1.22.1):

acceptance_test.go:1341: 
        	Error Trace:	/home/runner/work/cli/cli/libs/testdiff/testdiff.go:22
        	            				/home/runner/work/cli/cli/acceptance/acceptance_test.go:1341
        	            				/home/runner/work/cli/cli/acceptance/acceptance_test.go:1082
        	            				/home/runner/work/cli/cli/acceptance/acceptance_test.go:659
        	Error:      	Not equal: 
        	            	expected: "\n=== Expecting code_source_path rewritten to the uploaded artifact remote path\n>>> jq -s .[] | select(.path==\"/api/2.2/jobs/create\") | .body.tasks[].ai_runtime_task [OUTPUT_DIR]/out.requests.txt\n{\n  \"code_source_path\": \"/Workspace/foo/bar/artifacts/.internal/code.tgz\",\n  \"deployments\": [\n    {\n      \"command_path\": \"/Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files/command.sh\",\n      \"compute\": {\n        \"accelerator_count\": 1,\n        \"accelerator_type\": \"GPU_1xA10\"\n      }\n    }\n  ],\n  \"experiment\": \"my-experiment\"\n}\n\n=== Expecting the code_source tarball to be uploaded\n>>> jq .path\n\"/api/2.0/workspace-files/import-file/Workspace/foo/bar/artifacts/.internal/code.tgz\"\n"
        	            	actual  : "\n=== Expecting code_source_path rewritten to the uploaded artifact remote path\n>>> jq -s .[] | select(.path==\"/api/2.2/jobs/create\") | .body.tasks[].ai_runtime_task [OUTPUT_DIR]/out.requests.txt\n{\n  \"code_source_path\": \"/Workspace/foo/bar/artifacts/.internal/code.tgz\",\n  \"deployments\": [\n    {\n      \"command_path\": \"/Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files/command.sh\",\n      \"compute\": {\n        \"accelerator_count\": 1,\n        \"accelerator_type\": \"GPU_1xA10\"\n      }\n    }\n  ],\n  \"experiment\": \"my-experiment\"\n}\n\n=== Expecting the code_source tarball to be uploaded\n>>> jq .path\n\nExit code: 1\n"
        	            	
        	            	Diff:
        	            	--- Expected
        	            	+++ Actual
        	            	@@ -19,3 +19,4 @@
        	            	 >>> jq .path
        	            	-"/api/2.0/workspace-files/import-file/Workspace/foo/bar/artifacts/.internal/code.tgz"
        	            	 
        	            	+Exit code: 1
        	            	+
        	Test:       	TestAccept/bundle/artifacts/ai_runtime_code_source/DMS=true/READPLAN=1
        	Messages:   	bundle/artifacts/ai_runtime_code_source/output.txt vs /tmp/TestAcceptbundleartifactsai_runtime_code_sourceDMS=trueREAD2640958325/002/output.txt
    acceptance_test.go:1119: 
        LOG.deploy: Uploading code.tgz...
        LOG.deploy: Uploading bundle files to /Workspace/Users/tester@databricks.com/.bundle/test-bundle/default/files...
        LOG.deploy: Current Deployment Version: http://127.0.0.1:34829/deployments/2763?version=1
        LOG.deploy: Created jobs.job
        LOG.deploy: Files: 5 uploaded, 0 deleted
        LOG.deploy: Resources: 1 created, 0 changed, 0 deleted, 0 unchanged
    acceptance_test.go:1119: LOG.plan: Building code_source...
TestAccept/bundle/artifacts/artifact_upload_for_workspace/DMS=/READPLAN=: branch ✅ | main (e9687c1) ❌ | latest (v1.22.1) ❌

main (e9687c1):

acceptance_test.go:1341: Diff:
        --- bundle/artifacts/artifact_upload_for_workspace/output.txt
        +++ /tmp/TestAcceptbundleartifactsartifact_upload_for_workspaceDMS=R2827365008/002/output.txt
        @@ -49,41 +49,5 @@
         
         === Expecting wheel to be uploaded
         >>> jq .path
        -"/api/2.0/workspace-files/import-file/Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files/whl/source.whl"
        -"/api/2.0/workspace-files/import-file/Workspace/foo/bar/artifacts/.internal/source.whl"
         
        -=== Expecting environment dependencies to be updated
        ->>> jq -s .[] | select(.path=="/api/2.2/jobs/create") | .body.environments [OUTPUT_DIR]/out.requests.txt
        -[
        -  {
        -    "environment_key": "test_env",
        -    "spec": {
        -      "client": "1",
        -      "dependencies": [
        -        "/Workspace/foo/bar/artifacts/.internal/source.whl",
        -        "/Workspace/Users/foo@bar.test/mywheel.whl"
        -      ]
        -    }
        -  }
        -]
        -
        -=== Expecting delete request to artifact_path/.internal folder
        ->>> jq -s .[] | select(.path=="/api/2.0/workspace/delete") | select(.body.path | test(".*/artifacts/.internal")) [OUTPUT_DIR]/out.requests.txt
        -{
        -  "method": "POST",
        -  "path": "/api/2.0/workspace/delete",
        -  "body": {
        -    "path": "/Workspace/foo/bar/artifacts/.internal",
        -    "recursive": true
        -  }
        -}
        -
        -=== Expecting mkdirs request to artifact_path/.internal folder
        ->>> jq -s .[] | select(.path=="/api/2.0/workspace/mkdirs") | select(.body.path | test(".*/artifacts/.internal")) [OUTPUT_DIR]/out.requests.txt
        -{
        -  "method": "POST",
        -  "path": "/api/2.0/workspace/mkdirs",
        -  "body": {
        -    "path": "/Workspace/foo/bar/artifacts/.internal"
        -  }
        -}
        +Exit code: 1
        
    acceptance_test.go:1119: LOG.plan:

latest (v1.22.1): same output as main (e9687c1)

TestAccept/bundle/artifacts/artifact_upload_for_workspace/DMS=/READPLAN=1: branch ✅ | main (e9687c1) ❌ | latest (v1.22.1) ❌

main (e9687c1):

acceptance_test.go:1341: Diff:
        --- bundle/artifacts/artifact_upload_for_workspace/output.txt
        +++ /tmp/TestAcceptbundleartifactsartifact_upload_for_workspaceDMS=R2977749358/002/output.txt
        @@ -49,41 +49,5 @@
         
         === Expecting wheel to be uploaded
         >>> jq .path
        -"/api/2.0/workspace-files/import-file/Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files/whl/source.whl"
        -"/api/2.0/workspace-files/import-file/Workspace/foo/bar/artifacts/.internal/source.whl"
         
        -=== Expecting environment dependencies to be updated
        ->>> jq -s .[] | select(.path=="/api/2.2/jobs/create") | .body.environments [OUTPUT_DIR]/out.requests.txt
        -[
        -  {
        -    "environment_key": "test_env",
        -    "spec": {
        -      "client": "1",
        -      "dependencies": [
        -        "/Workspace/foo/bar/artifacts/.internal/source.whl",
        -        "/Workspace/Users/foo@bar.test/mywheel.whl"
        -      ]
        -    }
        -  }
        -]
        -
        -=== Expecting delete request to artifact_path/.internal folder
        ->>> jq -s .[] | select(.path=="/api/2.0/workspace/delete") | select(.body.path | test(".*/artifacts/.internal")) [OUTPUT_DIR]/out.requests.txt
        -{
        -  "method": "POST",
        -  "path": "/api/2.0/workspace/delete",
        -  "body": {
        -    "path": "/Workspace/foo/bar/artifacts/.internal",
        -    "recursive": true
        -  }
        -}
        -
        -=== Expecting mkdirs request to artifact_path/.internal folder
        ->>> jq -s .[] | select(.path=="/api/2.0/workspace/mkdirs") | select(.body.path | test(".*/artifacts/.internal")) [OUTPUT_DIR]/out.requests.txt
        -{
        -  "method": "POST",
        -  "path": "/api/2.0/workspace/mkdirs",
        -  "body": {
        -    "path": "/Workspace/foo/bar/artifacts/.internal"
        -  }
        -}
        +Exit code: 1
        
    acceptance_test.go:1119: LOG.plan:

latest (v1.22.1): same output as main (e9687c1)

TestAccept/bundle/artifacts/artifact_upload_for_workspace/DMS=true/READPLAN=: branch ✅ | main (e9687c1) ❌ | latest (v1.22.1) ❌

main (e9687c1):

acceptance_test.go:1341: Diff:
        --- bundle/artifacts/artifact_upload_for_workspace/output.txt
        +++ /tmp/TestAcceptbundleartifactsartifact_upload_for_workspaceDMS=tr3109633256/002/output.txt
        @@ -49,41 +49,5 @@
         
         === Expecting wheel to be uploaded
         >>> jq .path
        -"/api/2.0/workspace-files/import-file/Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files/whl/source.whl"
        -"/api/2.0/workspace-files/import-file/Workspace/foo/bar/artifacts/.internal/source.whl"
         
        -=== Expecting environment dependencies to be updated
        ->>> jq -s .[] | select(.path=="/api/2.2/jobs/create") | .body.environments [OUTPUT_DIR]/out.requests.txt
        -[
        -  {
        -    "environment_key": "test_env",
        -    "spec": {
        -      "client": "1",
        -      "dependencies": [
        -        "/Workspace/foo/bar/artifacts/.internal/source.whl",
        -        "/Workspace/Users/foo@bar.test/mywheel.whl"
        -      ]
        -    }
        -  }
        -]
        -
        -=== Expecting delete request to artifact_path/.internal folder
        ->>> jq -s .[] | select(.path=="/api/2.0/workspace/delete") | select(.body.path | test(".*/artifacts/.internal")) [OUTPUT_DIR]/out.requests.txt
        -{
        -  "method": "POST",
        -  "path": "/api/2.0/workspace/delete",
        -  "body": {
        -    "path": "/Workspace/foo/bar/artifacts/.internal",
        -    "recursive": true
        -  }
        -}
        -
        -=== Expecting mkdirs request to artifact_path/.internal folder
        ->>> jq -s .[] | select(.path=="/api/2.0/workspace/mkdirs") | select(.body.path | test(".*/artifacts/.internal")) [OUTPUT_DIR]/out.requests.txt
        -{
        -  "method": "POST",
        -  "path": "/api/2.0/workspace/mkdirs",
        -  "body": {
        -    "path": "/Workspace/foo/bar/artifacts/.internal"
        -  }
        -}
        +Exit code: 1
        
    acceptance_test.go:1119: LOG.plan:

latest (v1.22.1): same output as main (e9687c1)

TestAccept/bundle/artifacts/artifact_upload_for_workspace/DMS=true/READPLAN=1: branch ✅ | main (e9687c1) ❌ | latest (v1.22.1) ❌

main (e9687c1):

acceptance_test.go:1341: Diff:
        --- bundle/artifacts/artifact_upload_for_workspace/output.txt
        +++ /tmp/TestAcceptbundleartifactsartifact_upload_for_workspaceDMS=tr3440157200/002/output.txt
        @@ -49,41 +49,5 @@
         
         === Expecting wheel to be uploaded
         >>> jq .path
        -"/api/2.0/workspace-files/import-file/Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files/whl/source.whl"
        -"/api/2.0/workspace-files/import-file/Workspace/foo/bar/artifacts/.internal/source.whl"
         
        -=== Expecting environment dependencies to be updated
        ->>> jq -s .[] | select(.path=="/api/2.2/jobs/create") | .body.environments [OUTPUT_DIR]/out.requests.txt
        -[
        -  {
        -    "environment_key": "test_env",
        -    "spec": {
        -      "client": "1",
        -      "dependencies": [
        -        "/Workspace/foo/bar/artifacts/.internal/source.whl",
        -        "/Workspace/Users/foo@bar.test/mywheel.whl"
        -      ]
        -    }
        -  }
        -]
        -
        -=== Expecting delete request to artifact_path/.internal folder
        ->>> jq -s .[] | select(.path=="/api/2.0/workspace/delete") | select(.body.path | test(".*/artifacts/.internal")) [OUTPUT_DIR]/out.requests.txt
        -{
        -  "method": "POST",
        -  "path": "/api/2.0/workspace/delete",
        -  "body": {
        -    "path": "/Workspace/foo/bar/artifacts/.internal",
        -    "recursive": true
        -  }
        -}
        -
        -=== Expecting mkdirs request to artifact_path/.internal folder
        ->>> jq -s .[] | select(.path=="/api/2.0/workspace/mkdirs") | select(.body.path | test(".*/artifacts/.internal")) [OUTPUT_DIR]/out.requests.txt
        -{
        -  "method": "POST",
        -  "path": "/api/2.0/workspace/mkdirs",
        -  "body": {
        -    "path": "/Workspace/foo/bar/artifacts/.internal"
        -  }
        -}
        +Exit code: 1
        
    acceptance_test.go:1119: LOG.plan:

latest (v1.22.1): same output as main (e9687c1)

TestAccept/bundle/artifacts/artifact_upload_with_no_library_reference/DMS=/READPLAN=: branch ✅ | main (e9687c1) ❌ | latest (v1.22.1) ❌

main (e9687c1):

acceptance_test.go:1341: Diff:
        --- bundle/artifacts/artifact_upload_with_no_library_reference/output.txt
        +++ /tmp/TestAcceptbundleartifactsartifact_upload_with_no_library_refe2933644514/002/output.txt
        @@ -5,26 +5,5 @@
         
         === Expecting wheel to be uploaded
         >>> jq .path
        -"/api/2.0/workspace-files/import-file/Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files/whl/source.whl"
        -"/api/2.0/workspace-files/import-file/Workspace/foo/bar/artifacts/.internal/source.whl"
         
        -=== Expecting delete request to artifact_path/.internal folder
        ->>> jq -s .[] | select(.path=="/api/2.0/workspace/delete") | select(.body.path | test(".*/artifacts/.internal")) [OUTPUT_DIR]/out.requests.txt
        -{
        -  "method": "POST",
        -  "path": "/api/2.0/workspace/delete",
        -  "body": {
        -    "path": "/Workspace/foo/bar/artifacts/.internal",
        -    "recursive": true
        -  }
        -}
        -
        -=== Expecting mkdirs request to artifact_path/.internal folder
        ->>> jq -s .[] | select(.path=="/api/2.0/workspace/mkdirs") | select(.body.path | test(".*/artifacts/.internal")) [OUTPUT_DIR]/out.requests.txt
        -{
        -  "method": "POST",
        -  "path": "/api/2.0/workspace/mkdirs",
        -  "body": {
        -    "path": "/Workspace/foo/bar/artifacts/.internal"
        -  }
        -}
        +Exit code: 1
        
    acceptance_test.go:1119: LOG.plan:

latest (v1.22.1): same output as main (e9687c1)

TestAccept/bundle/artifacts/artifact_upload_with_no_library_reference/DMS=/READPLAN=1: branch ✅ | main (e9687c1) ❌ | latest (v1.22.1) ❌

main (e9687c1):

acceptance_test.go:1341: Diff:
        --- bundle/artifacts/artifact_upload_with_no_library_reference/output.txt
        +++ /tmp/TestAcceptbundleartifactsartifact_upload_with_no_library_refe3603512741/002/output.txt
        @@ -5,26 +5,5 @@
         
         === Expecting wheel to be uploaded
         >>> jq .path
        -"/api/2.0/workspace-files/import-file/Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files/whl/source.whl"
        -"/api/2.0/workspace-files/import-file/Workspace/foo/bar/artifacts/.internal/source.whl"
         
        -=== Expecting delete request to artifact_path/.internal folder
        ->>> jq -s .[] | select(.path=="/api/2.0/workspace/delete") | select(.body.path | test(".*/artifacts/.internal")) [OUTPUT_DIR]/out.requests.txt
        -{
        -  "method": "POST",
        -  "path": "/api/2.0/workspace/delete",
        -  "body": {
        -    "path": "/Workspace/foo/bar/artifacts/.internal",
        -    "recursive": true
        -  }
        -}
        -
        -=== Expecting mkdirs request to artifact_path/.internal folder
        ->>> jq -s .[] | select(.path=="/api/2.0/workspace/mkdirs") | select(.body.path | test(".*/artifacts/.internal")) [OUTPUT_DIR]/out.requests.txt
        -{
        -  "method": "POST",
        -  "path": "/api/2.0/workspace/mkdirs",
        -  "body": {
        -    "path": "/Workspace/foo/bar/artifacts/.internal"
        -  }
        -}
        +Exit code: 1
        
    acceptance_test.go:1119: LOG.plan:

latest (v1.22.1): same output as main (e9687c1)

TestAccept/bundle/artifacts/artifact_upload_with_no_library_reference/DMS=true/READPLAN=: branch ✅ | main (e9687c1) ❌ | latest (v1.22.1) ❌

main (e9687c1):

acceptance_test.go:1341: Diff:
        --- bundle/artifacts/artifact_upload_with_no_library_reference/output.txt
        +++ /tmp/TestAcceptbundleartifactsartifact_upload_with_no_library_refe1152852126/002/output.txt
        @@ -5,26 +5,5 @@
         
         === Expecting wheel to be uploaded
         >>> jq .path
        -"/api/2.0/workspace-files/import-file/Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files/whl/source.whl"
        -"/api/2.0/workspace-files/import-file/Workspace/foo/bar/artifacts/.internal/source.whl"
         
        -=== Expecting delete request to artifact_path/.internal folder
        ->>> jq -s .[] | select(.path=="/api/2.0/workspace/delete") | select(.body.path | test(".*/artifacts/.internal")) [OUTPUT_DIR]/out.requests.txt
        -{
        -  "method": "POST",
        -  "path": "/api/2.0/workspace/delete",
        -  "body": {
        -    "path": "/Workspace/foo/bar/artifacts/.internal",
        -    "recursive": true
        -  }
        -}
        -
        -=== Expecting mkdirs request to artifact_path/.internal folder
        ->>> jq -s .[] | select(.path=="/api/2.0/workspace/mkdirs") | select(.body.path | test(".*/artifacts/.internal")) [OUTPUT_DIR]/out.requests.txt
        -{
        -  "method": "POST",
        -  "path": "/api/2.0/workspace/mkdirs",
        -  "body": {
        -    "path": "/Workspace/foo/bar/artifacts/.internal"
        -  }
        -}
        +Exit code: 1
        
    acceptance_test.go:1119: LOG.plan:

latest (v1.22.1): same output as main (e9687c1)

TestAccept/bundle/artifacts/artifact_upload_with_no_library_reference/DMS=true/READPLAN=1: branch ✅ | main (e9687c1) ❌ | latest (v1.22.1) ❌

main (e9687c1):

acceptance_test.go:1341: Diff:
        --- bundle/artifacts/artifact_upload_with_no_library_reference/output.txt
        +++ /tmp/TestAcceptbundleartifactsartifact_upload_with_no_library_refe2350140679/002/output.txt
        @@ -5,26 +5,5 @@
         
         === Expecting wheel to be uploaded
         >>> jq .path
        -"/api/2.0/workspace-files/import-file/Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files/whl/source.whl"
        -"/api/2.0/workspace-files/import-file/Workspace/foo/bar/artifacts/.internal/source.whl"
         
        -=== Expecting delete request to artifact_path/.internal folder
        ->>> jq -s .[] | select(.path=="/api/2.0/workspace/delete") | select(.body.path | test(".*/artifacts/.internal")) [OUTPUT_DIR]/out.requests.txt
        -{
        -  "method": "POST",
        -  "path": "/api/2.0/workspace/delete",
        -  "body": {
        -    "path": "/Workspace/foo/bar/artifacts/.internal",
        -    "recursive": true
        -  }
        -}
        -
        -=== Expecting mkdirs request to artifact_path/.internal folder
        ->>> jq -s .[] | select(.path=="/api/2.0/workspace/mkdirs") | select(.body.path | test(".*/artifacts/.internal")) [OUTPUT_DIR]/out.requests.txt
        -{
        -  "method": "POST",
        -  "path": "/api/2.0/workspace/mkdirs",
        -  "body": {
        -    "path": "/Workspace/foo/bar/artifacts/.internal"
        -  }
        -}
        +Exit code: 1
        
    acceptance_test.go:1119: LOG.plan:

latest (v1.22.1): same output as main (e9687c1)

TestAccept/bundle/artifacts/upload_multiple_libraries/DMS=/READPLAN=: branch ✅ | main (e9687c1) ❌ | latest (v1.22.1) ❌

main (e9687c1):

acceptance_test.go:1341: Diff:
        --- bundle/artifacts/upload_multiple_libraries/output.txt
        +++ /tmp/TestAcceptbundleartifactsupload_multiple_librariesDMS=READP2346869649/002/output.txt
        @@ -39,29 +39,5 @@
         
         === Expecting 4 wheels to be uploaded
         >>> jq .path
        -"/api/2.0/workspace-files/import-file/Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files/whl/source1.whl"
        -"/api/2.0/workspace-files/import-file/Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files/whl/source2.whl"
        -"/api/2.0/workspace-files/import-file/Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files/whl/source3.whl"
        -"/api/2.0/workspace-files/import-file/Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files/whl/source4.whl"
        -"/api/2.0/workspace-files/import-file/Workspace/foo/bar/artifacts/.internal/source1.whl"
        -"/api/2.0/workspace-files/import-file/Workspace/foo/bar/artifacts/.internal/source2.whl"
        -"/api/2.0/workspace-files/import-file/Workspace/foo/bar/artifacts/.internal/source3.whl"
        -"/api/2.0/workspace-files/import-file/Workspace/foo/bar/artifacts/.internal/source4.whl"
         
        -=== Expecting environment dependencies to be updated
        ->>> jq -s .[] | select(.path=="/api/2.2/jobs/create") | .body.environments [OUTPUT_DIR]/out.requests.txt
        -[
        -  {
        -    "environment_key": "test_env",
        -    "spec": {
        -      "client": "1",
        -      "dependencies": [
        -        "/Workspace/foo/bar/artifacts/.internal/source1.whl",
        -        "/Workspace/foo/bar/artifacts/.internal/source2.whl",
        -        "/Workspace/foo/bar/artifacts/.internal/source3.whl",
        -        "/Workspace/foo/bar/artifacts/.internal/source4.whl",
        -        "/Workspace/Users/foo@bar.test/mywheel.whl"
        -      ]
        -    }
        -  }
        -]
        +Exit code: 1
        
    acceptance_test.go:1119: LOG.plan:

latest (v1.22.1): same output as main (e9687c1)

TestAccept/bundle/artifacts/upload_multiple_libraries/DMS=/READPLAN=1: branch ✅ | main (e9687c1) ❌ | latest (v1.22.1) ❌

main (e9687c1):

acceptance_test.go:1341: Diff:
        --- bundle/artifacts/upload_multiple_libraries/output.txt
        +++ /tmp/TestAcceptbundleartifactsupload_multiple_librariesDMS=READP2186171726/002/output.txt
        @@ -39,29 +39,5 @@
         
         === Expecting 4 wheels to be uploaded
         >>> jq .path
        -"/api/2.0/workspace-files/import-file/Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files/whl/source1.whl"
        -"/api/2.0/workspace-files/import-file/Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files/whl/source2.whl"
        -"/api/2.0/workspace-files/import-file/Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files/whl/source3.whl"
        -"/api/2.0/workspace-files/import-file/Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files/whl/source4.whl"
        -"/api/2.0/workspace-files/import-file/Workspace/foo/bar/artifacts/.internal/source1.whl"
        -"/api/2.0/workspace-files/import-file/Workspace/foo/bar/artifacts/.internal/source2.whl"
        -"/api/2.0/workspace-files/import-file/Workspace/foo/bar/artifacts/.internal/source3.whl"
        -"/api/2.0/workspace-files/import-file/Workspace/foo/bar/artifacts/.internal/source4.whl"
         
        -=== Expecting environment dependencies to be updated
        ->>> jq -s .[] | select(.path=="/api/2.2/jobs/create") | .body.environments [OUTPUT_DIR]/out.requests.txt
        -[
        -  {
        -    "environment_key": "test_env",
        -    "spec": {
        -      "client": "1",
        -      "dependencies": [
        -        "/Workspace/foo/bar/artifacts/.internal/source1.whl",
        -        "/Workspace/foo/bar/artifacts/.internal/source2.whl",
        -        "/Workspace/foo/bar/artifacts/.internal/source3.whl",
        -        "/Workspace/foo/bar/artifacts/.internal/source4.whl",
        -        "/Workspace/Users/foo@bar.test/mywheel.whl"
        -      ]
        -    }
        -  }
        -]
        +Exit code: 1
        
    acceptance_test.go:1119: LOG.plan:

latest (v1.22.1): same output as main (e9687c1)

TestAccept/bundle/artifacts/upload_multiple_libraries/DMS=true/READPLAN=: branch ✅ | main (e9687c1) ❌ | latest (v1.22.1) ❌

main (e9687c1):

acceptance_test.go:1341: Diff:
        --- bundle/artifacts/upload_multiple_libraries/output.txt
        +++ /tmp/TestAcceptbundleartifactsupload_multiple_librariesDMS=trueR1516273251/002/output.txt
        @@ -39,29 +39,5 @@
         
         === Expecting 4 wheels to be uploaded
         >>> jq .path
        -"/api/2.0/workspace-files/import-file/Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files/whl/source1.whl"
        -"/api/2.0/workspace-files/import-file/Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files/whl/source2.whl"
        -"/api/2.0/workspace-files/import-file/Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files/whl/source3.whl"
        -"/api/2.0/workspace-files/import-file/Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files/whl/source4.whl"
        -"/api/2.0/workspace-files/import-file/Workspace/foo/bar/artifacts/.internal/source1.whl"
        -"/api/2.0/workspace-files/import-file/Workspace/foo/bar/artifacts/.internal/source2.whl"
        -"/api/2.0/workspace-files/import-file/Workspace/foo/bar/artifacts/.internal/source3.whl"
        -"/api/2.0/workspace-files/import-file/Workspace/foo/bar/artifacts/.internal/source4.whl"
         
        -=== Expecting environment dependencies to be updated
        ->>> jq -s .[] | select(.path=="/api/2.2/jobs/create") | .body.environments [OUTPUT_DIR]/out.requests.txt
        -[
        -  {
        -    "environment_key": "test_env",
        -    "spec": {
        -      "client": "1",
        -      "dependencies": [
        -        "/Workspace/foo/bar/artifacts/.internal/source1.whl",
        -        "/Workspace/foo/bar/artifacts/.internal/source2.whl",
        -        "/Workspace/foo/bar/artifacts/.internal/source3.whl",
        -        "/Workspace/foo/bar/artifacts/.internal/source4.whl",
        -        "/Workspace/Users/foo@bar.test/mywheel.whl"
        -      ]
        -    }
        -  }
        -]
        +Exit code: 1
        
    acceptance_test.go:1119: LOG.plan:

latest (v1.22.1): same output as main (e9687c1)

TestAccept/bundle/artifacts/upload_multiple_libraries/DMS=true/READPLAN=1: branch ✅ | main (e9687c1) ❌ | latest (v1.22.1) ❌

main (e9687c1):

acceptance_test.go:1341: Diff:
        --- bundle/artifacts/upload_multiple_libraries/output.txt
        +++ /tmp/TestAcceptbundleartifactsupload_multiple_librariesDMS=trueR3899297742/002/output.txt
        @@ -39,29 +39,5 @@
         
         === Expecting 4 wheels to be uploaded
         >>> jq .path
        -"/api/2.0/workspace-files/import-file/Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files/whl/source1.whl"
        -"/api/2.0/workspace-files/import-file/Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files/whl/source2.whl"
        -"/api/2.0/workspace-files/import-file/Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files/whl/source3.whl"
        -"/api/2.0/workspace-files/import-file/Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files/whl/source4.whl"
        -"/api/2.0/workspace-files/import-file/Workspace/foo/bar/artifacts/.internal/source1.whl"
        -"/api/2.0/workspace-files/import-file/Workspace/foo/bar/artifacts/.internal/source2.whl"
        -"/api/2.0/workspace-files/import-file/Workspace/foo/bar/artifacts/.internal/source3.whl"
        -"/api/2.0/workspace-files/import-file/Workspace/foo/bar/artifacts/.internal/source4.whl"
         
        -=== Expecting environment dependencies to be updated
        ->>> jq -s .[] | select(.path=="/api/2.2/jobs/create") | .body.environments [OUTPUT_DIR]/out.requests.txt
        -[
        -  {
        -    "environment_key": "test_env",
        -    "spec": {
        -      "client": "1",
        -      "dependencies": [
        -        "/Workspace/foo/bar/artifacts/.internal/source1.whl",
        -        "/Workspace/foo/bar/artifacts/.internal/source2.whl",
        -        "/Workspace/foo/bar/artifacts/.internal/source3.whl",
        -        "/Workspace/foo/bar/artifacts/.internal/source4.whl",
        -        "/Workspace/Users/foo@bar.test/mywheel.whl"
        -      ]
        -    }
        -  }
        -]
        +Exit code: 1
        
    acceptance_test.go:1119: LOG.plan:

latest (v1.22.1): same output as main (e9687c1)

38 more failure details omitted, see the full report in the run.

Sankalp-Mittal and others added 2 commits October 28, 2026 12:46
Keep a single SQL notebook with a byte order mark. One bundle test covers
both version-switching failures, and the endpoint test covers AUTO vs RAW
and that overwrite can't change an object's type. Drop the other header
variants, .Rmd and AUTO's 200-byte rule, along with the testserver
R_MARKDOWN/.Rmd handling and the ruff exclusion they needed.

Co-authored-by: Isaac <no-reply@databricks.com>
Use a unique bundle name and clean up the workspace folder so the test can
run against a real workspace, and drop generic comments from test.toml.
Both tests pass on aws-cli with the recorded outputs.

Co-authored-by: Isaac <no-reply@databricks.com>
@eng-dev-ecosystem-bot

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

Copy link
Copy Markdown
Collaborator

Integration test report

Commit: 640e02f

Run: 40836330352

Env ✅​pass 🙈​skip Time
✅​ aws linux-2core-8gb 306 56 6:40
✅​ aws-windows-latest-4core-16gb 307 55 9:52
✅​ azure linux-2core-8gb 305 56 6:00
✅​ azure-windows-latest-4core-16gb 306 55 8:23
✅​ gcp linux-2core-8gb 306 56 6:22
✅​ gcp-windows-latest-4core-16gb 307 55 8:57
Top 7 slowest tests (at least 2 minutes):
duration env testname
7:54 aws-windows-latest-4core-16gb TestAccept
7:07 gcp-windows-latest-4core-16gb TestAccept
6:32 azure-windows-latest-4core-16gb TestAccept
3:47 azure linux-2core-8gb TestAccept
3:47 aws linux-2core-8gb TestAccept
3:47 gcp linux-2core-8gb TestAccept
2:26 aws linux-2core-8gb TestAccept/ssh/bulk-transfer

Sankalp-Mittal and others added 4 commits October 28, 2026 14:12
…/import (#6149)"

This reverts commit b4f7a43. /workspace/import classifies files
differently from import-file and can't overwrite some of them, which
broke deployments (#7216).

Forward-fixes for changes that landed on main after #6149:
- upload-504 tests (#7014) and upload/internal_server_error inject their
  faults on the import-file URL again; --body-contains is gone.
- The multipart request recorder in prepare_server.go stays, since
  snapshot uploads use it.
- The testserver keeps its /workspace/import modelling for
  `workspace import`, minus the JUPYTER format no test uses anymore.
- sync-upload-edge-cases, added by #6149, is removed.

Co-authored-by: Isaac <no-reply@databricks.com>
Overwrite can't change a node's type: import-file returns 400 when a file
holds the name of a notebook upload, and 409 when a notebook holds the
name of a file upload. Deployments made with v1.21 and v1.22 have such
files, because those versions uploaded some notebooks as plain files.
When an overwrite fails this way, delete the node of the other type and
upload once more, so the remote matches the local file.

Replace the #7216 Badness tests with bundle/sync/replace-node-type
(Cloud), which syncs over both kinds of mismatch.

Co-authored-by: Isaac <no-reply@databricks.com>
The revert of #7034 restored a direct comparison that errorlint now flags.

Co-authored-by: Isaac <no-reply@databricks.com>
@github-actions github-actions Bot added the AIR Databricks AI Runtime CLI label Oct 28, 2026
@Sankalp-Mittal Sankalp-Mittal changed the title acceptance: capture notebook-vs-file classification gaps behind #7216 Revert bundle file uploads to import-file and replace nodes of the other type Oct 28, 2026
@Sankalp-Mittal
Sankalp-Mittal marked this pull request as ready for review October 28, 2026 14:57
@Sankalp-Mittal
Sankalp-Mittal requested review from a team as code owners October 28, 2026 14:57
@Sankalp-Mittal
Sankalp-Mittal requested review from andrewnester and maksim-zuev-db and removed request for andrewnester and maksim-zuev-db October 28, 2026 14:57
Sankalp-Mittal and others added 3 commits October 28, 2026 15:00
…JUPYTER imports

The revert of #6149 and #7034 removed these, but they model the real API
and stay useful independently of which endpoint the CLI uploads with.

Co-authored-by: Isaac <no-reply@databricks.com>
The real import-file endpoint imports each entry of a .zip into the
archive's parent folder instead of storing the archive (importZipFile in
universe). The fake stored it as a file, so nothing tracked that behavior.
Add bundle/sync/zip-extract (Cloud), and have the ssh tests upload valid
placeholder archives, which the real endpoint requires too.

Co-authored-by: Isaac <no-reply@databricks.com>
…16-notebook-detection

# Conflicts:
#	acceptance/bundle/deployment/bind/pipelines/recreate/output.txt
#	acceptance/bundle/deployment/bind/pipelines/recreate/script
#	acceptance/bundle/deployment/bind/pipelines/update/output.txt
#	acceptance/bundle/deployment/bind/pipelines/update/script
@Sankalp-Mittal
Sankalp-Mittal requested a review from a team as a code owner October 28, 2026 15:06
@Sankalp-Mittal
Sankalp-Mittal requested review from louis-johnston-db and removed request for louis-johnston-db October 28, 2026 15:06
// RESOURCE_ALREADY_EXISTS, which no status maps to a conflict.
if errors.Is(err, apierr.ErrResourceConflict) || errors.Is(err, apierr.ErrResourceAlreadyExists) {
// This API returns 409 if the file already exists, when the object type is file
if aerr.StatusCode == http.StatusConflict {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Just to confirm, this logic identical to the previous state? We did not check ErrResourceAlreadyExists here?

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.

Yes this is identical other than the delete node logic, the error code check was added with the workspace import PR

Comment thread libs/filer/workspace_files_client.go Outdated
return permissionError{absPath, err}
var nodePath string
var nodeType workspace.ObjectType
switch aerr.StatusCode {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

this seems opaque and risky? determining the node type from the HTTP status code? Should we use a regex on the error message instead?

If the regex breaks in the future, that's fine since this cleanup is us best-effort trying to overwrite the file - to prevent breaking future.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We also know the expected node type so an alternative is maybe rely on that? I'm completely fine with relying on the error regex here though.

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.

using the expected node type here is risky since that caused the bug here in the first place so I'd rather just go with the regex here

Comment thread libs/notebook/detect.go
The testserver now unzips archives uploaded through import-file, like the
real endpoint, so the test needs a valid archive instead of a plain string.

Co-authored-by: Isaac <no-reply@databricks.com>
Comment thread .nextchanges/bundles/revert-workspace-import.md Outdated
Sankalp-Mittal and others added 3 commits October 28, 2026 15:52
The status code alone is ambiguous (any 400 matched). Match the two
collision messages import-file returns instead; any other error skips
the cleanup, as in v1.20.

Co-authored-by: Isaac <no-reply@databricks.com>
The revert restored the pre-#7034 shape of DetectWithFS, which behaves
the same for files on disk. Keep the main version instead so the PR does
not touch libs/notebook, and let the testserver use DetectBytes for
JUPYTER imports again.

Co-authored-by: Isaac <no-reply@databricks.com>
Co-authored-by: Isaac <no-reply@databricks.com>
if err != nil {
return false, err
}
if info.ObjectType != nodeType {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

this seems pointless? We determine the nodeType based on the error message but hten get node type based on GetStatus?

What are we trying to prevent here?

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.

there are a few edge cases that we would miss, in all the examples assume I am trying to upload x.sql

  • a folder x.sql exists at the path and a python notebook x we get the same error and the python notebook is deleted
  • a race condition when multiple writers are writing to the same workspace and both of them try to upload x.sql without this check the second one deletes the first ones upload (this should have failed but now it passes)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

a race condition when multiple writers are writing to the same workspace and both of them try to upload x.sql

We don't need to reason about this case. DABs in general acquires an exclusive lock over the deployment before starting upload.

a folder x.sql exists at the path and a python notebook x we get the same error and the python notebook is deleted

That is by design right? The entire point is we delete x (notebook) to make way for x.sql.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

a folder x.sql exists at the path and a python notebook x

this is probably not a legal state for the file system to end up in remotely.

The additional guard is OK though - atleast this way we know for sure that the remote object being deleted is a file or directory.

trace $CLI workspace-settings-v2 patch-public-workspace-setting port_fwd_serverless_enabled --json '{"name": "port_fwd_serverless_enabled", "boolean_val": {"value": false}}' >/dev/null

# No release artifacts locally and they're never executed; stand in empty archives.
# No release artifacts locally and they're never executed; stand in placeholder archives.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

unnecessary diff? I would expect this PR to be a noop wrt zip files?

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.

nope I am still keeping the changes to the testserver wrt how it handles zips, that was the reason for the first .zip regression being missed in the first case

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.

Now we create zips with actual data instead of empty ones

Sankalp-Mittal and others added 3 commits October 28, 2026 22:46
Require the name in the message to match the upload, and only delete a
notebook whose language matches the upload's extension. A folder holding
x.sql also returns the 409 message, and the old check then deleted an
unrelated Python notebook x.

Co-authored-by: Isaac <no-reply@databricks.com>
Since #7241, * in a fault pattern matches within one path segment and **
across segments. Upload paths span many segments, so the faults stopped
firing.

Co-authored-by: Isaac <no-reply@databricks.com>
Co-authored-by: Isaac <no-reply@databricks.com>
@Sankalp-Mittal
Sankalp-Mittal added this pull request to the merge queue Oct 29, 2026
Merged via the queue into main with commit 8afc86f Oct 29, 2026
30 checks passed
@Sankalp-Mittal
Sankalp-Mittal deleted the sankalp-mittal/acc-7216-notebook-detection branch October 29, 2026 08:20
Comment thread acceptance/script.prepare

# Workspace paths uploaded via /workspace/import, one per line. The path is a
# multipart form field, not part of the URL, so print_requests.py can't filter on it.
print_workspace_imports() {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think most of the PR is a git revert right, so this and most changes under acceptance/ are to a known stable. but would be nice to (in prep for the eventual roll-forward) we can reintroduce this abstraction to avoid having to change all script files again

Comment thread cmd/air/runsubmit_test.go
Comment on lines 432 to +433
server.Handle("POST", validateConfigPath, func(req testserver.Request) any { return tt.response })
server.Handle("POST", "/api/2.0/workspace/import", func(req testserver.Request) any {
server.Handle("POST", "/api/2.0/workspace-files/import-file/{path...}", func(req testserver.Request) any {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

unrelated to your change, but curious that cmd/air/*_test.go do these tests. they should really be using acceptance test for this

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

prefer to create archive.zip and archive_v2.zip inside script so we don't have opaque binaries committed

>>> list /Workspace/Users/[USERNAME]/.bundle/zip-extract-[UNIQUE_NAME]/default/files/pkg
FILE /pkg/a.txt

=== Syncing a changed archive overwrites the extracted files

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

let's list again after bundle sync?

uploadPath, opts := importRequest(absPath, body)
if overwrite {
opts = append(opts, workspace.UploadOverwrite())
err = w.apiClient.Do(ctx, http.MethodPost, urlPath, w.workspaceIDHeaders(), nil, body, nil)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

workspace_files_client.go:173

The legacy uploader creates notebook bom from BOM-prefixed bom.sql, but sync’s unchanged detector records bom.sql → bom.sql. I reproduced: upload, remove the local file, sync again → reports one deletion but leaves notebook bom behind. The same probe passes with the base branch’s uploader.

An existing snapshot also causes unchanged, previously misclassified files to be skipped after upgrading. The follow-up needs consistent remote-path bookkeeping and coverage for upgrade → replacement → deletion. This restores a v1.20-era problem rather than introducing it entirely anew.


Restoring backend classification also changes remote filenames for BOM-prefixed notebooks. bom.sql now uploads as notebook bom, but NewSnapshotState still records bom.sql → bom.sql because the local detector rejects the BOM. Removing the local file then reports a successful deletion while leaving bom behind. I reproduced this locally; it passes with the previous uploader. Please align the snapshot mapping and extend replace-node-type to cover deleting the file after replacement.

@eng-dev-ecosystem-bot

Copy link
Copy Markdown
Collaborator

Integration test report

Commit: 8afc86f

Run: 40841543419

Env 🔄​flaky ✅​pass 🙈​skip Time
✅​ aws linux-2core-8gb 1504 1226 129:32
✅​ aws-windows-latest-4core-16gb 1429 1251 149:09
🔄​ azure linux-2core-8gb 3 1348 1278 107:56
🔄​ azure-windows-latest-4core-16gb 3 1273 1303 120:47
🔄​ gcp linux-2core-8gb 2 1336 1283 113:09
✅​ gcp-windows-latest-4core-16gb 1263 1308 124:53
7 interesting tests: 7 flaky
Test Name azure linux-2core-8gb azure-windows-latest-4core-16gb gcp linux-2core-8gb
🔄​ TestAccept 🔄​f 🔄​f ✅​p
🔄​ TestAccept/bundle/invariant/delete_idempotent ✅​p 🔄​f ✅​p
🔄​ TestAccept/bundle/invariant/delete_idempotent/DMS=/INPUT_CONFIG=job_run.yml.tmpl/READPLAN=1 ✅​p 🔄​f ✅​p
🔄​ TestAccept/bundle/invariant/no_drift 🔄​f ✅​p ✅​p
🔄​ TestAccept/bundle/invariant/no_drift/DMS=true/INPUT_CONFIG=genie_space.yml.tmpl/READPLAN= 🔄​f ✅​p ✅​p
🔄​ TestFsCpFileToNonExistentDir ✅​p ✅​p 🔄​f
🔄​ TestFsCpFileToNonExistentDir/uc-volumes_to_uc-volumes ✅​p ✅​p 🔄​f
Top 50 slowest tests (at least 2 minutes):
duration env testname
12:44 aws linux-2core-8gb TestAccept/bundle/resources/clusters/lifecycle-started/DMS=
10:59 azure linux-2core-8gb TestAccept/bundle/resources/clusters/lifecycle-started/DMS=
9:50 azure-windows-latest-4core-16gb TestAccept/bundle/resources/clusters/lifecycle-started/DMS=
9:06 aws-windows-latest-4core-16gb TestAccept/bundle/resources/clusters/lifecycle-started/DMS=
9:01 gcp linux-2core-8gb TestAccept/bundle/resources/clusters/lifecycle-started/DMS=
8:40 aws-windows-latest-4core-16gb TestAccept/bundle/invariant/delete_idempotent/DMS=/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=
8:36 aws linux-2core-8gb TestAccept/bundle/resources/clusters/lifecycle-started-toggle/DMS=
8:18 aws-windows-latest-4core-16gb TestAccept/bundle/invariant/delete_idempotent/DMS=/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=1
8:14 aws-windows-latest-4core-16gb TestAccept/bundle/invariant/delete_idempotent/DMS=/INPUT_CONFIG=cluster_apply_policy_default_values.yml.tmpl/READPLAN=
8:13 aws linux-2core-8gb TestAccept/bundle/resources/clusters/lifecycle-started/DMS=true
8:10 azure linux-2core-8gb TestAccept/bundle/config-remote-sync/multiple_resources/DMS=true
8:06 gcp-windows-latest-4core-16gb TestAccept/bundle/resources/clusters/lifecycle-started/DMS=true
7:58 gcp linux-2core-8gb TestAccept/bundle/resources/clusters/deploy/local_ssd_count/DMS=
7:50 gcp linux-2core-8gb TestAccept/bundle/resources/clusters/lifecycle-started/DMS=true
7:36 gcp linux-2core-8gb TestAccept/bundle/resources/clusters/deploy/local_ssd_count/DMS=true
7:25 gcp linux-2core-8gb TestAccept/bundle/resources/apps/lifecycle-started/DMS=true
7:22 gcp-windows-latest-4core-16gb TestAccept/bundle/resources/clusters/deploy/local_ssd_count/DMS=
7:17 aws linux-2core-8gb TestAccept/bundle/resources/apps/lifecycle-started/DMS=
7:17 aws-windows-latest-4core-16gb TestAccept/bundle/resources/apps/lifecycle-started/DMS=
7:16 azure-windows-latest-4core-16gb TestAccept/bundle/resources/apps/lifecycle-started/DMS=
7:08 aws-windows-latest-4core-16gb TestAccept/bundle/resources/apps/lifecycle-started/DMS=true
7:05 aws-windows-latest-4core-16gb TestAccept/bundle/invariant/delete_idempotent/DMS=/INPUT_CONFIG=cluster_apply_policy_default_values.yml.tmpl/READPLAN=1
7:02 azure-windows-latest-4core-16gb TestAccept/bundle/resources/apps/lifecycle-started/DMS=true
7:01 azure-windows-latest-4core-16gb TestAccept/bundle/resources/clusters/lifecycle-started/DMS=true
6:57 azure linux-2core-8gb TestAccept/bundle/resources/apps/lifecycle-started/DMS=true
6:51 aws linux-2core-8gb TestAccept/bundle/resources/clusters/resize-terminated-fallback/DMS=
6:50 azure linux-2core-8gb TestAccept/bundle/config-remote-sync/multiple_resources/DMS=
6:48 gcp-windows-latest-4core-16gb TestAccept/bundle/resources/clusters/deploy/local_ssd_count/DMS=true
6:48 aws linux-2core-8gb TestAccept/bundle/resources/apps/lifecycle-started/DMS=true
6:44 gcp linux-2core-8gb TestAccept/bundle/resources/clusters/lifecycle-started-toggle/DMS=
6:44 azure linux-2core-8gb TestAccept/bundle/resources/clusters/deploy/update-after-create/DMS=
6:42 gcp-windows-latest-4core-16gb TestAccept/bundle/resources/clusters/lifecycle-started/DMS=
6:42 aws linux-2core-8gb TestAccept/bundle/config-remote-sync/multiple_resources/DMS=
6:40 aws-windows-latest-4core-16gb TestAccept/bundle/resources/clusters/lifecycle-started/DMS=true
6:40 gcp linux-2core-8gb TestAccept/bundle/config-remote-sync/multiple_resources/DMS=true
6:38 azure linux-2core-8gb TestAccept/bundle/resources/apps/lifecycle-started/DMS=
6:23 aws linux-2core-8gb TestAccept/bundle/config-remote-sync/multiple_resources/DMS=true
6:22 gcp-windows-latest-4core-16gb TestAccept/bundle/resources/apps/lifecycle-started/DMS=
6:21 gcp-windows-latest-4core-16gb TestAccept/bundle/invariant/no_drift/DMS=/INPUT_CONFIG=cluster.yml.tmpl/READPLAN=1
6:18 azure linux-2core-8gb TestAccept/bundle/resources/clusters/lifecycle-started/DMS=true
6:07 gcp-windows-latest-4core-16gb TestAccept/bundle/resources/clusters/lifecycle-started-toggle/DMS=
6:06 gcp linux-2core-8gb TestAccept/bundle/config-remote-sync/multiple_resources/DMS=
6:02 gcp linux-2core-8gb TestAccept/bundle/resources/clusters/lifecycle-started-toggle/DMS=true
5:56 azure linux-2core-8gb TestAccept/bundle/resources/clusters/deploy/simple/DMS=
5:32 gcp-windows-latest-4core-16gb TestAccept/bundle/resources/apps/lifecycle-started/DMS=true
5:28 azure-windows-latest-4core-16gb TestAccept/bundle/resources/clusters/deploy/data_security_mode/DMS=
5:26 aws-windows-latest-4core-16gb TestAccept/bundle/deploy/spark-jar-task/DMS=
5:21 gcp-windows-latest-4core-16gb TestAccept/bundle/deploy/spark-jar-task/DMS=
5:16 gcp linux-2core-8gb TestAccept/bundle/deploy/spark-jar-task/DMS=
5:11 gcp linux-2core-8gb TestAccept/bundle/resources/apps/lifecycle-started/DMS=

deco-sdk-tagging Bot added a commit that referenced this pull request Oct 29, 2026
## Release v1.23.0

### CLI

 * Fix GitHub API rate limit errors in `aitools list` and plugin installs by pinning skills to `0.2.32`. ([#7159](#7159))
 * `databricks ssh connect` now makes `claude` and `codex` available on dedicated clusters. ([#7190](#7190))
 * `databricks ssh connect` on serverless now makes `claude` and `codex` available in IDE sessions (`--ide`) and to non-interactive commands (e.g. `databricks ssh connect -- 'claude -p "..."'`). ([#7123](#7123))

### AI Runtime

 * Add workload support for the GPU_1xRTX6000 accelerator type in enabled workspaces. ([#7214](#7214))
 * Show only the accelerator types available in the current workspace in `databricks air run -h config.compute`. ([#6993](#6993))

### Bundles

 * Fixed `bundle validate` failing with "expected a map to index" when a job `schedule`, `trigger` or `continuous` is a reference to a whole block, such as `${resources.jobs.base.schedule}`. ([#7225](#7225))
 * Added `lifecycle.depends_on` to order resources without referencing their fields. ([#7120](#7120))
 * Immutable-folder deploys now refuse to deploy onto a snapshot that was modified outside the bundle (break glass); `bundle deploy --force` moves the deployment to a fresh snapshot. ([#6774](#6774))
 * Fix `--include-locations` failing when a resource is missing a required field. ([#7185](#7185))
 * Removed spurious "required field is not set" warnings for a field whose value is a reference to a whole block, such as `schedule: ${resources.jobs.base.schedule}`. ([#7226](#7226))
 * Revert bundle file uploads to the legacy `/workspace-files/import-file` endpoint, rolling back [#6149](#6149) and [#7034](#7034) released in [v1.21.0](https://github.com/databricks/cli/releases/tag/v1.21.0). This fixes notebooks being uploaded as plain files and deployments failing (for example SQL notebooks in [#7216](#7216)). A remote file or notebook whose type differs from the local one is now deleted and replaced instead of blocking the deploy. ([#7218](#7218))
 * Support selecting resources for deletion with `bundle deploy --select`. ([#7023](#7023))
 * Add the `workspace.sync_mode` setting with the values `overwrite` (default), `in-place`, and `immutable`. It replaces `presets.source_linked_deployment` (use `in-place`) and `experimental.immutable_folder` (use `immutable`), which are now deprecated and emit a warning. ([#7183](#7183))

### Dependency Updates

 * Bump dependencies with known vulnerabilities. ([#7213](#7213))
 * Update the Go SDK to [v0.190.0](https://github.com/databricks/databricks-sdk-go/releases/tag/v0.190.0). ([#7155](#7155))
 * Update the Go SDK to [v0.191.0](https://github.com/databricks/databricks-sdk-go/releases/tag/v0.191.0). ([#7211](#7211))
 * Bump Node.js downloaded by the `ssh` agent shim from v24.21.0 to v24.22.2. ([#7246](#7246))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AIR Databricks AI Runtime CLI DABs DABs related issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

RESOURCE_ALREADY_EXISTS error when deploying bundle with version 1.21.0

4 participants