Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
e347ff0
AIR CLI: address review feedback on renderer, hyperlink, and test config
riddhibhagwat-db Jul 15, 2026
a2b2da8
AIR CLI Integration: `--override` flag functionality (#5926)
riddhibhagwat-db Jul 17, 2026
046a953
AIR CLI: address review feedback on renderer, hyperlink, and test con…
riddhibhagwat-db Jul 17, 2026
861023c
AIR CLI Integration: Logs (`air logs` command) (#5970)
riddhibhagwat-db Jul 24, 2026
5fddda2
AIR CLI: implement `air run --watch` (stream logs until completion) (…
riddhibhagwat-db Jul 29, 2026
2f317bb
Merge main into air-cli (catch-up; 110 commits behind)
vinchenzo-db Jul 29, 2026
0811970
acceptance/air: pin engine matrix to ["direct"] (was [])
vinchenzo-db Jul 30, 2026
9da6a3b
acceptance/localenv: drop 3 stale tests calling removed `local-env` c…
vinchenzo-db Jul 30, 2026
e234419
acceptance/air: regenerate logs out.test.toml for ["direct"] engine
vinchenzo-db Jul 30, 2026
2943f5c
air run: package code_source tarball via DABs artifact upload (#6015)
vinchenzo-db Jul 30, 2026
b632473
regenerate pydabs bundle models after SDK v0.165 catch-up
vinchenzo-db Jul 30, 2026
ed69deb
Revert "regenerate pydabs bundle models after SDK v0.165 catch-up"
vinchenzo-db Jul 30, 2026
9557843
Air cli drop requirements yaml (#6121)
vinchenzo-db Jul 31, 2026
99bf6bf
Revert "Air cli drop requirements yaml (#6121)" (#6151)
riddhibhagwat-db Aug 3, 2026
64e7922
AIR CLI: send dependencies inline, stop uploading requirements.yaml (…
riddhibhagwat-db Aug 3, 2026
bda56d9
AIR CLI Integration: Port Register Image Functionality (#6090)
riddhibhagwat-db Aug 4, 2026
11d3f7f
AIR CLI Migration: resolve usage_policy_name to a policy id (#6152)
riddhibhagwat-db Aug 5, 2026
3a63b11
Revert the libs/cmdio change: keep IsPagerSupported
riddhibhagwat-db Aug 5, 2026
7c1a181
Drop stale .nextchanges fragments resurrected by the main catch-up merge
riddhibhagwat-db Aug 5, 2026
da1b765
Merge main into air-cli (catch-up; 21 commits behind)
riddhibhagwat-db Aug 5, 2026
1fcb3c0
Merge main into air-cli (picks up #6170: Windows aitools test fix)
riddhibhagwat-db Aug 5, 2026
1cce004
AIR CLI Integration: `-h` for yaml configuration (#6239)
riddhibhagwat-db Aug 12, 2026
e8b5d5f
AIR CLI Integration: show environment for AI Runtime runs in `air get…
riddhibhagwat-db Aug 12, 2026
0dd6def
AIR CLI: bring `air run` submit output to parity with the Python CLI …
riddhibhagwat-db Aug 12, 2026
49629a7
air: re-land `air logs --download-to` (restore #6153) (#6259)
riddhibhagwat-db Aug 13, 2026
9b7d263
AIR CLI: style air run submit links as blue underlined hyperlinks
riddhibhagwat-db Aug 13, 2026
9d77fad
AIR CLI Integration: fall back to MLflow when Bricklens returns no lo…
riddhibhagwat-db Aug 13, 2026
2471e2c
AIR CLI Integration: hyperlink Run ID/Experiment, MLflow run name, an…
riddhibhagwat-db Aug 14, 2026
1eafde0
[AIR Validation to Backend] Pre-flight config against ValidateConfig …
riddhibhagwat-db Aug 14, 2026
6d0aab3
AIR CLI Integration: remove requirements file path for config (#6257)
riddhibhagwat-db Aug 14, 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
3 changes: 0 additions & 3 deletions acceptance/experimental/air/cancel/test.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
# This command does not deploy a bundle, so no engine matrix is needed.
EnvMatrix.DATABRICKS_BUNDLE_ENGINE = ["direct"]

# The SDK occasionally probes host reachability with a HEAD request; stub it so
# the test is deterministic.
[[Server]]
Expand Down
110 changes: 110 additions & 0 deletions acceptance/experimental/air/config-help/output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@

=== command help
>>> [CLI] experimental air run --help
Submit a training workload to Databricks serverless GPU compute.

The workload is described by a YAML config file (see --file).

To look up a config field, pass its path to -h:

databricks experimental air run -h config
databricks experimental air run -h config.compute
databricks experimental air run -h config.compute.accelerator_type

The path must be a separate argument: cobra reserves -h as a boolean, so
-h=config.compute and -hconfig.compute are not accepted.

Usage:
databricks experimental air run [flags]

Flags:
--dry-run Validate the config without submitting
-f, --file string Path to the workload YAML config
-h, --help help for run
--idempotency-key string Return the existing run if this key was already used
--override stringArray Override a YAML field, e.g. compute.num_accelerators=8 (repeatable)
--watch Stream logs until the run completes

Global Flags:
--debug enable debug logging
-o, --output type output type: text or json (default text)
-p, --profile string ~/.databrickscfg profile
-t, --target string bundle target to use (if applicable)

=== schema overview
>>> [CLI] experimental air run -h config
config
The run YAML schema. Pass a field path for details, e.g. config.compute.accelerator_type.

Fields:
experiment_name (required) Name of the experiment.
compute (required) Which accelerators to run on and how many.
environment Python dependencies, or a custom Docker image, for the run's runtime.
command (required) Shell command that starts the workload.
env_variables Plain environment variables, as NAME: value.
secrets Environment variables sourced from secrets, as NAME: scope/key.
code_source Local code to upload and make available to the run.
max_retries How many times to retry a failed run.
timeout_minutes Wall-clock limit for the run in minutes.
idempotency_token Reuse token: a repeat submission with the same token returns the existing run instead of starting another.
parameters Free-form values passed through to the workload.
mlflow_run_name Name for the MLflow run.
mlflow_experiment_directory Workspace directory holding the MLflow experiment.
permissions Who may view or manage the run, as a list of principal plus level grants.
usage_policy_name Usage policy to bill the run to, by name.
usage_policy_id Usage policy to bill the run to, by id.

Use "-h config.<field>" for details on a field.

=== nested object lists its fields
>>> [CLI] experimental air run -h config.compute
config.compute
Which accelerators to run on and how many.

Fields:
num_accelerators Total number of GPUs to allocate.
accelerator_type Which accelerator to run on, e.g. GPU_1xA10.

Use "-h config.compute.<field>" for details on a field.

=== leaf field
>>> [CLI] experimental air run -h config.compute.accelerator_type
config.compute.accelerator_type
Which accelerator to run on, e.g. GPU_1xA10. See https://docs.databricks.com/aws/en/machine-learning/ai-runtime/cli/yaml-config#reference for the current list of supported GPU types. Matched case-sensitively.

Type: string
Required: no

=== conditionally required leaf
>>> [CLI] experimental air run -h config.environment.docker_image.url
config.environment.docker_image.url
Fully qualified image URL, e.g. myregistry.io/team/train:v3.

Type: string
Required: when environment.docker_image is set

=== union field reports both accepted shapes
>>> [CLI] experimental air run -h config.code_source.snapshot.git.remote
config.code_source.snapshot.git.remote
No longer supported: the snapshot archives your local copy. Only false is accepted; use commit to pin a revision.

Type: bool or string
Required: no

=== the config. prefix is optional
>>> [CLI] experimental air run -h compute.num_accelerators
config.compute.num_accelerators
Total number of GPUs to allocate. Must be a positive multiple of the accelerator type's per-node GPU count. See https://docs.databricks.com/aws/en/machine-learning/ai-runtime/cli/yaml-config#reference for supported GPU types.

Type: int
Required: no

=== unknown field suggests the near match
>>> [CLI] experimental air run -h config.compute.acclerator_type
Error: unknown config field "config.compute.acclerator_type"; did you mean "accelerator_type"?

fields under "config.compute" are: accelerator_type, num_accelerators

=== free-form map keys are not schema fields
>>> [CLI] experimental air run -h config.parameters.learning_rate
Error: "config.parameters" holds user-defined keys, so "learning_rate" is not part of the schema; see "config.parameters" instead
31 changes: 31 additions & 0 deletions acceptance/experimental/air/config-help/script
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Pin the rendered config field help. Any change to a `help:` struct tag on the
# run YAML schema shows up as a diff here.

# Plain -h must keep documenting the command itself, and advertise the config
# path syntax so the feature is discoverable.
title "command help"
trace $CLI experimental air run --help

title "schema overview"
trace $CLI experimental air run -h config

title "nested object lists its fields"
trace $CLI experimental air run -h config.compute

title "leaf field"
trace $CLI experimental air run -h config.compute.accelerator_type

title "conditionally required leaf"
trace $CLI experimental air run -h config.environment.docker_image.url

title "union field reports both accepted shapes"
trace $CLI experimental air run -h config.code_source.snapshot.git.remote

title "the config. prefix is optional"
trace $CLI experimental air run -h compute.num_accelerators

title "unknown field suggests the near match"
trace $CLI experimental air run -h config.compute.acclerator_type

title "free-form map keys are not schema fields"
trace $CLI experimental air run -h config.parameters.learning_rate
2 changes: 1 addition & 1 deletion acceptance/experimental/air/get-ai-runtime/output.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
│ MLflow Run my-run │
│ User user@example.com │
│ Accelerators 1x A10 │
│ Environment N/A
│ Environment 4
│ │
╰────────────────────────────────────────────────────────────────╯

Expand Down
13 changes: 8 additions & 5 deletions acceptance/experimental/air/get-ai-runtime/test.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
# This command does not deploy a bundle, so no engine matrix is needed.
EnvMatrix.DATABRICKS_BUNDLE_ENGINE = ["direct"]

# On Windows, Git Bash rewrites the leading-/ workspace paths passed to
# `workspace mkdirs`/`import` into C:/... paths; disable that conversion.
[Env]
Expand All @@ -12,8 +9,10 @@ MSYS_NO_PATHCONV = "1"
Pattern = "HEAD /"
Response.Body = ''

# The typed SDK GetRun response: an ai_runtime_task run has no gen_ai_compute_task,
# so the task comes back empty (the SDK has no field for ai_runtime_task).
# The GetRun response for an ai_runtime_task run. It has no gen_ai_compute_task,
# so the Environment cell instead comes from the run's environments[].spec (keyed
# by the task's environment_key), which the typed SDK Run drops — `air get` reads
# it with a raw request, so this route is hit twice (typed GetRun + that request).
[[Server]]
Pattern = "GET /api/2.2/jobs/runs/get"
Response.Body = '''
Expand All @@ -24,12 +23,16 @@ Response.Body = '''
"start_time": 1700000000000,
"end_time": 1700000012000,
"state": {"life_cycle_state": "TERMINATED", "result_state": "SUCCESS"},
"environments": [
{"environment_key": "default", "spec": {"environment_version": "4"}}
],
"tasks": [
{
"task_key": "train",
"run_id": 456,
"attempt_number": 0,
"max_retries": 3,
"environment_key": "default",
"ai_runtime_task": {
"experiment": "my-exp",
"deployments": [
Expand Down
2 changes: 1 addition & 1 deletion acceptance/experimental/air/get/output.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
│ MLflow Run my-run │
│ User user@example.com │
│ Accelerators 1x A10 │
│ Environment ml-runtime-gpu:1.0
│ Environment N/A
│ │
╰────────────────────────────────────────────────────────────────╯

Expand Down
3 changes: 0 additions & 3 deletions acceptance/experimental/air/get/test.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
# This command does not deploy a bundle, so no engine matrix is needed.
EnvMatrix.DATABRICKS_BUNDLE_ENGINE = ["direct"]

# The SDK occasionally probes host reachability with a HEAD request; stub it so
# the test is deterministic.
[[Server]]
Expand Down
21 changes: 21 additions & 0 deletions acceptance/experimental/air/help/output.txt
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,24 @@ Global Flags:
-o, --output type output type: text or json (default text)
-p, --profile string ~/.databrickscfg profile
-t, --target string bundle target to use (if applicable)

=== logs help
>>> [CLI] experimental air logs --help
Stream logs from an active run, or fetch logs from a completed run.

Usage:
databricks experimental air logs JOB_RUN_ID [flags]

Flags:
--download-to string Download all logs to this directory instead of printing
-h, --help help for logs
--lines int For completed runs, print the last N lines (default 10000)
--minutes int Fetch only logs from the last N minutes
--node int Fetch logs from this node
--retry int View logs from a specific retry attempt; -1 means latest (default -1)

Global Flags:
--debug enable debug logging
-o, --output type output type: text or json (default text)
-p, --profile string ~/.databrickscfg profile
-t, --target string bundle target to use (if applicable)
3 changes: 3 additions & 0 deletions acceptance/experimental/air/help/script
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,6 @@ trace $CLI experimental air --help

title "list help"
trace $CLI experimental air list --help

title "logs help"
trace $CLI experimental air logs --help
2 changes: 0 additions & 2 deletions acceptance/experimental/air/help/test.toml

This file was deleted.

8 changes: 4 additions & 4 deletions acceptance/experimental/air/list/output.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@

=== list (text)
>>> [CLI] experimental air list
Run ID Experiment Status Started Duration MLflow User Accelerators
[NUMID] qwen-train ● SUCCESS [TIMESTAMP] 12s …/runs/run1 [USERNAME] 8x H100
Run ID Experiment Status Started Duration MLflow User Accelerators
[NUMID] qwen-train ● SUCCESS [TIMESTAMP] 12s qwen-train-001 [USERNAME] 8x H100

=== list (json)
>>> [CLI] experimental air list -o json
Expand All @@ -25,8 +25,8 @@

=== list --all-status (text, via AiTrainingService index)
>>> [CLI] experimental air list --all-status
Run ID Experiment Status Started Duration MLflow User Accelerators
[NUMID] qwen-train ● SUCCESS [TIMESTAMP] 12s …/runs/run1 [USERNAME] 8x H100
Run ID Experiment Status Started Duration MLflow User Accelerators
[NUMID] qwen-train ● SUCCESS [TIMESTAMP] 12s qwen-train-001 [USERNAME] 8x H100

=== list --all-status (json)
>>> [CLI] experimental air list --all-status -o json
Expand Down
16 changes: 13 additions & 3 deletions acceptance/experimental/air/list/test.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
# This command does not deploy a bundle, so no engine matrix is needed.
EnvMatrix.DATABRICKS_BUNDLE_ENGINE = ["direct"]

# Disable the on-disk run cache so --all-status output is deterministic across runs.
[Env]
DATABRICKS_CACHE_ENABLED = "false"
Expand Down Expand Up @@ -64,6 +61,19 @@ Response.Body = '''
{"training_workflows": [{"job_run_id": "334747067049496", "submit_time": "2024-06-05T17:32:39Z"}]}
'''

# MLflow run names (for the MLflow column label) are fetched per AIR run (text mode).
[[Server]]
Pattern = "GET /api/2.0/mlflow/runs/get"
Response.Body = '''
{
"run": {
"info": {
"run_name": "qwen-train-001"
}
}
}
'''

# runs/get hydrates one index id into the same shape as a runs/list element.
[[Server]]
Pattern = "GET /api/2.2/jobs/runs/get"
Expand Down
3 changes: 3 additions & 0 deletions acceptance/experimental/air/logs-download/out.test.toml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions acceptance/experimental/air/logs-download/output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@

=== download-to reports no logs when none are available
>>> [CLI] experimental air logs 123 --download-to dl-logs
No logs available for run 123. Run terminated in state SUCCESS

=== download-to with an out-of-range node is rejected
>>> [CLI] experimental air logs 123 --download-to dl-logs --node 5
Error: invalid --node 5: run has 2 node(s), indexed 0 to 1

Exit code: 1

=== download-to cannot be combined with --lines
>>> [CLI] experimental air logs 123 --download-to dl-logs --lines 50
Error: --download-to writes complete logs, so it cannot be combined with --lines or --minutes

Exit code: 1
12 changes: 12 additions & 0 deletions acceptance/experimental/air/logs-download/script
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# --download-to resolves the run's node count, then downloads each node's logs.
# This run resolves no MLflow run id, so it reports no logs (the full byte
# download is covered by unit tests, since the pre-signed URL host is dynamic).

title "download-to reports no logs when none are available"
errcode trace $CLI experimental air logs 123 --download-to dl-logs

title "download-to with an out-of-range node is rejected"
errcode trace $CLI experimental air logs 123 --download-to dl-logs --node 5

title "download-to cannot be combined with --lines"
errcode trace $CLI experimental air logs 123 --download-to dl-logs --lines 50
40 changes: 40 additions & 0 deletions acceptance/experimental/air/logs-download/test.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# The command creates this download directory; don't treat it as test output.
Ignore = ["dl-logs"]

# The SDK occasionally probes host reachability with a HEAD request; stub it so
# the test is deterministic.
[[Server]]
Pattern = "HEAD /"
Response.Body = ''

# A completed 2-node run (GPU_1xA10 x 2 = 2 nodes).
[[Server]]
Pattern = "GET /api/2.2/jobs/runs/get"
Response.Body = '''
{
"run_id": 123,
"start_time": 1700000000000,
"end_time": 1700000012000,
"state": {"life_cycle_state": "TERMINATED", "result_state": "SUCCESS"},
"tasks": [
{
"task_key": "train",
"run_id": 456,
"attempt_number": 0,
"ai_runtime_task": {
"experiment": "dl-exp",
"deployments": [
{"command_path": "/x/command.sh", "compute": {"accelerator_type": "GPU_1xA10", "accelerator_count": 2}}
]
}
}
]
}
'''

# No MLflow run id resolvable, so the download reports no logs rather than
# attempting a (host-dynamic) pre-signed artifact fetch. The full download path
# is covered by unit tests.
[[Server]]
Pattern = "GET /api/2.2/jobs/runs/get-output"
Response.Body = '{}'

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions acceptance/experimental/air/logs-mlflow-fallback/output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@

=== logs falls back to mlflow (no logs)
>>> [CLI] experimental air logs 123
No logs available for run 123. Run terminated in state SUCCESS

=== logs falls back to mlflow (json)
>>> [CLI] experimental air logs 123 -o json
{"type":"ERROR","ts":"[TIMESTAMP]","node":0,"line":"No logs available for run 123. Run terminated in state SUCCESS"}
9 changes: 9 additions & 0 deletions acceptance/experimental/air/logs-mlflow-fallback/script
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Bricklens is gated off (FEATURE_DISABLED), so the command falls back to the
# MLflow log path. With no MLflow run id resolvable, the fallback reports no
# logs and exits non-zero — proving the try/catch routes to MLflow.

title "logs falls back to mlflow (no logs)"
errcode trace $CLI experimental air logs 123

title "logs falls back to mlflow (json)"
errcode trace $CLI experimental air logs 123 -o json
Loading