Skip to content

Package AI Runtime code_source via a tgz artifact, not a sync overlay - #6494

Merged
vinchenzo-db merged 3 commits into
mainfrom
vchen/air-code-source-via-artifact
Sep 3, 2026
Merged

vinchenzo-db merged 3 commits into
mainfrom
vchen/air-code-source-via-artifact

Conversation

@vinchenzo-db

@vinchenzo-db vinchenzo-db commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

#6110 <- basically reverting this pr

A local-directory code_source_path is now turned into a tgz artifact and built and uploaded through the standard artifact path, instead of the aicode mutator splicing a content-addressed tarball onto the sync root. The tgz artifact is the single packing mechanism.

  • aicode.PackageCodeSource now synthesizes a tgz artifact per local-dir code_source_path (path = the dir's parent, include = its basename, so archive entries nest under the basename for the /databricks/code_source/ layout) and rewrites code_source_path to the built tarball. It runs before artifacts.Prepare (initialize) instead of in the build phase.
  • Remove the sync-root overlay, the content-addressed packer (buildCodeSnapshot), bundle.HasAiRuntimeCodeSnapshot, bundle.AiCodeSnapshotDir, and the validateSnapshotDir guards that only existed for the overlay.
  • Behavior change: only .gitignore filters the packaged files now; the bundle-wide sync.include/exclude no longer apply to a code artifact.
  • Keep the git_source / immutable-folder / source-linked / for_each rejections.

Why

#6428 We recently merged a DABs native uploader, which supercedes this mutator workaround

Tests

Unit tests

E2E test:
Setup:

# v.chen at ip-10-90-20-219 in /tmp/pr2-e2e (git:) [18:59:50]
$ cd ~/.worktrees/cli-rmaicode && go build -o /tmp/cli-pr3 . && cd -

rm -rf /tmp/pr3-e2e && mkdir -p /tmp/pr3-e2e/src && cd /tmp/pr3-e2e
printf 'print("train ok")\n' > src/train.py
# hand-authored command.sh cds into the extracted code dir itself
printf 'cd /databricks/code_source/src\npython train.py\n' > src/command.sh
cat > databricks.yml <<'YAML'
bundle:
  name: pr3-code-source-demo
resources:
  jobs:
    train:
      name: "[${bundle.target}] pr3 demo"
      tasks:
        - task_key: train
          environment_key: default
          ai_runtime_task:
            experiment: pr3_demo
            code_source_path: ./src
            deployments:
              - command_path: src/command.sh
                compute: {accelerator_type: GPU_1xA10, accelerator_count: 1}
      environments:
        - environment_key: default
          spec:
            environment_version: "5"
targets:
  dev: {mode: development, default: true}
YAML

export DATABRICKS_CONFIG_PROFILE=e2-dogfood DATA
/tmp/pr2-e2e
# v.chen at ip-10-90-20-219 in /tmp/pr3-e2e (git:) [18:59:59]
$ /tmp/cli-pr3 bundle deploy
Building air_code_source_src...
Uploading .databricks/air_code_source/air_code_source_src.tar.gz...
Uploading bundle files to /Workspace/Users/v.chen@databricks.com/.bundle/pr3-code-source-demo/dev/files...
Created jobs.train
Files: 3 uploaded, 0 deleted
Resources: 1 created, 0 changed, 0 deleted, 0 unchanged

Show deploy works:

# v.chen at ip-10-90-20-219 in /tmp/pr3-e2e (git:) [19:00:14]
$ /tmp/cli-pr3 bundle deploy
Building air_code_source_src...
Uploading .databricks/air_code_source/air_code_source_src.tar.gz...
Uploading bundle files to /Workspace/Users/v.chen@databricks.com/.bundle/pr3-code-source-demo/dev/files...
Files: 0 uploaded, 0 deleted
Resources: 0 created, 0 changed, 0 deleted, 1 unchanged
# v.chen at ip-10-90-20-219 in /tmp/pr3-e2e (git:) [19:01:00]

Investigate what is in tar:

$ tar tzf .databricks/air_code_source/air_code_source_src.tar.gz
src/command.sh
src/train.py
# v.chen at ip-10-90-20-219 in /tmp/pr3-e2e (git:) [19:01:29]
$ 

bundle summary:

$ /tmp/cli-pr3 bundle summary
Name: pr3-code-source-demo
Target: dev
Workspace:
  User: v.chen@databricks.com
  Path: /Workspace/Users/v.chen@databricks.com/.bundle/pr3-code-source-demo/dev
Resources:
  Jobs:
    train:
      Name: [dev v_chen] [dev] pr3 demo
      URL:  https://e2-dogfood.staging.cloud.databricks.com/jobs/1015159229445184?w=6051921418418893
# v.chen at ip-10-90-20-219 in /tmp/pr3-e2e (git:) [19:01:51]
$ 

bundle run:

$ /tmp/cli-pr3 bundle run train --no-wait
Run URL: https://e2-dogfood.staging.cloud.databricks.com/jobs/1015159229445184/runs/174551477706538?o=6051921418418893

Run details:
image
image

A local-directory code_source_path is now turned into a `tgz` artifact and built
and uploaded through the standard artifact path, instead of the aicode mutator
splicing a content-addressed tarball onto the sync root. The tgz artifact is the
single packing mechanism.

- aicode.PackageCodeSource now synthesizes a `tgz` artifact per local-dir
  code_source_path (path = the dir's parent, include = its basename, so archive
  entries nest under the basename for the /databricks/code_source/<dir> layout)
  and rewrites code_source_path to the built tarball. It runs before
  artifacts.Prepare (initialize) instead of in the build phase.
- Remove the sync-root overlay, the content-addressed packer (buildCodeSnapshot),
  bundle.HasAiRuntimeCodeSnapshot, bundle.AiCodeSnapshotDir, and the
  validateSnapshotDir guards that only existed for the overlay.
- Behavior change: only .gitignore filters the packaged files now; the
  bundle-wide sync.include/exclude no longer apply to a code artifact.
- Keep the git_source / immutable-folder / source-linked / for_each rejections.

Co-authored-by: Isaac <no-reply@databricks.com>

@ben-hansen-db ben-hansen-db left a comment

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.

I think PR description could be a bit more clear. We are basically reverting the other PR right? That's the the majority of code changes are?

}), nil
// artifactKey is a stable, unique artifact name for a code directory (relative to the
// bundle). Two tasks pointing at the same directory collapse to one artifact.
func artifactKey(relDir string) string {

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.

from claude:

Issue: artifactKey maps every non-alphanumeric to _, so ./a/b and ./a_b both produce air_code_source_a_b. artifacts[key] (:85) + maps.Copy (:118) collapse them to one tarball; both tasks' code_source_path point at it, so one task silently ships the other's code.
Fix: Add a hash disambiguator to the key, or error on a collision across distinct relDirs

@vinchenzo-db

Copy link
Copy Markdown
Contributor Author

I think PR description could be a bit more clear. We are basically reverting the other PR right? That's the the majority of code changes are?

Yeah that's the idea + using new code uploader + keeping some of the old guardrails

artifactKey sanitizes non-alphanumerics to '_', so distinct code_source
directories ("a/b" and "a_b") could collide on one key and collapse into a
single tarball — silently shipping one task's code for another. Detect the
collision across distinct directories and error instead.

Co-authored-by: Isaac <no-reply@databricks.com>
Comment thread bundle/phases/initialize.go Outdated
// path. Runs before artifacts.Prepare so the synthesized artifact is prepared
// and built like any other. Remote values and local files are left untouched.
aicode.PackageCodeSource(),

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.

Can you move this next to aicode.Validate()?

// under .databricks (transient, not synced) so the built file is uploaded once via the
// artifact path and never swept into a sync or into the archive it produces.
const codeArtifactOutputDir = ".databricks/air_code_source"

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.

You could use b.CacheDir() instead of a const.

It resolves to the ~same and is guaranteed to not be swept up in sync.

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.

No literal b.CacheDir() here, the equivalent seems to be b.GetLocalStateDir, but it has the env.TempDir override, which can resolve outside the sync root.

diags = diags.Extend(diag.FromErr(err))
return diags
relDir := strings.TrimPrefix(filepath.ToSlash(cs.value), "./")
key := artifactKey(relDir)

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.

It might be nice to use the job name and task key in the filename instead of the src directory.

When combined, they are unique for this bundle.

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.

I kept the src-dir–based key on purpose: it dedups a code dir shared across tasks to a single tarball/upload, which matters for a multitask DAG where the tasks share one (potentially large like research or universe) code source. Job+task naming would re-upload identical code per task.

Per review, place the two aicode mutators adjacent. Still runs before
artifacts.Prepare; ApplyArtifactsDynamicVersion only touches whl artifacts, so
the intervening reorder does not affect the synthesized tgz.

Co-authored-by: Isaac <no-reply@databricks.com>
@vinchenzo-db
vinchenzo-db added this pull request to the merge queue Sep 3, 2026
@eng-dev-ecosystem-bot

Copy link
Copy Markdown
Collaborator

Integration test report

Commit: 9a051f0

Run: 33785863864

Env 💚​RECOVERED 🙈​SKIP ✅​pass 🙈​skip Time
💚​ aws linux 1 1 274 1220 5:33
💚​ aws windows 1 1 276 1218 4:05
💚​ azure linux 1 1 273 1220 6:42
💚​ azure windows 1 1 275 1218 5:48
💚​ gcp linux 1 1 274 1220 6:07
💚​ gcp windows 1 1 276 1218 5:00
Test Name aws linux aws windows azure linux azure windows gcp linux gcp windows
💚​ TestAccept 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R
🙈​ TestAccept/ssh/connection 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
Top 6 slowest tests (at least 2 minutes):
duration env testname
4:37 azure windows TestAccept
4:23 gcp windows TestAccept
4:01 aws windows TestAccept
2:12 aws linux TestAccept
2:05 gcp linux TestAccept
2:03 azure linux TestAccept

Merged via the queue into main with commit 8d2500f Sep 3, 2026
36 checks passed
@vinchenzo-db
vinchenzo-db deleted the vchen/air-code-source-via-artifact branch September 3, 2026 18:19
@eng-dev-ecosystem-bot

Copy link
Copy Markdown
Collaborator

Integration test report

Commit: 8d2500f

Run: 33789858378

Env ❌​FAIL 🟨​KNOWN 🙈​SKIP ✅​pass 🙈​skip Time
❌​ aws linux 39 1 1 1478 985 299:08
❌​ aws windows 25 1 1 1398 1008 331:37
❌​ azure linux 69 1 1 1273 1031 226:34
❌​ azure windows 65 1 1 1183 1054 225:34
❌​ gcp linux 19 1 1 1309 1035 238:48
❌​ gcp windows 22 1 1 1212 1058 241:51
133 interesting tests: 131 FAIL, 1 KNOWN, 1 SKIP
Test Name aws linux aws windows azure linux azure windows gcp linux gcp windows
🟨​ TestAccept 🟨​K 🟨​K 🟨​K 🟨​K 🟨​K 🟨​K
❌​ TestAccept/bundle/deploy/spark-jar-task ❌​F ✅​p ✅​p ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/deploy/spark-jar-task/DATABRICKS_BUNDLE_ENGINE=direct/DMS= ❌​F ✅​p ✅​p ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/deployment/unbind/grants ✅​p ✅​p ✅​p ❌​F ✅​p ✅​p
❌​ TestAccept/bundle/deployment/unbind/grants/DATABRICKS_BUNDLE_ENGINE=terraform/DMS= ✅​p ✅​p ✅​p ❌​F ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent ❌​F ❌​F ❌​F ❌​F ❌​F ❌​F
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=app.yml.tmpl/READPLAN=1 ✅​p ✅​p ❌​F ❌​F ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=catalog.yml.tmpl/READPLAN= ✅​p ✅​p ✅​p ❌​F ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=catalog.yml.tmpl/READPLAN=1 ✅​p ✅​p ✅​p ❌​F ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=cluster.yml.tmpl/READPLAN= ✅​p ❌​F ✅​p ❌​F ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=cluster.yml.tmpl/READPLAN=1 ❌​F ✅​p ✅​p ❌​F ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=cluster_apply_policy_default_values.yml.tmpl/READPLAN= ✅​p ✅​p ✅​p ❌​F ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=cluster_apply_policy_default_values.yml.tmpl/READPLAN=1 ❌​F ✅​p ✅​p ❌​F ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=cluster_policy.yml.tmpl/READPLAN= ✅​p ✅​p ✅​p ❌​F ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=cluster_policy.yml.tmpl/READPLAN=1 ✅​p ✅​p ✅​p ❌​F ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=dashboard.yml.tmpl/READPLAN= ✅​p ✅​p ✅​p ❌​F ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=dashboard.yml.tmpl/READPLAN=1 ✅​p ✅​p ✅​p ❌​F ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=job.yml.tmpl/READPLAN= ✅​p ✅​p ❌​F ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=job_apply_policy_default_values_for_each_task.yml.tmpl/READPLAN= ✅​p ✅​p ✅​p ❌​F ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=job_apply_policy_default_values_for_each_task.yml.tmpl/READPLAN=1 ✅​p ✅​p ✅​p ❌​F ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=job_apply_policy_default_values_job_cluster.yml.tmpl/READPLAN= ✅​p ✅​p ✅​p ❌​F ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=job_apply_policy_default_values_job_cluster.yml.tmpl/READPLAN=1 ✅​p ✅​p ✅​p ❌​F ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=job_apply_policy_default_values_task_cluster.yml.tmpl/READPLAN= ✅​p ✅​p ✅​p ❌​F ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=job_apply_policy_default_values_task_cluster.yml.tmpl/READPLAN=1 ✅​p ✅​p ✅​p ❌​F ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=job_cross_resource_ref.yml.tmpl/READPLAN= ✅​p ✅​p ❌​F ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=job_cross_resource_ref.yml.tmpl/READPLAN=1 ✅​p ✅​p ❌​F ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=job_escaped_refs.yml.tmpl/READPLAN= ✅​p ✅​p ❌​F ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=job_escaped_refs.yml.tmpl/READPLAN=1 ✅​p ✅​p ❌​F ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=job_permission_ref.yml.tmpl/READPLAN= ✅​p ✅​p ❌​F ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=job_permission_ref.yml.tmpl/READPLAN=1 ✅​p ✅​p ❌​F ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=job_pydabs_1000_tasks.yml.tmpl/READPLAN= ✅​p ✅​p ❌​F ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=job_pydabs_10_tasks.yml.tmpl/READPLAN=1 ✅​p ✅​p ❌​F ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=job_run.yml.tmpl/READPLAN= ✅​p ✅​p ❌​F ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=job_run.yml.tmpl/READPLAN=1 ✅​p ✅​p ❌​F ❌​F ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=job_table_update_trigger.yml.tmpl/READPLAN= ✅​p ✅​p ❌​F ❌​F ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=job_table_update_trigger.yml.tmpl/READPLAN=1 ✅​p ✅​p ❌​F ❌​F ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=job_with_depends_on.yml.tmpl/READPLAN= ✅​p ✅​p ❌​F ❌​F ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=job_with_depends_on.yml.tmpl/READPLAN=1 ✅​p ✅​p ❌​F ❌​F ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=job_with_task.yml.tmpl/READPLAN= ✅​p ✅​p ❌​F ❌​F ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=job_with_task.yml.tmpl/READPLAN=1 ✅​p ✅​p ❌​F ❌​F ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=model.yml.tmpl/READPLAN= ✅​p ✅​p ❌​F ❌​F ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=model.yml.tmpl/READPLAN=1 ✅​p ✅​p ❌​F ❌​F ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=model_serving_endpoint.yml.tmpl/READPLAN= ✅​p ✅​p ❌​F ❌​F ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=model_serving_endpoint.yml.tmpl/READPLAN=1 ✅​p ✅​p ❌​F ❌​F ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=model_with_permissions.yml.tmpl/READPLAN= ✅​p ✅​p ❌​F ❌​F ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=model_with_permissions.yml.tmpl/READPLAN=1 ✅​p ✅​p ❌​F ❌​F ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=pipeline.yml.tmpl/READPLAN= ✅​p ✅​p ❌​F ❌​F ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=pipeline.yml.tmpl/READPLAN=1 ✅​p ✅​p ❌​F ❌​F ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=pipeline_allow_duplicate_names.yml.tmpl/READPLAN= ✅​p ✅​p ❌​F ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=pipeline_allow_duplicate_names.yml.tmpl/READPLAN=1 ✅​p ✅​p ❌​F ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=pipeline_apply_policy_default_values.yml.tmpl/READPLAN= ✅​p ✅​p ❌​F ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=pipeline_apply_policy_default_values.yml.tmpl/READPLAN=1 ✅​p ✅​p ❌​F ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=pipeline_config_dots.yml.tmpl/READPLAN= ✅​p ✅​p ❌​F ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=pipeline_config_dots.yml.tmpl/READPLAN=1 ✅​p ✅​p ❌​F ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=registered_model.yml.tmpl/READPLAN= ✅​p ✅​p ❌​F ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=registered_model.yml.tmpl/READPLAN=1 ✅​p ✅​p ❌​F ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=schema.yml.tmpl/READPLAN= ✅​p ✅​p ❌​F ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=schema.yml.tmpl/READPLAN=1 ✅​p ✅​p ❌​F ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=schema_empty_grants.yml.tmpl/READPLAN= ✅​p ✅​p ❌​F ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=schema_empty_grants.yml.tmpl/READPLAN=1 ✅​p ✅​p ❌​F ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=schema_grant_ref.yml.tmpl/READPLAN= ✅​p ✅​p ❌​F ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=schema_grant_ref.yml.tmpl/READPLAN=1 ✅​p ✅​p ❌​F ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=schema_uppercase_name.yml.tmpl/READPLAN= ✅​p ✅​p ❌​F ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=schema_uppercase_name.yml.tmpl/READPLAN=1 ✅​p ✅​p ❌​F ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=secret.yml.tmpl/READPLAN= ❌​F ❌​F ❌​F ❌​F ❌​F ❌​F
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=secret.yml.tmpl/READPLAN=1 ❌​F ❌​F ❌​F ❌​F ❌​F ❌​F
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=secret_scope.yml.tmpl/READPLAN= ✅​p ✅​p ❌​F ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=secret_scope.yml.tmpl/READPLAN=1 ✅​p ✅​p ❌​F ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=secret_scope_default_backend_type.yml.tmpl/READPLAN= ✅​p ✅​p ❌​F ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=secret_scope_default_backend_type.yml.tmpl/READPLAN=1 ✅​p ✅​p ❌​F ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=sql_warehouse.yml.tmpl/READPLAN= ✅​p ✅​p ❌​F ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=vector_search_endpoint.yml.tmpl/READPLAN= ✅​p ✅​p ❌​F ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/invariant/destroy_idempotent ❌​F ❌​F ❌​F ❌​F ❌​F ❌​F
❌​ TestAccept/bundle/invariant/destroy_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=cluster.yml.tmpl/READPLAN= ❌​F ✅​p ✅​p ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/invariant/destroy_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=cluster.yml.tmpl/READPLAN=1 ❌​F ✅​p ✅​p ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/invariant/destroy_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=cluster_apply_policy_default_values.yml.tmpl/READPLAN= ❌​F ✅​p ✅​p ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/invariant/destroy_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=cluster_apply_policy_default_values.yml.tmpl/READPLAN=1 ❌​F ✅​p ✅​p ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/invariant/destroy_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=secret.yml.tmpl/READPLAN= ❌​F ❌​F ❌​F ❌​F ❌​F ❌​F
❌​ TestAccept/bundle/invariant/no_drift ❌​F ❌​F ❌​F ❌​F ❌​F ❌​F
❌​ TestAccept/bundle/invariant/no_drift/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=cluster.yml.tmpl/READPLAN= ❌​F ✅​p ✅​p ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/invariant/no_drift/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=cluster.yml.tmpl/READPLAN=1 ❌​F ✅​p ✅​p ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/invariant/no_drift/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=cluster_apply_policy_default_values.yml.tmpl/READPLAN= ✅​p ❌​F ✅​p ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/invariant/no_drift/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=secret.yml.tmpl/READPLAN= ❌​F ❌​F ❌​F ❌​F ❌​F ❌​F
❌​ TestAccept/bundle/invariant/no_drift/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true/INPUT_CONFIG=cluster.yml.tmpl/READPLAN= ❌​F ✅​p ✅​p ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/invariant/no_drift/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true/INPUT_CONFIG=secret.yml.tmpl/READPLAN= ❌​F ❌​F ❌​F ❌​F ❌​F ❌​F
❌​ TestAccept/bundle/resources/apps/lifecycle-started ✅​p ✅​p ❌​F ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/resources/apps/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct/DMS= ✅​p ✅​p ❌​F ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/resources/cluster_policies/basic ✅​p ✅​p ✅​p ✅​p ❌​F ✅​p
❌​ TestAccept/bundle/resources/cluster_policies/basic/DATABRICKS_BUNDLE_ENGINE=direct/DMS= ✅​p ✅​p ✅​p ✅​p ❌​F ✅​p
❌​ TestAccept/bundle/resources/clusters/deploy/data_security_mode ❌​F ✅​p ✅​p ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/resources/clusters/deploy/data_security_mode/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true ❌​F ✅​p ✅​p ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/resources/clusters/deploy/update-after-create ❌​F ✅​p ✅​p ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/resources/clusters/deploy/update-after-create/DATABRICKS_BUNDLE_ENGINE=direct/DMS= ❌​F ✅​p ✅​p ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/resources/clusters/lifecycle-started ❌​F ❌​F ✅​p ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/resources/clusters/lifecycle-started-toggle ❌​F ❌​F ✅​p ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/resources/clusters/lifecycle-started-toggle/DATABRICKS_BUNDLE_ENGINE=direct/DMS= ✅​p ❌​F ✅​p ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/resources/clusters/lifecycle-started-toggle/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true ❌​F ✅​p ✅​p ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/resources/clusters/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct/DMS= ❌​F ❌​F ✅​p ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/resources/clusters/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true ❌​F ✅​p ✅​p ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/resources/clusters/resize-terminated-fallback ❌​F ✅​p ✅​p ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/resources/clusters/resize-terminated-fallback/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true ❌​F ✅​p ✅​p ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/resources/dashboards/change-parent-path ✅​p ✅​p ✅​p ✅​p ✅​p ❌​F
❌​ TestAccept/bundle/resources/dashboards/change-parent-path/DATABRICKS_BUNDLE_ENGINE=terraform/DMS= ✅​p ✅​p ✅​p ✅​p ✅​p ❌​F
❌​ TestAccept/bundle/resources/registered_models/comment_cleared ✅​p ✅​p ✅​p ❌​F ✅​p ✅​p
❌​ TestAccept/bundle/resources/registered_models/comment_cleared/DATABRICKS_BUNDLE_ENGINE=direct/DMS= ✅​p ✅​p ✅​p ❌​F ✅​p ✅​p
❌​ TestAccept/bundle/resources/registered_models/comment_cleared/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true ✅​p ✅​p ✅​p ❌​F ✅​p ✅​p
❌​ TestAccept/bundle/resources/schemas/auto-approve ✅​p ✅​p ✅​p ❌​F ✅​p ✅​p
❌​ TestAccept/bundle/resources/schemas/auto-approve/DATABRICKS_BUNDLE_ENGINE=direct/DMS= ✅​p ✅​p ✅​p ❌​F ✅​p ✅​p
❌​ TestAccept/bundle/resources/schemas/auto-approve/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true ✅​p ✅​p ✅​p ❌​F ✅​p ✅​p
❌​ TestAccept/bundle/resources/schemas/auto-approve/DATABRICKS_BUNDLE_ENGINE=terraform/DMS= ✅​p ✅​p ✅​p ❌​F ✅​p ✅​p
❌​ TestAccept/bundle/resources/schemas/comment_out_of_band ✅​p ✅​p ✅​p ❌​F ✅​p ✅​p
❌​ TestAccept/bundle/resources/schemas/comment_out_of_band/DATABRICKS_BUNDLE_ENGINE=direct/DMS= ✅​p ✅​p ✅​p ❌​F ✅​p ✅​p
❌​ TestAccept/bundle/resources/schemas/comment_out_of_band/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true ✅​p ✅​p ✅​p ❌​F ✅​p ✅​p
❌​ TestAccept/bundle/resources/secret_scopes/basic ✅​p ✅​p ✅​p ❌​F ✅​p ✅​p
❌​ TestAccept/bundle/resources/secret_scopes/basic/DATABRICKS_BUNDLE_ENGINE=direct/DMS= ✅​p ✅​p ✅​p ❌​F ✅​p ✅​p
❌​ TestAccept/bundle/resources/secret_scopes/basic/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true ✅​p ✅​p ✅​p ❌​F ✅​p ✅​p
❌​ TestAccept/bundle/resources/secret_scopes/basic/DATABRICKS_BUNDLE_ENGINE=terraform/DMS= ✅​p ✅​p ✅​p ❌​F ✅​p ✅​p
❌​ TestAccept/bundle/resources/secrets/basic ❌​F ❌​F ❌​F ❌​F ❌​F ❌​F
❌​ TestAccept/bundle/resources/secrets/basic/DATABRICKS_BUNDLE_ENGINE=direct/DMS= ❌​F ❌​F ❌​F ❌​F ❌​F ❌​F
❌​ TestAccept/bundle/resources/secrets/basic/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true ❌​F ❌​F ❌​F ❌​F ❌​F ❌​F
❌​ TestAccept/bundle/resources/secrets/remove-expire-time ❌​F ❌​F ❌​F ❌​F ❌​F ❌​F
❌​ TestAccept/bundle/resources/secrets/remove-expire-time/DATABRICKS_BUNDLE_ENGINE=direct/DMS= ❌​F ❌​F ❌​F ❌​F ❌​F ❌​F
❌​ TestAccept/bundle/resources/secrets/remove-expire-time/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true ❌​F ❌​F ❌​F ❌​F ❌​F ❌​F
❌​ TestAccept/bundle/resources/secrets/update-expire-time ❌​F ❌​F ❌​F ❌​F ❌​F ❌​F
❌​ TestAccept/bundle/resources/secrets/update-expire-time/DATABRICKS_BUNDLE_ENGINE=direct/DMS= ❌​F ❌​F ❌​F ❌​F ❌​F ❌​F
❌​ TestAccept/bundle/resources/secrets/update-expire-time/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true ❌​F ❌​F ❌​F ❌​F ❌​F ❌​F
❌​ TestAccept/bundle/resources/vector_search_endpoints/drift/recreated_same_name ✅​p ❌​F ❌​F ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/resources/vector_search_endpoints/drift/recreated_same_name/DATABRICKS_BUNDLE_ENGINE=direct/DMS= ✅​p ✅​p ❌​F ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/resources/vector_search_endpoints/drift/recreated_same_name/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true ✅​p ❌​F ✅​p ✅​p ✅​p ✅​p
❌​ TestAccept/bundle/resources/volumes/uppercase-name ✅​p ✅​p ✅​p ✅​p ✅​p ❌​F
❌​ TestAccept/bundle/resources/volumes/uppercase-name/DATABRICKS_BUNDLE_ENGINE=direct/DMS= ✅​p ✅​p ✅​p ✅​p ✅​p ❌​F
🙈​ TestAccept/ssh/connection 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
❌​ TestSyncIncrementalSyncFileToPythonNotebook ✅​p ✅​p ✅​p ✅​p ✅​p ❌​F
Top 50 slowest tests (at least 2 minutes):
duration env testname
41:07 aws windows TestAccept/bundle/deploy/spark-jar-task/DATABRICKS_BUNDLE_ENGINE=direct/DMS=
29:09 aws linux TestAccept/bundle/resources/clusters/resize-terminated-fallback/DATABRICKS_BUNDLE_ENGINE=direct/DMS=
28:08 aws windows TestAccept/bundle/resources/apps/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true
25:25 aws windows TestAccept/bundle/resources/clusters/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true
23:24 aws linux TestAccept/bundle/resources/clusters/lifecycle-started-toggle/DATABRICKS_BUNDLE_ENGINE=direct/DMS=
23:10 aws windows TestAccept/bundle/deploy/spark-jar-task/DATABRICKS_BUNDLE_ENGINE=terraform/DMS=
19:43 aws windows TestAccept/bundle/resources/clusters/deploy/update-after-create/DATABRICKS_BUNDLE_ENGINE=direct/DMS=
19:06 aws windows TestAccept/bundle/invariant/no_drift/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true/INPUT_CONFIG=cluster.yml.tmpl/READPLAN=
17:23 aws windows TestAccept/bundle/invariant/destroy_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=cluster.yml.tmpl/READPLAN=1
15:43 gcp linux TestAccept/bundle/resources/apps/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct/DMS=
15:22 gcp windows TestAccept/bundle/resources/apps/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct/DMS=
15:02 aws windows TestAccept/bundle/resources/clusters/lifecycle-started-toggle/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true
14:18 gcp linux TestAccept/bundle/resources/apps/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true
14:07 gcp windows TestAccept/bundle/resources/apps/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true
12:51 aws linux TestAccept/bundle/resources/clusters/deploy/update-after-create/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true
12:27 aws linux TestAccept/bundle/invariant/no_drift/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true/INPUT_CONFIG=cluster_apply_policy_default_values.yml.tmpl/READPLAN=
12:19 aws windows TestAccept/bundle/resources/clusters/resize-terminated-fallback/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true
12:13 aws windows TestAccept/bundle/resources/clusters/deploy/data_security_mode/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true
12:01 azure windows TestAccept/bundle/resources/clusters/lifecycle-started-toggle/DATABRICKS_BUNDLE_ENGINE=direct/DMS=
11:29 aws windows TestAccept/bundle/resources/clusters/resize-terminated-fallback/DATABRICKS_BUNDLE_ENGINE=direct/DMS=
11:06 aws linux TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=cluster_apply_policy_default_values.yml.tmpl/READPLAN=
10:25 aws linux TestAccept/bundle/resources/clusters/deploy/data_security_mode/DATABRICKS_BUNDLE_ENGINE=direct/DMS=
9:59 gcp windows TestAccept/bundle/resources/clusters/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct/DMS=
9:54 gcp linux TestAccept/bundle/resources/clusters/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct/DMS=
9:46 gcp windows TestAccept/bundle/resources/clusters/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true
9:41 azure windows TestAccept/bundle/resources/apps/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true
9:30 aws windows TestAccept/bundle/resources/clusters/deploy/update-after-create/DATABRICKS_BUNDLE_ENGINE=terraform/DMS=
9:17 aws linux TestAccept/bundle/deploy/spark-jar-task/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true
9:09 aws windows TestAccept/bundle/invariant/no_drift/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=cluster.yml.tmpl/READPLAN=1
8:57 aws linux TestAccept/bundle/deploy/spark-jar-task/DATABRICKS_BUNDLE_ENGINE=terraform/DMS=
8:50 gcp linux TestAccept/bundle/resources/clusters/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true
8:49 aws windows TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=cluster.yml.tmpl/READPLAN=1
8:45 aws windows TestAccept/bundle/invariant/no_drift/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=cluster_apply_policy_default_values.yml.tmpl/READPLAN=1
8:41 aws windows TestAccept/bundle/deploy/spark-jar-task/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true
8:41 aws linux TestAccept/bundle/resources/apps/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true
8:40 aws windows TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=cluster_apply_policy_default_values.yml.tmpl/READPLAN=
8:36 aws linux TestAccept/bundle/resources/clusters/deploy/update-after-create/DATABRICKS_BUNDLE_ENGINE=terraform/DMS=
8:36 azure windows TestAccept/bundle/resources/apps/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct/DMS=
8:23 gcp windows TestAccept/bundle/resources/clusters/lifecycle-started-toggle/DATABRICKS_BUNDLE_ENGINE=direct/DMS=
8:20 aws linux TestAccept/bundle/resources/apps/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct/DMS=
8:17 gcp linux TestAccept/bundle/resources/clusters/deploy/local_ssd_count/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true
8:09 aws windows TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=cluster_apply_policy_default_values.yml.tmpl/READPLAN=1
8:07 gcp linux TestAccept/bundle/resources/apps/lifecycle-started-toggle/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true
8:04 aws windows TestAccept/bundle/resources/clusters/deploy/data_security_mode/DATABRICKS_BUNDLE_ENGINE=direct/DMS=
8:03 azure windows TestAccept/bundle/resources/clusters/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true
8:01 aws windows TestAccept/bundle/resources/apps/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct/DMS=
7:55 gcp linux TestAccept/bundle/resources/clusters/deploy/local_ssd_count/DATABRICKS_BUNDLE_ENGINE=direct/DMS=
7:53 azure linux TestAccept/bundle/resources/apps/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true
7:45 azure linux TestAccept/bundle/resources/clusters/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct/DMS=
7:43 gcp linux TestAccept/bundle/resources/clusters/deploy/simple/DATABRICKS_BUNDLE_ENGINE=direct/DMS=

chenyuem-db pushed a commit to chenyuem-db/cli that referenced this pull request Sep 9, 2026
…abricks#6532)

Basically, remove the aicode mutator entirely. That way
`convert-to-dabs` just calls the `artifacts` block. Clean up the code.

Reverts the user-facing local-dir shorthand from databricks#6110 / databricks#6494.

## Changes
<!-- Brief summary of your changes that is easy to understand -->

## Why
We should simplify the UJ to limit ways to upload code.

## Tests
Setup
```
# v.chen at ip-10-90-19-147 in ~ (git:) [19:17:23]
$ cd ~/.worktrees/cli-rm-aicode && go build -o /tmp/dbcli-rmaicode .
# v.chen at ip-10-90-19-147 in ~/.worktrees/cli-rm-aicode (git:vchen/air-rm-aicode-mutator) [19:17:24]
$ mkdir -p ~/air-rmaicode-e2e/src && cd ~/air-rmaicode-e2e

cat > run.yaml <<'EOF'
experiment_name: rmaicode-e2e
command: cd "$CODE_SOURCE_PATH" && python train.py
compute:
  accelerator_type: GPU_1xA10
  num_accelerators: 1
environment:
  version: 5
  dependencies:
    - numpy
code_source:
  type: snapshot
  snapshot:
    root_path: ./src
EOF

cat > src/train.py <<'EOF'
import os, mlflow
print("hello from delivered code_source", flush=True)
print("CODE_SOURCE_PATH=" + os.environ.get("CODE_SOURCE_PATH", "<unset>"), flush=True)
mlflow.log_metric("ok", 1)
print("done", flush=True)
EOF
```

Run convert-to-dabs:
```
$ /tmp/dbcli-rmaicode experimental air convert-to-dabs run.yaml --force                                                                                     
cat databricks.yml                                      
Wrote a Databricks Asset Bundle to .:
  databricks.yml
  generated_artifacts/training_config.yaml
  generated_artifacts/command.sh

To deploy and run this workload as a bundle:
  1. /tmp/dbcli-rmaicode bundle validate
  2. /tmp/dbcli-rmaicode bundle deploy
  3. /tmp/dbcli-rmaicode bundle run rmaicode-e2e --no-wait

bundle deploy uploads the code source and launch scripts automatically.
To see what it deployed and where: /tmp/dbcli-rmaicode bundle summary

Unlike `air run` (which submits an ephemeral run), bundle deploy creates a
persistent job that is not garbage-collected. When you are done, remove the
job and its uploaded files with:
  /tmp/dbcli-rmaicode bundle destroy
bundle:
  name: rmaicode-e2e
sync:
  paths:
    - generated_artifacts
artifacts:
  code_source:
    type: tgz
    path: .
    include:
      - src
    files:
      - source: ./dist/code_source.tgz
targets:
  dev:
    mode: development
    default: true
resources:
  jobs:
    rmaicode-e2e:
      name: rmaicode-e2e
      tasks:
        - task_key: rmaicode-e2e
          environment_key: default
          max_retries: 3
          ai_runtime_task:
            experiment: rmaicode-e2e
            deployments:
              - command_path: ./generated_artifacts/command.sh
                compute:
                  accelerator_type: GPU_1xA10
                  accelerator_count: 1
            code_source_path: ./dist/code_source.tgz
      environments:
        - environment_key: default
          spec:
            environment_version: "5"
            dependencies:
              - numpy
```
Validate and deploy:
```
$ /tmp/dbcli-rmaicode bundle validate -t dev -p e2-dogfood                                                                      
/tmp/dbcli-rmaicode bundle deploy   -t dev -p e2-dogfood
Name: rmaicode-e2e
Target: dev
Workspace:
  User: v.chen@databricks.com
  Path: /Workspace/Users/v.chen@databricks.com/.bundle/rmaicode-e2e/dev

Validation OK!
Building code_source...
Uploading dist/code_source.tgz...
Uploading bundle files to /Workspace/Users/v.chen@databricks.com/.bundle/rmaicode-e2e/dev/files...
Files: 2 uploaded, 0 deleted
Resources: 0 created, 0 changed, 0 deleted, 1 unchanged

```
Run:
```
# v.chen at ip-10-90-19-147 in ~/air-rmaicode-e2e (git:) [19:20:10]
$ JOBID=$(/tmp/dbcli-rmaicode bundle summary -t dev -p e2-dogfood -o json | grep -oE '"id":[^,]*' | head -1 | grep -oE '[0-9]+')
/tmp/dbcli-rmaicode jobs get $JOBID -p e2-dogfood | grep -oE '"code_source_path":[^,]*'
"code_source_path": "/Workspace/Users/v.chen@databricks.com/.bundle/rmaicode-e2e/dev/artifacts/.internal/code_source.tgz"
# v.chen at ip-10-90-19-147 in ~/air-rmaicode-e2e (git:) [19:20:16]
$ /tmp/dbcli-rmaicode bundle run rmaicode-e2e -t dev -p e2-dogfood --no-wait                                                    
Run URL: https://e2-dogfood.staging.cloud.databricks.com/jobs/1103803560415808/runs/174957625358063?o=6051921418418893

```

<img width="1517" height="698" alt="image"
src="https://github.com/user-attachments/assets/bdb5ec8d-5445-4b55-9e75-a0b4db7b45b1"
/>
<img width="1524" height="754" alt="image"
src="https://github.com/user-attachments/assets/de66dc59-ee2d-44f2-9a97-65ed1c7e3d99"
/>

Co-authored-by: Isaac <no-reply@databricks.com>
denik added a commit that referenced this pull request Sep 9, 2026
sync force-includes only the internal dir; the AI Runtime sync overlay was
replaced by a tgz artifact on main (#6494, #6532).
@denik

denik commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

@vinchenzo-db are you going to delete other things added in #6110, such as libs/vfs/overlay.go ?

denik added a commit that referenced this pull request Sep 10, 2026
sync force-includes only the internal dir; the AI Runtime sync overlay was
replaced by a tgz artifact on main (#6494, #6532).
pranshupand-db pushed a commit to pranshupand-db/cli that referenced this pull request Sep 11, 2026
`vfs.Overlay` returned a `Path` that served in-memory files on top of a
real tree. It was added in databricks#6110 (Aug 2026) to inject generated files
into the bundle sync root for AI Runtime `code_source_path`.

Its only caller was removed in databricks#6494 (Sep 2026), which packages the
`code_source` as a tgz artifact instead of a sync overlay. Since then
`Overlay` (and its whole `overlayPath`/`memFile` machinery) has been
reachable only from its own unit tests.

`deadcode -test ./...` doesn't catch this because the test suite keeps
it "live"; it surfaces only when reachability is computed without test
roots.

This pull request and its description were written by Isaac.

Co-authored-by: Isaac <no-reply@databricks.com>
janniklasrose pushed a commit that referenced this pull request Sep 15, 2026
…#6494)

#6110 <- basically reverting this
pr

A local-directory code_source_path is now turned into a `tgz` artifact
and built and uploaded through the standard artifact path, instead of
the aicode mutator splicing a content-addressed tarball onto the sync
root. The tgz artifact is the single packing mechanism.

- aicode.PackageCodeSource now synthesizes a `tgz` artifact per
local-dir code_source_path (path = the dir's parent, include = its
basename, so archive entries nest under the basename for the
/databricks/code_source/<dir> layout) and rewrites code_source_path to
the built tarball. It runs before artifacts.Prepare (initialize) instead
of in the build phase.
- Remove the sync-root overlay, the content-addressed packer
(buildCodeSnapshot), bundle.HasAiRuntimeCodeSnapshot,
bundle.AiCodeSnapshotDir, and the validateSnapshotDir guards that only
existed for the overlay.
- Behavior change: only .gitignore filters the packaged files now; the
bundle-wide sync.include/exclude no longer apply to a code artifact.
- Keep the git_source / immutable-folder / source-linked / for_each
rejections.

## Why
#6428 We
recently merged a DABs native uploader, which supercedes this mutator
workaround

## Tests
Unit tests

E2E test:
Setup:
```
# v.chen at ip-10-90-20-219 in /tmp/pr2-e2e (git:) [18:59:50]
$ cd ~/.worktrees/cli-rmaicode && go build -o /tmp/cli-pr3 . && cd -

rm -rf /tmp/pr3-e2e && mkdir -p /tmp/pr3-e2e/src && cd /tmp/pr3-e2e
printf 'print("train ok")\n' > src/train.py
# hand-authored command.sh cds into the extracted code dir itself
printf 'cd /databricks/code_source/src\npython train.py\n' > src/command.sh
cat > databricks.yml <<'YAML'
bundle:
  name: pr3-code-source-demo
resources:
  jobs:
    train:
      name: "[${bundle.target}] pr3 demo"
      tasks:
        - task_key: train
          environment_key: default
          ai_runtime_task:
            experiment: pr3_demo
            code_source_path: ./src
            deployments:
              - command_path: src/command.sh
                compute: {accelerator_type: GPU_1xA10, accelerator_count: 1}
      environments:
        - environment_key: default
          spec:
            environment_version: "5"
targets:
  dev: {mode: development, default: true}
YAML

export DATABRICKS_CONFIG_PROFILE=e2-dogfood DATA
/tmp/pr2-e2e
# v.chen at ip-10-90-20-219 in /tmp/pr3-e2e (git:) [18:59:59]
$ /tmp/cli-pr3 bundle deploy
Building air_code_source_src...
Uploading .databricks/air_code_source/air_code_source_src.tar.gz...
Uploading bundle files to /Workspace/Users/v.chen@databricks.com/.bundle/pr3-code-source-demo/dev/files...
Created jobs.train
Files: 3 uploaded, 0 deleted
Resources: 1 created, 0 changed, 0 deleted, 0 unchanged
```
Show deploy works:
```
# v.chen at ip-10-90-20-219 in /tmp/pr3-e2e (git:) [19:00:14]
$ /tmp/cli-pr3 bundle deploy
Building air_code_source_src...
Uploading .databricks/air_code_source/air_code_source_src.tar.gz...
Uploading bundle files to /Workspace/Users/v.chen@databricks.com/.bundle/pr3-code-source-demo/dev/files...
Files: 0 uploaded, 0 deleted
Resources: 0 created, 0 changed, 0 deleted, 1 unchanged
# v.chen at ip-10-90-20-219 in /tmp/pr3-e2e (git:) [19:01:00]
```
Investigate what is in tar:
```
$ tar tzf .databricks/air_code_source/air_code_source_src.tar.gz
src/command.sh
src/train.py
# v.chen at ip-10-90-20-219 in /tmp/pr3-e2e (git:) [19:01:29]
$ 
```
bundle summary:
```
$ /tmp/cli-pr3 bundle summary
Name: pr3-code-source-demo
Target: dev
Workspace:
  User: v.chen@databricks.com
  Path: /Workspace/Users/v.chen@databricks.com/.bundle/pr3-code-source-demo/dev
Resources:
  Jobs:
    train:
      Name: [dev v_chen] [dev] pr3 demo
      URL:  https://e2-dogfood.staging.cloud.databricks.com/jobs/1015159229445184?w=6051921418418893
# v.chen at ip-10-90-20-219 in /tmp/pr3-e2e (git:) [19:01:51]
$ 
```
bundle run:
```
$ /tmp/cli-pr3 bundle run train --no-wait
Run URL: https://e2-dogfood.staging.cloud.databricks.com/jobs/1015159229445184/runs/174551477706538?o=6051921418418893
```

Run details:
<img width="1512" height="821" alt="image"
src="https://github.com/user-attachments/assets/b18e41ce-f861-42be-b247-b5af50b6ce43"
/>
<img width="1495" height="672" alt="image"
src="https://github.com/user-attachments/assets/193f8e8e-97c0-4e0b-a12f-e5671c19f102"
/>

---------

Co-authored-by: Isaac <no-reply@databricks.com>
janniklasrose pushed a commit that referenced this pull request Sep 15, 2026
Basically, remove the aicode mutator entirely. That way
`convert-to-dabs` just calls the `artifacts` block. Clean up the code.

Reverts the user-facing local-dir shorthand from #6110 / #6494.

## Changes
<!-- Brief summary of your changes that is easy to understand -->

## Why
We should simplify the UJ to limit ways to upload code.

## Tests
Setup
```
# v.chen at ip-10-90-19-147 in ~ (git:) [19:17:23]
$ cd ~/.worktrees/cli-rm-aicode && go build -o /tmp/dbcli-rmaicode .
# v.chen at ip-10-90-19-147 in ~/.worktrees/cli-rm-aicode (git:vchen/air-rm-aicode-mutator) [19:17:24]
$ mkdir -p ~/air-rmaicode-e2e/src && cd ~/air-rmaicode-e2e

cat > run.yaml <<'EOF'
experiment_name: rmaicode-e2e
command: cd "$CODE_SOURCE_PATH" && python train.py
compute:
  accelerator_type: GPU_1xA10
  num_accelerators: 1
environment:
  version: 5
  dependencies:
    - numpy
code_source:
  type: snapshot
  snapshot:
    root_path: ./src
EOF

cat > src/train.py <<'EOF'
import os, mlflow
print("hello from delivered code_source", flush=True)
print("CODE_SOURCE_PATH=" + os.environ.get("CODE_SOURCE_PATH", "<unset>"), flush=True)
mlflow.log_metric("ok", 1)
print("done", flush=True)
EOF
```

Run convert-to-dabs:
```
$ /tmp/dbcli-rmaicode experimental air convert-to-dabs run.yaml --force                                                                                     
cat databricks.yml                                      
Wrote a Databricks Asset Bundle to .:
  databricks.yml
  generated_artifacts/training_config.yaml
  generated_artifacts/command.sh

To deploy and run this workload as a bundle:
  1. /tmp/dbcli-rmaicode bundle validate
  2. /tmp/dbcli-rmaicode bundle deploy
  3. /tmp/dbcli-rmaicode bundle run rmaicode-e2e --no-wait

bundle deploy uploads the code source and launch scripts automatically.
To see what it deployed and where: /tmp/dbcli-rmaicode bundle summary

Unlike `air run` (which submits an ephemeral run), bundle deploy creates a
persistent job that is not garbage-collected. When you are done, remove the
job and its uploaded files with:
  /tmp/dbcli-rmaicode bundle destroy
bundle:
  name: rmaicode-e2e
sync:
  paths:
    - generated_artifacts
artifacts:
  code_source:
    type: tgz
    path: .
    include:
      - src
    files:
      - source: ./dist/code_source.tgz
targets:
  dev:
    mode: development
    default: true
resources:
  jobs:
    rmaicode-e2e:
      name: rmaicode-e2e
      tasks:
        - task_key: rmaicode-e2e
          environment_key: default
          max_retries: 3
          ai_runtime_task:
            experiment: rmaicode-e2e
            deployments:
              - command_path: ./generated_artifacts/command.sh
                compute:
                  accelerator_type: GPU_1xA10
                  accelerator_count: 1
            code_source_path: ./dist/code_source.tgz
      environments:
        - environment_key: default
          spec:
            environment_version: "5"
            dependencies:
              - numpy
```
Validate and deploy:
```
$ /tmp/dbcli-rmaicode bundle validate -t dev -p e2-dogfood                                                                      
/tmp/dbcli-rmaicode bundle deploy   -t dev -p e2-dogfood
Name: rmaicode-e2e
Target: dev
Workspace:
  User: v.chen@databricks.com
  Path: /Workspace/Users/v.chen@databricks.com/.bundle/rmaicode-e2e/dev

Validation OK!
Building code_source...
Uploading dist/code_source.tgz...
Uploading bundle files to /Workspace/Users/v.chen@databricks.com/.bundle/rmaicode-e2e/dev/files...
Files: 2 uploaded, 0 deleted
Resources: 0 created, 0 changed, 0 deleted, 1 unchanged

```
Run:
```
# v.chen at ip-10-90-19-147 in ~/air-rmaicode-e2e (git:) [19:20:10]
$ JOBID=$(/tmp/dbcli-rmaicode bundle summary -t dev -p e2-dogfood -o json | grep -oE '"id":[^,]*' | head -1 | grep -oE '[0-9]+')
/tmp/dbcli-rmaicode jobs get $JOBID -p e2-dogfood | grep -oE '"code_source_path":[^,]*'
"code_source_path": "/Workspace/Users/v.chen@databricks.com/.bundle/rmaicode-e2e/dev/artifacts/.internal/code_source.tgz"
# v.chen at ip-10-90-19-147 in ~/air-rmaicode-e2e (git:) [19:20:16]
$ /tmp/dbcli-rmaicode bundle run rmaicode-e2e -t dev -p e2-dogfood --no-wait                                                    
Run URL: https://e2-dogfood.staging.cloud.databricks.com/jobs/1103803560415808/runs/174957625358063?o=6051921418418893

```

<img width="1517" height="698" alt="image"
src="https://github.com/user-attachments/assets/bdb5ec8d-5445-4b55-9e75-a0b4db7b45b1"
/>
<img width="1524" height="754" alt="image"
src="https://github.com/user-attachments/assets/de66dc59-ee2d-44f2-9a97-65ed1c7e3d99"
/>

Co-authored-by: Isaac <no-reply@databricks.com>
janniklasrose pushed a commit that referenced this pull request Sep 15, 2026
`vfs.Overlay` returned a `Path` that served in-memory files on top of a
real tree. It was added in #6110 (Aug 2026) to inject generated files
into the bundle sync root for AI Runtime `code_source_path`.

Its only caller was removed in #6494 (Sep 2026), which packages the
`code_source` as a tgz artifact instead of a sync overlay. Since then
`Overlay` (and its whole `overlayPath`/`memFile` machinery) has been
reachable only from its own unit tests.

`deadcode -test ./...` doesn't catch this because the test suite keeps
it "live"; it surfaces only when reachability is computed without test
roots.

This pull request and its description were written by Isaac.

Co-authored-by: Isaac <no-reply@databricks.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants