Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
82b0c54
initial filesystem changes
Sankalp-Mittal Aug 3, 2026
ed23668
filer: switch workspace upload from import-file to /workspace/import
Sankalp-Mittal Aug 3, 2026
86cf272
update comments
Sankalp-Mittal Aug 4, 2026
15d3b59
Source upload size and rate limits from public docs
Sankalp-Mittal Aug 5, 2026
83b8bc5
acceptance: migrate ai_runtime_task snapshot upload assertions
Sankalp-Mittal Aug 5, 2026
c25f052
filer: fix already-exists detection for errors without an error_code
Sankalp-Mittal Aug 5, 2026
ac122b4
filer: build the import form locally to keep workspace routing correct
Sankalp-Mittal Aug 6, 2026
dc0e0c6
filer: assert Write against a testserver instead of a mocked SDK client
Sankalp-Mittal Aug 6, 2026
c97c1af
filer: condense the upload size-limit and conflict comments
Sankalp-Mittal Aug 6, 2026
90becb3
testserver: tighten format=AUTO handling in the import fake
Sankalp-Mittal Aug 6, 2026
c5a41a3
acceptance: parse fault.py arguments with argparse
Sankalp-Mittal Aug 6, 2026
0f683db
testserver: cover case-insensitive notebook extension detection
Sankalp-Mittal Aug 6, 2026
bb2a05d
acceptance: re-aim run-submit-deps upload assertions at /workspace/im…
Sankalp-Mittal Aug 6, 2026
7842866
acceptance: pin ai_runtime_task snapshot inputs to LF
Sankalp-Mittal Aug 6, 2026
770cf45
acceptance: keep update_file.py from rewriting line endings
Sankalp-Mittal Aug 6, 2026
2e42fb4
add a descriptive error on 500 upload failure
Sankalp-Mittal Aug 7, 2026
b42de03
acceptance: regenerate upload goldens for the descriptive error
Sankalp-Mittal Aug 7, 2026
a99899f
acceptance: sort auto-migrate-empty-tfstate uploads deterministically
Sankalp-Mittal Aug 7, 2026
11fefde
acceptance: regenerate sync-upload-edge-cases out.test.toml
Sankalp-Mittal Aug 7, 2026
1913093
acceptance: match update_file.py search strings across CRLF
Sankalp-Mittal Aug 7, 2026
0552229
filer: upload via the SDK's Workspace.Upload
Sankalp-Mittal Aug 12, 2026
6ccfb37
inline the constant
Sankalp-Mittal Aug 14, 2026
2590a5a
update comment to reflect latest change
Sankalp-Mittal Aug 17, 2026
e2f004a
update comments
Sankalp-Mittal Aug 17, 2026
1766a0a
update PR with latest universe changes
Sankalp-Mittal Aug 26, 2026
d4fb7c0
acceptance: update goldens for /workspace/import after rebase
Sankalp-Mittal Aug 26, 2026
86a4621
Merge origin/main into sankalp-mittal/workspace-import-migration
Sankalp-Mittal Sep 16, 2026
e1e59d5
changelog: reformat nextchanges fragment as a single bullet line
Sankalp-Mittal Sep 16, 2026
f8e5f5f
acceptance: restore goldens corrupted by test-update timeouts
Sankalp-Mittal Sep 16, 2026
4c7da85
acceptance: fix permissions and telemetry goldens after merge
Sankalp-Mittal Sep 16, 2026
f38be39
acceptance: re-aim upload fault stubs at /workspace/import
Sankalp-Mittal Sep 16, 2026
17f8e48
Merge origin/main into sankalp-mittal/workspace-import-migration
Sankalp-Mittal Sep 16, 2026
de55cac
filer: drop the already-exists message fallback
Sankalp-Mittal Sep 16, 2026
d360240
Merge origin/main into sankalp-mittal/workspace-import-migration
Sankalp-Mittal Oct 12, 2026
62738b7
filer: drop the workspace ID "none" normalization
Sankalp-Mittal Oct 12, 2026
eb90d8d
acceptance: keep fault.py's hand-rolled parser, add only --body-contains
Sankalp-Mittal Oct 12, 2026
9da608d
acceptance: add print_workspace_imports helper for uploaded paths
Sankalp-Mittal Oct 12, 2026
a8129af
acceptance: fault only file_to_upload.txt in upload/internal_server_e…
Sankalp-Mittal Oct 12, 2026
885339c
filer: drop Write unit tests covered by filer and acceptance tests
Sankalp-Mittal Oct 12, 2026
932444a
acceptance: avoid a leading slash in fault.py --body-contains
Sankalp-Mittal Oct 12, 2026
6d8dddd
Merge remote-tracking branch 'origin/main' into sankalp-mittal/worksp…
Sankalp-Mittal Oct 12, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .nextchanges/bundles/6149.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* Bundle file uploads now use the multipart `POST /api/2.0/workspace/import` endpoint instead of the deprecated `POST /api/2.0/workspace-files/import-file`, raising the per-workspace upload rate limit and improving deploy throughput under concurrency. ([#6149](https://github.com/databricks/cli/pull/6149))
6 changes: 3 additions & 3 deletions acceptance/air/run-submit-deps/output.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ Stream logs after submission using:
databricks air logs 555

=== 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"}
>>> print_requests.py //api/2.0/workspace/import --oneline --sort --unique --keep
{"method": "POST", "path": "/api/2.0/workspace/import", "body": {"multipart_form": {"content": "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", "format": "AUTO", "overwrite": "true", "path": "/Workspace/Users/[USERNAME]/.air/cli_launch/deps-smoke/deps-smoke_[RUN_ID]/training_config.yaml"}}}
{"method": "POST", "path": "/api/2.0/workspace/import", "body": {"multipart_form": {"content": "python train.py", "format": "AUTO", "overwrite": "true", "path": "/Workspace/Users/[USERNAME]/.air/cli_launch/deps-smoke/deps-smoke_[RUN_ID]/command.sh"}}}

=== inline deps, artifact location, and capacity id reach the submit payload
>>> print_requests.py //api/2.2/jobs/runs/submit
Expand Down
5 changes: 4 additions & 1 deletion acceptance/air/run-submit-deps/script
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ title "submit with inline dependencies"
trace $CLI air run -f run.yaml

title "only config + command are uploaded; no requirements.yaml"
trace print_requests.py //api/2.0/workspace-files/import-file --oneline --sort --unique --keep
# Uploads go to POST /workspace/import, which carries the target filename in the
# multipart body rather than the URL, so each uploaded path shows up under
# body.multipart_form.path instead of in the request path.
trace print_requests.py //api/2.0/workspace/import --oneline --sort --unique --keep

title "inline deps, artifact location, and capacity id reach the submit payload"
trace print_requests.py //api/2.2/jobs/runs/submit
Expand Down
8 changes: 4 additions & 4 deletions acceptance/air/run-submit-overrides/output.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Stream logs after submission using:
databricks air logs 555

=== 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"}
>>> print_requests.py //api/2.0/workspace/import --oneline --sort --unique
{"method": "POST", "path": "/api/2.0/workspace/import", "body": {"multipart_form": {"content": "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", "format": "AUTO", "overwrite": "true", "path": "/Workspace/Users/[USERNAME]/.air/cli_launch/overrides-smoke/overrides-smoke_[RUN_ID]/training_config.yaml"}}}
{"method": "POST", "path": "/api/2.0/workspace/import", "body": {"multipart_form": {"content": "model:\n hidden_size: 2048\noptimizer:\n learning_rate: 0.001\n name: adamw\n", "format": "AUTO", "overwrite": "true", "path": "/Workspace/Users/[USERNAME]/.air/cli_launch/overrides-smoke/overrides-smoke_[RUN_ID]/hyperparameters.yaml"}}}
{"method": "POST", "path": "/api/2.0/workspace/import", "body": {"multipart_form": {"content": "python train.py", "format": "AUTO", "overwrite": "true", "path": "/Workspace/Users/[USERNAME]/.air/cli_launch/overrides-smoke/overrides-smoke_[RUN_ID]/command.sh"}}}
2 changes: 1 addition & 1 deletion acceptance/air/run-submit-overrides/script
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ trace $CLI air run -f run.yaml \
--override parameters.optimizer.learning_rate=0.001

title "the uploaded config preserves source order and contains overrides"
trace print_requests.py //api/2.0/workspace-files/import-file --oneline --sort --unique
trace print_requests.py //api/2.0/workspace/import --oneline --sort --unique
16 changes: 14 additions & 2 deletions acceptance/bin/fault.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
#!/usr/bin/env python3
"""Set up a fault rule on the testserver for the current test token.

Usage: fault.py [--after-handler] PATTERN STATUS_CODE OFFSET TIMES [ERROR_CODE]
Comment thread
Sankalp-Mittal marked this conversation as resolved.
Resolved
Usage: fault.py [--after-handler] [--body-contains SUBSTR] PATTERN STATUS_CODE OFFSET TIMES [ERROR_CODE]

--after-handler run the handler first; keep its effect and replace only the response
--body-contains only fire when the request body contains SUBSTR, e.g. to target one
file's /workspace/import upload (all uploads share that path)
PATTERN HTTP method and path, supports trailing * wildcard,
e.g. "PUT /api/2.0/permissions/pipelines/*"
STATUS_CODE HTTP status code to return, e.g. 504
Expand Down Expand Up @@ -33,8 +35,17 @@
if after_handler:
args.remove("--after-handler")

body_contains = ""
if "--body-contains" in args:
i = args.index("--body-contains")
body_contains = args[i + 1]
del args[i : i + 2]

if len(args) not in (4, 5):
print(f"usage: {sys.argv[0]} [--after-handler] PATTERN STATUS_CODE OFFSET TIMES [ERROR_CODE]", file=sys.stderr)
print(
f"usage: {sys.argv[0]} [--after-handler] [--body-contains SUBSTR] PATTERN STATUS_CODE OFFSET TIMES [ERROR_CODE]",
file=sys.stderr,
)
sys.exit(1)

pattern, status_code, offset, times = args[0], int(args[1]), int(args[2]), int(args[3])
Expand All @@ -49,6 +60,7 @@
"offset": offset,
"times": times,
"after_handler": after_handler,
"body_contains": body_contains,
}
).encode()

Expand Down
14 changes: 9 additions & 5 deletions acceptance/bundle/apps/app_yaml/out.app.yml.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
{
"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"
"path": "/api/2.0/workspace/import",
"body": {
"multipart_form": {
"content": "command:\n - python\n - app.py\n",
"format": "AUTO",
"overwrite": "true",
"path": "/Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files/app/app.yml"
}
}
}
2 changes: 1 addition & 1 deletion acceptance/bundle/apps/app_yaml/output.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Created apps.myapp
Files: 3 uploaded, 0 deleted
Resources: 1 created, 0 changed, 0 deleted, 0 unchanged

>>> jq select(.path | test("app.yml")) [OUTPUT_DIR]/out.requests.txt
>>> jq select(.body.multipart_form.path | strings | test("app.yml")) [OUTPUT_DIR]/out.requests.txt

>>> [CLI] bundle destroy --auto-approve
The following resources will be deleted:
Expand Down
2 changes: 1 addition & 1 deletion acceptance/bundle/apps/app_yaml/script
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
trace $CLI bundle validate
trace $CLI bundle plan
trace $CLI bundle deploy
trace jq 'select(.path | test("app.yml"))' "$OUT_REQUESTS" | sed 's/\\r//g' > out.app.yml.txt
trace jq 'select(.body.multipart_form.path | strings | test("app.yml"))' "$OUT_REQUESTS" | sed 's/\\r//g' > out.app.yml.txt
#trace print_requests.py //apps # currently fails due to TF inserting description=""
rm "$OUT_REQUESTS"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@
}

=== Expecting the code_source tarball to be uploaded
>>> jq .path
"/api/2.0/workspace-files/import-file/Workspace/foo/bar/artifacts/.internal/code.tgz"
>>> print_workspace_imports
/Workspace/foo/bar/artifacts/.internal/code.tgz
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ title "Expecting code_source_path rewritten to the uploaded artifact remote path
trace jq -s '.[] | select(.path=="/api/2.2/jobs/create") | .body.tasks[].ai_runtime_task' "$OUT_REQUESTS"

title "Expecting the code_source tarball to be uploaded"
trace jq .path < "$OUT_REQUESTS" | grep import | grep code.tgz | sort
trace print_workspace_imports | grep code.tgz | sort

rm "$OUT_REQUESTS"
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ Resources: 1 created, 0 changed, 0 deleted, 0 unchanged
]

=== 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"
>>> print_workspace_imports
/Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files/whl/source.whl
/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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ title "Expecting 2 wheels in libraries section in /jobs/create"
trace jq -s '.[] | select(.path=="/api/2.2/jobs/create") | .body.tasks' "$OUT_REQUESTS"

title "Expecting wheel to be uploaded"
trace jq .path < "$OUT_REQUESTS" | grep import | grep whl | sort
trace print_workspace_imports | grep whl | sort

title "Expecting environment dependencies to be updated"
trace jq -s '.[] | select(.path=="/api/2.2/jobs/create") | .body.environments' "$OUT_REQUESTS"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ Files: 4 uploaded, 0 deleted
Resources: 0 created, 0 changed, 0 deleted, 0 unchanged

=== 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"
>>> print_workspace_imports
/Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files/whl/source.whl
/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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ $CLI bundle plan -o json > tmp.plan.json 2>>LOG.plan
$CLI bundle deploy $(readplanarg tmp.plan.json)

title "Expecting wheel to be uploaded"
trace jq .path < "$OUT_REQUESTS" | grep import | grep whl | sort
trace print_workspace_imports | grep whl | sort

title "Expecting delete request to artifact_path/.internal folder"
trace jq -s '.[] | select(.path=="/api/2.0/workspace/delete") | select(.body.path | test(".*/artifacts/.internal"))' "$OUT_REQUESTS"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,15 @@ Resources: 1 created, 0 changed, 0 deleted, 0 unchanged
]

=== 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"
>>> print_workspace_imports
/Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files/whl/source1.whl
/Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files/whl/source2.whl
/Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files/whl/source3.whl
/Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files/whl/source4.whl
/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

=== Expecting environment dependencies to be updated
>>> jq -s .[] | select(.path=="/api/2.2/jobs/create") | .body.environments [OUTPUT_DIR]/out.requests.txt
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ title "Expecting 5 wheels in libraries section in /jobs/create"
trace jq -s '.[] | select(.path=="/api/2.2/jobs/create") | .body.tasks' "$OUT_REQUESTS"

title "Expecting 4 wheels to be uploaded"
trace jq .path < "$OUT_REQUESTS" | grep import | grep whl | sort
trace print_workspace_imports | grep whl | sort

title "Expecting environment dependencies to be updated"
trace jq -s '.[] | select(.path=="/api/2.2/jobs/create") | .body.environments' "$OUT_REQUESTS"
Expand Down
Loading
Loading