From b7781f3ee188f93893361ea1aa67ec8df8b3d198 Mon Sep 17 00:00:00 2001 From: Rada Kamysheva Date: Mon, 15 Jun 2026 07:18:51 +0000 Subject: [PATCH 01/17] direct: Add preliminary job_runs resource Introduce the job_runs bundle resource backed by the Jobs RunNow API. This is a preliminary skeleton: it wires up the config type, the direct engine resource, registration, and drift handling. Generated schema, validation output, and tests are intentionally left for follow-ups. --- .../config/mutator/resourcemutator/run_as.go | 11 +++ bundle/config/resources.go | 3 + bundle/config/resources/job_run.go | 71 ++++++++++++++ bundle/direct/dresources/all.go | 1 + bundle/direct/dresources/job_run.go | 93 +++++++++++++++++++ bundle/direct/dresources/resources.yml | 66 +++++++++++++ 6 files changed, 245 insertions(+) create mode 100644 bundle/config/resources/job_run.go create mode 100644 bundle/direct/dresources/job_run.go diff --git a/bundle/config/mutator/resourcemutator/run_as.go b/bundle/config/mutator/resourcemutator/run_as.go index 4f5e3ce9036..132f0d1dfa5 100644 --- a/bundle/config/mutator/resourcemutator/run_as.go +++ b/bundle/config/mutator/resourcemutator/run_as.go @@ -126,6 +126,17 @@ func validateRunAs(b *bundle.Bundle) diag.Diagnostics { )) } + // Job runs execute under the triggered job's own identity; the RunNow API + // has no run_as field, so a differing bundle run_as cannot be honored. + if len(b.Config.Resources.JobRuns) > 0 { + diags = diags.Extend(reportRunAsNotSupported( + "job_runs", + b.Config.GetLocation("resources.job_runs"), + b.Config.Workspace.CurrentUser.UserName, + identity, + )) + } + return diags } diff --git a/bundle/config/resources.go b/bundle/config/resources.go index 8d294aef103..cfbfbe9fff5 100644 --- a/bundle/config/resources.go +++ b/bundle/config/resources.go @@ -12,6 +12,7 @@ import ( // Resources defines Databricks resources associated with the bundle. type Resources struct { Jobs map[string]*resources.Job `json:"jobs,omitempty"` + JobRuns map[string]*resources.JobRun `json:"job_runs,omitempty"` Pipelines map[string]*resources.Pipeline `json:"pipelines,omitempty"` Models map[string]*resources.MlflowModel `json:"models,omitempty"` @@ -96,6 +97,7 @@ func (r *Resources) AllResources() []ResourceGroup { descriptions := SupportedResources() return []ResourceGroup{ collectResourceMap(descriptions["jobs"], r.Jobs), + collectResourceMap(descriptions["job_runs"], r.JobRuns), collectResourceMap(descriptions["pipelines"], r.Pipelines), collectResourceMap(descriptions["models"], r.Models), collectResourceMap(descriptions["experiments"], r.Experiments), @@ -157,6 +159,7 @@ func (r *Resources) FindResourceByConfigKey(key string) (ConfigResource, error) func SupportedResources() map[string]resources.ResourceDescription { return map[string]resources.ResourceDescription{ "jobs": (&resources.Job{}).ResourceDescription(), + "job_runs": (&resources.JobRun{}).ResourceDescription(), "pipelines": (&resources.Pipeline{}).ResourceDescription(), "models": (&resources.MlflowModel{}).ResourceDescription(), "experiments": (&resources.MlflowExperiment{}).ResourceDescription(), diff --git a/bundle/config/resources/job_run.go b/bundle/config/resources/job_run.go new file mode 100644 index 00000000000..765a2938df1 --- /dev/null +++ b/bundle/config/resources/job_run.go @@ -0,0 +1,71 @@ +package resources + +import ( + "context" + "net/url" + "strconv" + + "github.com/databricks/cli/libs/log" + "github.com/databricks/databricks-sdk-go" + "github.com/databricks/databricks-sdk-go/marshal" + "github.com/databricks/databricks-sdk-go/service/jobs" +) + +// JobRun is the bundle config for a triggered job run. The run is described by +// the same fields as the Jobs RunNow API request, so we embed jobs.RunNow +// directly instead of re-declaring them. +type JobRun struct { + BaseResource + jobs.RunNow +} + +func (r *JobRun) UnmarshalJSON(b []byte) error { + return marshal.Unmarshal(b, r) +} + +func (r JobRun) MarshalJSON() ([]byte, error) { + return marshal.Marshal(r) +} + +// Exists reports whether the run identified by id (a numeric run id) still +// exists in the workspace. A run is the unit of existence here: once RunNow has +// been called, the run is retrievable via GetRun for as long as the workspace +// retains its history. +func (r *JobRun) Exists(ctx context.Context, w *databricks.WorkspaceClient, id string) (bool, error) { + runID, err := strconv.ParseInt(id, 10, 64) + if err != nil { + return false, err + } + _, err = w.Jobs.GetRun(ctx, jobs.GetRunRequest{ + RunId: runID, + }) + if err != nil { + log.Debugf(ctx, "job run %s does not exist", id) + return false, err + } + return true, nil +} + +func (r *JobRun) ResourceDescription() ResourceDescription { + return ResourceDescription{ + SingularName: "job_run", + PluralName: "job_runs", + SingularTitle: "Job Run", + PluralTitle: "Job Runs", + } +} + +// GetName returns the in-product name. A run has no user-assigned name, so this +// is empty. +func (r *JobRun) GetName() string { + return "" +} + +func (r *JobRun) GetURL() string { + return r.URL +} + +// InitializeURL is a no-op for now: surfacing a stable run URL is deferred to a +// later milestone. +func (r *JobRun) InitializeURL(_ url.URL) { +} diff --git a/bundle/direct/dresources/all.go b/bundle/direct/dresources/all.go index 4df9dfe58b8..9856e6f979d 100644 --- a/bundle/direct/dresources/all.go +++ b/bundle/direct/dresources/all.go @@ -8,6 +8,7 @@ import ( var SupportedResources = map[string]any{ "jobs": (*ResourceJob)(nil), + "job_runs": (*ResourceJobRun)(nil), "pipelines": (*ResourcePipeline)(nil), "experiments": (*ResourceExperiment)(nil), "catalogs": (*ResourceCatalog)(nil), diff --git a/bundle/direct/dresources/job_run.go b/bundle/direct/dresources/job_run.go new file mode 100644 index 00000000000..4e9dfe47a49 --- /dev/null +++ b/bundle/direct/dresources/job_run.go @@ -0,0 +1,93 @@ +package dresources + +import ( + "context" + "fmt" + "strconv" + + "github.com/databricks/cli/bundle/config/resources" + "github.com/databricks/databricks-sdk-go" + "github.com/databricks/databricks-sdk-go/marshal" + "github.com/databricks/databricks-sdk-go/service/jobs" +) + +// JobRunRemote is the return type for DoRead. It embeds jobs.RunNow so that +// every field of the state type (jobs.RunNow) is also a valid path in the +// remote type, as required by the framework. GetRun does not echo back the +// RunNow request, so the embedded RunNow is left zero on read; the actual +// remote identity lives in RunId. Drift on the embedded request fields is +// suppressed via ignore_remote_changes in resources.yml. +type JobRunRemote struct { + jobs.RunNow + + RunId int64 `json:"run_id,omitempty"` +} + +func (s *JobRunRemote) UnmarshalJSON(b []byte) error { + return marshal.Unmarshal(b, s) +} + +func (s JobRunRemote) MarshalJSON() ([]byte, error) { + return marshal.Marshal(s) +} + +type ResourceJobRun struct { + client *databricks.WorkspaceClient +} + +func (*ResourceJobRun) New(client *databricks.WorkspaceClient) *ResourceJobRun { + return &ResourceJobRun{ + client: client, + } +} + +func (*ResourceJobRun) PrepareState(input *resources.JobRun) *jobs.RunNow { + return &input.RunNow +} + +func (*ResourceJobRun) RemapState(remote *JobRunRemote) *jobs.RunNow { + return &remote.RunNow +} + +func (r *ResourceJobRun) DoRead(ctx context.Context, id string) (*JobRunRemote, error) { + runID, err := parseRunID(id) + if err != nil { + return nil, err + } + run, err := r.client.Jobs.GetRun(ctx, jobs.GetRunRequest{ + RunId: runID, + }) + if err != nil { + return nil, err + } + return &JobRunRemote{RunId: run.RunId}, nil +} + +func (r *ResourceJobRun) DoCreate(ctx context.Context, config *jobs.RunNow) (string, *JobRunRemote, error) { + // RunNow returns immediately with the new run id; waiting for completion is + // a later milestone. + wait, err := r.client.Jobs.RunNow(ctx, *config) + if err != nil { + return "", nil, err + } + return strconv.FormatInt(wait.RunId, 10), nil, nil +} + +// DoUpdate is intentionally not implemented: there is no API to modify a run in +// place. Every request field is marked recreate_on_changes in resources.yml, so +// any config change goes through delete + create (a fresh RunNow). + +// DoDelete is a no-op: a triggered run cannot be "undeployed". On recreate the +// framework calls this before DoCreate, so a no-op delete followed by RunNow +// re-triggers the run, which is the intended behavior. +func (r *ResourceJobRun) DoDelete(ctx context.Context, id string, _ *jobs.RunNow) error { + return nil +} + +func parseRunID(id string) (int64, error) { + result, err := strconv.ParseInt(id, 10, 64) + if err != nil { + return 0, fmt.Errorf("internal error: run id is not integer: %q: %w", id, err) + } + return result, nil +} diff --git a/bundle/direct/dresources/resources.yml b/bundle/direct/dresources/resources.yml index 624e0eb580f..cf850d8851b 100644 --- a/bundle/direct/dresources/resources.yml +++ b/bundle/direct/dresources/resources.yml @@ -116,6 +116,72 @@ resources: - field: tasks[*].new_cluster.data_security_mode - field: job_clusters[*].new_cluster.data_security_mode + job_runs: + # GetRun returns the run's execution metadata, never the RunNow request that + # triggered it. So on every plan the request fields look like remote drift. + # Ignore that drift (input_only): the request fields are write-only inputs. + ignore_remote_changes: + - field: dbt_commands + reason: input_only + - field: idempotency_token + reason: input_only + - field: jar_params + reason: input_only + - field: job_id + reason: input_only + - field: job_parameters + reason: input_only + - field: notebook_params + reason: input_only + - field: only + reason: input_only + - field: performance_target + reason: input_only + - field: pipeline_params + reason: input_only + - field: python_named_params + reason: input_only + - field: python_params + reason: input_only + - field: queue + reason: input_only + - field: spark_submit_params + reason: input_only + - field: sql_params + reason: input_only + # There is no API to modify a run in place, so any change to the request must + # re-trigger a fresh run. With no DoUpdate, recreate (no-op delete + RunNow) + # is the only path; every request field is marked immutable here. + recreate_on_changes: + - field: dbt_commands + reason: immutable + - field: idempotency_token + reason: immutable + - field: jar_params + reason: immutable + - field: job_id + reason: immutable + - field: job_parameters + reason: immutable + - field: notebook_params + reason: immutable + - field: only + reason: immutable + - field: performance_target + reason: immutable + - field: pipeline_params + reason: immutable + - field: python_named_params + reason: immutable + - field: python_params + reason: immutable + - field: queue + reason: immutable + - field: spark_submit_params + reason: immutable + - field: sql_params + reason: immutable + pipelines: recreate_on_changes: - field: storage From 2d12f1d03f112163057b433955694952f81cfbae Mon Sep 17 00:00:00 2001 From: Rada Kamysheva Date: Mon, 15 Jun 2026 10:53:39 +0000 Subject: [PATCH 02/17] direct: Generate job_runs bundle schema Run the schema generator for the new job_runs resource and add real descriptions for the job_runs map, JobRun.lifecycle, and JobRun.python_named_params so the required-annotations guard test passes. --- bundle/schema/jsonschema.json | 123 ++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) diff --git a/bundle/schema/jsonschema.json b/bundle/schema/jsonschema.json index 1afe4321798..f63597efd3d 100644 --- a/bundle/schema/jsonschema.json +++ b/bundle/schema/jsonschema.json @@ -992,6 +992,111 @@ } ] }, + "resources.JobRun": { + "oneOf": [ + { + "type": "object", + "properties": { + "dbt_commands": { + "description": "An array of commands to execute for jobs with the dbt task, for example `\"dbt_commands\": [\"dbt deps\", \"dbt seed\", \"dbt deps\", \"dbt seed\", \"dbt run\"]`\n\n⚠ **Deprecation note** Use [job parameters](https://docs.databricks.com/jobs/job-parameters.html#job-parameter-pushdown) to pass information down to tasks.", + "$ref": "#/$defs/slice/string", + "x-databricks-preview": "PRIVATE", + "deprecationMessage": "This field is deprecated", + "doNotSuggest": true, + "deprecated": true + }, + "idempotency_token": { + "description": "An optional token to guarantee the idempotency of job run requests. If a run with the provided token already exists,\nthe request does not create a new run but returns the ID of the existing run instead. If a run with the provided token is deleted,\nan error is returned.\n\nIf you specify the idempotency token, upon failure you can retry until the request succeeds. Databricks guarantees that exactly one run\nis launched with that idempotency token.\n\nThis token must have at most 64 characters.\n\nFor more information, see [How to ensure idempotency for jobs](https://kb.databricks.com/jobs/jobs-idempotency.html).", + "$ref": "#/$defs/string" + }, + "jar_params": { + "description": "A list of parameters for jobs with Spark JAR tasks, for example `\"jar_params\": [\"john doe\", \"35\"]`.\nThe parameters are used to invoke the main function of the main class specified in the Spark JAR task.\nIf not specified upon `run-now`, it defaults to an empty list.\njar_params cannot be specified in conjunction with notebook_params.\nThe JSON representation of this field (for example `{\"jar_params\":[\"john doe\",\"35\"]}`) cannot exceed 10,000 bytes.\n\n⚠ **Deprecation note** Use [job parameters](https://docs.databricks.com/jobs/job-parameters.html#job-parameter-pushdown) to pass information down to tasks.", + "$ref": "#/$defs/slice/string", + "x-databricks-preview": "PRIVATE", + "deprecationMessage": "This field is deprecated", + "doNotSuggest": true, + "deprecated": true + }, + "job_id": { + "description": "The ID of the job to be executed", + "$ref": "#/$defs/int64" + }, + "job_parameters": { + "description": "Job-level parameters used in the run. for example `\"param\": \"overriding_val\"`", + "$ref": "#/$defs/map/string" + }, + "lifecycle": { + "description": "Lifecycle is a struct that contains the lifecycle settings for a resource. It controls the behavior of the resource when it is deployed or destroyed.", + "$ref": "#/$defs/github.com/databricks/cli/bundle/config/resources.Lifecycle" + }, + "notebook_params": { + "description": "A map from keys to values for jobs with notebook task, for example `\"notebook_params\": {\"name\": \"john doe\", \"age\": \"35\"}`.\nThe map is passed to the notebook and is accessible through the [dbutils.widgets.get](https://docs.databricks.com/dev-tools/databricks-utils.html) function.\n\nIf not specified upon `run-now`, the triggered run uses the job’s base parameters.\n\nnotebook_params cannot be specified in conjunction with jar_params.\n\n⚠ **Deprecation note** Use [job parameters](https://docs.databricks.com/jobs/job-parameters.html#job-parameter-pushdown) to pass information down to tasks.\n\nThe JSON representation of this field (for example `{\"notebook_params\":{\"name\":\"john doe\",\"age\":\"35\"}}`) cannot exceed 10,000 bytes.", + "$ref": "#/$defs/map/string", + "x-databricks-preview": "PRIVATE", + "deprecationMessage": "This field is deprecated", + "doNotSuggest": true, + "deprecated": true + }, + "only": { + "description": "A list of task keys to run inside of the job. If this field is not provided, all tasks in the job will be run.", + "$ref": "#/$defs/slice/string" + }, + "performance_target": { + "description": "The performance mode on a serverless job. The performance target determines the level of compute performance or cost-efficiency for the run. This field overrides the performance target defined on the job level.\n\n* `STANDARD`: Enables cost-efficient execution of serverless workloads.\n* `PERFORMANCE_OPTIMIZED`: Prioritizes fast startup and execution times through rapid scaling and optimized cluster performance.", + "$ref": "#/$defs/github.com/databricks/databricks-sdk-go/service/jobs.PerformanceTarget" + }, + "pipeline_params": { + "description": "Controls whether the pipeline should perform a full refresh", + "$ref": "#/$defs/github.com/databricks/databricks-sdk-go/service/jobs.PipelineParams" + }, + "python_named_params": { + "description": "A map from keys to values for jobs with Python wheel tasks, for example `\"python_named_params\": {\"name\": \"task\", \"data\": \"dbfs:/path/to/data.json\"}`.", + "$ref": "#/$defs/map/string", + "x-databricks-preview": "PRIVATE", + "deprecationMessage": "This field is deprecated", + "doNotSuggest": true, + "deprecated": true + }, + "python_params": { + "description": "A list of parameters for jobs with Python tasks, for example `\"python_params\": [\"john doe\", \"35\"]`.\nThe parameters are passed to Python file as command-line parameters. If specified upon `run-now`, it would overwrite\nthe parameters specified in job setting. The JSON representation of this field (for example `{\"python_params\":[\"john doe\",\"35\"]}`)\ncannot exceed 10,000 bytes.\n\n⚠ **Deprecation note** Use [job parameters](https://docs.databricks.com/jobs/job-parameters.html#job-parameter-pushdown) to pass information down to tasks.\n\nImportant\n\nThese parameters accept only Latin characters (ASCII character set). Using non-ASCII characters returns an error.\nExamples of invalid, non-ASCII characters are Chinese, Japanese kanjis, and emojis.", + "$ref": "#/$defs/slice/string", + "x-databricks-preview": "PRIVATE", + "deprecationMessage": "This field is deprecated", + "doNotSuggest": true, + "deprecated": true + }, + "queue": { + "description": "The queue settings of the run.", + "$ref": "#/$defs/github.com/databricks/databricks-sdk-go/service/jobs.QueueSettings" + }, + "spark_submit_params": { + "description": "A list of parameters for jobs with spark submit task, for example `\"spark_submit_params\": [\"--class\", \"org.apache.spark.examples.SparkPi\"]`.\nThe parameters are passed to spark-submit script as command-line parameters. If specified upon `run-now`, it would overwrite the\nparameters specified in job setting. The JSON representation of this field (for example `{\"python_params\":[\"john doe\",\"35\"]}`)\ncannot exceed 10,000 bytes.\n\n⚠ **Deprecation note** Use [job parameters](https://docs.databricks.com/jobs/job-parameters.html#job-parameter-pushdown) to pass information down to tasks.\n\nImportant\n\nThese parameters accept only Latin characters (ASCII character set). Using non-ASCII characters returns an error.\nExamples of invalid, non-ASCII characters are Chinese, Japanese kanjis, and emojis.", + "$ref": "#/$defs/slice/string", + "x-databricks-preview": "PRIVATE", + "deprecationMessage": "This field is deprecated", + "doNotSuggest": true, + "deprecated": true + }, + "sql_params": { + "description": "A map from keys to values for jobs with SQL task, for example `\"sql_params\": {\"name\": \"john doe\", \"age\": \"35\"}`. The SQL alert task does not support custom parameters.\n\n⚠ **Deprecation note** Use [job parameters](https://docs.databricks.com/jobs/job-parameters.html#job-parameter-pushdown) to pass information down to tasks.", + "$ref": "#/$defs/map/string", + "x-databricks-preview": "PRIVATE", + "deprecationMessage": "This field is deprecated", + "doNotSuggest": true, + "deprecated": true + } + }, + "additionalProperties": false, + "required": [ + "job_id" + ] + }, + { + "type": "string", + "pattern": "\\$\\{(var(\\.\\p{L}+([-_]*[\\p{L}\\p{N}]+)*(\\[[0-9]+\\])*)+)\\}" + } + ] + }, "resources.Lifecycle": { "oneOf": [ { @@ -2880,6 +2985,10 @@ "genie_spaces": { "$ref": "#/$defs/map/github.com/databricks/cli/bundle/config/resources.GenieSpace" }, + "job_runs": { + "description": "The job run definitions for the bundle, where each key is the name of the job run.", + "$ref": "#/$defs/map/github.com/databricks/cli/bundle/config/resources.JobRun" + }, "jobs": { "description": "The job definitions for the bundle, where each key is the name of the job.", "$ref": "#/$defs/map/github.com/databricks/cli/bundle/config/resources.Job", @@ -13256,6 +13365,20 @@ } ] }, + "resources.JobRun": { + "oneOf": [ + { + "type": "object", + "additionalProperties": { + "$ref": "#/$defs/github.com/databricks/cli/bundle/config/resources.JobRun" + } + }, + { + "type": "string", + "pattern": "\\$\\{(var(\\.\\p{L}+([-_]*[\\p{L}\\p{N}]+)*(\\[[0-9]+\\])*)+)\\}" + } + ] + }, "resources.MlflowExperiment": { "oneOf": [ { From 8236aa9b99171b2f420f4605183a0256fad0110e Mon Sep 17 00:00:00 2001 From: Rada Kamysheva Date: Mon, 15 Jun 2026 12:00:21 +0000 Subject: [PATCH 03/17] direct: Generate job_runs required-field validation Regenerate the validation rules so job_runs picks up its required field (job_id) and the performance_target enum. Missing required fields surface as warnings via the existing validate:required mutator. --- bundle/internal/validation/generated/enum_fields.go | 2 ++ bundle/internal/validation/generated/required_fields.go | 3 +++ 2 files changed, 5 insertions(+) diff --git a/bundle/internal/validation/generated/enum_fields.go b/bundle/internal/validation/generated/enum_fields.go index d5f62ac45b8..0509372f157 100644 --- a/bundle/internal/validation/generated/enum_fields.go +++ b/bundle/internal/validation/generated/enum_fields.go @@ -64,6 +64,8 @@ var EnumFields = map[string][]string{ "resources.genie_spaces.*.permissions[*].level": {"CAN_ATTACH_TO", "CAN_BIND", "CAN_CREATE", "CAN_CREATE_APP", "CAN_EDIT", "CAN_EDIT_METADATA", "CAN_MANAGE", "CAN_MANAGE_PRODUCTION_VERSIONS", "CAN_MANAGE_RUN", "CAN_MANAGE_STAGING_VERSIONS", "CAN_MONITOR", "CAN_MONITOR_ONLY", "CAN_QUERY", "CAN_READ", "CAN_RESTART", "CAN_RUN", "CAN_USE", "CAN_VIEW", "CAN_VIEW_METADATA", "IS_OWNER"}, + "resources.job_runs.*.performance_target": {"PERFORMANCE_OPTIMIZED", "STANDARD"}, + "resources.jobs.*.continuous.pause_status": {"PAUSED", "UNPAUSED"}, "resources.jobs.*.continuous.task_retry_mode": {"NEVER", "ON_FAILURE"}, "resources.jobs.*.deployment.kind": {"BUNDLE", "SYSTEM_MANAGED"}, diff --git a/bundle/internal/validation/generated/required_fields.go b/bundle/internal/validation/generated/required_fields.go index 46862290d10..c80a433422c 100644 --- a/bundle/internal/validation/generated/required_fields.go +++ b/bundle/internal/validation/generated/required_fields.go @@ -66,6 +66,9 @@ var RequiredFields = map[string][]string{ "resources.genie_spaces.*.permissions[*]": {"level"}, + "resources.job_runs.*": {"job_id"}, + "resources.job_runs.*.queue": {"enabled"}, + "resources.jobs.*.deployment": {"kind"}, "resources.jobs.*.environments[*]": {"environment_key"}, "resources.jobs.*.git_source": {"git_provider", "git_url"}, From d23fa96779ee112eeb3677f12010fd061af6c0c4 Mon Sep 17 00:00:00 2001 From: Rada Kamysheva Date: Mon, 15 Jun 2026 12:39:15 +0000 Subject: [PATCH 04/17] direct: Add job_runs happy-path acceptance test Deploy a bundle with a job and a job_run referencing it, and assert that exactly one RunNow request is made and the returned run id is stored in state. Restricted to the direct engine since job_runs has no Terraform equivalent. --- .../resources/job_runs/basic/databricks.yml | 15 ++++++++ .../resources/job_runs/basic/out.test.toml | 3 ++ .../resources/job_runs/basic/output.txt | 34 +++++++++++++++++++ .../bundle/resources/job_runs/basic/script | 15 ++++++++ .../bundle/resources/job_runs/basic/test.toml | 4 +++ 5 files changed, 71 insertions(+) create mode 100644 acceptance/bundle/resources/job_runs/basic/databricks.yml create mode 100644 acceptance/bundle/resources/job_runs/basic/out.test.toml create mode 100644 acceptance/bundle/resources/job_runs/basic/output.txt create mode 100644 acceptance/bundle/resources/job_runs/basic/script create mode 100644 acceptance/bundle/resources/job_runs/basic/test.toml diff --git a/acceptance/bundle/resources/job_runs/basic/databricks.yml b/acceptance/bundle/resources/job_runs/basic/databricks.yml new file mode 100644 index 00000000000..5ea02d60dc2 --- /dev/null +++ b/acceptance/bundle/resources/job_runs/basic/databricks.yml @@ -0,0 +1,15 @@ +bundle: + name: job-runs-basic + +resources: + jobs: + my_job: + name: my-job + tasks: + - task_key: main + notebook_task: + notebook_path: /Workspace/test + + job_runs: + my_run: + job_id: ${resources.jobs.my_job.id} diff --git a/acceptance/bundle/resources/job_runs/basic/out.test.toml b/acceptance/bundle/resources/job_runs/basic/out.test.toml new file mode 100644 index 00000000000..e90b6d5d1ba --- /dev/null +++ b/acceptance/bundle/resources/job_runs/basic/out.test.toml @@ -0,0 +1,3 @@ +Local = true +Cloud = false +EnvMatrix.DATABRICKS_BUNDLE_ENGINE = ["direct"] diff --git a/acceptance/bundle/resources/job_runs/basic/output.txt b/acceptance/bundle/resources/job_runs/basic/output.txt new file mode 100644 index 00000000000..5100598f5d9 --- /dev/null +++ b/acceptance/bundle/resources/job_runs/basic/output.txt @@ -0,0 +1,34 @@ + +=== deploy triggers exactly one run +>>> [CLI] bundle deploy +Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/job-runs-basic/default/files... +Deploying resources... +Updating deployment state... +Deployment complete! + +=== exactly one run-now request was made +>>> print_requests.py //jobs/run-now +{ + "method": "POST", + "path": "/api/2.2/jobs/run-now", + "body": { + "job_id": [MY_JOB_ID] + } +} + +=== the triggered run id is stored in state +>>> read_id.py my_run +[MY_RUN_ID] + +>>> read_id.py my_job +[MY_JOB_ID] + +>>> [CLI] bundle destroy --auto-approve +The following resources will be deleted: + delete resources.job_runs.my_run + delete resources.jobs.my_job + +All files and directories at the following location will be deleted: /Workspace/Users/[USERNAME]/.bundle/job-runs-basic/default + +Deleting files... +Destroy complete! diff --git a/acceptance/bundle/resources/job_runs/basic/script b/acceptance/bundle/resources/job_runs/basic/script new file mode 100644 index 00000000000..ce2d8c414e5 --- /dev/null +++ b/acceptance/bundle/resources/job_runs/basic/script @@ -0,0 +1,15 @@ +cleanup() { + trace $CLI bundle destroy --auto-approve + rm out.requests.txt +} +trap cleanup EXIT + +title "deploy triggers exactly one run" +trace $CLI bundle deploy + +title "exactly one run-now request was made" +trace print_requests.py //jobs/run-now + +title "the triggered run id is stored in state" +trace read_id.py my_run +trace read_id.py my_job diff --git a/acceptance/bundle/resources/job_runs/basic/test.toml b/acceptance/bundle/resources/job_runs/basic/test.toml new file mode 100644 index 00000000000..4b94d8b58e9 --- /dev/null +++ b/acceptance/bundle/resources/job_runs/basic/test.toml @@ -0,0 +1,4 @@ +# job_runs is a direct-engine-only resource; the Terraform provider has no +# equivalent, so restrict the matrix to direct. +EnvMatrix.DATABRICKS_BUNDLE_ENGINE = ["direct"] +RecordRequests = true From 7756b6d34521718a83c80e886c2d3c2af9efe2b4 Mon Sep 17 00:00:00 2001 From: Rada Kamysheva Date: Mon, 15 Jun 2026 12:50:09 +0000 Subject: [PATCH 05/17] direct: Add job_runs redeploy acceptance test Verify that changing a job_run's configuration re-triggers the run: after the initial deploy, a config change (job_parameters) causes a second, distinct RunNow request on redeploy via the recreate-on-change path. --- .../job_runs/redeploy/databricks.yml | 17 ++++++ .../resources/job_runs/redeploy/out.test.toml | 3 ++ .../resources/job_runs/redeploy/output.txt | 54 +++++++++++++++++++ .../bundle/resources/job_runs/redeploy/script | 17 ++++++ .../resources/job_runs/redeploy/test.toml | 4 ++ 5 files changed, 95 insertions(+) create mode 100644 acceptance/bundle/resources/job_runs/redeploy/databricks.yml create mode 100644 acceptance/bundle/resources/job_runs/redeploy/out.test.toml create mode 100644 acceptance/bundle/resources/job_runs/redeploy/output.txt create mode 100644 acceptance/bundle/resources/job_runs/redeploy/script create mode 100644 acceptance/bundle/resources/job_runs/redeploy/test.toml diff --git a/acceptance/bundle/resources/job_runs/redeploy/databricks.yml b/acceptance/bundle/resources/job_runs/redeploy/databricks.yml new file mode 100644 index 00000000000..370829ce20c --- /dev/null +++ b/acceptance/bundle/resources/job_runs/redeploy/databricks.yml @@ -0,0 +1,17 @@ +bundle: + name: job-runs-redeploy + +resources: + jobs: + my_job: + name: my-job + tasks: + - task_key: main + notebook_task: + notebook_path: /Workspace/test + + job_runs: + my_run: + job_id: ${resources.jobs.my_job.id} + job_parameters: + env: dev diff --git a/acceptance/bundle/resources/job_runs/redeploy/out.test.toml b/acceptance/bundle/resources/job_runs/redeploy/out.test.toml new file mode 100644 index 00000000000..e90b6d5d1ba --- /dev/null +++ b/acceptance/bundle/resources/job_runs/redeploy/out.test.toml @@ -0,0 +1,3 @@ +Local = true +Cloud = false +EnvMatrix.DATABRICKS_BUNDLE_ENGINE = ["direct"] diff --git a/acceptance/bundle/resources/job_runs/redeploy/output.txt b/acceptance/bundle/resources/job_runs/redeploy/output.txt new file mode 100644 index 00000000000..fb73c865fb9 --- /dev/null +++ b/acceptance/bundle/resources/job_runs/redeploy/output.txt @@ -0,0 +1,54 @@ + +=== initial deploy triggers the first run +>>> [CLI] bundle deploy +Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/job-runs-redeploy/default/files... +Deploying resources... +Updating deployment state... +Deployment complete! + +>>> read_id.py my_job +[MY_JOB_ID] + +>>> print_requests.py //jobs/run-now +{ + "method": "POST", + "path": "/api/2.2/jobs/run-now", + "body": { + "job_id": [MY_JOB_ID], + "job_parameters": { + "env": "dev" + } + } +} + +=== change the run configuration and redeploy +>>> update_file.py databricks.yml env: dev env: prod + +>>> [CLI] bundle deploy +Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/job-runs-redeploy/default/files... +Deploying resources... +Updating deployment state... +Deployment complete! + +=== the config change triggered a second, different run +>>> print_requests.py //jobs/run-now +{ + "method": "POST", + "path": "/api/2.2/jobs/run-now", + "body": { + "job_id": [MY_JOB_ID], + "job_parameters": { + "env": "prod" + } + } +} + +>>> [CLI] bundle destroy --auto-approve +The following resources will be deleted: + delete resources.job_runs.my_run + delete resources.jobs.my_job + +All files and directories at the following location will be deleted: /Workspace/Users/[USERNAME]/.bundle/job-runs-redeploy/default + +Deleting files... +Destroy complete! diff --git a/acceptance/bundle/resources/job_runs/redeploy/script b/acceptance/bundle/resources/job_runs/redeploy/script new file mode 100644 index 00000000000..d712dd7b079 --- /dev/null +++ b/acceptance/bundle/resources/job_runs/redeploy/script @@ -0,0 +1,17 @@ +cleanup() { + trace $CLI bundle destroy --auto-approve + rm out.requests.txt +} +trap cleanup EXIT + +title "initial deploy triggers the first run" +trace $CLI bundle deploy +trace read_id.py my_job +trace print_requests.py //jobs/run-now + +title "change the run configuration and redeploy" +trace update_file.py databricks.yml "env: dev" "env: prod" +trace $CLI bundle deploy + +title "the config change triggered a second, different run" +trace print_requests.py //jobs/run-now diff --git a/acceptance/bundle/resources/job_runs/redeploy/test.toml b/acceptance/bundle/resources/job_runs/redeploy/test.toml new file mode 100644 index 00000000000..4b94d8b58e9 --- /dev/null +++ b/acceptance/bundle/resources/job_runs/redeploy/test.toml @@ -0,0 +1,4 @@ +# job_runs is a direct-engine-only resource; the Terraform provider has no +# equivalent, so restrict the matrix to direct. +EnvMatrix.DATABRICKS_BUNDLE_ENGINE = ["direct"] +RecordRequests = true From e4f1ee9463cf9b124168afa09e32402ad38ab70d Mon Sep 17 00:00:00 2001 From: Rada Kamysheva Date: Mon, 15 Jun 2026 13:23:32 +0000 Subject: [PATCH 06/17] direct: Update resource enumeration tests for job_runs Several reflection/enumeration tests iterate or hardcode the full resource set and were not updated when the job_runs resource was added, leaving CI red. Add job_runs to each: the run_as allResourceTypes list, the permissions unsupportedResources list, the target-mode mock bundle, the Terraform lifecycle skip list (direct-only), a bind fixture + GetRun mock, and a direct CRUD fixture that triggers a run against a newly created job. The CRUD test also treats job_runs as a no-op delete, since a triggered run cannot be undeployed and stays readable afterward. --- .../apply_bundle_permissions_test.go | 1 + .../resourcemutator/apply_target_mode_test.go | 3 ++ .../mutator/resourcemutator/run_as_test.go | 1 + bundle/config/resources_test.go | 6 ++++ bundle/deploy/terraform/lifecycle_test.go | 1 + bundle/direct/dresources/all_test.go | 28 ++++++++++++++++++- 6 files changed, 39 insertions(+), 1 deletion(-) diff --git a/bundle/config/mutator/resourcemutator/apply_bundle_permissions_test.go b/bundle/config/mutator/resourcemutator/apply_bundle_permissions_test.go index 2fbe07b270a..41686b326ac 100644 --- a/bundle/config/mutator/resourcemutator/apply_bundle_permissions_test.go +++ b/bundle/config/mutator/resourcemutator/apply_bundle_permissions_test.go @@ -33,6 +33,7 @@ var unsupportedResources = []string{ "postgres_roles", "postgres_synced_tables", "vector_search_indexes", + "job_runs", } func TestApplyBundlePermissions(t *testing.T) { diff --git a/bundle/config/mutator/resourcemutator/apply_target_mode_test.go b/bundle/config/mutator/resourcemutator/apply_target_mode_test.go index bc3b44cbdca..da9fcab9770 100644 --- a/bundle/config/mutator/resourcemutator/apply_target_mode_test.go +++ b/bundle/config/mutator/resourcemutator/apply_target_mode_test.go @@ -92,6 +92,9 @@ func mockBundle(mode config.Mode) *bundle.Bundle { }, }, }, + JobRuns: map[string]*resources.JobRun{ + "job_run1": {RunNow: jobs.RunNow{JobId: 1234}}, + }, Pipelines: map[string]*resources.Pipeline{ "pipeline1": {CreatePipeline: pipelines.CreatePipeline{Name: "pipeline1", Continuous: true}}, }, diff --git a/bundle/config/mutator/resourcemutator/run_as_test.go b/bundle/config/mutator/resourcemutator/run_as_test.go index 5f98190ecb3..01da5d753f7 100644 --- a/bundle/config/mutator/resourcemutator/run_as_test.go +++ b/bundle/config/mutator/resourcemutator/run_as_test.go @@ -42,6 +42,7 @@ func allResourceTypes(t *testing.T) []string { "experiments", "external_locations", "genie_spaces", + "job_runs", "jobs", "model_serving_endpoints", "models", diff --git a/bundle/config/resources_test.go b/bundle/config/resources_test.go index c5f32267531..2a399284d8d 100644 --- a/bundle/config/resources_test.go +++ b/bundle/config/resources_test.go @@ -159,6 +159,11 @@ func TestResourcesBindSupport(t *testing.T) { JobSettings: jobs.JobSettings{}, }, }, + JobRuns: map[string]*resources.JobRun{ + "my_job_run": { + RunNow: jobs.RunNow{}, + }, + }, Pipelines: map[string]*resources.Pipeline{ "my_pipeline": { CreatePipeline: pipelines.CreatePipeline{}, @@ -336,6 +341,7 @@ func TestResourcesBindSupport(t *testing.T) { ctx := t.Context() m := mocks.NewMockWorkspaceClient(t) m.GetMockJobsAPI().EXPECT().Get(mock.Anything, mock.Anything).Return(nil, nil) + m.GetMockJobsAPI().EXPECT().GetRun(mock.Anything, mock.Anything).Return(nil, nil) m.GetMockPipelinesAPI().EXPECT().Get(mock.Anything, mock.Anything).Return(nil, nil) m.GetMockExperimentsAPI().EXPECT().GetExperiment(mock.Anything, mock.Anything).Return(nil, nil) m.GetMockRegisteredModelsAPI().EXPECT().Get(mock.Anything, mock.Anything).Return(nil, nil) diff --git a/bundle/deploy/terraform/lifecycle_test.go b/bundle/deploy/terraform/lifecycle_test.go index b60bff612c7..248a66c21a9 100644 --- a/bundle/deploy/terraform/lifecycle_test.go +++ b/bundle/deploy/terraform/lifecycle_test.go @@ -18,6 +18,7 @@ func TestConvertLifecycleForAllResources(t *testing.T) { "catalogs", "external_locations", "genie_spaces", + "job_runs", "vector_search_endpoints", "vector_search_indexes", } diff --git a/bundle/direct/dresources/all_test.go b/bundle/direct/dresources/all_test.go index a986ca3ac47..35cc16374f7 100644 --- a/bundle/direct/dresources/all_test.go +++ b/bundle/direct/dresources/all_test.go @@ -319,6 +319,30 @@ var testDeps = map[string]prepareWorkspace{ return testConfig["vector_search_indexes"], nil }, + "job_runs": func(ctx context.Context, client *databricks.WorkspaceClient) (any, error) { + // A run can only be triggered against an existing job, so create one first. + resp, err := client.Jobs.Create(ctx, jobs.CreateJob{ + Name: "job-for-run", + Tasks: []jobs.Task{ + { + TaskKey: "t", + NotebookTask: &jobs.NotebookTask{ + NotebookPath: "/Workspace/Users/user@example.com/notebook", + }, + }, + }, + }) + if err != nil { + return nil, err + } + + return &resources.JobRun{ + RunNow: jobs.RunNow{ + JobId: resp.JobId, + }, + }, nil + }, + "jobs.permissions": func(ctx context.Context, client *databricks.WorkspaceClient) (any, error) { resp, err := client.Jobs.Create(ctx, jobs.CreateJob{ Name: "job-permissions", @@ -1025,7 +1049,9 @@ func testCRUD(t *testing.T, group string, adapter *Adapter, client *databricks.W require.NoError(t, err) } - deleteIsNoop := strings.HasSuffix(group, "permissions") || strings.HasSuffix(group, "grants") + // job_runs has a no-op DoDelete (a triggered run cannot be "undeployed"), so + // the run remains readable after delete, like permissions and grants. + deleteIsNoop := strings.HasSuffix(group, "permissions") || strings.HasSuffix(group, "grants") || group == "job_runs" remoteAfterDelete, err := adapter.DoRead(ctx, createdID) if deleteIsNoop { From 81c0092b195ae6b0edcf06d5c7da5b25d4681e47 Mon Sep 17 00:00:00 2001 From: Rada Kamysheva Date: Mon, 15 Jun 2026 13:44:12 +0000 Subject: [PATCH 07/17] direct: Fix job_runs lint and regenerate stale artifacts Fully populate the GetRunRequest and JobRunRemote literals in job_run.go to satisfy exhaustruct, and regenerate the schema/refschema/apitypes artifacts so the committed job_runs generated files match their generators. --- acceptance/bundle/refschema/out.fields.txt | 39 +++++++++++++++++++ .../direct/dresources/apitypes.generated.yml | 2 + bundle/direct/dresources/job_run.go | 11 +++++- .../direct/dresources/resources.generated.yml | 2 + bundle/schema/jsonschema.json | 14 +++---- 5 files changed, 59 insertions(+), 9 deletions(-) diff --git a/acceptance/bundle/refschema/out.fields.txt b/acceptance/bundle/refschema/out.fields.txt index a6776c50393..3ba064f02f5 100644 --- a/acceptance/bundle/refschema/out.fields.txt +++ b/acceptance/bundle/refschema/out.fields.txt @@ -756,6 +756,45 @@ resources.genie_spaces.*.permissions[*].group_name string ALL resources.genie_spaces.*.permissions[*].level iam.PermissionLevel ALL resources.genie_spaces.*.permissions[*].service_principal_name string ALL resources.genie_spaces.*.permissions[*].user_name string ALL +resources.job_runs.*.dbt_commands []string ALL +resources.job_runs.*.dbt_commands[*] string ALL +resources.job_runs.*.id string INPUT +resources.job_runs.*.idempotency_token string ALL +resources.job_runs.*.jar_params []string ALL +resources.job_runs.*.jar_params[*] string ALL +resources.job_runs.*.job_id int64 ALL +resources.job_runs.*.job_parameters map[string]string ALL +resources.job_runs.*.job_parameters.* string ALL +resources.job_runs.*.lifecycle resources.Lifecycle INPUT +resources.job_runs.*.lifecycle.prevent_destroy bool INPUT +resources.job_runs.*.modified_status string INPUT +resources.job_runs.*.notebook_params map[string]string ALL +resources.job_runs.*.notebook_params.* string ALL +resources.job_runs.*.only []string ALL +resources.job_runs.*.only[*] string ALL +resources.job_runs.*.performance_target jobs.PerformanceTarget ALL +resources.job_runs.*.pipeline_params *jobs.PipelineParams ALL +resources.job_runs.*.pipeline_params.full_refresh bool ALL +resources.job_runs.*.pipeline_params.full_refresh_selection []string ALL +resources.job_runs.*.pipeline_params.full_refresh_selection[*] string ALL +resources.job_runs.*.pipeline_params.refresh_flow_selection []string ALL +resources.job_runs.*.pipeline_params.refresh_flow_selection[*] string ALL +resources.job_runs.*.pipeline_params.refresh_selection []string ALL +resources.job_runs.*.pipeline_params.refresh_selection[*] string ALL +resources.job_runs.*.pipeline_params.reset_checkpoint_selection []string ALL +resources.job_runs.*.pipeline_params.reset_checkpoint_selection[*] string ALL +resources.job_runs.*.python_named_params map[string]string ALL +resources.job_runs.*.python_named_params.* string ALL +resources.job_runs.*.python_params []string ALL +resources.job_runs.*.python_params[*] string ALL +resources.job_runs.*.queue *jobs.QueueSettings ALL +resources.job_runs.*.queue.enabled bool ALL +resources.job_runs.*.run_id int64 REMOTE +resources.job_runs.*.spark_submit_params []string ALL +resources.job_runs.*.spark_submit_params[*] string ALL +resources.job_runs.*.sql_params map[string]string ALL +resources.job_runs.*.sql_params.* string ALL +resources.job_runs.*.url string INPUT resources.jobs.*.budget_policy_id string ALL resources.jobs.*.continuous *jobs.Continuous ALL resources.jobs.*.continuous.pause_status jobs.PauseStatus ALL diff --git a/bundle/direct/dresources/apitypes.generated.yml b/bundle/direct/dresources/apitypes.generated.yml index 8fb3f0117c4..8fc2eec34a0 100644 --- a/bundle/direct/dresources/apitypes.generated.yml +++ b/bundle/direct/dresources/apitypes.generated.yml @@ -20,6 +20,8 @@ external_locations: catalog.CreateExternalLocation genie_spaces: dashboards.GenieUpdateSpaceRequest +job_runs: jobs.RunNow + jobs: jobs.JobSettings model_serving_endpoints: serving.CreateServingEndpoint diff --git a/bundle/direct/dresources/job_run.go b/bundle/direct/dresources/job_run.go index 4e9dfe47a49..4e5f2b37071 100644 --- a/bundle/direct/dresources/job_run.go +++ b/bundle/direct/dresources/job_run.go @@ -55,12 +55,19 @@ func (r *ResourceJobRun) DoRead(ctx context.Context, id string) (*JobRunRemote, return nil, err } run, err := r.client.Jobs.GetRun(ctx, jobs.GetRunRequest{ - RunId: runID, + RunId: runID, + IncludeHistory: false, + IncludeResolvedValues: false, + PageToken: "", + ForceSendFields: nil, }) if err != nil { return nil, err } - return &JobRunRemote{RunId: run.RunId}, nil + // GetRun does not echo back the RunNow request, so the embedded RunNow is + // left zero here; the remote identity lives in RunId. + var emptyRunNow jobs.RunNow + return &JobRunRemote{RunNow: emptyRunNow, RunId: run.RunId}, nil } func (r *ResourceJobRun) DoCreate(ctx context.Context, config *jobs.RunNow) (string, *JobRunRemote, error) { diff --git a/bundle/direct/dresources/resources.generated.yml b/bundle/direct/dresources/resources.generated.yml index d1dab12b17d..e67e7a3282f 100644 --- a/bundle/direct/dresources/resources.generated.yml +++ b/bundle/direct/dresources/resources.generated.yml @@ -176,6 +176,8 @@ resources: - field: etag reason: spec:output_only + # job_runs: no api field behaviors + # jobs: no api field behaviors # model_serving_endpoints: no api field behaviors diff --git a/bundle/schema/jsonschema.json b/bundle/schema/jsonschema.json index f63597efd3d..67b2817b984 100644 --- a/bundle/schema/jsonschema.json +++ b/bundle/schema/jsonschema.json @@ -998,7 +998,7 @@ "type": "object", "properties": { "dbt_commands": { - "description": "An array of commands to execute for jobs with the dbt task, for example `\"dbt_commands\": [\"dbt deps\", \"dbt seed\", \"dbt deps\", \"dbt seed\", \"dbt run\"]`\n\n⚠ **Deprecation note** Use [job parameters](https://docs.databricks.com/jobs/job-parameters.html#job-parameter-pushdown) to pass information down to tasks.", + "description": "[Private Preview] An array of commands to execute for jobs with the dbt task, for example `\"dbt_commands\": [\"dbt deps\", \"dbt seed\", \"dbt deps\", \"dbt seed\", \"dbt run\"]`\n\n⚠ **Deprecation note** Use [job parameters](https://docs.databricks.com/jobs/job-parameters.html#job-parameter-pushdown) to pass information down to tasks.", "$ref": "#/$defs/slice/string", "x-databricks-preview": "PRIVATE", "deprecationMessage": "This field is deprecated", @@ -1010,7 +1010,7 @@ "$ref": "#/$defs/string" }, "jar_params": { - "description": "A list of parameters for jobs with Spark JAR tasks, for example `\"jar_params\": [\"john doe\", \"35\"]`.\nThe parameters are used to invoke the main function of the main class specified in the Spark JAR task.\nIf not specified upon `run-now`, it defaults to an empty list.\njar_params cannot be specified in conjunction with notebook_params.\nThe JSON representation of this field (for example `{\"jar_params\":[\"john doe\",\"35\"]}`) cannot exceed 10,000 bytes.\n\n⚠ **Deprecation note** Use [job parameters](https://docs.databricks.com/jobs/job-parameters.html#job-parameter-pushdown) to pass information down to tasks.", + "description": "[Private Preview] A list of parameters for jobs with Spark JAR tasks, for example `\"jar_params\": [\"john doe\", \"35\"]`.\nThe parameters are used to invoke the main function of the main class specified in the Spark JAR task.\nIf not specified upon `run-now`, it defaults to an empty list.\njar_params cannot be specified in conjunction with notebook_params.\nThe JSON representation of this field (for example `{\"jar_params\":[\"john doe\",\"35\"]}`) cannot exceed 10,000 bytes.\n\n⚠ **Deprecation note** Use [job parameters](https://docs.databricks.com/jobs/job-parameters.html#job-parameter-pushdown) to pass information down to tasks.", "$ref": "#/$defs/slice/string", "x-databricks-preview": "PRIVATE", "deprecationMessage": "This field is deprecated", @@ -1030,7 +1030,7 @@ "$ref": "#/$defs/github.com/databricks/cli/bundle/config/resources.Lifecycle" }, "notebook_params": { - "description": "A map from keys to values for jobs with notebook task, for example `\"notebook_params\": {\"name\": \"john doe\", \"age\": \"35\"}`.\nThe map is passed to the notebook and is accessible through the [dbutils.widgets.get](https://docs.databricks.com/dev-tools/databricks-utils.html) function.\n\nIf not specified upon `run-now`, the triggered run uses the job’s base parameters.\n\nnotebook_params cannot be specified in conjunction with jar_params.\n\n⚠ **Deprecation note** Use [job parameters](https://docs.databricks.com/jobs/job-parameters.html#job-parameter-pushdown) to pass information down to tasks.\n\nThe JSON representation of this field (for example `{\"notebook_params\":{\"name\":\"john doe\",\"age\":\"35\"}}`) cannot exceed 10,000 bytes.", + "description": "[Private Preview] A map from keys to values for jobs with notebook task, for example `\"notebook_params\": {\"name\": \"john doe\", \"age\": \"35\"}`.\nThe map is passed to the notebook and is accessible through the [dbutils.widgets.get](https://docs.databricks.com/dev-tools/databricks-utils.html) function.\n\nIf not specified upon `run-now`, the triggered run uses the job’s base parameters.\n\nnotebook_params cannot be specified in conjunction with jar_params.\n\n⚠ **Deprecation note** Use [job parameters](https://docs.databricks.com/jobs/job-parameters.html#job-parameter-pushdown) to pass information down to tasks.\n\nThe JSON representation of this field (for example `{\"notebook_params\":{\"name\":\"john doe\",\"age\":\"35\"}}`) cannot exceed 10,000 bytes.", "$ref": "#/$defs/map/string", "x-databricks-preview": "PRIVATE", "deprecationMessage": "This field is deprecated", @@ -1050,7 +1050,7 @@ "$ref": "#/$defs/github.com/databricks/databricks-sdk-go/service/jobs.PipelineParams" }, "python_named_params": { - "description": "A map from keys to values for jobs with Python wheel tasks, for example `\"python_named_params\": {\"name\": \"task\", \"data\": \"dbfs:/path/to/data.json\"}`.", + "description": "[Private Preview] A map from keys to values for jobs with Python wheel tasks, for example `\"python_named_params\": {\"name\": \"task\", \"data\": \"dbfs:/path/to/data.json\"}`.", "$ref": "#/$defs/map/string", "x-databricks-preview": "PRIVATE", "deprecationMessage": "This field is deprecated", @@ -1058,7 +1058,7 @@ "deprecated": true }, "python_params": { - "description": "A list of parameters for jobs with Python tasks, for example `\"python_params\": [\"john doe\", \"35\"]`.\nThe parameters are passed to Python file as command-line parameters. If specified upon `run-now`, it would overwrite\nthe parameters specified in job setting. The JSON representation of this field (for example `{\"python_params\":[\"john doe\",\"35\"]}`)\ncannot exceed 10,000 bytes.\n\n⚠ **Deprecation note** Use [job parameters](https://docs.databricks.com/jobs/job-parameters.html#job-parameter-pushdown) to pass information down to tasks.\n\nImportant\n\nThese parameters accept only Latin characters (ASCII character set). Using non-ASCII characters returns an error.\nExamples of invalid, non-ASCII characters are Chinese, Japanese kanjis, and emojis.", + "description": "[Private Preview] A list of parameters for jobs with Python tasks, for example `\"python_params\": [\"john doe\", \"35\"]`.\nThe parameters are passed to Python file as command-line parameters. If specified upon `run-now`, it would overwrite\nthe parameters specified in job setting. The JSON representation of this field (for example `{\"python_params\":[\"john doe\",\"35\"]}`)\ncannot exceed 10,000 bytes.\n\n⚠ **Deprecation note** Use [job parameters](https://docs.databricks.com/jobs/job-parameters.html#job-parameter-pushdown) to pass information down to tasks.\n\nImportant\n\nThese parameters accept only Latin characters (ASCII character set). Using non-ASCII characters returns an error.\nExamples of invalid, non-ASCII characters are Chinese, Japanese kanjis, and emojis.", "$ref": "#/$defs/slice/string", "x-databricks-preview": "PRIVATE", "deprecationMessage": "This field is deprecated", @@ -1070,7 +1070,7 @@ "$ref": "#/$defs/github.com/databricks/databricks-sdk-go/service/jobs.QueueSettings" }, "spark_submit_params": { - "description": "A list of parameters for jobs with spark submit task, for example `\"spark_submit_params\": [\"--class\", \"org.apache.spark.examples.SparkPi\"]`.\nThe parameters are passed to spark-submit script as command-line parameters. If specified upon `run-now`, it would overwrite the\nparameters specified in job setting. The JSON representation of this field (for example `{\"python_params\":[\"john doe\",\"35\"]}`)\ncannot exceed 10,000 bytes.\n\n⚠ **Deprecation note** Use [job parameters](https://docs.databricks.com/jobs/job-parameters.html#job-parameter-pushdown) to pass information down to tasks.\n\nImportant\n\nThese parameters accept only Latin characters (ASCII character set). Using non-ASCII characters returns an error.\nExamples of invalid, non-ASCII characters are Chinese, Japanese kanjis, and emojis.", + "description": "[Private Preview] A list of parameters for jobs with spark submit task, for example `\"spark_submit_params\": [\"--class\", \"org.apache.spark.examples.SparkPi\"]`.\nThe parameters are passed to spark-submit script as command-line parameters. If specified upon `run-now`, it would overwrite the\nparameters specified in job setting. The JSON representation of this field (for example `{\"python_params\":[\"john doe\",\"35\"]}`)\ncannot exceed 10,000 bytes.\n\n⚠ **Deprecation note** Use [job parameters](https://docs.databricks.com/jobs/job-parameters.html#job-parameter-pushdown) to pass information down to tasks.\n\nImportant\n\nThese parameters accept only Latin characters (ASCII character set). Using non-ASCII characters returns an error.\nExamples of invalid, non-ASCII characters are Chinese, Japanese kanjis, and emojis.", "$ref": "#/$defs/slice/string", "x-databricks-preview": "PRIVATE", "deprecationMessage": "This field is deprecated", @@ -1078,7 +1078,7 @@ "deprecated": true }, "sql_params": { - "description": "A map from keys to values for jobs with SQL task, for example `\"sql_params\": {\"name\": \"john doe\", \"age\": \"35\"}`. The SQL alert task does not support custom parameters.\n\n⚠ **Deprecation note** Use [job parameters](https://docs.databricks.com/jobs/job-parameters.html#job-parameter-pushdown) to pass information down to tasks.", + "description": "[Private Preview] A map from keys to values for jobs with SQL task, for example `\"sql_params\": {\"name\": \"john doe\", \"age\": \"35\"}`. The SQL alert task does not support custom parameters.\n\n⚠ **Deprecation note** Use [job parameters](https://docs.databricks.com/jobs/job-parameters.html#job-parameter-pushdown) to pass information down to tasks.", "$ref": "#/$defs/map/string", "x-databricks-preview": "PRIVATE", "deprecationMessage": "This field is deprecated", From c24048ce12d545a4176e8c98b2a27f661a2435b0 Mon Sep 17 00:00:00 2001 From: Rada Kamysheva Date: Mon, 15 Jun 2026 14:28:45 +0000 Subject: [PATCH 08/17] direct: Update completeness tests for job_runs Add job_runs coverage to the two reflection-driven completeness tests: add "job_runs" to the noURL set in TestBundleResourcePluralNamesResolveInWorkspaceURLs (no stable workspace URL yet) and exercise Resources.JobRuns in the StateToBundle test suite. --- bundle/config/resources_test.go | 3 +++ bundle/statemgmt/state_load_test.go | 35 +++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/bundle/config/resources_test.go b/bundle/config/resources_test.go index 2a399284d8d..f23c349035a 100644 --- a/bundle/config/resources_test.go +++ b/bundle/config/resources_test.go @@ -125,6 +125,9 @@ func TestBundleResourcePluralNamesResolveInWorkspaceURLs(t *testing.T) { // Resources that intentionally have no workspace URL. noURL := map[string]bool{ "external_locations": true, + // A job run has no stable workspace URL yet; surfacing one is deferred + // to a later milestone (see JobRun.InitializeURL). + "job_runs": true, "postgres_branches": true, "postgres_databases": true, "postgres_endpoints": true, diff --git a/bundle/statemgmt/state_load_test.go b/bundle/statemgmt/state_load_test.go index 86d7f76f806..313348f30d2 100644 --- a/bundle/statemgmt/state_load_test.go +++ b/bundle/statemgmt/state_load_test.go @@ -27,6 +27,7 @@ func TestStateToBundleEmptyLocalResources(t *testing.T) { state := ExportedResourcesMap{ "resources.jobs.test_job": {ID: "1"}, + "resources.job_runs.test_job_run": {ID: "1"}, "resources.pipelines.test_pipeline": {ID: "1"}, "resources.models.test_mlflow_model": {ID: "1"}, "resources.experiments.test_mlflow_experiment": {ID: "1"}, @@ -63,6 +64,9 @@ func TestStateToBundleEmptyLocalResources(t *testing.T) { assert.Equal(t, "1", config.Resources.Jobs["test_job"].ID) assert.Equal(t, resources.ModifiedStatusDeleted, config.Resources.Jobs["test_job"].ModifiedStatus) + assert.Equal(t, "1", config.Resources.JobRuns["test_job_run"].ID) + assert.Equal(t, resources.ModifiedStatusDeleted, config.Resources.JobRuns["test_job_run"].ModifiedStatus) + assert.Equal(t, "1", config.Resources.Pipelines["test_pipeline"].ID) assert.Equal(t, resources.ModifiedStatusDeleted, config.Resources.Pipelines["test_pipeline"].ModifiedStatus) @@ -158,6 +162,13 @@ func TestStateToBundleEmptyRemoteResources(t *testing.T) { }, }, }, + JobRuns: map[string]*resources.JobRun{ + "test_job_run": { + RunNow: jobs.RunNow{ + JobId: 1234, + }, + }, + }, Pipelines: map[string]*resources.Pipeline{ "test_pipeline": { CreatePipeline: pipelines.CreatePipeline{ @@ -376,6 +387,9 @@ func TestStateToBundleEmptyRemoteResources(t *testing.T) { assert.Empty(t, config.Resources.Jobs["test_job"].ID) assert.Equal(t, resources.ModifiedStatusCreated, config.Resources.Jobs["test_job"].ModifiedStatus) + assert.Empty(t, config.Resources.JobRuns["test_job_run"].ID) + assert.Equal(t, resources.ModifiedStatusCreated, config.Resources.JobRuns["test_job_run"].ModifiedStatus) + assert.Empty(t, config.Resources.Pipelines["test_pipeline"].ID) assert.Equal(t, resources.ModifiedStatusCreated, config.Resources.Pipelines["test_pipeline"].ModifiedStatus) @@ -481,6 +495,18 @@ func TestStateToBundleModifiedResources(t *testing.T) { }, }, }, + JobRuns: map[string]*resources.JobRun{ + "test_job_run": { + RunNow: jobs.RunNow{ + JobId: 1234, + }, + }, + "test_job_run_new": { + RunNow: jobs.RunNow{ + JobId: 5678, + }, + }, + }, Pipelines: map[string]*resources.Pipeline{ "test_pipeline": { CreatePipeline: pipelines.CreatePipeline{ @@ -835,6 +861,8 @@ func TestStateToBundleModifiedResources(t *testing.T) { state := ExportedResourcesMap{ "resources.jobs.test_job": {ID: "1"}, "resources.jobs.test_job_old": {ID: "2"}, + "resources.job_runs.test_job_run": {ID: "1"}, + "resources.job_runs.test_job_run_old": {ID: "2"}, "resources.pipelines.test_pipeline": {ID: "1"}, "resources.pipelines.test_pipeline_old": {ID: "2"}, "resources.models.test_mlflow_model": {ID: "1"}, @@ -896,6 +924,13 @@ func TestStateToBundleModifiedResources(t *testing.T) { assert.Empty(t, config.Resources.Jobs["test_job_new"].ID) assert.Equal(t, resources.ModifiedStatusCreated, config.Resources.Jobs["test_job_new"].ModifiedStatus) + assert.Equal(t, "1", config.Resources.JobRuns["test_job_run"].ID) + assert.Empty(t, config.Resources.JobRuns["test_job_run"].ModifiedStatus) + assert.Equal(t, "2", config.Resources.JobRuns["test_job_run_old"].ID) + assert.Equal(t, resources.ModifiedStatusDeleted, config.Resources.JobRuns["test_job_run_old"].ModifiedStatus) + assert.Empty(t, config.Resources.JobRuns["test_job_run_new"].ID) + assert.Equal(t, resources.ModifiedStatusCreated, config.Resources.JobRuns["test_job_run_new"].ModifiedStatus) + assert.Equal(t, "1", config.Resources.Pipelines["test_pipeline"].ID) assert.Empty(t, config.Resources.Pipelines["test_pipeline"].ModifiedStatus) assert.Equal(t, "2", config.Resources.Pipelines["test_pipeline_old"].ID) From 22802ea03b64dd8650e6779b82d527113bdba358 Mon Sep 17 00:00:00 2001 From: Rada Kamysheva Date: Wed, 17 Jun 2026 12:56:54 +0000 Subject: [PATCH 09/17] direct: Extend job_runs acceptance tests Add a notebook_change acceptance test that verifies editing a job's notebook_path updates the job (jobs/reset) without re-triggering the run, confirming the run only recreates when its own RunNow config changes. Also extend the basic and redeploy tests with plan/summary/validate traces to make the deploy lifecycle visible in the recorded output. --- .../resources/job_runs/basic/output.txt | 56 ++++++++++++++ .../bundle/resources/job_runs/basic/script | 9 +++ .../job_runs/notebook_change/databricks.yml | 17 +++++ .../job_runs/notebook_change/out.test.toml | 3 + .../job_runs/notebook_change/output.txt | 75 +++++++++++++++++++ .../resources/job_runs/notebook_change/script | 20 +++++ .../job_runs/notebook_change/test.toml | 4 + .../resources/job_runs/redeploy/output.txt | 38 ++++++++++ .../bundle/resources/job_runs/redeploy/script | 4 + 9 files changed, 226 insertions(+) create mode 100644 acceptance/bundle/resources/job_runs/notebook_change/databricks.yml create mode 100644 acceptance/bundle/resources/job_runs/notebook_change/out.test.toml create mode 100644 acceptance/bundle/resources/job_runs/notebook_change/output.txt create mode 100644 acceptance/bundle/resources/job_runs/notebook_change/script create mode 100644 acceptance/bundle/resources/job_runs/notebook_change/test.toml diff --git a/acceptance/bundle/resources/job_runs/basic/output.txt b/acceptance/bundle/resources/job_runs/basic/output.txt index 5100598f5d9..d00f7b26559 100644 --- a/acceptance/bundle/resources/job_runs/basic/output.txt +++ b/acceptance/bundle/resources/job_runs/basic/output.txt @@ -1,11 +1,67 @@ === deploy triggers exactly one run +>>> [CLI] bundle validate +Name: job-runs-basic +Target: default +Workspace: + User: [USERNAME] + Path: /Workspace/Users/[USERNAME]/.bundle/job-runs-basic/default + +Validation OK! + +>>> [CLI] bundle plan +create job_runs.my_run +create jobs.my_job + +Plan: 2 to add, 0 to change, 0 to delete, 0 unchanged + +>>> [CLI] bundle summary +Name: job-runs-basic +Target: default +Workspace: + User: [USERNAME] + Path: /Workspace/Users/[USERNAME]/.bundle/job-runs-basic/default +Resources: + Job Runs: + my_run: + Name: + URL: (not deployed) + Jobs: + my_job: + Name: my-job + URL: (not deployed) + >>> [CLI] bundle deploy Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/job-runs-basic/default/files... Deploying resources... Updating deployment state... Deployment complete! +>>> [CLI] bundle deploy +Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/job-runs-basic/default/files... +Deploying resources... +Updating deployment state... +Deployment complete! + +>>> [CLI] bundle plan +Plan: 0 to add, 0 to change, 0 to delete, 2 unchanged + +>>> [CLI] bundle summary +Name: job-runs-basic +Target: default +Workspace: + User: [USERNAME] + Path: /Workspace/Users/[USERNAME]/.bundle/job-runs-basic/default +Resources: + Job Runs: + my_run: + Name: + URL: (not deployed) + Jobs: + my_job: + Name: my-job + URL: [DATABRICKS_URL]/jobs/[MY_JOB_ID]?w=[NUMID] + === exactly one run-now request was made >>> print_requests.py //jobs/run-now { diff --git a/acceptance/bundle/resources/job_runs/basic/script b/acceptance/bundle/resources/job_runs/basic/script index ce2d8c414e5..e9bdc54d706 100644 --- a/acceptance/bundle/resources/job_runs/basic/script +++ b/acceptance/bundle/resources/job_runs/basic/script @@ -5,8 +5,17 @@ cleanup() { trap cleanup EXIT title "deploy triggers exactly one run" +trace $CLI bundle validate +trace $CLI bundle plan +trace $CLI bundle summary trace $CLI bundle deploy +# confirm that redeploy does not trigger a second run +trace $CLI bundle deploy + +trace $CLI bundle plan +trace $CLI bundle summary + title "exactly one run-now request was made" trace print_requests.py //jobs/run-now diff --git a/acceptance/bundle/resources/job_runs/notebook_change/databricks.yml b/acceptance/bundle/resources/job_runs/notebook_change/databricks.yml new file mode 100644 index 00000000000..65eecc64082 --- /dev/null +++ b/acceptance/bundle/resources/job_runs/notebook_change/databricks.yml @@ -0,0 +1,17 @@ +bundle: + name: job-runs-notebook-change + +resources: + jobs: + my_job: + name: my-job + tasks: + - task_key: main + notebook_task: + notebook_path: /Workspace/test + + job_runs: + my_run: + job_id: ${resources.jobs.my_job.id} + job_parameters: + env: dev diff --git a/acceptance/bundle/resources/job_runs/notebook_change/out.test.toml b/acceptance/bundle/resources/job_runs/notebook_change/out.test.toml new file mode 100644 index 00000000000..e90b6d5d1ba --- /dev/null +++ b/acceptance/bundle/resources/job_runs/notebook_change/out.test.toml @@ -0,0 +1,3 @@ +Local = true +Cloud = false +EnvMatrix.DATABRICKS_BUNDLE_ENGINE = ["direct"] diff --git a/acceptance/bundle/resources/job_runs/notebook_change/output.txt b/acceptance/bundle/resources/job_runs/notebook_change/output.txt new file mode 100644 index 00000000000..e256d76bd5d --- /dev/null +++ b/acceptance/bundle/resources/job_runs/notebook_change/output.txt @@ -0,0 +1,75 @@ + +=== initial deploy triggers the first run +>>> [CLI] bundle deploy +Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/job-runs-notebook-change/default/files... +Deploying resources... +Updating deployment state... +Deployment complete! + +>>> print_requests.py //jobs/run-now +{ + "method": "POST", + "path": "/api/2.2/jobs/run-now", + "body": { + "job_id": [NUMID], + "job_parameters": { + "env": "dev" + } + } +} + +=== change the job notebook_path and redeploy +>>> update_file.py databricks.yml notebook_path: /Workspace/test notebook_path: /Workspace/other + +>>> [CLI] bundle deploy +Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/job-runs-notebook-change/default/files... +Deploying resources... +Updating deployment state... +Deployment complete! + +>>> [CLI] bundle plan +Plan: 0 to add, 0 to change, 0 to delete, 2 unchanged + +=== the job was updated with the new notebook_path +>>> print_requests.py --keep //jobs/reset +{ + "method": "POST", + "path": "/api/2.2/jobs/reset", + "body": { + "job_id": [NUMID], + "new_settings": { + "deployment": { + "kind": "BUNDLE", + "metadata_file_path": "/Workspace/Users/[USERNAME]/.bundle/job-runs-notebook-change/default/state/metadata.json" + }, + "edit_mode": "UI_LOCKED", + "format": "MULTI_TASK", + "max_concurrent_runs": 1, + "name": "my-job", + "queue": { + "enabled": true + }, + "tasks": [ + { + "notebook_task": { + "notebook_path": "/Workspace/other" + }, + "task_key": "main" + } + ] + } + } +} + +=== but the run config did not change, so no new run was triggered +>>> print_requests.py //jobs/run-now + +>>> [CLI] bundle destroy --auto-approve +The following resources will be deleted: + delete resources.job_runs.my_run + delete resources.jobs.my_job + +All files and directories at the following location will be deleted: /Workspace/Users/[USERNAME]/.bundle/job-runs-notebook-change/default + +Deleting files... +Destroy complete! diff --git a/acceptance/bundle/resources/job_runs/notebook_change/script b/acceptance/bundle/resources/job_runs/notebook_change/script new file mode 100644 index 00000000000..f6158a14992 --- /dev/null +++ b/acceptance/bundle/resources/job_runs/notebook_change/script @@ -0,0 +1,20 @@ +cleanup() { + trace $CLI bundle destroy --auto-approve + rm out.requests.txt +} +trap cleanup EXIT + +title "initial deploy triggers the first run" +trace $CLI bundle deploy +trace print_requests.py //jobs/run-now + +title "change the job notebook_path and redeploy" +trace update_file.py databricks.yml "notebook_path: /Workspace/test" "notebook_path: /Workspace/other" +trace $CLI bundle deploy +trace $CLI bundle plan + +title "the job was updated with the new notebook_path" +trace print_requests.py --keep //jobs/reset + +title "but the run config did not change, so no new run was triggered" +trace print_requests.py //jobs/run-now diff --git a/acceptance/bundle/resources/job_runs/notebook_change/test.toml b/acceptance/bundle/resources/job_runs/notebook_change/test.toml new file mode 100644 index 00000000000..4b94d8b58e9 --- /dev/null +++ b/acceptance/bundle/resources/job_runs/notebook_change/test.toml @@ -0,0 +1,4 @@ +# job_runs is a direct-engine-only resource; the Terraform provider has no +# equivalent, so restrict the matrix to direct. +EnvMatrix.DATABRICKS_BUNDLE_ENGINE = ["direct"] +RecordRequests = true diff --git a/acceptance/bundle/resources/job_runs/redeploy/output.txt b/acceptance/bundle/resources/job_runs/redeploy/output.txt index fb73c865fb9..7d6c45f74b4 100644 --- a/acceptance/bundle/resources/job_runs/redeploy/output.txt +++ b/acceptance/bundle/resources/job_runs/redeploy/output.txt @@ -6,6 +6,25 @@ Deploying resources... Updating deployment state... Deployment complete! +>>> [CLI] bundle plan +Plan: 0 to add, 0 to change, 0 to delete, 2 unchanged + +>>> [CLI] bundle summary +Name: job-runs-redeploy +Target: default +Workspace: + User: [USERNAME] + Path: /Workspace/Users/[USERNAME]/.bundle/job-runs-redeploy/default +Resources: + Job Runs: + my_run: + Name: + URL: (not deployed) + Jobs: + my_job: + Name: my-job + URL: [DATABRICKS_URL]/jobs/[MY_JOB_ID]?w=[NUMID] + >>> read_id.py my_job [MY_JOB_ID] @@ -30,6 +49,25 @@ Deploying resources... Updating deployment state... Deployment complete! +>>> [CLI] bundle plan +Plan: 0 to add, 0 to change, 0 to delete, 2 unchanged + +>>> [CLI] bundle summary +Name: job-runs-redeploy +Target: default +Workspace: + User: [USERNAME] + Path: /Workspace/Users/[USERNAME]/.bundle/job-runs-redeploy/default +Resources: + Job Runs: + my_run: + Name: + URL: (not deployed) + Jobs: + my_job: + Name: my-job + URL: [DATABRICKS_URL]/jobs/[MY_JOB_ID]?w=[NUMID] + === the config change triggered a second, different run >>> print_requests.py //jobs/run-now { diff --git a/acceptance/bundle/resources/job_runs/redeploy/script b/acceptance/bundle/resources/job_runs/redeploy/script index d712dd7b079..6665c870881 100644 --- a/acceptance/bundle/resources/job_runs/redeploy/script +++ b/acceptance/bundle/resources/job_runs/redeploy/script @@ -6,12 +6,16 @@ trap cleanup EXIT title "initial deploy triggers the first run" trace $CLI bundle deploy +trace $CLI bundle plan +trace $CLI bundle summary trace read_id.py my_job trace print_requests.py //jobs/run-now title "change the run configuration and redeploy" trace update_file.py databricks.yml "env: dev" "env: prod" trace $CLI bundle deploy +trace $CLI bundle plan +trace $CLI bundle summary title "the config change triggered a second, different run" trace print_requests.py //jobs/run-now From 243bc4ae5bfc4c13ba9971663267acb63dc9720e Mon Sep 17 00:00:00 2001 From: Rada Kamysheva Date: Wed, 17 Jun 2026 14:25:49 +0000 Subject: [PATCH 10/17] direct: Address job_runs review feedback Map GetRun fields (job_id, job_parameters, overriding parameters) back into the RunNow shape in DoRead instead of returning an empty RunNow, so the framework can compute a real diff for the run config. Add a job_settings snapshot to the job_run config and state: setting job_settings to a whole-job reference (e.g. ${resources.jobs.my_job}) lets a change to the targeted job re-trigger the run, since the snapshot is marked recreate_on_changes. The notebook_change acceptance test now asserts a notebook_path edit re-triggers the run via this snapshot. Regenerate schema/validation artifacts for the new job_settings field. --- acceptance/bundle/refschema/out.fields.txt | 947 ++++++++++++++++++ .../job_runs/notebook_change/databricks.yml | 2 + .../job_runs/notebook_change/output.txt | 12 +- .../resources/job_runs/notebook_change/script | 2 +- bundle/config/resources/job_run.go | 8 + bundle/direct/dresources/job_run.go | 93 +- bundle/direct/dresources/resources.yml | 33 +- bundle/internal/schema/annotations.yml | 13 + .../validation/generated/enum_fields.go | 67 +- .../validation/generated/required_fields.go | 107 +- bundle/schema/jsonschema.json | 139 ++- libs/testserver/jobs.go | 53 +- 12 files changed, 1415 insertions(+), 61 deletions(-) diff --git a/acceptance/bundle/refschema/out.fields.txt b/acceptance/bundle/refschema/out.fields.txt index 3ba064f02f5..89df2b973bf 100644 --- a/acceptance/bundle/refschema/out.fields.txt +++ b/acceptance/bundle/refschema/out.fields.txt @@ -765,6 +765,953 @@ resources.job_runs.*.jar_params[*] string ALL resources.job_runs.*.job_id int64 ALL resources.job_runs.*.job_parameters map[string]string ALL resources.job_runs.*.job_parameters.* string ALL +resources.job_runs.*.job_settings *jobs.JobSettings ALL +resources.job_runs.*.job_settings.budget_policy_id string ALL +resources.job_runs.*.job_settings.continuous *jobs.Continuous ALL +resources.job_runs.*.job_settings.continuous.pause_status jobs.PauseStatus ALL +resources.job_runs.*.job_settings.continuous.task_retry_mode jobs.TaskRetryMode ALL +resources.job_runs.*.job_settings.deployment *jobs.JobDeployment ALL +resources.job_runs.*.job_settings.deployment.deployment_id string ALL +resources.job_runs.*.job_settings.deployment.kind jobs.JobDeploymentKind ALL +resources.job_runs.*.job_settings.deployment.metadata_file_path string ALL +resources.job_runs.*.job_settings.deployment.version_id string ALL +resources.job_runs.*.job_settings.description string ALL +resources.job_runs.*.job_settings.edit_mode jobs.JobEditMode ALL +resources.job_runs.*.job_settings.email_notifications *jobs.JobEmailNotifications ALL +resources.job_runs.*.job_settings.email_notifications.no_alert_for_skipped_runs bool ALL +resources.job_runs.*.job_settings.email_notifications.on_duration_warning_threshold_exceeded []string ALL +resources.job_runs.*.job_settings.email_notifications.on_duration_warning_threshold_exceeded[*] string ALL +resources.job_runs.*.job_settings.email_notifications.on_failure []string ALL +resources.job_runs.*.job_settings.email_notifications.on_failure[*] string ALL +resources.job_runs.*.job_settings.email_notifications.on_start []string ALL +resources.job_runs.*.job_settings.email_notifications.on_start[*] string ALL +resources.job_runs.*.job_settings.email_notifications.on_streaming_backlog_exceeded []string ALL +resources.job_runs.*.job_settings.email_notifications.on_streaming_backlog_exceeded[*] string ALL +resources.job_runs.*.job_settings.email_notifications.on_success []string ALL +resources.job_runs.*.job_settings.email_notifications.on_success[*] string ALL +resources.job_runs.*.job_settings.environments []jobs.JobEnvironment ALL +resources.job_runs.*.job_settings.environments[*] jobs.JobEnvironment ALL +resources.job_runs.*.job_settings.environments[*].environment_key string ALL +resources.job_runs.*.job_settings.environments[*].spec *compute.Environment ALL +resources.job_runs.*.job_settings.environments[*].spec.base_environment string ALL +resources.job_runs.*.job_settings.environments[*].spec.client string ALL +resources.job_runs.*.job_settings.environments[*].spec.dependencies []string ALL +resources.job_runs.*.job_settings.environments[*].spec.dependencies[*] string ALL +resources.job_runs.*.job_settings.environments[*].spec.environment_version string ALL +resources.job_runs.*.job_settings.environments[*].spec.java_dependencies []string ALL +resources.job_runs.*.job_settings.environments[*].spec.java_dependencies[*] string ALL +resources.job_runs.*.job_settings.format jobs.Format ALL +resources.job_runs.*.job_settings.git_source *jobs.GitSource ALL +resources.job_runs.*.job_settings.git_source.git_branch string ALL +resources.job_runs.*.job_settings.git_source.git_commit string ALL +resources.job_runs.*.job_settings.git_source.git_provider jobs.GitProvider ALL +resources.job_runs.*.job_settings.git_source.git_snapshot *jobs.GitSnapshot ALL +resources.job_runs.*.job_settings.git_source.git_snapshot.used_commit string ALL +resources.job_runs.*.job_settings.git_source.git_tag string ALL +resources.job_runs.*.job_settings.git_source.git_url string ALL +resources.job_runs.*.job_settings.git_source.job_source *jobs.JobSource ALL +resources.job_runs.*.job_settings.git_source.job_source.dirty_state jobs.JobSourceDirtyState ALL +resources.job_runs.*.job_settings.git_source.job_source.import_from_git_branch string ALL +resources.job_runs.*.job_settings.git_source.job_source.job_config_path string ALL +resources.job_runs.*.job_settings.git_source.sparse_checkout *jobs.SparseCheckout ALL +resources.job_runs.*.job_settings.git_source.sparse_checkout.patterns []string ALL +resources.job_runs.*.job_settings.git_source.sparse_checkout.patterns[*] string ALL +resources.job_runs.*.job_settings.health *jobs.JobsHealthRules ALL +resources.job_runs.*.job_settings.health.rules []jobs.JobsHealthRule ALL +resources.job_runs.*.job_settings.health.rules[*] jobs.JobsHealthRule ALL +resources.job_runs.*.job_settings.health.rules[*].metric jobs.JobsHealthMetric ALL +resources.job_runs.*.job_settings.health.rules[*].op jobs.JobsHealthOperator ALL +resources.job_runs.*.job_settings.health.rules[*].value int64 ALL +resources.job_runs.*.job_settings.job_clusters []jobs.JobCluster ALL +resources.job_runs.*.job_settings.job_clusters[*] jobs.JobCluster ALL +resources.job_runs.*.job_settings.job_clusters[*].job_cluster_key string ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster compute.ClusterSpec ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.apply_policy_default_values bool ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.autoscale *compute.AutoScale ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.autoscale.max_workers int ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.autoscale.min_workers int ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.autotermination_minutes int ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.aws_attributes *compute.AwsAttributes ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.aws_attributes.availability compute.AwsAvailability ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.aws_attributes.ebs_volume_count int ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.aws_attributes.ebs_volume_iops int ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.aws_attributes.ebs_volume_size int ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.aws_attributes.ebs_volume_throughput int ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.aws_attributes.ebs_volume_type compute.EbsVolumeType ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.aws_attributes.first_on_demand int ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.aws_attributes.instance_profile_arn string ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.aws_attributes.spot_bid_price_percent int ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.aws_attributes.zone_id string ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.azure_attributes *compute.AzureAttributes ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.azure_attributes.availability compute.AzureAvailability ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.azure_attributes.first_on_demand int ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.azure_attributes.log_analytics_info *compute.LogAnalyticsInfo ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.azure_attributes.log_analytics_info.log_analytics_primary_key string ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.azure_attributes.log_analytics_info.log_analytics_workspace_id string ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.azure_attributes.spot_bid_max_price float64 ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.cluster_log_conf *compute.ClusterLogConf ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.cluster_log_conf.dbfs *compute.DbfsStorageInfo ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.cluster_log_conf.dbfs.destination string ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.cluster_log_conf.s3 *compute.S3StorageInfo ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.cluster_log_conf.s3.canned_acl string ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.cluster_log_conf.s3.destination string ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.cluster_log_conf.s3.enable_encryption bool ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.cluster_log_conf.s3.encryption_type string ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.cluster_log_conf.s3.endpoint string ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.cluster_log_conf.s3.kms_key string ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.cluster_log_conf.s3.region string ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.cluster_log_conf.volumes *compute.VolumesStorageInfo ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.cluster_log_conf.volumes.destination string ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.cluster_name string ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.custom_tags map[string]string ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.custom_tags.* string ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.data_security_mode compute.DataSecurityMode ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.docker_image *compute.DockerImage ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.docker_image.basic_auth *compute.DockerBasicAuth ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.docker_image.basic_auth.password string ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.docker_image.basic_auth.username string ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.docker_image.url string ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.driver_instance_pool_id string ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.driver_node_type_flexibility *compute.NodeTypeFlexibility ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.driver_node_type_flexibility.alternate_node_type_ids []string ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.driver_node_type_flexibility.alternate_node_type_ids[*] string ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.driver_node_type_id string ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.enable_elastic_disk bool ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.enable_local_disk_encryption bool ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.gcp_attributes *compute.GcpAttributes ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.gcp_attributes.availability compute.GcpAvailability ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.gcp_attributes.boot_disk_size int ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.gcp_attributes.confidential_compute_type compute.ConfidentialComputeType ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.gcp_attributes.first_on_demand int ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.gcp_attributes.google_service_account string ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.gcp_attributes.local_ssd_count int ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.gcp_attributes.use_preemptible_executors bool ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.gcp_attributes.zone_id string ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.init_scripts []compute.InitScriptInfo ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.init_scripts[*] compute.InitScriptInfo ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.init_scripts[*].abfss *compute.Adlsgen2Info ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.init_scripts[*].abfss.destination string ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.init_scripts[*].dbfs *compute.DbfsStorageInfo ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.init_scripts[*].dbfs.destination string ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.init_scripts[*].file *compute.LocalFileInfo ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.init_scripts[*].file.destination string ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.init_scripts[*].gcs *compute.GcsStorageInfo ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.init_scripts[*].gcs.destination string ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.init_scripts[*].s3 *compute.S3StorageInfo ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.init_scripts[*].s3.canned_acl string ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.init_scripts[*].s3.destination string ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.init_scripts[*].s3.enable_encryption bool ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.init_scripts[*].s3.encryption_type string ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.init_scripts[*].s3.endpoint string ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.init_scripts[*].s3.kms_key string ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.init_scripts[*].s3.region string ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.init_scripts[*].volumes *compute.VolumesStorageInfo ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.init_scripts[*].volumes.destination string ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.init_scripts[*].workspace *compute.WorkspaceStorageInfo ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.init_scripts[*].workspace.destination string ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.instance_pool_id string ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.is_single_node bool ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.kind compute.Kind ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.node_type_id string ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.num_workers int ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.policy_id string ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.remote_disk_throughput int ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.runtime_engine compute.RuntimeEngine ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.single_user_name string ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.spark_conf map[string]string ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.spark_conf.* string ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.spark_env_vars map[string]string ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.spark_env_vars.* string ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.spark_version string ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.ssh_public_keys []string ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.ssh_public_keys[*] string ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.total_initial_remote_disk_size int ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.use_ml_runtime bool ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.worker_node_type_flexibility *compute.NodeTypeFlexibility ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.worker_node_type_flexibility.alternate_node_type_ids []string ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.worker_node_type_flexibility.alternate_node_type_ids[*] string ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.workload_type *compute.WorkloadType ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.workload_type.clients compute.ClientsTypes ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.workload_type.clients.jobs bool ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.workload_type.clients.notebooks bool ALL +resources.job_runs.*.job_settings.max_concurrent_runs int ALL +resources.job_runs.*.job_settings.name string ALL +resources.job_runs.*.job_settings.notification_settings *jobs.JobNotificationSettings ALL +resources.job_runs.*.job_settings.notification_settings.no_alert_for_canceled_runs bool ALL +resources.job_runs.*.job_settings.notification_settings.no_alert_for_skipped_runs bool ALL +resources.job_runs.*.job_settings.parameters []jobs.JobParameterDefinition ALL +resources.job_runs.*.job_settings.parameters[*] jobs.JobParameterDefinition ALL +resources.job_runs.*.job_settings.parameters[*].default string ALL +resources.job_runs.*.job_settings.parameters[*].name string ALL +resources.job_runs.*.job_settings.performance_target jobs.PerformanceTarget ALL +resources.job_runs.*.job_settings.queue *jobs.QueueSettings ALL +resources.job_runs.*.job_settings.queue.enabled bool ALL +resources.job_runs.*.job_settings.run_as *jobs.JobRunAs ALL +resources.job_runs.*.job_settings.run_as.group_name string ALL +resources.job_runs.*.job_settings.run_as.service_principal_name string ALL +resources.job_runs.*.job_settings.run_as.user_name string ALL +resources.job_runs.*.job_settings.schedule *jobs.CronSchedule ALL +resources.job_runs.*.job_settings.schedule.pause_status jobs.PauseStatus ALL +resources.job_runs.*.job_settings.schedule.quartz_cron_expression string ALL +resources.job_runs.*.job_settings.schedule.timezone_id string ALL +resources.job_runs.*.job_settings.tags map[string]string ALL +resources.job_runs.*.job_settings.tags.* string ALL +resources.job_runs.*.job_settings.tasks []jobs.Task ALL +resources.job_runs.*.job_settings.tasks[*] jobs.Task ALL +resources.job_runs.*.job_settings.tasks[*].alert_task *jobs.AlertTask ALL +resources.job_runs.*.job_settings.tasks[*].alert_task.alert_id string ALL +resources.job_runs.*.job_settings.tasks[*].alert_task.subscribers []jobs.AlertTaskSubscriber ALL +resources.job_runs.*.job_settings.tasks[*].alert_task.subscribers[*] jobs.AlertTaskSubscriber ALL +resources.job_runs.*.job_settings.tasks[*].alert_task.subscribers[*].destination_id string ALL +resources.job_runs.*.job_settings.tasks[*].alert_task.subscribers[*].user_name string ALL +resources.job_runs.*.job_settings.tasks[*].alert_task.warehouse_id string ALL +resources.job_runs.*.job_settings.tasks[*].alert_task.workspace_path string ALL +resources.job_runs.*.job_settings.tasks[*].clean_rooms_notebook_task *jobs.CleanRoomsNotebookTask ALL +resources.job_runs.*.job_settings.tasks[*].clean_rooms_notebook_task.clean_room_name string ALL +resources.job_runs.*.job_settings.tasks[*].clean_rooms_notebook_task.etag string ALL +resources.job_runs.*.job_settings.tasks[*].clean_rooms_notebook_task.notebook_base_parameters map[string]string ALL +resources.job_runs.*.job_settings.tasks[*].clean_rooms_notebook_task.notebook_base_parameters.* string ALL +resources.job_runs.*.job_settings.tasks[*].clean_rooms_notebook_task.notebook_name string ALL +resources.job_runs.*.job_settings.tasks[*].compute *jobs.Compute ALL +resources.job_runs.*.job_settings.tasks[*].compute.hardware_accelerator compute.HardwareAcceleratorType ALL +resources.job_runs.*.job_settings.tasks[*].condition_task *jobs.ConditionTask ALL +resources.job_runs.*.job_settings.tasks[*].condition_task.left string ALL +resources.job_runs.*.job_settings.tasks[*].condition_task.op jobs.ConditionTaskOp ALL +resources.job_runs.*.job_settings.tasks[*].condition_task.right string ALL +resources.job_runs.*.job_settings.tasks[*].dashboard_task *jobs.DashboardTask ALL +resources.job_runs.*.job_settings.tasks[*].dashboard_task.dashboard_id string ALL +resources.job_runs.*.job_settings.tasks[*].dashboard_task.filters map[string]string ALL +resources.job_runs.*.job_settings.tasks[*].dashboard_task.filters.* string ALL +resources.job_runs.*.job_settings.tasks[*].dashboard_task.subscription *jobs.Subscription ALL +resources.job_runs.*.job_settings.tasks[*].dashboard_task.subscription.custom_subject string ALL +resources.job_runs.*.job_settings.tasks[*].dashboard_task.subscription.paused bool ALL +resources.job_runs.*.job_settings.tasks[*].dashboard_task.subscription.subscribers []jobs.SubscriptionSubscriber ALL +resources.job_runs.*.job_settings.tasks[*].dashboard_task.subscription.subscribers[*] jobs.SubscriptionSubscriber ALL +resources.job_runs.*.job_settings.tasks[*].dashboard_task.subscription.subscribers[*].destination_id string ALL +resources.job_runs.*.job_settings.tasks[*].dashboard_task.subscription.subscribers[*].user_name string ALL +resources.job_runs.*.job_settings.tasks[*].dashboard_task.warehouse_id string ALL +resources.job_runs.*.job_settings.tasks[*].dbt_cloud_task *jobs.DbtCloudTask ALL +resources.job_runs.*.job_settings.tasks[*].dbt_cloud_task.connection_resource_name string ALL +resources.job_runs.*.job_settings.tasks[*].dbt_cloud_task.dbt_cloud_job_id int64 ALL +resources.job_runs.*.job_settings.tasks[*].dbt_platform_task *jobs.DbtPlatformTask ALL +resources.job_runs.*.job_settings.tasks[*].dbt_platform_task.connection_resource_name string ALL +resources.job_runs.*.job_settings.tasks[*].dbt_platform_task.dbt_platform_job_id string ALL +resources.job_runs.*.job_settings.tasks[*].dbt_task *jobs.DbtTask ALL +resources.job_runs.*.job_settings.tasks[*].dbt_task.catalog string ALL +resources.job_runs.*.job_settings.tasks[*].dbt_task.commands []string ALL +resources.job_runs.*.job_settings.tasks[*].dbt_task.commands[*] string ALL +resources.job_runs.*.job_settings.tasks[*].dbt_task.profiles_directory string ALL +resources.job_runs.*.job_settings.tasks[*].dbt_task.project_directory string ALL +resources.job_runs.*.job_settings.tasks[*].dbt_task.schema string ALL +resources.job_runs.*.job_settings.tasks[*].dbt_task.source jobs.Source ALL +resources.job_runs.*.job_settings.tasks[*].dbt_task.warehouse_id string ALL +resources.job_runs.*.job_settings.tasks[*].depends_on []jobs.TaskDependency ALL +resources.job_runs.*.job_settings.tasks[*].depends_on[*] jobs.TaskDependency ALL +resources.job_runs.*.job_settings.tasks[*].depends_on[*].outcome string ALL +resources.job_runs.*.job_settings.tasks[*].depends_on[*].task_key string ALL +resources.job_runs.*.job_settings.tasks[*].description string ALL +resources.job_runs.*.job_settings.tasks[*].disable_auto_optimization bool ALL +resources.job_runs.*.job_settings.tasks[*].disabled bool ALL +resources.job_runs.*.job_settings.tasks[*].email_notifications *jobs.TaskEmailNotifications ALL +resources.job_runs.*.job_settings.tasks[*].email_notifications.no_alert_for_skipped_runs bool ALL +resources.job_runs.*.job_settings.tasks[*].email_notifications.on_duration_warning_threshold_exceeded []string ALL +resources.job_runs.*.job_settings.tasks[*].email_notifications.on_duration_warning_threshold_exceeded[*] string ALL +resources.job_runs.*.job_settings.tasks[*].email_notifications.on_failure []string ALL +resources.job_runs.*.job_settings.tasks[*].email_notifications.on_failure[*] string ALL +resources.job_runs.*.job_settings.tasks[*].email_notifications.on_start []string ALL +resources.job_runs.*.job_settings.tasks[*].email_notifications.on_start[*] string ALL +resources.job_runs.*.job_settings.tasks[*].email_notifications.on_streaming_backlog_exceeded []string ALL +resources.job_runs.*.job_settings.tasks[*].email_notifications.on_streaming_backlog_exceeded[*] string ALL +resources.job_runs.*.job_settings.tasks[*].email_notifications.on_success []string ALL +resources.job_runs.*.job_settings.tasks[*].email_notifications.on_success[*] string ALL +resources.job_runs.*.job_settings.tasks[*].environment_key string ALL +resources.job_runs.*.job_settings.tasks[*].existing_cluster_id string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task *jobs.ForEachTask ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.concurrency int ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.inputs string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task jobs.Task ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.alert_task *jobs.AlertTask ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.alert_task.alert_id string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.alert_task.subscribers []jobs.AlertTaskSubscriber ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.alert_task.subscribers[*] jobs.AlertTaskSubscriber ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.alert_task.subscribers[*].destination_id string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.alert_task.subscribers[*].user_name string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.alert_task.warehouse_id string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.alert_task.workspace_path string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.clean_rooms_notebook_task *jobs.CleanRoomsNotebookTask ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.clean_rooms_notebook_task.clean_room_name string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.clean_rooms_notebook_task.etag string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.clean_rooms_notebook_task.notebook_base_parameters map[string]string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.clean_rooms_notebook_task.notebook_base_parameters.* string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.clean_rooms_notebook_task.notebook_name string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.compute *jobs.Compute ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.compute.hardware_accelerator compute.HardwareAcceleratorType ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.condition_task *jobs.ConditionTask ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.condition_task.left string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.condition_task.op jobs.ConditionTaskOp ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.condition_task.right string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.dashboard_task *jobs.DashboardTask ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.dashboard_task.dashboard_id string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.dashboard_task.filters map[string]string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.dashboard_task.filters.* string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.dashboard_task.subscription *jobs.Subscription ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.dashboard_task.subscription.custom_subject string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.dashboard_task.subscription.paused bool ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.dashboard_task.subscription.subscribers []jobs.SubscriptionSubscriber ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.dashboard_task.subscription.subscribers[*] jobs.SubscriptionSubscriber ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.dashboard_task.subscription.subscribers[*].destination_id string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.dashboard_task.subscription.subscribers[*].user_name string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.dashboard_task.warehouse_id string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.dbt_cloud_task *jobs.DbtCloudTask ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.dbt_cloud_task.connection_resource_name string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.dbt_cloud_task.dbt_cloud_job_id int64 ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.dbt_platform_task *jobs.DbtPlatformTask ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.dbt_platform_task.connection_resource_name string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.dbt_platform_task.dbt_platform_job_id string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.dbt_task *jobs.DbtTask ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.dbt_task.catalog string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.dbt_task.commands []string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.dbt_task.commands[*] string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.dbt_task.profiles_directory string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.dbt_task.project_directory string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.dbt_task.schema string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.dbt_task.source jobs.Source ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.dbt_task.warehouse_id string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.depends_on []jobs.TaskDependency ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.depends_on[*] jobs.TaskDependency ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.depends_on[*].outcome string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.depends_on[*].task_key string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.description string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.disable_auto_optimization bool ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.disabled bool ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.email_notifications *jobs.TaskEmailNotifications ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.email_notifications.no_alert_for_skipped_runs bool ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.email_notifications.on_duration_warning_threshold_exceeded []string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.email_notifications.on_duration_warning_threshold_exceeded[*] string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.email_notifications.on_failure []string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.email_notifications.on_failure[*] string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.email_notifications.on_start []string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.email_notifications.on_start[*] string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.email_notifications.on_streaming_backlog_exceeded []string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.email_notifications.on_streaming_backlog_exceeded[*] string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.email_notifications.on_success []string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.email_notifications.on_success[*] string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.environment_key string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.existing_cluster_id string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.for_each_task *jobs.ForEachTask ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.for_each_task.concurrency int ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.for_each_task.inputs string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.for_each_task.task jobs.Task ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.gen_ai_compute_task *jobs.GenAiComputeTask ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.gen_ai_compute_task.command string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.gen_ai_compute_task.compute *jobs.ComputeConfig ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.gen_ai_compute_task.compute.gpu_node_pool_id string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.gen_ai_compute_task.compute.gpu_type string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.gen_ai_compute_task.compute.num_gpus int ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.gen_ai_compute_task.dl_runtime_image string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.gen_ai_compute_task.mlflow_experiment_name string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.gen_ai_compute_task.source jobs.Source ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.gen_ai_compute_task.training_script_path string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.gen_ai_compute_task.yaml_parameters string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.gen_ai_compute_task.yaml_parameters_file_path string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.health *jobs.JobsHealthRules ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.health.rules []jobs.JobsHealthRule ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.health.rules[*] jobs.JobsHealthRule ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.health.rules[*].metric jobs.JobsHealthMetric ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.health.rules[*].op jobs.JobsHealthOperator ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.health.rules[*].value int64 ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.job_cluster_key string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.libraries []compute.Library ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.libraries[*] compute.Library ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.libraries[*].cran *compute.RCranLibrary ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.libraries[*].cran.package string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.libraries[*].cran.repo string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.libraries[*].egg string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.libraries[*].jar string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.libraries[*].maven *compute.MavenLibrary ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.libraries[*].maven.coordinates string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.libraries[*].maven.exclusions []string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.libraries[*].maven.exclusions[*] string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.libraries[*].maven.repo string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.libraries[*].pypi *compute.PythonPyPiLibrary ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.libraries[*].pypi.package string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.libraries[*].pypi.repo string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.libraries[*].requirements string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.libraries[*].whl string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.max_retries int ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.min_retry_interval_millis int ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster *compute.ClusterSpec ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.apply_policy_default_values bool ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.autoscale *compute.AutoScale ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.autoscale.max_workers int ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.autoscale.min_workers int ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.autotermination_minutes int ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.aws_attributes *compute.AwsAttributes ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.aws_attributes.availability compute.AwsAvailability ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.aws_attributes.ebs_volume_count int ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.aws_attributes.ebs_volume_iops int ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.aws_attributes.ebs_volume_size int ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.aws_attributes.ebs_volume_throughput int ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.aws_attributes.ebs_volume_type compute.EbsVolumeType ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.aws_attributes.first_on_demand int ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.aws_attributes.instance_profile_arn string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.aws_attributes.spot_bid_price_percent int ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.aws_attributes.zone_id string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.azure_attributes *compute.AzureAttributes ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.azure_attributes.availability compute.AzureAvailability ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.azure_attributes.first_on_demand int ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.azure_attributes.log_analytics_info *compute.LogAnalyticsInfo ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.azure_attributes.log_analytics_info.log_analytics_primary_key string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.azure_attributes.log_analytics_info.log_analytics_workspace_id string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.azure_attributes.spot_bid_max_price float64 ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.cluster_log_conf *compute.ClusterLogConf ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.cluster_log_conf.dbfs *compute.DbfsStorageInfo ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.cluster_log_conf.dbfs.destination string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.cluster_log_conf.s3 *compute.S3StorageInfo ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.cluster_log_conf.s3.canned_acl string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.cluster_log_conf.s3.destination string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.cluster_log_conf.s3.enable_encryption bool ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.cluster_log_conf.s3.encryption_type string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.cluster_log_conf.s3.endpoint string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.cluster_log_conf.s3.kms_key string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.cluster_log_conf.s3.region string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.cluster_log_conf.volumes *compute.VolumesStorageInfo ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.cluster_log_conf.volumes.destination string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.cluster_name string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.custom_tags map[string]string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.custom_tags.* string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.data_security_mode compute.DataSecurityMode ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.docker_image *compute.DockerImage ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.docker_image.basic_auth *compute.DockerBasicAuth ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.docker_image.basic_auth.password string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.docker_image.basic_auth.username string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.docker_image.url string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.driver_instance_pool_id string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.driver_node_type_flexibility *compute.NodeTypeFlexibility ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.driver_node_type_flexibility.alternate_node_type_ids []string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.driver_node_type_flexibility.alternate_node_type_ids[*] string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.driver_node_type_id string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.enable_elastic_disk bool ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.enable_local_disk_encryption bool ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.gcp_attributes *compute.GcpAttributes ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.gcp_attributes.availability compute.GcpAvailability ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.gcp_attributes.boot_disk_size int ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.gcp_attributes.confidential_compute_type compute.ConfidentialComputeType ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.gcp_attributes.first_on_demand int ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.gcp_attributes.google_service_account string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.gcp_attributes.local_ssd_count int ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.gcp_attributes.use_preemptible_executors bool ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.gcp_attributes.zone_id string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.init_scripts []compute.InitScriptInfo ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.init_scripts[*] compute.InitScriptInfo ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.init_scripts[*].abfss *compute.Adlsgen2Info ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.init_scripts[*].abfss.destination string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.init_scripts[*].dbfs *compute.DbfsStorageInfo ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.init_scripts[*].dbfs.destination string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.init_scripts[*].file *compute.LocalFileInfo ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.init_scripts[*].file.destination string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.init_scripts[*].gcs *compute.GcsStorageInfo ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.init_scripts[*].gcs.destination string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.init_scripts[*].s3 *compute.S3StorageInfo ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.init_scripts[*].s3.canned_acl string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.init_scripts[*].s3.destination string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.init_scripts[*].s3.enable_encryption bool ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.init_scripts[*].s3.encryption_type string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.init_scripts[*].s3.endpoint string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.init_scripts[*].s3.kms_key string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.init_scripts[*].s3.region string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.init_scripts[*].volumes *compute.VolumesStorageInfo ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.init_scripts[*].volumes.destination string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.init_scripts[*].workspace *compute.WorkspaceStorageInfo ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.init_scripts[*].workspace.destination string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.instance_pool_id string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.is_single_node bool ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.kind compute.Kind ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.node_type_id string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.num_workers int ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.policy_id string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.remote_disk_throughput int ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.runtime_engine compute.RuntimeEngine ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.single_user_name string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.spark_conf map[string]string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.spark_conf.* string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.spark_env_vars map[string]string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.spark_env_vars.* string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.spark_version string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.ssh_public_keys []string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.ssh_public_keys[*] string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.total_initial_remote_disk_size int ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.use_ml_runtime bool ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.worker_node_type_flexibility *compute.NodeTypeFlexibility ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.worker_node_type_flexibility.alternate_node_type_ids []string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.worker_node_type_flexibility.alternate_node_type_ids[*] string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.workload_type *compute.WorkloadType ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.workload_type.clients compute.ClientsTypes ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.workload_type.clients.jobs bool ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.workload_type.clients.notebooks bool ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.notebook_task *jobs.NotebookTask ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.notebook_task.base_parameters map[string]string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.notebook_task.base_parameters.* string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.notebook_task.notebook_path string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.notebook_task.source jobs.Source ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.notebook_task.warehouse_id string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.notification_settings *jobs.TaskNotificationSettings ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.notification_settings.alert_on_last_attempt bool ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.notification_settings.no_alert_for_canceled_runs bool ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.notification_settings.no_alert_for_skipped_runs bool ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.pipeline_task *jobs.PipelineTask ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.pipeline_task.full_refresh bool ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.pipeline_task.full_refresh_selection []string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.pipeline_task.full_refresh_selection[*] string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.pipeline_task.parameters map[string]string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.pipeline_task.parameters.* string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.pipeline_task.pipeline_id string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.pipeline_task.refresh_flow_selection []string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.pipeline_task.refresh_flow_selection[*] string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.pipeline_task.refresh_selection []string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.pipeline_task.refresh_selection[*] string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.pipeline_task.reset_checkpoint_selection []string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.pipeline_task.reset_checkpoint_selection[*] string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.power_bi_task *jobs.PowerBiTask ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.power_bi_task.connection_resource_name string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.power_bi_task.power_bi_model *jobs.PowerBiModel ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.power_bi_task.power_bi_model.authentication_method jobs.AuthenticationMethod ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.power_bi_task.power_bi_model.model_name string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.power_bi_task.power_bi_model.overwrite_existing bool ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.power_bi_task.power_bi_model.storage_mode jobs.StorageMode ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.power_bi_task.power_bi_model.workspace_name string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.power_bi_task.refresh_after_update bool ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.power_bi_task.tables []jobs.PowerBiTable ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.power_bi_task.tables[*] jobs.PowerBiTable ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.power_bi_task.tables[*].catalog string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.power_bi_task.tables[*].name string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.power_bi_task.tables[*].schema string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.power_bi_task.tables[*].storage_mode jobs.StorageMode ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.power_bi_task.warehouse_id string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.python_operator_task *jobs.PythonOperatorTask ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.python_operator_task.main string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.python_operator_task.parameters []jobs.PythonOperatorTaskParameter ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.python_operator_task.parameters[*] jobs.PythonOperatorTaskParameter ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.python_operator_task.parameters[*].name string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.python_operator_task.parameters[*].value string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.python_wheel_task *jobs.PythonWheelTask ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.python_wheel_task.entry_point string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.python_wheel_task.named_parameters map[string]string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.python_wheel_task.named_parameters.* string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.python_wheel_task.package_name string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.python_wheel_task.parameters []string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.python_wheel_task.parameters[*] string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.retry_on_timeout bool ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.run_if jobs.RunIf ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.run_job_task *jobs.RunJobTask ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.run_job_task.dbt_commands []string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.run_job_task.dbt_commands[*] string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.run_job_task.jar_params []string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.run_job_task.jar_params[*] string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.run_job_task.job_id int64 ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.run_job_task.job_parameters map[string]string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.run_job_task.job_parameters.* string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.run_job_task.notebook_params map[string]string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.run_job_task.notebook_params.* string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.run_job_task.pipeline_params *jobs.PipelineParams ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.run_job_task.pipeline_params.full_refresh bool ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.run_job_task.pipeline_params.full_refresh_selection []string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.run_job_task.pipeline_params.full_refresh_selection[*] string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.run_job_task.pipeline_params.refresh_flow_selection []string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.run_job_task.pipeline_params.refresh_flow_selection[*] string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.run_job_task.pipeline_params.refresh_selection []string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.run_job_task.pipeline_params.refresh_selection[*] string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.run_job_task.pipeline_params.reset_checkpoint_selection []string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.run_job_task.pipeline_params.reset_checkpoint_selection[*] string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.run_job_task.python_named_params map[string]string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.run_job_task.python_named_params.* string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.run_job_task.python_params []string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.run_job_task.python_params[*] string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.run_job_task.spark_submit_params []string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.run_job_task.spark_submit_params[*] string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.run_job_task.sql_params map[string]string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.run_job_task.sql_params.* string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.spark_jar_task *jobs.SparkJarTask ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.spark_jar_task.jar_uri string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.spark_jar_task.main_class_name string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.spark_jar_task.parameters []string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.spark_jar_task.parameters[*] string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.spark_jar_task.run_as_repl bool ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.spark_python_task *jobs.SparkPythonTask ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.spark_python_task.parameters []string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.spark_python_task.parameters[*] string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.spark_python_task.python_file string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.spark_python_task.source jobs.Source ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.spark_submit_task *jobs.SparkSubmitTask ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.spark_submit_task.parameters []string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.spark_submit_task.parameters[*] string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.sql_task *jobs.SqlTask ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.sql_task.alert *jobs.SqlTaskAlert ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.sql_task.alert.alert_id string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.sql_task.alert.pause_subscriptions bool ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.sql_task.alert.subscriptions []jobs.SqlTaskSubscription ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.sql_task.alert.subscriptions[*] jobs.SqlTaskSubscription ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.sql_task.alert.subscriptions[*].destination_id string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.sql_task.alert.subscriptions[*].user_name string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.sql_task.dashboard *jobs.SqlTaskDashboard ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.sql_task.dashboard.custom_subject string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.sql_task.dashboard.dashboard_id string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.sql_task.dashboard.pause_subscriptions bool ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.sql_task.dashboard.subscriptions []jobs.SqlTaskSubscription ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.sql_task.dashboard.subscriptions[*] jobs.SqlTaskSubscription ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.sql_task.dashboard.subscriptions[*].destination_id string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.sql_task.dashboard.subscriptions[*].user_name string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.sql_task.file *jobs.SqlTaskFile ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.sql_task.file.path string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.sql_task.file.source jobs.Source ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.sql_task.parameters map[string]string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.sql_task.parameters.* string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.sql_task.query *jobs.SqlTaskQuery ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.sql_task.query.query_id string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.sql_task.warehouse_id string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.task_key string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.timeout_seconds int ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.webhook_notifications *jobs.WebhookNotifications ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.webhook_notifications.on_duration_warning_threshold_exceeded []jobs.Webhook ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.webhook_notifications.on_duration_warning_threshold_exceeded[*] jobs.Webhook ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.webhook_notifications.on_duration_warning_threshold_exceeded[*].id string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.webhook_notifications.on_failure []jobs.Webhook ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.webhook_notifications.on_failure[*] jobs.Webhook ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.webhook_notifications.on_failure[*].id string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.webhook_notifications.on_start []jobs.Webhook ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.webhook_notifications.on_start[*] jobs.Webhook ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.webhook_notifications.on_start[*].id string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.webhook_notifications.on_streaming_backlog_exceeded []jobs.Webhook ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.webhook_notifications.on_streaming_backlog_exceeded[*] jobs.Webhook ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.webhook_notifications.on_streaming_backlog_exceeded[*].id string ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.webhook_notifications.on_success []jobs.Webhook ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.webhook_notifications.on_success[*] jobs.Webhook ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.webhook_notifications.on_success[*].id string ALL +resources.job_runs.*.job_settings.tasks[*].gen_ai_compute_task *jobs.GenAiComputeTask ALL +resources.job_runs.*.job_settings.tasks[*].gen_ai_compute_task.command string ALL +resources.job_runs.*.job_settings.tasks[*].gen_ai_compute_task.compute *jobs.ComputeConfig ALL +resources.job_runs.*.job_settings.tasks[*].gen_ai_compute_task.compute.gpu_node_pool_id string ALL +resources.job_runs.*.job_settings.tasks[*].gen_ai_compute_task.compute.gpu_type string ALL +resources.job_runs.*.job_settings.tasks[*].gen_ai_compute_task.compute.num_gpus int ALL +resources.job_runs.*.job_settings.tasks[*].gen_ai_compute_task.dl_runtime_image string ALL +resources.job_runs.*.job_settings.tasks[*].gen_ai_compute_task.mlflow_experiment_name string ALL +resources.job_runs.*.job_settings.tasks[*].gen_ai_compute_task.source jobs.Source ALL +resources.job_runs.*.job_settings.tasks[*].gen_ai_compute_task.training_script_path string ALL +resources.job_runs.*.job_settings.tasks[*].gen_ai_compute_task.yaml_parameters string ALL +resources.job_runs.*.job_settings.tasks[*].gen_ai_compute_task.yaml_parameters_file_path string ALL +resources.job_runs.*.job_settings.tasks[*].health *jobs.JobsHealthRules ALL +resources.job_runs.*.job_settings.tasks[*].health.rules []jobs.JobsHealthRule ALL +resources.job_runs.*.job_settings.tasks[*].health.rules[*] jobs.JobsHealthRule ALL +resources.job_runs.*.job_settings.tasks[*].health.rules[*].metric jobs.JobsHealthMetric ALL +resources.job_runs.*.job_settings.tasks[*].health.rules[*].op jobs.JobsHealthOperator ALL +resources.job_runs.*.job_settings.tasks[*].health.rules[*].value int64 ALL +resources.job_runs.*.job_settings.tasks[*].job_cluster_key string ALL +resources.job_runs.*.job_settings.tasks[*].libraries []compute.Library ALL +resources.job_runs.*.job_settings.tasks[*].libraries[*] compute.Library ALL +resources.job_runs.*.job_settings.tasks[*].libraries[*].cran *compute.RCranLibrary ALL +resources.job_runs.*.job_settings.tasks[*].libraries[*].cran.package string ALL +resources.job_runs.*.job_settings.tasks[*].libraries[*].cran.repo string ALL +resources.job_runs.*.job_settings.tasks[*].libraries[*].egg string ALL +resources.job_runs.*.job_settings.tasks[*].libraries[*].jar string ALL +resources.job_runs.*.job_settings.tasks[*].libraries[*].maven *compute.MavenLibrary ALL +resources.job_runs.*.job_settings.tasks[*].libraries[*].maven.coordinates string ALL +resources.job_runs.*.job_settings.tasks[*].libraries[*].maven.exclusions []string ALL +resources.job_runs.*.job_settings.tasks[*].libraries[*].maven.exclusions[*] string ALL +resources.job_runs.*.job_settings.tasks[*].libraries[*].maven.repo string ALL +resources.job_runs.*.job_settings.tasks[*].libraries[*].pypi *compute.PythonPyPiLibrary ALL +resources.job_runs.*.job_settings.tasks[*].libraries[*].pypi.package string ALL +resources.job_runs.*.job_settings.tasks[*].libraries[*].pypi.repo string ALL +resources.job_runs.*.job_settings.tasks[*].libraries[*].requirements string ALL +resources.job_runs.*.job_settings.tasks[*].libraries[*].whl string ALL +resources.job_runs.*.job_settings.tasks[*].max_retries int ALL +resources.job_runs.*.job_settings.tasks[*].min_retry_interval_millis int ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster *compute.ClusterSpec ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.apply_policy_default_values bool ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.autoscale *compute.AutoScale ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.autoscale.max_workers int ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.autoscale.min_workers int ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.autotermination_minutes int ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.aws_attributes *compute.AwsAttributes ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.aws_attributes.availability compute.AwsAvailability ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.aws_attributes.ebs_volume_count int ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.aws_attributes.ebs_volume_iops int ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.aws_attributes.ebs_volume_size int ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.aws_attributes.ebs_volume_throughput int ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.aws_attributes.ebs_volume_type compute.EbsVolumeType ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.aws_attributes.first_on_demand int ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.aws_attributes.instance_profile_arn string ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.aws_attributes.spot_bid_price_percent int ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.aws_attributes.zone_id string ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.azure_attributes *compute.AzureAttributes ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.azure_attributes.availability compute.AzureAvailability ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.azure_attributes.first_on_demand int ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.azure_attributes.log_analytics_info *compute.LogAnalyticsInfo ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.azure_attributes.log_analytics_info.log_analytics_primary_key string ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.azure_attributes.log_analytics_info.log_analytics_workspace_id string ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.azure_attributes.spot_bid_max_price float64 ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.cluster_log_conf *compute.ClusterLogConf ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.cluster_log_conf.dbfs *compute.DbfsStorageInfo ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.cluster_log_conf.dbfs.destination string ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.cluster_log_conf.s3 *compute.S3StorageInfo ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.cluster_log_conf.s3.canned_acl string ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.cluster_log_conf.s3.destination string ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.cluster_log_conf.s3.enable_encryption bool ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.cluster_log_conf.s3.encryption_type string ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.cluster_log_conf.s3.endpoint string ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.cluster_log_conf.s3.kms_key string ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.cluster_log_conf.s3.region string ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.cluster_log_conf.volumes *compute.VolumesStorageInfo ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.cluster_log_conf.volumes.destination string ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.cluster_name string ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.custom_tags map[string]string ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.custom_tags.* string ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.data_security_mode compute.DataSecurityMode ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.docker_image *compute.DockerImage ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.docker_image.basic_auth *compute.DockerBasicAuth ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.docker_image.basic_auth.password string ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.docker_image.basic_auth.username string ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.docker_image.url string ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.driver_instance_pool_id string ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.driver_node_type_flexibility *compute.NodeTypeFlexibility ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.driver_node_type_flexibility.alternate_node_type_ids []string ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.driver_node_type_flexibility.alternate_node_type_ids[*] string ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.driver_node_type_id string ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.enable_elastic_disk bool ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.enable_local_disk_encryption bool ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.gcp_attributes *compute.GcpAttributes ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.gcp_attributes.availability compute.GcpAvailability ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.gcp_attributes.boot_disk_size int ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.gcp_attributes.confidential_compute_type compute.ConfidentialComputeType ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.gcp_attributes.first_on_demand int ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.gcp_attributes.google_service_account string ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.gcp_attributes.local_ssd_count int ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.gcp_attributes.use_preemptible_executors bool ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.gcp_attributes.zone_id string ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.init_scripts []compute.InitScriptInfo ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.init_scripts[*] compute.InitScriptInfo ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.init_scripts[*].abfss *compute.Adlsgen2Info ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.init_scripts[*].abfss.destination string ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.init_scripts[*].dbfs *compute.DbfsStorageInfo ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.init_scripts[*].dbfs.destination string ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.init_scripts[*].file *compute.LocalFileInfo ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.init_scripts[*].file.destination string ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.init_scripts[*].gcs *compute.GcsStorageInfo ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.init_scripts[*].gcs.destination string ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.init_scripts[*].s3 *compute.S3StorageInfo ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.init_scripts[*].s3.canned_acl string ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.init_scripts[*].s3.destination string ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.init_scripts[*].s3.enable_encryption bool ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.init_scripts[*].s3.encryption_type string ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.init_scripts[*].s3.endpoint string ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.init_scripts[*].s3.kms_key string ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.init_scripts[*].s3.region string ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.init_scripts[*].volumes *compute.VolumesStorageInfo ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.init_scripts[*].volumes.destination string ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.init_scripts[*].workspace *compute.WorkspaceStorageInfo ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.init_scripts[*].workspace.destination string ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.instance_pool_id string ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.is_single_node bool ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.kind compute.Kind ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.node_type_id string ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.num_workers int ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.policy_id string ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.remote_disk_throughput int ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.runtime_engine compute.RuntimeEngine ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.single_user_name string ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.spark_conf map[string]string ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.spark_conf.* string ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.spark_env_vars map[string]string ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.spark_env_vars.* string ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.spark_version string ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.ssh_public_keys []string ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.ssh_public_keys[*] string ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.total_initial_remote_disk_size int ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.use_ml_runtime bool ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.worker_node_type_flexibility *compute.NodeTypeFlexibility ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.worker_node_type_flexibility.alternate_node_type_ids []string ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.worker_node_type_flexibility.alternate_node_type_ids[*] string ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.workload_type *compute.WorkloadType ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.workload_type.clients compute.ClientsTypes ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.workload_type.clients.jobs bool ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.workload_type.clients.notebooks bool ALL +resources.job_runs.*.job_settings.tasks[*].notebook_task *jobs.NotebookTask ALL +resources.job_runs.*.job_settings.tasks[*].notebook_task.base_parameters map[string]string ALL +resources.job_runs.*.job_settings.tasks[*].notebook_task.base_parameters.* string ALL +resources.job_runs.*.job_settings.tasks[*].notebook_task.notebook_path string ALL +resources.job_runs.*.job_settings.tasks[*].notebook_task.source jobs.Source ALL +resources.job_runs.*.job_settings.tasks[*].notebook_task.warehouse_id string ALL +resources.job_runs.*.job_settings.tasks[*].notification_settings *jobs.TaskNotificationSettings ALL +resources.job_runs.*.job_settings.tasks[*].notification_settings.alert_on_last_attempt bool ALL +resources.job_runs.*.job_settings.tasks[*].notification_settings.no_alert_for_canceled_runs bool ALL +resources.job_runs.*.job_settings.tasks[*].notification_settings.no_alert_for_skipped_runs bool ALL +resources.job_runs.*.job_settings.tasks[*].pipeline_task *jobs.PipelineTask ALL +resources.job_runs.*.job_settings.tasks[*].pipeline_task.full_refresh bool ALL +resources.job_runs.*.job_settings.tasks[*].pipeline_task.full_refresh_selection []string ALL +resources.job_runs.*.job_settings.tasks[*].pipeline_task.full_refresh_selection[*] string ALL +resources.job_runs.*.job_settings.tasks[*].pipeline_task.parameters map[string]string ALL +resources.job_runs.*.job_settings.tasks[*].pipeline_task.parameters.* string ALL +resources.job_runs.*.job_settings.tasks[*].pipeline_task.pipeline_id string ALL +resources.job_runs.*.job_settings.tasks[*].pipeline_task.refresh_flow_selection []string ALL +resources.job_runs.*.job_settings.tasks[*].pipeline_task.refresh_flow_selection[*] string ALL +resources.job_runs.*.job_settings.tasks[*].pipeline_task.refresh_selection []string ALL +resources.job_runs.*.job_settings.tasks[*].pipeline_task.refresh_selection[*] string ALL +resources.job_runs.*.job_settings.tasks[*].pipeline_task.reset_checkpoint_selection []string ALL +resources.job_runs.*.job_settings.tasks[*].pipeline_task.reset_checkpoint_selection[*] string ALL +resources.job_runs.*.job_settings.tasks[*].power_bi_task *jobs.PowerBiTask ALL +resources.job_runs.*.job_settings.tasks[*].power_bi_task.connection_resource_name string ALL +resources.job_runs.*.job_settings.tasks[*].power_bi_task.power_bi_model *jobs.PowerBiModel ALL +resources.job_runs.*.job_settings.tasks[*].power_bi_task.power_bi_model.authentication_method jobs.AuthenticationMethod ALL +resources.job_runs.*.job_settings.tasks[*].power_bi_task.power_bi_model.model_name string ALL +resources.job_runs.*.job_settings.tasks[*].power_bi_task.power_bi_model.overwrite_existing bool ALL +resources.job_runs.*.job_settings.tasks[*].power_bi_task.power_bi_model.storage_mode jobs.StorageMode ALL +resources.job_runs.*.job_settings.tasks[*].power_bi_task.power_bi_model.workspace_name string ALL +resources.job_runs.*.job_settings.tasks[*].power_bi_task.refresh_after_update bool ALL +resources.job_runs.*.job_settings.tasks[*].power_bi_task.tables []jobs.PowerBiTable ALL +resources.job_runs.*.job_settings.tasks[*].power_bi_task.tables[*] jobs.PowerBiTable ALL +resources.job_runs.*.job_settings.tasks[*].power_bi_task.tables[*].catalog string ALL +resources.job_runs.*.job_settings.tasks[*].power_bi_task.tables[*].name string ALL +resources.job_runs.*.job_settings.tasks[*].power_bi_task.tables[*].schema string ALL +resources.job_runs.*.job_settings.tasks[*].power_bi_task.tables[*].storage_mode jobs.StorageMode ALL +resources.job_runs.*.job_settings.tasks[*].power_bi_task.warehouse_id string ALL +resources.job_runs.*.job_settings.tasks[*].python_operator_task *jobs.PythonOperatorTask ALL +resources.job_runs.*.job_settings.tasks[*].python_operator_task.main string ALL +resources.job_runs.*.job_settings.tasks[*].python_operator_task.parameters []jobs.PythonOperatorTaskParameter ALL +resources.job_runs.*.job_settings.tasks[*].python_operator_task.parameters[*] jobs.PythonOperatorTaskParameter ALL +resources.job_runs.*.job_settings.tasks[*].python_operator_task.parameters[*].name string ALL +resources.job_runs.*.job_settings.tasks[*].python_operator_task.parameters[*].value string ALL +resources.job_runs.*.job_settings.tasks[*].python_wheel_task *jobs.PythonWheelTask ALL +resources.job_runs.*.job_settings.tasks[*].python_wheel_task.entry_point string ALL +resources.job_runs.*.job_settings.tasks[*].python_wheel_task.named_parameters map[string]string ALL +resources.job_runs.*.job_settings.tasks[*].python_wheel_task.named_parameters.* string ALL +resources.job_runs.*.job_settings.tasks[*].python_wheel_task.package_name string ALL +resources.job_runs.*.job_settings.tasks[*].python_wheel_task.parameters []string ALL +resources.job_runs.*.job_settings.tasks[*].python_wheel_task.parameters[*] string ALL +resources.job_runs.*.job_settings.tasks[*].retry_on_timeout bool ALL +resources.job_runs.*.job_settings.tasks[*].run_if jobs.RunIf ALL +resources.job_runs.*.job_settings.tasks[*].run_job_task *jobs.RunJobTask ALL +resources.job_runs.*.job_settings.tasks[*].run_job_task.dbt_commands []string ALL +resources.job_runs.*.job_settings.tasks[*].run_job_task.dbt_commands[*] string ALL +resources.job_runs.*.job_settings.tasks[*].run_job_task.jar_params []string ALL +resources.job_runs.*.job_settings.tasks[*].run_job_task.jar_params[*] string ALL +resources.job_runs.*.job_settings.tasks[*].run_job_task.job_id int64 ALL +resources.job_runs.*.job_settings.tasks[*].run_job_task.job_parameters map[string]string ALL +resources.job_runs.*.job_settings.tasks[*].run_job_task.job_parameters.* string ALL +resources.job_runs.*.job_settings.tasks[*].run_job_task.notebook_params map[string]string ALL +resources.job_runs.*.job_settings.tasks[*].run_job_task.notebook_params.* string ALL +resources.job_runs.*.job_settings.tasks[*].run_job_task.pipeline_params *jobs.PipelineParams ALL +resources.job_runs.*.job_settings.tasks[*].run_job_task.pipeline_params.full_refresh bool ALL +resources.job_runs.*.job_settings.tasks[*].run_job_task.pipeline_params.full_refresh_selection []string ALL +resources.job_runs.*.job_settings.tasks[*].run_job_task.pipeline_params.full_refresh_selection[*] string ALL +resources.job_runs.*.job_settings.tasks[*].run_job_task.pipeline_params.refresh_flow_selection []string ALL +resources.job_runs.*.job_settings.tasks[*].run_job_task.pipeline_params.refresh_flow_selection[*] string ALL +resources.job_runs.*.job_settings.tasks[*].run_job_task.pipeline_params.refresh_selection []string ALL +resources.job_runs.*.job_settings.tasks[*].run_job_task.pipeline_params.refresh_selection[*] string ALL +resources.job_runs.*.job_settings.tasks[*].run_job_task.pipeline_params.reset_checkpoint_selection []string ALL +resources.job_runs.*.job_settings.tasks[*].run_job_task.pipeline_params.reset_checkpoint_selection[*] string ALL +resources.job_runs.*.job_settings.tasks[*].run_job_task.python_named_params map[string]string ALL +resources.job_runs.*.job_settings.tasks[*].run_job_task.python_named_params.* string ALL +resources.job_runs.*.job_settings.tasks[*].run_job_task.python_params []string ALL +resources.job_runs.*.job_settings.tasks[*].run_job_task.python_params[*] string ALL +resources.job_runs.*.job_settings.tasks[*].run_job_task.spark_submit_params []string ALL +resources.job_runs.*.job_settings.tasks[*].run_job_task.spark_submit_params[*] string ALL +resources.job_runs.*.job_settings.tasks[*].run_job_task.sql_params map[string]string ALL +resources.job_runs.*.job_settings.tasks[*].run_job_task.sql_params.* string ALL +resources.job_runs.*.job_settings.tasks[*].spark_jar_task *jobs.SparkJarTask ALL +resources.job_runs.*.job_settings.tasks[*].spark_jar_task.jar_uri string ALL +resources.job_runs.*.job_settings.tasks[*].spark_jar_task.main_class_name string ALL +resources.job_runs.*.job_settings.tasks[*].spark_jar_task.parameters []string ALL +resources.job_runs.*.job_settings.tasks[*].spark_jar_task.parameters[*] string ALL +resources.job_runs.*.job_settings.tasks[*].spark_jar_task.run_as_repl bool ALL +resources.job_runs.*.job_settings.tasks[*].spark_python_task *jobs.SparkPythonTask ALL +resources.job_runs.*.job_settings.tasks[*].spark_python_task.parameters []string ALL +resources.job_runs.*.job_settings.tasks[*].spark_python_task.parameters[*] string ALL +resources.job_runs.*.job_settings.tasks[*].spark_python_task.python_file string ALL +resources.job_runs.*.job_settings.tasks[*].spark_python_task.source jobs.Source ALL +resources.job_runs.*.job_settings.tasks[*].spark_submit_task *jobs.SparkSubmitTask ALL +resources.job_runs.*.job_settings.tasks[*].spark_submit_task.parameters []string ALL +resources.job_runs.*.job_settings.tasks[*].spark_submit_task.parameters[*] string ALL +resources.job_runs.*.job_settings.tasks[*].sql_task *jobs.SqlTask ALL +resources.job_runs.*.job_settings.tasks[*].sql_task.alert *jobs.SqlTaskAlert ALL +resources.job_runs.*.job_settings.tasks[*].sql_task.alert.alert_id string ALL +resources.job_runs.*.job_settings.tasks[*].sql_task.alert.pause_subscriptions bool ALL +resources.job_runs.*.job_settings.tasks[*].sql_task.alert.subscriptions []jobs.SqlTaskSubscription ALL +resources.job_runs.*.job_settings.tasks[*].sql_task.alert.subscriptions[*] jobs.SqlTaskSubscription ALL +resources.job_runs.*.job_settings.tasks[*].sql_task.alert.subscriptions[*].destination_id string ALL +resources.job_runs.*.job_settings.tasks[*].sql_task.alert.subscriptions[*].user_name string ALL +resources.job_runs.*.job_settings.tasks[*].sql_task.dashboard *jobs.SqlTaskDashboard ALL +resources.job_runs.*.job_settings.tasks[*].sql_task.dashboard.custom_subject string ALL +resources.job_runs.*.job_settings.tasks[*].sql_task.dashboard.dashboard_id string ALL +resources.job_runs.*.job_settings.tasks[*].sql_task.dashboard.pause_subscriptions bool ALL +resources.job_runs.*.job_settings.tasks[*].sql_task.dashboard.subscriptions []jobs.SqlTaskSubscription ALL +resources.job_runs.*.job_settings.tasks[*].sql_task.dashboard.subscriptions[*] jobs.SqlTaskSubscription ALL +resources.job_runs.*.job_settings.tasks[*].sql_task.dashboard.subscriptions[*].destination_id string ALL +resources.job_runs.*.job_settings.tasks[*].sql_task.dashboard.subscriptions[*].user_name string ALL +resources.job_runs.*.job_settings.tasks[*].sql_task.file *jobs.SqlTaskFile ALL +resources.job_runs.*.job_settings.tasks[*].sql_task.file.path string ALL +resources.job_runs.*.job_settings.tasks[*].sql_task.file.source jobs.Source ALL +resources.job_runs.*.job_settings.tasks[*].sql_task.parameters map[string]string ALL +resources.job_runs.*.job_settings.tasks[*].sql_task.parameters.* string ALL +resources.job_runs.*.job_settings.tasks[*].sql_task.query *jobs.SqlTaskQuery ALL +resources.job_runs.*.job_settings.tasks[*].sql_task.query.query_id string ALL +resources.job_runs.*.job_settings.tasks[*].sql_task.warehouse_id string ALL +resources.job_runs.*.job_settings.tasks[*].task_key string ALL +resources.job_runs.*.job_settings.tasks[*].timeout_seconds int ALL +resources.job_runs.*.job_settings.tasks[*].webhook_notifications *jobs.WebhookNotifications ALL +resources.job_runs.*.job_settings.tasks[*].webhook_notifications.on_duration_warning_threshold_exceeded []jobs.Webhook ALL +resources.job_runs.*.job_settings.tasks[*].webhook_notifications.on_duration_warning_threshold_exceeded[*] jobs.Webhook ALL +resources.job_runs.*.job_settings.tasks[*].webhook_notifications.on_duration_warning_threshold_exceeded[*].id string ALL +resources.job_runs.*.job_settings.tasks[*].webhook_notifications.on_failure []jobs.Webhook ALL +resources.job_runs.*.job_settings.tasks[*].webhook_notifications.on_failure[*] jobs.Webhook ALL +resources.job_runs.*.job_settings.tasks[*].webhook_notifications.on_failure[*].id string ALL +resources.job_runs.*.job_settings.tasks[*].webhook_notifications.on_start []jobs.Webhook ALL +resources.job_runs.*.job_settings.tasks[*].webhook_notifications.on_start[*] jobs.Webhook ALL +resources.job_runs.*.job_settings.tasks[*].webhook_notifications.on_start[*].id string ALL +resources.job_runs.*.job_settings.tasks[*].webhook_notifications.on_streaming_backlog_exceeded []jobs.Webhook ALL +resources.job_runs.*.job_settings.tasks[*].webhook_notifications.on_streaming_backlog_exceeded[*] jobs.Webhook ALL +resources.job_runs.*.job_settings.tasks[*].webhook_notifications.on_streaming_backlog_exceeded[*].id string ALL +resources.job_runs.*.job_settings.tasks[*].webhook_notifications.on_success []jobs.Webhook ALL +resources.job_runs.*.job_settings.tasks[*].webhook_notifications.on_success[*] jobs.Webhook ALL +resources.job_runs.*.job_settings.tasks[*].webhook_notifications.on_success[*].id string ALL +resources.job_runs.*.job_settings.timeout_seconds int ALL +resources.job_runs.*.job_settings.trigger *jobs.TriggerSettings ALL +resources.job_runs.*.job_settings.trigger.file_arrival *jobs.FileArrivalTriggerConfiguration ALL +resources.job_runs.*.job_settings.trigger.file_arrival.min_time_between_triggers_seconds int ALL +resources.job_runs.*.job_settings.trigger.file_arrival.url string ALL +resources.job_runs.*.job_settings.trigger.file_arrival.wait_after_last_change_seconds int ALL +resources.job_runs.*.job_settings.trigger.model *jobs.ModelTriggerConfiguration ALL +resources.job_runs.*.job_settings.trigger.model.aliases []string ALL +resources.job_runs.*.job_settings.trigger.model.aliases[*] string ALL +resources.job_runs.*.job_settings.trigger.model.condition jobs.ModelTriggerConfigurationCondition ALL +resources.job_runs.*.job_settings.trigger.model.min_time_between_triggers_seconds int ALL +resources.job_runs.*.job_settings.trigger.model.securable_name string ALL +resources.job_runs.*.job_settings.trigger.model.wait_after_last_change_seconds int ALL +resources.job_runs.*.job_settings.trigger.pause_status jobs.PauseStatus ALL +resources.job_runs.*.job_settings.trigger.periodic *jobs.PeriodicTriggerConfiguration ALL +resources.job_runs.*.job_settings.trigger.periodic.interval int ALL +resources.job_runs.*.job_settings.trigger.periodic.unit jobs.PeriodicTriggerConfigurationTimeUnit ALL +resources.job_runs.*.job_settings.trigger.table_update *jobs.TableUpdateTriggerConfiguration ALL +resources.job_runs.*.job_settings.trigger.table_update.condition jobs.Condition ALL +resources.job_runs.*.job_settings.trigger.table_update.min_time_between_triggers_seconds int ALL +resources.job_runs.*.job_settings.trigger.table_update.table_names []string ALL +resources.job_runs.*.job_settings.trigger.table_update.table_names[*] string ALL +resources.job_runs.*.job_settings.trigger.table_update.wait_after_last_change_seconds int ALL +resources.job_runs.*.job_settings.usage_policy_id string ALL +resources.job_runs.*.job_settings.webhook_notifications *jobs.WebhookNotifications ALL +resources.job_runs.*.job_settings.webhook_notifications.on_duration_warning_threshold_exceeded []jobs.Webhook ALL +resources.job_runs.*.job_settings.webhook_notifications.on_duration_warning_threshold_exceeded[*] jobs.Webhook ALL +resources.job_runs.*.job_settings.webhook_notifications.on_duration_warning_threshold_exceeded[*].id string ALL +resources.job_runs.*.job_settings.webhook_notifications.on_failure []jobs.Webhook ALL +resources.job_runs.*.job_settings.webhook_notifications.on_failure[*] jobs.Webhook ALL +resources.job_runs.*.job_settings.webhook_notifications.on_failure[*].id string ALL +resources.job_runs.*.job_settings.webhook_notifications.on_start []jobs.Webhook ALL +resources.job_runs.*.job_settings.webhook_notifications.on_start[*] jobs.Webhook ALL +resources.job_runs.*.job_settings.webhook_notifications.on_start[*].id string ALL +resources.job_runs.*.job_settings.webhook_notifications.on_streaming_backlog_exceeded []jobs.Webhook ALL +resources.job_runs.*.job_settings.webhook_notifications.on_streaming_backlog_exceeded[*] jobs.Webhook ALL +resources.job_runs.*.job_settings.webhook_notifications.on_streaming_backlog_exceeded[*].id string ALL +resources.job_runs.*.job_settings.webhook_notifications.on_success []jobs.Webhook ALL +resources.job_runs.*.job_settings.webhook_notifications.on_success[*] jobs.Webhook ALL +resources.job_runs.*.job_settings.webhook_notifications.on_success[*].id string ALL resources.job_runs.*.lifecycle resources.Lifecycle INPUT resources.job_runs.*.lifecycle.prevent_destroy bool INPUT resources.job_runs.*.modified_status string INPUT diff --git a/acceptance/bundle/resources/job_runs/notebook_change/databricks.yml b/acceptance/bundle/resources/job_runs/notebook_change/databricks.yml index 65eecc64082..61808fb33bc 100644 --- a/acceptance/bundle/resources/job_runs/notebook_change/databricks.yml +++ b/acceptance/bundle/resources/job_runs/notebook_change/databricks.yml @@ -15,3 +15,5 @@ resources: job_id: ${resources.jobs.my_job.id} job_parameters: env: dev + # Snapshot the whole job so any change to it (e.g. notebook_path) re-triggers the run. + job_settings: ${resources.jobs.my_job} diff --git a/acceptance/bundle/resources/job_runs/notebook_change/output.txt b/acceptance/bundle/resources/job_runs/notebook_change/output.txt index e256d76bd5d..8e03aa3eeb7 100644 --- a/acceptance/bundle/resources/job_runs/notebook_change/output.txt +++ b/acceptance/bundle/resources/job_runs/notebook_change/output.txt @@ -61,8 +61,18 @@ Plan: 0 to add, 0 to change, 0 to delete, 2 unchanged } } -=== but the run config did not change, so no new run was triggered +=== the job change re-triggered the run via the job_settings snapshot >>> print_requests.py //jobs/run-now +{ + "method": "POST", + "path": "/api/2.2/jobs/run-now", + "body": { + "job_id": [NUMID], + "job_parameters": { + "env": "dev" + } + } +} >>> [CLI] bundle destroy --auto-approve The following resources will be deleted: diff --git a/acceptance/bundle/resources/job_runs/notebook_change/script b/acceptance/bundle/resources/job_runs/notebook_change/script index f6158a14992..8a1ec570e43 100644 --- a/acceptance/bundle/resources/job_runs/notebook_change/script +++ b/acceptance/bundle/resources/job_runs/notebook_change/script @@ -16,5 +16,5 @@ trace $CLI bundle plan title "the job was updated with the new notebook_path" trace print_requests.py --keep //jobs/reset -title "but the run config did not change, so no new run was triggered" +title "the job change re-triggered the run via the job_settings snapshot" trace print_requests.py //jobs/run-now diff --git a/bundle/config/resources/job_run.go b/bundle/config/resources/job_run.go index 765a2938df1..51a8310c636 100644 --- a/bundle/config/resources/job_run.go +++ b/bundle/config/resources/job_run.go @@ -17,6 +17,14 @@ import ( type JobRun struct { BaseResource jobs.RunNow + + // JobSettings snapshots the settings of the job this run targets. RunNow only + // carries the job_id, which is stable across edits to the job, so without this + // the run has no way to notice that the job's definition changed. Set it to a + // whole-job reference (e.g. job_settings: ${resources.jobs.my_job}) and any + // change to the job re-triggers the run, since the snapshot is marked + // recreate_on_changes in resources.yml. + JobSettings *jobs.JobSettings `json:"job_settings,omitempty"` } func (r *JobRun) UnmarshalJSON(b []byte) error { diff --git a/bundle/direct/dresources/job_run.go b/bundle/direct/dresources/job_run.go index 4e5f2b37071..05c8f23c0c5 100644 --- a/bundle/direct/dresources/job_run.go +++ b/bundle/direct/dresources/job_run.go @@ -11,15 +11,34 @@ import ( "github.com/databricks/databricks-sdk-go/service/jobs" ) -// JobRunRemote is the return type for DoRead. It embeds jobs.RunNow so that -// every field of the state type (jobs.RunNow) is also a valid path in the -// remote type, as required by the framework. GetRun does not echo back the -// RunNow request, so the embedded RunNow is left zero on read; the actual -// remote identity lives in RunId. Drift on the embedded request fields is -// suppressed via ignore_remote_changes in resources.yml. -type JobRunRemote struct { +// JobRunState is what we persist for a triggered run: the RunNow request plus a +// snapshot of the targeted job's settings. The snapshot is what lets a change to +// the job re-trigger the run (RunNow only carries the stable job_id). A custom +// marshaler is required because the embedded jobs.RunNow has its own MarshalJSON +// which would otherwise take over and drop JobSettings. +type JobRunState struct { jobs.RunNow + JobSettings *jobs.JobSettings `json:"job_settings,omitempty"` +} + +func (s *JobRunState) UnmarshalJSON(b []byte) error { + return marshal.Unmarshal(b, s) +} + +func (s JobRunState) MarshalJSON() ([]byte, error) { + return marshal.Marshal(s) +} + +// JobRunRemote is the return type for DoRead. It embeds JobRunState so that every +// path in StateType is also a valid path in RemoteType (required by the +// framework). DoRead fills the embedded state from the GetRun response, mapping +// the run's job-level and overriding parameters back into the RunNow shape so the +// framework can diff them against the desired config. RunId is the remote +// identity, kept here for the detailed plan. +type JobRunRemote struct { + JobRunState + RunId int64 `json:"run_id,omitempty"` } @@ -41,12 +60,30 @@ func (*ResourceJobRun) New(client *databricks.WorkspaceClient) *ResourceJobRun { } } -func (*ResourceJobRun) PrepareState(input *resources.JobRun) *jobs.RunNow { - return &input.RunNow +func (*ResourceJobRun) PrepareState(input *resources.JobRun) *JobRunState { + return &JobRunState{ + RunNow: input.RunNow, + JobSettings: input.JobSettings, + } } -func (*ResourceJobRun) RemapState(remote *JobRunRemote) *jobs.RunNow { - return &remote.RunNow +func (*ResourceJobRun) RemapState(remote *JobRunRemote) *JobRunState { + return &remote.JobRunState +} + +// jobParametersToMap converts the run's job parameters (a list of name/value +// pairs as returned by GetRun) into the name->value map shape used by RunNow. +// It returns nil for an empty list so the diff matches a config that sets no +// job parameters. +func jobParametersToMap(params []jobs.JobParameter) map[string]string { + if len(params) == 0 { + return nil + } + m := make(map[string]string, len(params)) + for _, p := range params { + m[p.Name] = p.Value + } + return m } func (r *ResourceJobRun) DoRead(ctx context.Context, id string) (*JobRunRemote, error) { @@ -64,16 +101,36 @@ func (r *ResourceJobRun) DoRead(ctx context.Context, id string) (*JobRunRemote, if err != nil { return nil, err } - // GetRun does not echo back the RunNow request, so the embedded RunNow is - // left zero here; the remote identity lives in RunId. - var emptyRunNow jobs.RunNow - return &JobRunRemote{RunNow: emptyRunNow, RunId: run.RunId}, nil + // Map the run back into the RunNow shape so the framework can diff the run's + // actual parameters against the desired config. GetRun does not return the + // request-only fields (idempotency_token, only, performance_target, queue) or + // the synthetic job_settings snapshot; those are handled via + // ignore_remote_changes in resources.yml. + state := JobRunState{ + RunNow: jobs.RunNow{ + JobId: run.JobId, + JobParameters: jobParametersToMap(run.JobParameters), + }, + } + if p := run.OverridingParameters; p != nil { + state.DbtCommands = p.DbtCommands + state.JarParams = p.JarParams + state.NotebookParams = p.NotebookParams + state.PipelineParams = p.PipelineParams + state.PythonNamedParams = p.PythonNamedParams + state.PythonParams = p.PythonParams + state.SparkSubmitParams = p.SparkSubmitParams + state.SqlParams = p.SqlParams + } + return &JobRunRemote{JobRunState: state, RunId: run.RunId}, nil } -func (r *ResourceJobRun) DoCreate(ctx context.Context, config *jobs.RunNow) (string, *JobRunRemote, error) { +func (r *ResourceJobRun) DoCreate(ctx context.Context, config *JobRunState) (string, *JobRunRemote, error) { + // Only the RunNow request is sent to the backend; JobSettings is a local-only + // snapshot used to detect job changes, not part of the run-now payload. // RunNow returns immediately with the new run id; waiting for completion is // a later milestone. - wait, err := r.client.Jobs.RunNow(ctx, *config) + wait, err := r.client.Jobs.RunNow(ctx, config.RunNow) if err != nil { return "", nil, err } @@ -87,7 +144,7 @@ func (r *ResourceJobRun) DoCreate(ctx context.Context, config *jobs.RunNow) (str // DoDelete is a no-op: a triggered run cannot be "undeployed". On recreate the // framework calls this before DoCreate, so a no-op delete followed by RunNow // re-triggers the run, which is the intended behavior. -func (r *ResourceJobRun) DoDelete(ctx context.Context, id string, _ *jobs.RunNow) error { +func (r *ResourceJobRun) DoDelete(ctx context.Context, id string, _ *JobRunState) error { return nil } diff --git a/bundle/direct/dresources/resources.yml b/bundle/direct/dresources/resources.yml index cf850d8851b..454e04b4697 100644 --- a/bundle/direct/dresources/resources.yml +++ b/bundle/direct/dresources/resources.yml @@ -117,38 +117,23 @@ resources: - field: job_clusters[*].new_cluster.data_security_mode job_runs: - # GetRun returns the run's execution metadata, never the RunNow request that - # triggered it. So on every plan the request fields look like remote drift. - # Ignore that drift (input_only): the request fields are write-only inputs. + # GetRun echoes the run's job-level and overriding parameters, so DoRead maps + # those back (see RemapState) and the framework diffs them directly. Only the + # fields GetRun does NOT return are ignored here: the request-only inputs that + # never appear in the run, plus the synthetic job_settings snapshot. ignore_remote_changes: - - field: dbt_commands - reason: input_only - field: idempotency_token reason: input_only - - field: jar_params - reason: input_only - - field: job_id - reason: input_only - - field: job_parameters - reason: input_only - - field: notebook_params + # Local-only snapshot of the targeted job's settings; GetRun never returns + # it, so it always looks like remote drift unless ignored here. + - field: job_settings reason: input_only - field: only reason: input_only - field: performance_target reason: input_only - - field: pipeline_params - reason: input_only - - field: python_named_params - reason: input_only - - field: python_params - reason: input_only - field: queue reason: input_only - - field: spark_submit_params - reason: input_only - - field: sql_params - reason: input_only # There is no API to modify a run in place, so any change to the request must # re-trigger a fresh run. With no DoUpdate, recreate (no-op delete + RunNow) # is the only path; every request field is marked immutable here. @@ -163,6 +148,10 @@ resources: reason: immutable - field: job_parameters reason: immutable + # A change to the targeted job's settings snapshot must re-trigger the run; + # prefix matching means any nested job field counts as a change. + - field: job_settings + reason: immutable - field: notebook_params reason: immutable - field: only diff --git a/bundle/internal/schema/annotations.yml b/bundle/internal/schema/annotations.yml index 3adb9e9e740..2aa564372d5 100644 --- a/bundle/internal/schema/annotations.yml +++ b/bundle/internal/schema/annotations.yml @@ -788,6 +788,19 @@ resources: "warehouse_id": "description": |- ID of the SQL warehouse used to run queries for this Genie space. + "job_runs": + "description": |- + PLACEHOLDER + "$fields": + "job_settings": + "description": |- + PLACEHOLDER + "lifecycle": + "description": |- + PLACEHOLDER + "python_named_params": + "description": |- + PLACEHOLDER "jobs": "description": |- The job definitions for the bundle, where each key is the name of the job. diff --git a/bundle/internal/validation/generated/enum_fields.go b/bundle/internal/validation/generated/enum_fields.go index 0509372f157..d605d98a00c 100644 --- a/bundle/internal/validation/generated/enum_fields.go +++ b/bundle/internal/validation/generated/enum_fields.go @@ -64,7 +64,72 @@ var EnumFields = map[string][]string{ "resources.genie_spaces.*.permissions[*].level": {"CAN_ATTACH_TO", "CAN_BIND", "CAN_CREATE", "CAN_CREATE_APP", "CAN_EDIT", "CAN_EDIT_METADATA", "CAN_MANAGE", "CAN_MANAGE_PRODUCTION_VERSIONS", "CAN_MANAGE_RUN", "CAN_MANAGE_STAGING_VERSIONS", "CAN_MONITOR", "CAN_MONITOR_ONLY", "CAN_QUERY", "CAN_READ", "CAN_RESTART", "CAN_RUN", "CAN_USE", "CAN_VIEW", "CAN_VIEW_METADATA", "IS_OWNER"}, - "resources.job_runs.*.performance_target": {"PERFORMANCE_OPTIMIZED", "STANDARD"}, + "resources.job_runs.*.job_settings.continuous.pause_status": {"PAUSED", "UNPAUSED"}, + "resources.job_runs.*.job_settings.continuous.task_retry_mode": {"NEVER", "ON_FAILURE"}, + "resources.job_runs.*.job_settings.deployment.kind": {"BUNDLE", "SYSTEM_MANAGED"}, + "resources.job_runs.*.job_settings.edit_mode": {"EDITABLE", "UI_LOCKED"}, + "resources.job_runs.*.job_settings.format": {"MULTI_TASK", "SINGLE_TASK"}, + "resources.job_runs.*.job_settings.git_source.git_provider": {"awsCodeCommit", "azureDevOpsServices", "bitbucketCloud", "bitbucketServer", "gitHub", "gitHubEnterprise", "gitLab", "gitLabEnterpriseEdition"}, + "resources.job_runs.*.job_settings.git_source.job_source.dirty_state": {"DISCONNECTED", "NOT_SYNCED"}, + "resources.job_runs.*.job_settings.health.rules[*].metric": {"RUN_DURATION_SECONDS", "STREAMING_BACKLOG_BYTES", "STREAMING_BACKLOG_FILES", "STREAMING_BACKLOG_RECORDS", "STREAMING_BACKLOG_SECONDS"}, + "resources.job_runs.*.job_settings.health.rules[*].op": {"GREATER_THAN"}, + "resources.job_runs.*.job_settings.job_clusters[*].new_cluster.aws_attributes.availability": {"ON_DEMAND", "SPOT", "SPOT_WITH_FALLBACK"}, + "resources.job_runs.*.job_settings.job_clusters[*].new_cluster.aws_attributes.ebs_volume_type": {"GENERAL_PURPOSE_SSD", "THROUGHPUT_OPTIMIZED_HDD"}, + "resources.job_runs.*.job_settings.job_clusters[*].new_cluster.azure_attributes.availability": {"ON_DEMAND_AZURE", "SPOT_AZURE", "SPOT_WITH_FALLBACK_AZURE"}, + "resources.job_runs.*.job_settings.job_clusters[*].new_cluster.data_security_mode": {"DATA_SECURITY_MODE_AUTO", "DATA_SECURITY_MODE_DEDICATED", "DATA_SECURITY_MODE_STANDARD", "LEGACY_PASSTHROUGH", "LEGACY_SINGLE_USER", "LEGACY_SINGLE_USER_STANDARD", "LEGACY_TABLE_ACL", "NONE", "SINGLE_USER", "USER_ISOLATION"}, + "resources.job_runs.*.job_settings.job_clusters[*].new_cluster.gcp_attributes.availability": {"ON_DEMAND_GCP", "PREEMPTIBLE_GCP", "PREEMPTIBLE_WITH_FALLBACK_GCP"}, + "resources.job_runs.*.job_settings.job_clusters[*].new_cluster.gcp_attributes.confidential_compute_type": {"CONFIDENTIAL_COMPUTE_TYPE_NONE", "SEV_SNP"}, + "resources.job_runs.*.job_settings.job_clusters[*].new_cluster.kind": {"CLASSIC_PREVIEW"}, + "resources.job_runs.*.job_settings.job_clusters[*].new_cluster.runtime_engine": {"NULL", "PHOTON", "STANDARD"}, + "resources.job_runs.*.job_settings.performance_target": {"PERFORMANCE_OPTIMIZED", "STANDARD"}, + "resources.job_runs.*.job_settings.schedule.pause_status": {"PAUSED", "UNPAUSED"}, + "resources.job_runs.*.job_settings.tasks[*].compute.hardware_accelerator": {"GPU_1xA10", "GPU_8xH100"}, + "resources.job_runs.*.job_settings.tasks[*].condition_task.op": {"EQUAL_TO", "GREATER_THAN", "GREATER_THAN_OR_EQUAL", "LESS_THAN", "LESS_THAN_OR_EQUAL", "NOT_EQUAL"}, + "resources.job_runs.*.job_settings.tasks[*].dbt_task.source": {"GIT", "WORKSPACE"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.compute.hardware_accelerator": {"GPU_1xA10", "GPU_8xH100"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.condition_task.op": {"EQUAL_TO", "GREATER_THAN", "GREATER_THAN_OR_EQUAL", "LESS_THAN", "LESS_THAN_OR_EQUAL", "NOT_EQUAL"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.dbt_task.source": {"GIT", "WORKSPACE"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.gen_ai_compute_task.source": {"GIT", "WORKSPACE"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.health.rules[*].metric": {"RUN_DURATION_SECONDS", "STREAMING_BACKLOG_BYTES", "STREAMING_BACKLOG_FILES", "STREAMING_BACKLOG_RECORDS", "STREAMING_BACKLOG_SECONDS"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.health.rules[*].op": {"GREATER_THAN"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.aws_attributes.availability": {"ON_DEMAND", "SPOT", "SPOT_WITH_FALLBACK"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.aws_attributes.ebs_volume_type": {"GENERAL_PURPOSE_SSD", "THROUGHPUT_OPTIMIZED_HDD"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.azure_attributes.availability": {"ON_DEMAND_AZURE", "SPOT_AZURE", "SPOT_WITH_FALLBACK_AZURE"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.data_security_mode": {"DATA_SECURITY_MODE_AUTO", "DATA_SECURITY_MODE_DEDICATED", "DATA_SECURITY_MODE_STANDARD", "LEGACY_PASSTHROUGH", "LEGACY_SINGLE_USER", "LEGACY_SINGLE_USER_STANDARD", "LEGACY_TABLE_ACL", "NONE", "SINGLE_USER", "USER_ISOLATION"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.gcp_attributes.availability": {"ON_DEMAND_GCP", "PREEMPTIBLE_GCP", "PREEMPTIBLE_WITH_FALLBACK_GCP"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.gcp_attributes.confidential_compute_type": {"CONFIDENTIAL_COMPUTE_TYPE_NONE", "SEV_SNP"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.kind": {"CLASSIC_PREVIEW"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.runtime_engine": {"NULL", "PHOTON", "STANDARD"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.notebook_task.source": {"GIT", "WORKSPACE"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.power_bi_task.power_bi_model.authentication_method": {"OAUTH", "PAT"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.power_bi_task.power_bi_model.storage_mode": {"DIRECT_QUERY", "DUAL", "IMPORT"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.power_bi_task.tables[*].storage_mode": {"DIRECT_QUERY", "DUAL", "IMPORT"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.run_if": {"ALL_DONE", "ALL_FAILED", "ALL_SUCCESS", "AT_LEAST_ONE_FAILED", "AT_LEAST_ONE_SUCCESS", "NONE_FAILED"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.spark_python_task.source": {"GIT", "WORKSPACE"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.sql_task.file.source": {"GIT", "WORKSPACE"}, + "resources.job_runs.*.job_settings.tasks[*].gen_ai_compute_task.source": {"GIT", "WORKSPACE"}, + "resources.job_runs.*.job_settings.tasks[*].health.rules[*].metric": {"RUN_DURATION_SECONDS", "STREAMING_BACKLOG_BYTES", "STREAMING_BACKLOG_FILES", "STREAMING_BACKLOG_RECORDS", "STREAMING_BACKLOG_SECONDS"}, + "resources.job_runs.*.job_settings.tasks[*].health.rules[*].op": {"GREATER_THAN"}, + "resources.job_runs.*.job_settings.tasks[*].new_cluster.aws_attributes.availability": {"ON_DEMAND", "SPOT", "SPOT_WITH_FALLBACK"}, + "resources.job_runs.*.job_settings.tasks[*].new_cluster.aws_attributes.ebs_volume_type": {"GENERAL_PURPOSE_SSD", "THROUGHPUT_OPTIMIZED_HDD"}, + "resources.job_runs.*.job_settings.tasks[*].new_cluster.azure_attributes.availability": {"ON_DEMAND_AZURE", "SPOT_AZURE", "SPOT_WITH_FALLBACK_AZURE"}, + "resources.job_runs.*.job_settings.tasks[*].new_cluster.data_security_mode": {"DATA_SECURITY_MODE_AUTO", "DATA_SECURITY_MODE_DEDICATED", "DATA_SECURITY_MODE_STANDARD", "LEGACY_PASSTHROUGH", "LEGACY_SINGLE_USER", "LEGACY_SINGLE_USER_STANDARD", "LEGACY_TABLE_ACL", "NONE", "SINGLE_USER", "USER_ISOLATION"}, + "resources.job_runs.*.job_settings.tasks[*].new_cluster.gcp_attributes.availability": {"ON_DEMAND_GCP", "PREEMPTIBLE_GCP", "PREEMPTIBLE_WITH_FALLBACK_GCP"}, + "resources.job_runs.*.job_settings.tasks[*].new_cluster.gcp_attributes.confidential_compute_type": {"CONFIDENTIAL_COMPUTE_TYPE_NONE", "SEV_SNP"}, + "resources.job_runs.*.job_settings.tasks[*].new_cluster.kind": {"CLASSIC_PREVIEW"}, + "resources.job_runs.*.job_settings.tasks[*].new_cluster.runtime_engine": {"NULL", "PHOTON", "STANDARD"}, + "resources.job_runs.*.job_settings.tasks[*].notebook_task.source": {"GIT", "WORKSPACE"}, + "resources.job_runs.*.job_settings.tasks[*].power_bi_task.power_bi_model.authentication_method": {"OAUTH", "PAT"}, + "resources.job_runs.*.job_settings.tasks[*].power_bi_task.power_bi_model.storage_mode": {"DIRECT_QUERY", "DUAL", "IMPORT"}, + "resources.job_runs.*.job_settings.tasks[*].power_bi_task.tables[*].storage_mode": {"DIRECT_QUERY", "DUAL", "IMPORT"}, + "resources.job_runs.*.job_settings.tasks[*].run_if": {"ALL_DONE", "ALL_FAILED", "ALL_SUCCESS", "AT_LEAST_ONE_FAILED", "AT_LEAST_ONE_SUCCESS", "NONE_FAILED"}, + "resources.job_runs.*.job_settings.tasks[*].spark_python_task.source": {"GIT", "WORKSPACE"}, + "resources.job_runs.*.job_settings.tasks[*].sql_task.file.source": {"GIT", "WORKSPACE"}, + "resources.job_runs.*.job_settings.trigger.model.condition": {"MODEL_ALIAS_SET", "MODEL_CREATED", "MODEL_VERSION_READY"}, + "resources.job_runs.*.job_settings.trigger.pause_status": {"PAUSED", "UNPAUSED"}, + "resources.job_runs.*.job_settings.trigger.periodic.unit": {"DAYS", "HOURS", "WEEKS"}, + "resources.job_runs.*.job_settings.trigger.table_update.condition": {"ALL_UPDATED", "ANY_UPDATED"}, + "resources.job_runs.*.performance_target": {"PERFORMANCE_OPTIMIZED", "STANDARD"}, "resources.jobs.*.continuous.pause_status": {"PAUSED", "UNPAUSED"}, "resources.jobs.*.continuous.task_retry_mode": {"NEVER", "ON_FAILURE"}, diff --git a/bundle/internal/validation/generated/required_fields.go b/bundle/internal/validation/generated/required_fields.go index c80a433422c..ba367d33532 100644 --- a/bundle/internal/validation/generated/required_fields.go +++ b/bundle/internal/validation/generated/required_fields.go @@ -66,7 +66,112 @@ var RequiredFields = map[string][]string{ "resources.genie_spaces.*.permissions[*]": {"level"}, - "resources.job_runs.*": {"job_id"}, + "resources.job_runs.*": {"job_id"}, + "resources.job_runs.*.job_settings.deployment": {"kind"}, + "resources.job_runs.*.job_settings.environments[*]": {"environment_key"}, + "resources.job_runs.*.job_settings.git_source": {"git_provider", "git_url"}, + "resources.job_runs.*.job_settings.git_source.job_source": {"import_from_git_branch", "job_config_path"}, + "resources.job_runs.*.job_settings.health.rules[*]": {"metric", "op", "value"}, + "resources.job_runs.*.job_settings.job_clusters[*]": {"job_cluster_key", "new_cluster"}, + "resources.job_runs.*.job_settings.job_clusters[*].new_cluster.cluster_log_conf.dbfs": {"destination"}, + "resources.job_runs.*.job_settings.job_clusters[*].new_cluster.cluster_log_conf.s3": {"destination"}, + "resources.job_runs.*.job_settings.job_clusters[*].new_cluster.cluster_log_conf.volumes": {"destination"}, + "resources.job_runs.*.job_settings.job_clusters[*].new_cluster.init_scripts[*].abfss": {"destination"}, + "resources.job_runs.*.job_settings.job_clusters[*].new_cluster.init_scripts[*].dbfs": {"destination"}, + "resources.job_runs.*.job_settings.job_clusters[*].new_cluster.init_scripts[*].file": {"destination"}, + "resources.job_runs.*.job_settings.job_clusters[*].new_cluster.init_scripts[*].gcs": {"destination"}, + "resources.job_runs.*.job_settings.job_clusters[*].new_cluster.init_scripts[*].s3": {"destination"}, + "resources.job_runs.*.job_settings.job_clusters[*].new_cluster.init_scripts[*].volumes": {"destination"}, + "resources.job_runs.*.job_settings.job_clusters[*].new_cluster.init_scripts[*].workspace": {"destination"}, + "resources.job_runs.*.job_settings.job_clusters[*].new_cluster.workload_type": {"clients"}, + "resources.job_runs.*.job_settings.parameters[*]": {"default", "name"}, + "resources.job_runs.*.job_settings.queue": {"enabled"}, + "resources.job_runs.*.job_settings.schedule": {"quartz_cron_expression", "timezone_id"}, + "resources.job_runs.*.job_settings.tasks[*]": {"task_key"}, + "resources.job_runs.*.job_settings.tasks[*].clean_rooms_notebook_task": {"clean_room_name", "notebook_name"}, + "resources.job_runs.*.job_settings.tasks[*].condition_task": {"left", "op", "right"}, + "resources.job_runs.*.job_settings.tasks[*].dbt_task": {"commands"}, + "resources.job_runs.*.job_settings.tasks[*].depends_on[*]": {"task_key"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task": {"inputs", "task"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task": {"task_key"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.clean_rooms_notebook_task": {"clean_room_name", "notebook_name"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.condition_task": {"left", "op", "right"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.dbt_task": {"commands"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.depends_on[*]": {"task_key"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.for_each_task": {"inputs", "task"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.gen_ai_compute_task": {"dl_runtime_image"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.gen_ai_compute_task.compute": {"num_gpus"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.health.rules[*]": {"metric", "op", "value"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.libraries[*].cran": {"package"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.libraries[*].maven": {"coordinates"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.libraries[*].pypi": {"package"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.cluster_log_conf.dbfs": {"destination"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.cluster_log_conf.s3": {"destination"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.cluster_log_conf.volumes": {"destination"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.init_scripts[*].abfss": {"destination"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.init_scripts[*].dbfs": {"destination"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.init_scripts[*].file": {"destination"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.init_scripts[*].gcs": {"destination"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.init_scripts[*].s3": {"destination"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.init_scripts[*].volumes": {"destination"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.init_scripts[*].workspace": {"destination"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.workload_type": {"clients"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.notebook_task": {"notebook_path"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.pipeline_task": {"pipeline_id"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.python_wheel_task": {"entry_point", "package_name"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.run_job_task": {"job_id"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.spark_python_task": {"python_file"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.sql_task": {"warehouse_id"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.sql_task.alert": {"alert_id"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.sql_task.dashboard": {"dashboard_id"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.sql_task.file": {"path"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.sql_task.query": {"query_id"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.webhook_notifications.on_duration_warning_threshold_exceeded[*]": {"id"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.webhook_notifications.on_failure[*]": {"id"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.webhook_notifications.on_start[*]": {"id"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.webhook_notifications.on_streaming_backlog_exceeded[*]": {"id"}, + "resources.job_runs.*.job_settings.tasks[*].for_each_task.task.webhook_notifications.on_success[*]": {"id"}, + "resources.job_runs.*.job_settings.tasks[*].gen_ai_compute_task": {"dl_runtime_image"}, + "resources.job_runs.*.job_settings.tasks[*].gen_ai_compute_task.compute": {"num_gpus"}, + "resources.job_runs.*.job_settings.tasks[*].health.rules[*]": {"metric", "op", "value"}, + "resources.job_runs.*.job_settings.tasks[*].libraries[*].cran": {"package"}, + "resources.job_runs.*.job_settings.tasks[*].libraries[*].maven": {"coordinates"}, + "resources.job_runs.*.job_settings.tasks[*].libraries[*].pypi": {"package"}, + "resources.job_runs.*.job_settings.tasks[*].new_cluster.cluster_log_conf.dbfs": {"destination"}, + "resources.job_runs.*.job_settings.tasks[*].new_cluster.cluster_log_conf.s3": {"destination"}, + "resources.job_runs.*.job_settings.tasks[*].new_cluster.cluster_log_conf.volumes": {"destination"}, + "resources.job_runs.*.job_settings.tasks[*].new_cluster.init_scripts[*].abfss": {"destination"}, + "resources.job_runs.*.job_settings.tasks[*].new_cluster.init_scripts[*].dbfs": {"destination"}, + "resources.job_runs.*.job_settings.tasks[*].new_cluster.init_scripts[*].file": {"destination"}, + "resources.job_runs.*.job_settings.tasks[*].new_cluster.init_scripts[*].gcs": {"destination"}, + "resources.job_runs.*.job_settings.tasks[*].new_cluster.init_scripts[*].s3": {"destination"}, + "resources.job_runs.*.job_settings.tasks[*].new_cluster.init_scripts[*].volumes": {"destination"}, + "resources.job_runs.*.job_settings.tasks[*].new_cluster.init_scripts[*].workspace": {"destination"}, + "resources.job_runs.*.job_settings.tasks[*].new_cluster.workload_type": {"clients"}, + "resources.job_runs.*.job_settings.tasks[*].notebook_task": {"notebook_path"}, + "resources.job_runs.*.job_settings.tasks[*].pipeline_task": {"pipeline_id"}, + "resources.job_runs.*.job_settings.tasks[*].python_wheel_task": {"entry_point", "package_name"}, + "resources.job_runs.*.job_settings.tasks[*].run_job_task": {"job_id"}, + "resources.job_runs.*.job_settings.tasks[*].spark_python_task": {"python_file"}, + "resources.job_runs.*.job_settings.tasks[*].sql_task": {"warehouse_id"}, + "resources.job_runs.*.job_settings.tasks[*].sql_task.alert": {"alert_id"}, + "resources.job_runs.*.job_settings.tasks[*].sql_task.dashboard": {"dashboard_id"}, + "resources.job_runs.*.job_settings.tasks[*].sql_task.file": {"path"}, + "resources.job_runs.*.job_settings.tasks[*].sql_task.query": {"query_id"}, + "resources.job_runs.*.job_settings.tasks[*].webhook_notifications.on_duration_warning_threshold_exceeded[*]": {"id"}, + "resources.job_runs.*.job_settings.tasks[*].webhook_notifications.on_failure[*]": {"id"}, + "resources.job_runs.*.job_settings.tasks[*].webhook_notifications.on_start[*]": {"id"}, + "resources.job_runs.*.job_settings.tasks[*].webhook_notifications.on_streaming_backlog_exceeded[*]": {"id"}, + "resources.job_runs.*.job_settings.tasks[*].webhook_notifications.on_success[*]": {"id"}, + "resources.job_runs.*.job_settings.trigger.file_arrival": {"url"}, + "resources.job_runs.*.job_settings.trigger.model": {"condition"}, + "resources.job_runs.*.job_settings.trigger.periodic": {"interval", "unit"}, + "resources.job_runs.*.job_settings.trigger.table_update": {"table_names"}, + "resources.job_runs.*.job_settings.webhook_notifications.on_duration_warning_threshold_exceeded[*]": {"id"}, + "resources.job_runs.*.job_settings.webhook_notifications.on_failure[*]": {"id"}, + "resources.job_runs.*.job_settings.webhook_notifications.on_start[*]": {"id"}, + "resources.job_runs.*.job_settings.webhook_notifications.on_streaming_backlog_exceeded[*]": {"id"}, + "resources.job_runs.*.job_settings.webhook_notifications.on_success[*]": {"id"}, "resources.job_runs.*.queue": {"enabled"}, "resources.jobs.*.deployment": {"kind"}, diff --git a/bundle/schema/jsonschema.json b/bundle/schema/jsonschema.json index 67b2817b984..d7ecad4ac68 100644 --- a/bundle/schema/jsonschema.json +++ b/bundle/schema/jsonschema.json @@ -1000,7 +1000,7 @@ "dbt_commands": { "description": "[Private Preview] An array of commands to execute for jobs with the dbt task, for example `\"dbt_commands\": [\"dbt deps\", \"dbt seed\", \"dbt deps\", \"dbt seed\", \"dbt run\"]`\n\n⚠ **Deprecation note** Use [job parameters](https://docs.databricks.com/jobs/job-parameters.html#job-parameter-pushdown) to pass information down to tasks.", "$ref": "#/$defs/slice/string", - "x-databricks-preview": "PRIVATE", + "x-databricks-launch-stage": "PRIVATE_PREVIEW", "deprecationMessage": "This field is deprecated", "doNotSuggest": true, "deprecated": true @@ -1012,7 +1012,7 @@ "jar_params": { "description": "[Private Preview] A list of parameters for jobs with Spark JAR tasks, for example `\"jar_params\": [\"john doe\", \"35\"]`.\nThe parameters are used to invoke the main function of the main class specified in the Spark JAR task.\nIf not specified upon `run-now`, it defaults to an empty list.\njar_params cannot be specified in conjunction with notebook_params.\nThe JSON representation of this field (for example `{\"jar_params\":[\"john doe\",\"35\"]}`) cannot exceed 10,000 bytes.\n\n⚠ **Deprecation note** Use [job parameters](https://docs.databricks.com/jobs/job-parameters.html#job-parameter-pushdown) to pass information down to tasks.", "$ref": "#/$defs/slice/string", - "x-databricks-preview": "PRIVATE", + "x-databricks-launch-stage": "PRIVATE_PREVIEW", "deprecationMessage": "This field is deprecated", "doNotSuggest": true, "deprecated": true @@ -1025,14 +1025,16 @@ "description": "Job-level parameters used in the run. for example `\"param\": \"overriding_val\"`", "$ref": "#/$defs/map/string" }, + "job_settings": { + "$ref": "#/$defs/github.com/databricks/databricks-sdk-go/service/jobs.JobSettings" + }, "lifecycle": { - "description": "Lifecycle is a struct that contains the lifecycle settings for a resource. It controls the behavior of the resource when it is deployed or destroyed.", "$ref": "#/$defs/github.com/databricks/cli/bundle/config/resources.Lifecycle" }, "notebook_params": { "description": "[Private Preview] A map from keys to values for jobs with notebook task, for example `\"notebook_params\": {\"name\": \"john doe\", \"age\": \"35\"}`.\nThe map is passed to the notebook and is accessible through the [dbutils.widgets.get](https://docs.databricks.com/dev-tools/databricks-utils.html) function.\n\nIf not specified upon `run-now`, the triggered run uses the job’s base parameters.\n\nnotebook_params cannot be specified in conjunction with jar_params.\n\n⚠ **Deprecation note** Use [job parameters](https://docs.databricks.com/jobs/job-parameters.html#job-parameter-pushdown) to pass information down to tasks.\n\nThe JSON representation of this field (for example `{\"notebook_params\":{\"name\":\"john doe\",\"age\":\"35\"}}`) cannot exceed 10,000 bytes.", "$ref": "#/$defs/map/string", - "x-databricks-preview": "PRIVATE", + "x-databricks-launch-stage": "PRIVATE_PREVIEW", "deprecationMessage": "This field is deprecated", "doNotSuggest": true, "deprecated": true @@ -1050,9 +1052,9 @@ "$ref": "#/$defs/github.com/databricks/databricks-sdk-go/service/jobs.PipelineParams" }, "python_named_params": { - "description": "[Private Preview] A map from keys to values for jobs with Python wheel tasks, for example `\"python_named_params\": {\"name\": \"task\", \"data\": \"dbfs:/path/to/data.json\"}`.", + "description": "[Private Preview]", "$ref": "#/$defs/map/string", - "x-databricks-preview": "PRIVATE", + "x-databricks-launch-stage": "PRIVATE_PREVIEW", "deprecationMessage": "This field is deprecated", "doNotSuggest": true, "deprecated": true @@ -1060,7 +1062,7 @@ "python_params": { "description": "[Private Preview] A list of parameters for jobs with Python tasks, for example `\"python_params\": [\"john doe\", \"35\"]`.\nThe parameters are passed to Python file as command-line parameters. If specified upon `run-now`, it would overwrite\nthe parameters specified in job setting. The JSON representation of this field (for example `{\"python_params\":[\"john doe\",\"35\"]}`)\ncannot exceed 10,000 bytes.\n\n⚠ **Deprecation note** Use [job parameters](https://docs.databricks.com/jobs/job-parameters.html#job-parameter-pushdown) to pass information down to tasks.\n\nImportant\n\nThese parameters accept only Latin characters (ASCII character set). Using non-ASCII characters returns an error.\nExamples of invalid, non-ASCII characters are Chinese, Japanese kanjis, and emojis.", "$ref": "#/$defs/slice/string", - "x-databricks-preview": "PRIVATE", + "x-databricks-launch-stage": "PRIVATE_PREVIEW", "deprecationMessage": "This field is deprecated", "doNotSuggest": true, "deprecated": true @@ -1072,7 +1074,7 @@ "spark_submit_params": { "description": "[Private Preview] A list of parameters for jobs with spark submit task, for example `\"spark_submit_params\": [\"--class\", \"org.apache.spark.examples.SparkPi\"]`.\nThe parameters are passed to spark-submit script as command-line parameters. If specified upon `run-now`, it would overwrite the\nparameters specified in job setting. The JSON representation of this field (for example `{\"python_params\":[\"john doe\",\"35\"]}`)\ncannot exceed 10,000 bytes.\n\n⚠ **Deprecation note** Use [job parameters](https://docs.databricks.com/jobs/job-parameters.html#job-parameter-pushdown) to pass information down to tasks.\n\nImportant\n\nThese parameters accept only Latin characters (ASCII character set). Using non-ASCII characters returns an error.\nExamples of invalid, non-ASCII characters are Chinese, Japanese kanjis, and emojis.", "$ref": "#/$defs/slice/string", - "x-databricks-preview": "PRIVATE", + "x-databricks-launch-stage": "PRIVATE_PREVIEW", "deprecationMessage": "This field is deprecated", "doNotSuggest": true, "deprecated": true @@ -1080,7 +1082,7 @@ "sql_params": { "description": "[Private Preview] A map from keys to values for jobs with SQL task, for example `\"sql_params\": {\"name\": \"john doe\", \"age\": \"35\"}`. The SQL alert task does not support custom parameters.\n\n⚠ **Deprecation note** Use [job parameters](https://docs.databricks.com/jobs/job-parameters.html#job-parameter-pushdown) to pass information down to tasks.", "$ref": "#/$defs/map/string", - "x-databricks-preview": "PRIVATE", + "x-databricks-launch-stage": "PRIVATE_PREVIEW", "deprecationMessage": "This field is deprecated", "doNotSuggest": true, "deprecated": true @@ -2986,7 +2988,6 @@ "$ref": "#/$defs/map/github.com/databricks/cli/bundle/config/resources.GenieSpace" }, "job_runs": { - "description": "The job run definitions for the bundle, where each key is the name of the job run.", "$ref": "#/$defs/map/github.com/databricks/cli/bundle/config/resources.JobRun" }, "jobs": { @@ -7191,6 +7192,124 @@ } ] }, + "jobs.JobSettings": { + "oneOf": [ + { + "type": "object", + "properties": { + "budget_policy_id": { + "description": "[Public Preview] The id of the user specified budget policy to use for this job.\nIf not specified, a default budget policy may be applied when creating or modifying the job.\nSee `effective_budget_policy_id` for the budget policy used by this workload.", + "$ref": "#/$defs/string" + }, + "continuous": { + "description": "An optional continuous property for this job. The continuous property will ensure that there is always one run executing. Only one of `schedule` and `continuous` can be used.", + "$ref": "#/$defs/github.com/databricks/databricks-sdk-go/service/jobs.Continuous" + }, + "deployment": { + "description": "Deployment information for jobs managed by external sources.", + "$ref": "#/$defs/github.com/databricks/databricks-sdk-go/service/jobs.JobDeployment" + }, + "description": { + "description": "An optional description for the job. The maximum length is 27700 characters in UTF-8 encoding.", + "$ref": "#/$defs/string" + }, + "edit_mode": { + "description": "Edit mode of the job.\n\n* `UI_LOCKED`: The job is in a locked UI state and cannot be modified.\n* `EDITABLE`: The job is in an editable state and can be modified.", + "$ref": "#/$defs/github.com/databricks/databricks-sdk-go/service/jobs.JobEditMode" + }, + "email_notifications": { + "description": "An optional set of email addresses that is notified when runs of this job begin or complete as well as when this job is deleted.", + "$ref": "#/$defs/github.com/databricks/databricks-sdk-go/service/jobs.JobEmailNotifications" + }, + "environments": { + "description": "A list of task execution environment specifications that can be referenced by serverless tasks of this job.\nFor serverless notebook tasks, if the environment_key is not specified, the notebook environment will be used if present. If a jobs environment is specified, it will override the notebook environment.\nFor other serverless tasks, the task environment is required to be specified using environment_key in the task settings.", + "$ref": "#/$defs/slice/github.com/databricks/databricks-sdk-go/service/jobs.JobEnvironment" + }, + "format": { + "description": "Used to tell what is the format of the job. This field is ignored in Create/Update/Reset calls. When using the Jobs API 2.1 this value is always set to `\"MULTI_TASK\"`.", + "$ref": "#/$defs/github.com/databricks/databricks-sdk-go/service/jobs.Format", + "deprecationMessage": "This field is deprecated", + "deprecated": true + }, + "git_source": { + "description": "An optional specification for a remote Git repository containing the source code used by tasks. Version-controlled source code is supported by notebook, dbt, Python script, and SQL File tasks.\n\nIf `git_source` is set, these tasks retrieve the file from the remote repository by default. However, this behavior can be overridden by setting `source` to `WORKSPACE` on the task.\n\nNote: dbt and SQL File tasks support only version-controlled sources. If dbt or SQL File tasks are used, `git_source` must be defined on the job.", + "$ref": "#/$defs/github.com/databricks/databricks-sdk-go/service/jobs.GitSource" + }, + "health": { + "description": "An optional set of health rules that can be defined for this job.", + "$ref": "#/$defs/github.com/databricks/databricks-sdk-go/service/jobs.JobsHealthRules" + }, + "job_clusters": { + "description": "A list of job cluster specifications that can be shared and reused by tasks of this job. Libraries cannot be declared in a shared job cluster. You must declare dependent libraries in task settings.", + "$ref": "#/$defs/slice/github.com/databricks/databricks-sdk-go/service/jobs.JobCluster" + }, + "max_concurrent_runs": { + "description": "An optional maximum allowed number of concurrent runs of the job.\nSet this value if you want to be able to execute multiple runs of the same job concurrently.\nThis is useful for example if you trigger your job on a frequent schedule and want to allow consecutive runs to overlap with each other, or if you want to trigger multiple runs which differ by their input parameters.\nThis setting affects only new runs. For example, suppose the job’s concurrency is 4 and there are 4 concurrent active runs. Then setting the concurrency to 3 won’t kill any of the active runs.\nHowever, from then on, new runs are skipped unless there are fewer than 3 active runs.\nThis value cannot exceed 1000. Setting this value to `0` causes all new runs to be skipped.", + "$ref": "#/$defs/int" + }, + "name": { + "description": "An optional name for the job. The maximum length is 4096 bytes in UTF-8 encoding.", + "$ref": "#/$defs/string" + }, + "notification_settings": { + "description": "Optional notification settings that are used when sending notifications to each of the `email_notifications` and `webhook_notifications` for this job.", + "$ref": "#/$defs/github.com/databricks/databricks-sdk-go/service/jobs.JobNotificationSettings" + }, + "parameters": { + "description": "Job-level parameter definitions", + "$ref": "#/$defs/slice/github.com/databricks/databricks-sdk-go/service/jobs.JobParameterDefinition" + }, + "performance_target": { + "description": "The performance mode on a serverless job. This field determines the level of compute performance or cost-efficiency for the run.\nThe performance target does not apply to tasks that run on Serverless GPU compute.\n\n* `STANDARD`: Enables cost-efficient execution of serverless workloads.\n* `PERFORMANCE_OPTIMIZED`: Prioritizes fast startup and execution times through rapid scaling and optimized cluster performance.", + "$ref": "#/$defs/github.com/databricks/databricks-sdk-go/service/jobs.PerformanceTarget" + }, + "queue": { + "description": "The queue settings of the job.", + "$ref": "#/$defs/github.com/databricks/databricks-sdk-go/service/jobs.QueueSettings" + }, + "run_as": { + "description": "The user or service principal that the job runs as, if specified in the request.\nThis field indicates the explicit configuration of `run_as` for the job.\nTo find the value in all cases, explicit or implicit, use `run_as_user_name`.", + "$ref": "#/$defs/github.com/databricks/databricks-sdk-go/service/jobs.JobRunAs" + }, + "schedule": { + "description": "An optional periodic schedule for this job. The default behavior is that the job only runs when triggered by clicking “Run Now” in the Jobs UI or sending an API request to `runNow`.", + "$ref": "#/$defs/github.com/databricks/databricks-sdk-go/service/jobs.CronSchedule" + }, + "tags": { + "description": "A map of tags associated with the job. These are forwarded to the cluster as cluster tags for jobs clusters, and are subject to the same limitations as cluster tags. A maximum of 25 tags can be added to the job.", + "$ref": "#/$defs/map/string" + }, + "tasks": { + "description": "A list of task specifications to be executed by this job.\nIt supports up to 1000 elements in write endpoints (:method:jobs/create, :method:jobs/reset, :method:jobs/update, :method:jobs/submit).\nRead endpoints return only 100 tasks. If more than 100 tasks are available, you can paginate through them using :method:jobs/get. Use the `next_page_token` field at the object root to determine if more results are available.", + "$ref": "#/$defs/slice/github.com/databricks/databricks-sdk-go/service/jobs.Task" + }, + "timeout_seconds": { + "description": "An optional timeout applied to each run of this job. A value of `0` means no timeout.", + "$ref": "#/$defs/int" + }, + "trigger": { + "description": "A configuration to trigger a run when certain conditions are met. The default behavior is that the job runs only when triggered by clicking “Run Now” in the Jobs UI or sending an API request to `runNow`.", + "$ref": "#/$defs/github.com/databricks/databricks-sdk-go/service/jobs.TriggerSettings" + }, + "usage_policy_id": { + "description": "[Private Preview] The id of the user specified usage policy to use for this job.\nIf not specified, a default usage policy may be applied when creating or modifying the job.\nSee `effective_usage_policy_id` for the usage policy used by this workload.", + "$ref": "#/$defs/string", + "x-databricks-launch-stage": "PRIVATE_PREVIEW", + "doNotSuggest": true + }, + "webhook_notifications": { + "description": "A collection of system notification IDs to notify when runs of this job begin or complete.", + "$ref": "#/$defs/github.com/databricks/databricks-sdk-go/service/jobs.WebhookNotifications" + } + }, + "additionalProperties": false + }, + { + "type": "string", + "pattern": "\\$\\{(var(\\.\\p{L}+([-_]*[\\p{L}\\p{N}]+)*(\\[[0-9]+\\])*)+)\\}" + } + ] + }, "jobs.JobSource": { "oneOf": [ { diff --git a/libs/testserver/jobs.go b/libs/testserver/jobs.go index e9468f7f681..62211a0c497 100644 --- a/libs/testserver/jobs.go +++ b/libs/testserver/jobs.go @@ -324,18 +324,57 @@ func (s *FakeWorkspace) JobsRunNow(req Request) Response { } s.JobRuns[runId] = jobs.Run{ - RunId: runId, - JobId: request.JobId, - State: &jobs.RunState{LifeCycleState: jobs.RunLifeCycleStateRunning}, - RunPageUrl: fmt.Sprintf("%s/?o=900800700600#job/%d/run/%d", s.url, request.JobId, runId), - RunType: jobs.RunTypeJobRun, - RunName: runName, - Tasks: tasks, + RunId: runId, + JobId: request.JobId, + State: &jobs.RunState{LifeCycleState: jobs.RunLifeCycleStateRunning}, + RunPageUrl: fmt.Sprintf("%s/?o=900800700600#job/%d/run/%d", s.url, request.JobId, runId), + RunType: jobs.RunTypeJobRun, + RunName: runName, + Tasks: tasks, + JobParameters: runJobParameters(request.JobParameters), + OverridingParameters: runOverridingParameters(request), } return Response{Body: jobs.RunNowResponse{RunId: runId}} } +// runJobParameters mirrors how GetRun echoes job-level parameters: as a list of +// name/value pairs. Sorted by name for deterministic output. +func runJobParameters(params map[string]string) []jobs.JobParameter { + if len(params) == 0 { + return nil + } + result := make([]jobs.JobParameter, 0, len(params)) + for name, value := range params { + result = append(result, jobs.JobParameter{Name: name, Value: value}) + } + slices.SortFunc(result, func(a, b jobs.JobParameter) int { + return cmp.Compare(a.Name, b.Name) + }) + return result +} + +// runOverridingParameters mirrors how GetRun echoes the run's overriding +// parameters. Returns nil when the request set none. +func runOverridingParameters(request jobs.RunNow) *jobs.RunParameters { + p := jobs.RunParameters{ + DbtCommands: request.DbtCommands, + JarParams: request.JarParams, + NotebookParams: request.NotebookParams, + PipelineParams: request.PipelineParams, + PythonNamedParams: request.PythonNamedParams, + PythonParams: request.PythonParams, + SparkSubmitParams: request.SparkSubmitParams, + SqlParams: request.SqlParams, + } + if len(p.DbtCommands) == 0 && len(p.JarParams) == 0 && len(p.NotebookParams) == 0 && + p.PipelineParams == nil && len(p.PythonNamedParams) == 0 && len(p.PythonParams) == 0 && + len(p.SparkSubmitParams) == 0 && len(p.SqlParams) == 0 { + return nil + } + return &p +} + // executePythonWheelTask runs a python wheel task locally using uv. // For tasks using existing_cluster_id, the venv is cached per cluster to match // cloud behavior where libraries are cached on running clusters. From 23e6afb76fb6e0308c98e64f9ae049e735e65ab5 Mon Sep 17 00:00:00 2001 From: Rada Kamysheva Date: Wed, 17 Jun 2026 15:04:54 +0000 Subject: [PATCH 11/17] direct: Fix job_runs CI lint and field-count test Avoid partial struct literals in job_run DoRead so exhaustruct passes, and raise the config.Root field-count upper bound now that job_runs snapshots a full job_settings. --- bundle/direct/dresources/job_run.go | 9 +++------ libs/structs/structwalk/walktype_test.go | 2 +- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/bundle/direct/dresources/job_run.go b/bundle/direct/dresources/job_run.go index 05c8f23c0c5..32b436fe397 100644 --- a/bundle/direct/dresources/job_run.go +++ b/bundle/direct/dresources/job_run.go @@ -106,12 +106,9 @@ func (r *ResourceJobRun) DoRead(ctx context.Context, id string) (*JobRunRemote, // request-only fields (idempotency_token, only, performance_target, queue) or // the synthetic job_settings snapshot; those are handled via // ignore_remote_changes in resources.yml. - state := JobRunState{ - RunNow: jobs.RunNow{ - JobId: run.JobId, - JobParameters: jobParametersToMap(run.JobParameters), - }, - } + var state JobRunState + state.JobId = run.JobId + state.JobParameters = jobParametersToMap(run.JobParameters) if p := run.OverridingParameters; p != nil { state.DbtCommands = p.DbtCommands state.JarParams = p.JarParams diff --git a/libs/structs/structwalk/walktype_test.go b/libs/structs/structwalk/walktype_test.go index 78ccc6c3f61..00f803be24c 100644 --- a/libs/structs/structwalk/walktype_test.go +++ b/libs/structs/structwalk/walktype_test.go @@ -136,7 +136,7 @@ func TestTypeJobSettings(t *testing.T) { func TestTypeRoot(t *testing.T) { testStruct(t, reflect.TypeFor[config.Root](), - 5000, 6000, // 5813 after genie_space resource added + 5000, 8000, // 7767 after job_runs resource added (snapshots a full job_settings) map[string]any{ "bundle.target": "", `variables.*.lookup.dashboard`: "", From 927b7bcb425f8ba38dc2a9b34c016723ba6e5a34 Mon Sep 17 00:00:00 2001 From: Rada Kamysheva Date: Thu, 18 Jun 2026 20:12:11 +0000 Subject: [PATCH 12/17] direct: Record only faithfully-echoed fields in job_runs DoRead DoRead now records the run's remote state as what we actually created: the job_id and the overriding parameters GetRun echoes back. It no longer maps run.JobParameters, which GetRun resolves to the job's full parameter set (including defaults the run never overrode) and which therefore does not represent what we created; that field is handled via ignore_remote_changes. The local diff (config vs saved state) still re-triggers a run on any job_parameters change via recreate_on_changes, independent of DoRead. The testserver now resolves the full parameter set like the real GetRun, and a new acceptance test asserts the resolved default does not look like drift. --- .../job_runs/job_parameters/databricks.yml | 26 ++++++++++ .../job_runs/job_parameters/out.test.toml | 3 ++ .../job_runs/job_parameters/output.txt | 49 +++++++++++++++++++ .../resources/job_runs/job_parameters/script | 13 +++++ .../job_runs/job_parameters/test.toml | 4 ++ bundle/direct/dresources/job_run.go | 32 +++++------- bundle/direct/dresources/resources.yml | 16 ++++-- libs/testserver/jobs.go | 31 +++++++++--- 8 files changed, 141 insertions(+), 33 deletions(-) create mode 100644 acceptance/bundle/resources/job_runs/job_parameters/databricks.yml create mode 100644 acceptance/bundle/resources/job_runs/job_parameters/out.test.toml create mode 100644 acceptance/bundle/resources/job_runs/job_parameters/output.txt create mode 100644 acceptance/bundle/resources/job_runs/job_parameters/script create mode 100644 acceptance/bundle/resources/job_runs/job_parameters/test.toml diff --git a/acceptance/bundle/resources/job_runs/job_parameters/databricks.yml b/acceptance/bundle/resources/job_runs/job_parameters/databricks.yml new file mode 100644 index 00000000000..fb6970b9286 --- /dev/null +++ b/acceptance/bundle/resources/job_runs/job_parameters/databricks.yml @@ -0,0 +1,26 @@ +bundle: + name: job-runs-job-parameters + +resources: + jobs: + my_job: + name: my-job + parameters: + - name: env + default: dev + - name: region + default: us + tasks: + - task_key: main + notebook_task: + notebook_path: /Workspace/test + + job_runs: + my_run: + job_id: ${resources.jobs.my_job.id} + # Override only one of the job's two parameters. GetRun resolves the full + # parameter set (including the un-overridden `region` default), so without + # job_parameters in ignore_remote_changes this drift would recreate the run + # on every plan. + job_parameters: + env: prod diff --git a/acceptance/bundle/resources/job_runs/job_parameters/out.test.toml b/acceptance/bundle/resources/job_runs/job_parameters/out.test.toml new file mode 100644 index 00000000000..e90b6d5d1ba --- /dev/null +++ b/acceptance/bundle/resources/job_runs/job_parameters/out.test.toml @@ -0,0 +1,3 @@ +Local = true +Cloud = false +EnvMatrix.DATABRICKS_BUNDLE_ENGINE = ["direct"] diff --git a/acceptance/bundle/resources/job_runs/job_parameters/output.txt b/acceptance/bundle/resources/job_runs/job_parameters/output.txt new file mode 100644 index 00000000000..5b32916f588 --- /dev/null +++ b/acceptance/bundle/resources/job_runs/job_parameters/output.txt @@ -0,0 +1,49 @@ + +=== deploy triggers the run with only the overridden parameter +>>> [CLI] bundle deploy +Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/job-runs-job-parameters/default/files... +Deploying resources... +Updating deployment state... +Deployment complete! + +>>> print_requests.py //jobs/run-now +{ + "method": "POST", + "path": "/api/2.2/jobs/run-now", + "body": { + "job_id": [NUMID], + "job_parameters": { + "env": "prod" + } + } +} + +=== plan is stable: the resolved job default does not look like drift +>>> [CLI] bundle plan +Plan: 0 to add, 0 to change, 0 to delete, 2 unchanged + +>>> [CLI] bundle summary +Name: job-runs-job-parameters +Target: default +Workspace: + User: [USERNAME] + Path: /Workspace/Users/[USERNAME]/.bundle/job-runs-job-parameters/default +Resources: + Job Runs: + my_run: + Name: + URL: (not deployed) + Jobs: + my_job: + Name: my-job + URL: [DATABRICKS_URL]/jobs/[NUMID]?w=[NUMID] + +>>> [CLI] bundle destroy --auto-approve +The following resources will be deleted: + delete resources.job_runs.my_run + delete resources.jobs.my_job + +All files and directories at the following location will be deleted: /Workspace/Users/[USERNAME]/.bundle/job-runs-job-parameters/default + +Deleting files... +Destroy complete! diff --git a/acceptance/bundle/resources/job_runs/job_parameters/script b/acceptance/bundle/resources/job_runs/job_parameters/script new file mode 100644 index 00000000000..7128b53ef68 --- /dev/null +++ b/acceptance/bundle/resources/job_runs/job_parameters/script @@ -0,0 +1,13 @@ +cleanup() { + trace $CLI bundle destroy --auto-approve + rm out.requests.txt +} +trap cleanup EXIT + +title "deploy triggers the run with only the overridden parameter" +trace $CLI bundle deploy +trace print_requests.py //jobs/run-now + +title "plan is stable: the resolved job default does not look like drift" +trace $CLI bundle plan +trace $CLI bundle summary diff --git a/acceptance/bundle/resources/job_runs/job_parameters/test.toml b/acceptance/bundle/resources/job_runs/job_parameters/test.toml new file mode 100644 index 00000000000..4b94d8b58e9 --- /dev/null +++ b/acceptance/bundle/resources/job_runs/job_parameters/test.toml @@ -0,0 +1,4 @@ +# job_runs is a direct-engine-only resource; the Terraform provider has no +# equivalent, so restrict the matrix to direct. +EnvMatrix.DATABRICKS_BUNDLE_ENGINE = ["direct"] +RecordRequests = true diff --git a/bundle/direct/dresources/job_run.go b/bundle/direct/dresources/job_run.go index 32b436fe397..52a8e84f8ed 100644 --- a/bundle/direct/dresources/job_run.go +++ b/bundle/direct/dresources/job_run.go @@ -71,21 +71,6 @@ func (*ResourceJobRun) RemapState(remote *JobRunRemote) *JobRunState { return &remote.JobRunState } -// jobParametersToMap converts the run's job parameters (a list of name/value -// pairs as returned by GetRun) into the name->value map shape used by RunNow. -// It returns nil for an empty list so the diff matches a config that sets no -// job parameters. -func jobParametersToMap(params []jobs.JobParameter) map[string]string { - if len(params) == 0 { - return nil - } - m := make(map[string]string, len(params)) - for _, p := range params { - m[p.Name] = p.Value - } - return m -} - func (r *ResourceJobRun) DoRead(ctx context.Context, id string) (*JobRunRemote, error) { runID, err := parseRunID(id) if err != nil { @@ -101,14 +86,19 @@ func (r *ResourceJobRun) DoRead(ctx context.Context, id string) (*JobRunRemote, if err != nil { return nil, err } - // Map the run back into the RunNow shape so the framework can diff the run's - // actual parameters against the desired config. GetRun does not return the - // request-only fields (idempotency_token, only, performance_target, queue) or - // the synthetic job_settings snapshot; those are handled via - // ignore_remote_changes in resources.yml. + // Record the remote state as what we actually created: the fields GetRun + // echoes back faithfully, namely the run's job_id and the overriding + // parameters it was launched with. This is what the out-of-band diff compares + // against the state saved by DoCreate. + // + // We deliberately do NOT map run.JobParameters here: GetRun resolves it to the + // job's full parameter set (including defaults the run never overrode), which + // is not what we created. Mapping it would only feed a diff we then have to + // suppress, so job_parameters (along with the request-only fields and the + // synthetic job_settings snapshot, none of which GetRun returns) is handled + // via ignore_remote_changes in resources.yml. var state JobRunState state.JobId = run.JobId - state.JobParameters = jobParametersToMap(run.JobParameters) if p := run.OverridingParameters; p != nil { state.DbtCommands = p.DbtCommands state.JarParams = p.JarParams diff --git a/bundle/direct/dresources/resources.yml b/bundle/direct/dresources/resources.yml index 454e04b4697..e2c951918e3 100644 --- a/bundle/direct/dresources/resources.yml +++ b/bundle/direct/dresources/resources.yml @@ -117,13 +117,21 @@ resources: - field: job_clusters[*].new_cluster.data_security_mode job_runs: - # GetRun echoes the run's job-level and overriding parameters, so DoRead maps - # those back (see RemapState) and the framework diffs them directly. Only the - # fields GetRun does NOT return are ignored here: the request-only inputs that - # never appear in the run, plus the synthetic job_settings snapshot. + # GetRun echoes the run's overriding parameters, so DoRead maps those back + # (see RemapState) and the framework diffs them directly. Ignored here are the + # fields GetRun does NOT return faithfully: the request-only inputs that never + # appear in the run, the synthetic job_settings snapshot, and job_parameters + # (GetRun resolves the job's full parameter set, including defaults the run + # never overrode, so a direct diff would look like perpetual remote drift). ignore_remote_changes: - field: idempotency_token reason: input_only + # GetRun returns every parameter the job defines with its resolved value, + # not just the ones the run overrode, so a direct diff against the RunNow + # request would always show drift. A local change still re-triggers the run + # via recreate_on_changes below. + - field: job_parameters + reason: input_only # Local-only snapshot of the targeted job's settings; GetRun never returns # it, so it always looks like remote drift unless ignored here. - field: job_settings diff --git a/libs/testserver/jobs.go b/libs/testserver/jobs.go index 62211a0c497..e1793880742 100644 --- a/libs/testserver/jobs.go +++ b/libs/testserver/jobs.go @@ -331,22 +331,37 @@ func (s *FakeWorkspace) JobsRunNow(req Request) Response { RunType: jobs.RunTypeJobRun, RunName: runName, Tasks: tasks, - JobParameters: runJobParameters(request.JobParameters), + JobParameters: runJobParameters(job.Settings, request.JobParameters), OverridingParameters: runOverridingParameters(request), } return Response{Body: jobs.RunNowResponse{RunId: runId}} } -// runJobParameters mirrors how GetRun echoes job-level parameters: as a list of -// name/value pairs. Sorted by name for deterministic output. -func runJobParameters(params map[string]string) []jobs.JobParameter { - if len(params) == 0 { +// runJobParameters mirrors how GetRun resolves job-level parameters: it returns +// every parameter the job defines with its value, applying the run's overrides +// on top of the job's defaults. This is the cloud behavior that lets a run +// surface a job parameter it never explicitly overrode. Sorted by name for +// deterministic output. +func runJobParameters(settings *jobs.JobSettings, overrides map[string]string) []jobs.JobParameter { + resolved := map[string]jobs.JobParameter{} + if settings != nil { + for _, p := range settings.Parameters { + resolved[p.Name] = jobs.JobParameter{Name: p.Name, Default: p.Default, Value: p.Default} + } + } + for name, value := range overrides { + p := resolved[name] + p.Name = name + p.Value = value + resolved[name] = p + } + if len(resolved) == 0 { return nil } - result := make([]jobs.JobParameter, 0, len(params)) - for name, value := range params { - result = append(result, jobs.JobParameter{Name: name, Value: value}) + result := make([]jobs.JobParameter, 0, len(resolved)) + for _, p := range resolved { + result = append(result, p) } slices.SortFunc(result, func(a, b jobs.JobParameter) int { return cmp.Compare(a.Name, b.Name) From c268de21db960d210dc125c69aaa818d8a2a313f Mon Sep 17 00:00:00 2001 From: Rada Kamysheva Date: Fri, 19 Jun 2026 08:07:46 +0000 Subject: [PATCH 13/17] direct: Return remote state from job_runs DoCreate RunNow's response only carries the new run id, so DoCreate previously returned nil remote state. Reconstruct it from the request we just sent plus the run id, giving the framework a faithful record of what we created to compute the out-of-band diff against DoRead. --- bundle/direct/dresources/job_run.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/bundle/direct/dresources/job_run.go b/bundle/direct/dresources/job_run.go index 52a8e84f8ed..55dd07d22c9 100644 --- a/bundle/direct/dresources/job_run.go +++ b/bundle/direct/dresources/job_run.go @@ -121,7 +121,12 @@ func (r *ResourceJobRun) DoCreate(ctx context.Context, config *JobRunState) (str if err != nil { return "", nil, err } - return strconv.FormatInt(wait.RunId, 10), nil, nil + // RunNow's response carries only the run id, so we reconstruct the remote + // state from the request we just sent (the faithful record of what we + // created) plus the new run id. This lets the framework compute the + // out-of-band diff against what DoRead later reads back. + remote := &JobRunRemote{JobRunState: *config, RunId: wait.RunId} + return strconv.FormatInt(wait.RunId, 10), remote, nil } // DoUpdate is intentionally not implemented: there is no API to modify a run in From 88b87d105627c983229e3179a6926e1601f11869 Mon Sep 17 00:00:00 2001 From: Rada Kamysheva Date: Fri, 19 Jun 2026 08:20:58 +0000 Subject: [PATCH 14/17] Update generated files --- python/codegen/uv.lock | 12 ++++---- python/uv.lock | 66 +++++++++++++++++++++--------------------- 2 files changed, 39 insertions(+), 39 deletions(-) diff --git a/python/codegen/uv.lock b/python/codegen/uv.lock index 681ead3c4f0..1a91255086e 100644 --- a/python/codegen/uv.lock +++ b/python/codegen/uv.lock @@ -20,7 +20,7 @@ dev = [{ name = "pytest" }] [[package]] name = "colorama" version = "0.4.6" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, @@ -29,7 +29,7 @@ wheels = [ [[package]] name = "iniconfig" version = "2.1.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/f2/97/ebf4da567aa6827c909642694d71c9fcf53e5b504f2d96afea02718862f3/iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7", size = 4793, upload-time = "2025-03-19T20:09:59.721Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/2c/e1/e6716421ea10d38022b952c159d5161ca1193197fb744506875fbb87ea7b/iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760", size = 6050, upload-time = "2025-03-19T20:10:01.071Z" }, @@ -38,7 +38,7 @@ wheels = [ [[package]] name = "packaging" version = "24.2" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/d0/63/68dbb6eb2de9cb10ee4c9c14a0148804425e13c4fb20d61cce69f53106da/packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f", size = 163950, upload-time = "2024-11-08T09:47:47.202Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/88/ef/eb23f262cca3c0c4eb7ab1933c3b1f03d021f2c48f54763065b6f0e321be/packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759", size = 65451, upload-time = "2024-11-08T09:47:44.722Z" }, @@ -47,7 +47,7 @@ wheels = [ [[package]] name = "pluggy" version = "1.5.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/96/2d/02d4312c973c6050a18b314a5ad0b3210edb65a906f868e31c111dede4a6/pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1", size = 67955, upload-time = "2024-04-20T21:34:42.531Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/88/5f/e351af9a41f866ac3f1fac4ca0613908d9a41741cfcf2228f4ad853b697d/pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669", size = 20556, upload-time = "2024-04-20T21:34:40.434Z" }, @@ -56,7 +56,7 @@ wheels = [ [[package]] name = "pygments" version = "2.20.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" }, @@ -65,7 +65,7 @@ wheels = [ [[package]] name = "pytest" version = "9.0.3" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, { name = "iniconfig" }, diff --git a/python/uv.lock b/python/uv.lock index 4e303f20437..db8db18521b 100644 --- a/python/uv.lock +++ b/python/uv.lock @@ -5,7 +5,7 @@ requires-python = ">=3.10" [[package]] name = "alabaster" version = "1.0.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/a6/f8/d9c74d0daf3f742840fd818d69cfae176fa332022fd44e3469487d5a9420/alabaster-1.0.0.tar.gz", hash = "sha256:c00dca57bca26fa62a6d7d0a9fcce65f3e026e9bfe33e9c538fd3fbb2144fd9e", size = 24210, upload-time = "2024-07-26T18:15:03.762Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/7e/b3/6b4067be973ae96ba0d615946e314c5ae35f9f993eca561b356540bb0c2b/alabaster-1.0.0-py3-none-any.whl", hash = "sha256:fc6786402dc3fcb2de3cabd5fe455a2db534b371124f1f21de8731783dec828b", size = 13929, upload-time = "2024-07-26T18:15:02.05Z" }, @@ -14,7 +14,7 @@ wheels = [ [[package]] name = "babel" version = "2.17.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/7d/6b/d52e42361e1aa00709585ecc30b3f9684b3ab62530771402248b1b1d6240/babel-2.17.0.tar.gz", hash = "sha256:0c54cffb19f690cdcc52a3b50bcbf71e07a808d1c80d549f2459b9d2cf0afb9d", size = 9951852, upload-time = "2025-02-01T15:17:41.026Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/b7/b8/3fe70c75fe32afc4bb507f75563d39bc5642255d1d94f1f23604725780bf/babel-2.17.0-py3-none-any.whl", hash = "sha256:4d0b53093fdfb4b21c92b5213dba5a1b23885afa8383709427046b21c366e5f2", size = 10182537, upload-time = "2025-02-01T15:17:37.39Z" }, @@ -23,7 +23,7 @@ wheels = [ [[package]] name = "certifi" version = "2025.1.31" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/1c/ab/c9f1e32b7b1bf505bf26f0ef697775960db7932abeb7b516de930ba2705f/certifi-2025.1.31.tar.gz", hash = "sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651", size = 167577, upload-time = "2025-01-31T02:16:47.166Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/38/fc/bce832fd4fd99766c04d1ee0eead6b0ec6486fb100ae5e74c1d91292b982/certifi-2025.1.31-py3-none-any.whl", hash = "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe", size = 166393, upload-time = "2025-01-31T02:16:45.015Z" }, @@ -32,7 +32,7 @@ wheels = [ [[package]] name = "charset-normalizer" version = "3.4.1" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/16/b0/572805e227f01586461c80e0fd25d65a2115599cc9dad142fee4b747c357/charset_normalizer-3.4.1.tar.gz", hash = "sha256:44251f18cd68a75b56585dd00dae26183e102cd5e0f9f1466e6df5da2ed64ea3", size = 123188, upload-time = "2024-12-24T18:12:35.43Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/0d/58/5580c1716040bc89206c77d8f74418caf82ce519aae06450393ca73475d1/charset_normalizer-3.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:91b36a978b5ae0ee86c394f5a54d6ef44db1de0815eb43de826d41d21e4af3de", size = 198013, upload-time = "2024-12-24T18:09:43.671Z" }, @@ -93,7 +93,7 @@ wheels = [ [[package]] name = "colorama" version = "0.4.6" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, @@ -102,7 +102,7 @@ wheels = [ [[package]] name = "coverage" version = "7.6.12" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/0c/d6/2b53ab3ee99f2262e6f0b8369a43f6d66658eab45510331c0b3d5c8c4272/coverage-7.6.12.tar.gz", hash = "sha256:48cfc4641d95d34766ad41d9573cc0f22a48aa88d22657a1fe01dca0dbae4de2", size = 805941, upload-time = "2025-02-11T14:47:03.797Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/ba/67/81dc41ec8f548c365d04a29f1afd492d3176b372c33e47fa2a45a01dc13a/coverage-7.6.12-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:704c8c8c6ce6569286ae9622e534b4f5b9759b6f2cd643f1c1a61f666d534fe8", size = 208345, upload-time = "2025-02-11T14:44:51.83Z" }, @@ -194,7 +194,7 @@ dev = [ [[package]] name = "docutils" version = "0.21.2" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/ae/ed/aefcc8cd0ba62a0560c3c18c33925362d46c6075480bfa4df87b28e169a9/docutils-0.21.2.tar.gz", hash = "sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f", size = 2204444, upload-time = "2024-04-23T18:57:18.24Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/8f/d7/9322c609343d929e75e7e5e6255e614fcc67572cfd083959cdef3b7aad79/docutils-0.21.2-py3-none-any.whl", hash = "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2", size = 587408, upload-time = "2024-04-23T18:57:14.835Z" }, @@ -203,7 +203,7 @@ wheels = [ [[package]] name = "exceptiongroup" version = "1.2.2" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/09/35/2495c4ac46b980e4ca1f6ad6db102322ef3ad2410b79fdde159a4b0f3b92/exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc", size = 28883, upload-time = "2024-07-12T22:26:00.161Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/02/cc/b7e31358aac6ed1ef2bb790a9746ac2c69bcb3c8588b41616914eb106eaf/exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b", size = 16453, upload-time = "2024-07-12T22:25:58.476Z" }, @@ -212,7 +212,7 @@ wheels = [ [[package]] name = "idna" version = "3.15" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/82/77/7b3966d0b9d1d31a36ddf1746926a11dface89a83409bf1483f0237aa758/idna-3.15.tar.gz", hash = "sha256:ca962446ea538f7092a95e057da437618e886f4d349216d2b1e294abfdb65fdc", size = 199245, upload-time = "2026-05-12T22:45:57.011Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/d2/23/408243171aa9aaba178d3e2559159c24c1171a641aa83b67bdd3394ead8e/idna-3.15-py3-none-any.whl", hash = "sha256:048adeaf8c2d788c40fee287673ccaa74c24ffd8dcf09ffa555a2fbb59f10ac8", size = 72340, upload-time = "2026-05-12T22:45:55.733Z" }, @@ -221,7 +221,7 @@ wheels = [ [[package]] name = "imagesize" version = "1.4.1" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/a7/84/62473fb57d61e31fef6e36d64a179c8781605429fd927b5dd608c997be31/imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a", size = 1280026, upload-time = "2022-07-01T12:21:05.687Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/ff/62/85c4c919272577931d407be5ba5d71c20f0b616d31a0befe0ae45bb79abd/imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b", size = 8769, upload-time = "2022-07-01T12:21:02.467Z" }, @@ -230,7 +230,7 @@ wheels = [ [[package]] name = "iniconfig" version = "2.0.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/d7/4b/cbd8e699e64a6f16ca3a8220661b5f83792b3017d0f79807cb8708d33913/iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3", size = 4646, upload-time = "2023-01-07T11:08:11.254Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374", size = 5892, upload-time = "2023-01-07T11:08:09.864Z" }, @@ -239,7 +239,7 @@ wheels = [ [[package]] name = "jinja2" version = "3.1.6" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } dependencies = [ { name = "markupsafe" }, ] @@ -251,7 +251,7 @@ wheels = [ [[package]] name = "markupsafe" version = "3.0.2" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/b2/97/5d42485e71dfc078108a86d6de8fa46db44a1a9295e89c5d6d4a06e23a62/markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0", size = 20537, upload-time = "2024-10-18T15:21:54.129Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/04/90/d08277ce111dd22f77149fd1a5d4653eeb3b3eaacbdfcbae5afb2600eebd/MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8", size = 14357, upload-time = "2024-10-18T15:20:51.44Z" }, @@ -309,7 +309,7 @@ wheels = [ [[package]] name = "nodeenv" version = "1.9.1" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/43/16/fc88b08840de0e0a72a2f9d8c6bae36be573e475a6326ae854bcc549fc45/nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f", size = 47437, upload-time = "2024-06-04T18:44:11.171Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/d2/1d/1b658dbd2b9fa9c4c9f32accbfc0205d532c8c6194dc0f2a4c0428e7128a/nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9", size = 22314, upload-time = "2024-06-04T18:44:08.352Z" }, @@ -318,7 +318,7 @@ wheels = [ [[package]] name = "packaging" version = "24.2" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/d0/63/68dbb6eb2de9cb10ee4c9c14a0148804425e13c4fb20d61cce69f53106da/packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f", size = 163950, upload-time = "2024-11-08T09:47:47.202Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/88/ef/eb23f262cca3c0c4eb7ab1933c3b1f03d021f2c48f54763065b6f0e321be/packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759", size = 65451, upload-time = "2024-11-08T09:47:44.722Z" }, @@ -327,7 +327,7 @@ wheels = [ [[package]] name = "pluggy" version = "1.5.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/96/2d/02d4312c973c6050a18b314a5ad0b3210edb65a906f868e31c111dede4a6/pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1", size = 67955, upload-time = "2024-04-20T21:34:42.531Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/88/5f/e351af9a41f866ac3f1fac4ca0613908d9a41741cfcf2228f4ad853b697d/pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669", size = 20556, upload-time = "2024-04-20T21:34:40.434Z" }, @@ -336,7 +336,7 @@ wheels = [ [[package]] name = "pygments" version = "2.20.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" }, @@ -345,7 +345,7 @@ wheels = [ [[package]] name = "pyright" version = "1.1.380" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } dependencies = [ { name = "nodeenv" }, ] @@ -357,7 +357,7 @@ wheels = [ [[package]] name = "pytest" version = "9.0.3" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, @@ -375,7 +375,7 @@ wheels = [ [[package]] name = "pytest-cov" version = "5.0.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } dependencies = [ { name = "coverage", extra = ["toml"] }, { name = "pytest" }, @@ -388,7 +388,7 @@ wheels = [ [[package]] name = "requests" version = "2.33.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } dependencies = [ { name = "certifi" }, { name = "charset-normalizer" }, @@ -403,7 +403,7 @@ wheels = [ [[package]] name = "ruff" version = "0.9.1" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/67/3e/e89f736f01aa9517a97e2e7e0ce8d34a4d8207087b3cfdec95133fee13b5/ruff-0.9.1.tar.gz", hash = "sha256:fd2b25ecaf907d6458fa842675382c8597b3c746a2dde6717fe3415425df0c17", size = 3498844, upload-time = "2025-01-10T18:57:53.896Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/dc/05/c3a2e0feb3d5d394cdfd552de01df9d3ec8a3a3771bbff247fab7e668653/ruff-0.9.1-py3-none-linux_armv6l.whl", hash = "sha256:84330dda7abcc270e6055551aca93fdde1b0685fc4fd358f26410f9349cf1743", size = 10645241, upload-time = "2025-01-10T18:56:45.897Z" }, @@ -428,7 +428,7 @@ wheels = [ [[package]] name = "snowballstemmer" version = "2.2.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/44/7b/af302bebf22c749c56c9c3e8ae13190b5b5db37a33d9068652e8f73b7089/snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1", size = 86699, upload-time = "2021-11-16T18:38:38.009Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/ed/dc/c02e01294f7265e63a7315fe086dd1df7dacb9f840a804da846b96d01b96/snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a", size = 93002, upload-time = "2021-11-16T18:38:34.792Z" }, @@ -437,7 +437,7 @@ wheels = [ [[package]] name = "sphinx" version = "8.0.2" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } dependencies = [ { name = "alabaster" }, { name = "babel" }, @@ -465,7 +465,7 @@ wheels = [ [[package]] name = "sphinxcontrib-applehelp" version = "2.0.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/ba/6e/b837e84a1a704953c62ef8776d45c3e8d759876b4a84fe14eba2859106fe/sphinxcontrib_applehelp-2.0.0.tar.gz", hash = "sha256:2f29ef331735ce958efa4734873f084941970894c6090408b079c61b2e1c06d1", size = 20053, upload-time = "2024-07-29T01:09:00.465Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/5d/85/9ebeae2f76e9e77b952f4b274c27238156eae7979c5421fba91a28f4970d/sphinxcontrib_applehelp-2.0.0-py3-none-any.whl", hash = "sha256:4cd3f0ec4ac5dd9c17ec65e9ab272c9b867ea77425228e68ecf08d6b28ddbdb5", size = 119300, upload-time = "2024-07-29T01:08:58.99Z" }, @@ -474,7 +474,7 @@ wheels = [ [[package]] name = "sphinxcontrib-devhelp" version = "2.0.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/f6/d2/5beee64d3e4e747f316bae86b55943f51e82bb86ecd325883ef65741e7da/sphinxcontrib_devhelp-2.0.0.tar.gz", hash = "sha256:411f5d96d445d1d73bb5d52133377b4248ec79db5c793ce7dbe59e074b4dd1ad", size = 12967, upload-time = "2024-07-29T01:09:23.417Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/35/7a/987e583882f985fe4d7323774889ec58049171828b58c2217e7f79cdf44e/sphinxcontrib_devhelp-2.0.0-py3-none-any.whl", hash = "sha256:aefb8b83854e4b0998877524d1029fd3e6879210422ee3780459e28a1f03a8a2", size = 82530, upload-time = "2024-07-29T01:09:21.945Z" }, @@ -483,7 +483,7 @@ wheels = [ [[package]] name = "sphinxcontrib-htmlhelp" version = "2.1.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/43/93/983afd9aa001e5201eab16b5a444ed5b9b0a7a010541e0ddfbbfd0b2470c/sphinxcontrib_htmlhelp-2.1.0.tar.gz", hash = "sha256:c9e2916ace8aad64cc13a0d233ee22317f2b9025b9cf3295249fa985cc7082e9", size = 22617, upload-time = "2024-07-29T01:09:37.889Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/0a/7b/18a8c0bcec9182c05a0b3ec2a776bba4ead82750a55ff798e8d406dae604/sphinxcontrib_htmlhelp-2.1.0-py3-none-any.whl", hash = "sha256:166759820b47002d22914d64a075ce08f4c46818e17cfc9470a9786b759b19f8", size = 98705, upload-time = "2024-07-29T01:09:36.407Z" }, @@ -492,7 +492,7 @@ wheels = [ [[package]] name = "sphinxcontrib-jsmath" version = "1.0.1" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/b2/e8/9ed3830aeed71f17c026a07a5097edcf44b692850ef215b161b8ad875729/sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8", size = 5787, upload-time = "2019-01-21T16:10:16.347Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/c2/42/4c8646762ee83602e3fb3fbe774c2fac12f317deb0b5dbeeedd2d3ba4b77/sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178", size = 5071, upload-time = "2019-01-21T16:10:14.333Z" }, @@ -501,7 +501,7 @@ wheels = [ [[package]] name = "sphinxcontrib-qthelp" version = "2.0.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/68/bc/9104308fc285eb3e0b31b67688235db556cd5b0ef31d96f30e45f2e51cae/sphinxcontrib_qthelp-2.0.0.tar.gz", hash = "sha256:4fe7d0ac8fc171045be623aba3e2a8f613f8682731f9153bb2e40ece16b9bbab", size = 17165, upload-time = "2024-07-29T01:09:56.435Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/27/83/859ecdd180cacc13b1f7e857abf8582a64552ea7a061057a6c716e790fce/sphinxcontrib_qthelp-2.0.0-py3-none-any.whl", hash = "sha256:b18a828cdba941ccd6ee8445dbe72ffa3ef8cbe7505d8cd1fa0d42d3f2d5f3eb", size = 88743, upload-time = "2024-07-29T01:09:54.885Z" }, @@ -510,7 +510,7 @@ wheels = [ [[package]] name = "sphinxcontrib-serializinghtml" version = "2.0.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/3b/44/6716b257b0aa6bfd51a1b31665d1c205fb12cb5ad56de752dfa15657de2f/sphinxcontrib_serializinghtml-2.0.0.tar.gz", hash = "sha256:e9d912827f872c029017a53f0ef2180b327c3f7fd23c87229f7a8e8b70031d4d", size = 16080, upload-time = "2024-07-29T01:10:09.332Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/52/a7/d2782e4e3f77c8450f727ba74a8f12756d5ba823d81b941f1b04da9d033a/sphinxcontrib_serializinghtml-2.0.0-py3-none-any.whl", hash = "sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331", size = 92072, upload-time = "2024-07-29T01:10:08.203Z" }, @@ -519,7 +519,7 @@ wheels = [ [[package]] name = "tomli" version = "2.2.1" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/18/87/302344fed471e44a87289cf4967697d07e532f2421fdaf868a303cbae4ff/tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff", size = 17175, upload-time = "2024-11-27T22:38:36.873Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/43/ca/75707e6efa2b37c77dadb324ae7d9571cb424e61ea73fad7c56c2d14527f/tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249", size = 131077, upload-time = "2024-11-27T22:37:54.956Z" }, @@ -558,7 +558,7 @@ wheels = [ [[package]] name = "typing-extensions" version = "4.12.2" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/df/db/f35a00659bc03fec321ba8bce9420de607a1d37f8342eee1863174c69557/typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8", size = 85321, upload-time = "2024-06-07T18:52:15.995Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/26/9f/ad63fc0248c5379346306f8668cda6e2e2e9c95e01216d2b8ffd9ff037d0/typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", size = 37438, upload-time = "2024-06-07T18:52:13.582Z" }, @@ -567,7 +567,7 @@ wheels = [ [[package]] name = "urllib3" version = "2.7.0" -source = { registry = "https://pypi.org/simple" } +source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } sdist = { url = "https://files.pythonhosted.org/packages/53/0c/06f8b233b8fd13b9e5ee11424ef85419ba0d8ba0b3138bf360be2ff56953/urllib3-2.7.0.tar.gz", hash = "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c", size = 433602, upload-time = "2026-05-07T16:13:18.596Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/7f/3e/5db95bcf282c52709639744ca2a8b149baccf648e39c8cc87553df9eae0c/urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897", size = 131087, upload-time = "2026-05-07T16:13:17.151Z" }, From 8a71c9e97ae4d09e5ada7f2a2a013e17c36154be Mon Sep 17 00:00:00 2001 From: Rada Kamysheva Date: Fri, 19 Jun 2026 08:28:30 +0000 Subject: [PATCH 15/17] Update generated files Regenerate out.fields.txt after rebasing onto main, which bumped databricks-sdk-go to v0.147.0. The new SDK adds azure_attributes.capacity_reservation_group, which the validate-generated job picks up when generating against the PR-merged-with-main commit. --- acceptance/bundle/refschema/out.fields.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/acceptance/bundle/refschema/out.fields.txt b/acceptance/bundle/refschema/out.fields.txt index 89df2b973bf..ace5495a5e1 100644 --- a/acceptance/bundle/refschema/out.fields.txt +++ b/acceptance/bundle/refschema/out.fields.txt @@ -844,6 +844,7 @@ resources.job_runs.*.job_settings.job_clusters[*].new_cluster.aws_attributes.spo resources.job_runs.*.job_settings.job_clusters[*].new_cluster.aws_attributes.zone_id string ALL resources.job_runs.*.job_settings.job_clusters[*].new_cluster.azure_attributes *compute.AzureAttributes ALL resources.job_runs.*.job_settings.job_clusters[*].new_cluster.azure_attributes.availability compute.AzureAvailability ALL +resources.job_runs.*.job_settings.job_clusters[*].new_cluster.azure_attributes.capacity_reservation_group string ALL resources.job_runs.*.job_settings.job_clusters[*].new_cluster.azure_attributes.first_on_demand int ALL resources.job_runs.*.job_settings.job_clusters[*].new_cluster.azure_attributes.log_analytics_info *compute.LogAnalyticsInfo ALL resources.job_runs.*.job_settings.job_clusters[*].new_cluster.azure_attributes.log_analytics_info.log_analytics_primary_key string ALL @@ -1159,6 +1160,7 @@ resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.aws_at resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.aws_attributes.zone_id string ALL resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.azure_attributes *compute.AzureAttributes ALL resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.azure_attributes.availability compute.AzureAvailability ALL +resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.azure_attributes.capacity_reservation_group string ALL resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.azure_attributes.first_on_demand int ALL resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.azure_attributes.log_analytics_info *compute.LogAnalyticsInfo ALL resources.job_runs.*.job_settings.tasks[*].for_each_task.task.new_cluster.azure_attributes.log_analytics_info.log_analytics_primary_key string ALL @@ -1444,6 +1446,7 @@ resources.job_runs.*.job_settings.tasks[*].new_cluster.aws_attributes.spot_bid_p resources.job_runs.*.job_settings.tasks[*].new_cluster.aws_attributes.zone_id string ALL resources.job_runs.*.job_settings.tasks[*].new_cluster.azure_attributes *compute.AzureAttributes ALL resources.job_runs.*.job_settings.tasks[*].new_cluster.azure_attributes.availability compute.AzureAvailability ALL +resources.job_runs.*.job_settings.tasks[*].new_cluster.azure_attributes.capacity_reservation_group string ALL resources.job_runs.*.job_settings.tasks[*].new_cluster.azure_attributes.first_on_demand int ALL resources.job_runs.*.job_settings.tasks[*].new_cluster.azure_attributes.log_analytics_info *compute.LogAnalyticsInfo ALL resources.job_runs.*.job_settings.tasks[*].new_cluster.azure_attributes.log_analytics_info.log_analytics_primary_key string ALL From c9890d864282a91156ef53b2ba9830351540f434 Mon Sep 17 00:00:00 2001 From: Rada Kamysheva Date: Fri, 19 Jun 2026 10:42:39 +0000 Subject: [PATCH 16/17] Revert unrelated uv.lock registry changes These pypi-proxy registry rewrites in python/uv.lock and python/codegen/uv.lock were environment artifacts unrelated to the job_runs resource. Restore both lockfiles to match main. --- python/codegen/uv.lock | 12 ++++---- python/uv.lock | 66 +++++++++++++++++++++--------------------- 2 files changed, 39 insertions(+), 39 deletions(-) diff --git a/python/codegen/uv.lock b/python/codegen/uv.lock index 1a91255086e..681ead3c4f0 100644 --- a/python/codegen/uv.lock +++ b/python/codegen/uv.lock @@ -20,7 +20,7 @@ dev = [{ name = "pytest" }] [[package]] name = "colorama" version = "0.4.6" -source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, @@ -29,7 +29,7 @@ wheels = [ [[package]] name = "iniconfig" version = "2.1.0" -source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/f2/97/ebf4da567aa6827c909642694d71c9fcf53e5b504f2d96afea02718862f3/iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7", size = 4793, upload-time = "2025-03-19T20:09:59.721Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/2c/e1/e6716421ea10d38022b952c159d5161ca1193197fb744506875fbb87ea7b/iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760", size = 6050, upload-time = "2025-03-19T20:10:01.071Z" }, @@ -38,7 +38,7 @@ wheels = [ [[package]] name = "packaging" version = "24.2" -source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/d0/63/68dbb6eb2de9cb10ee4c9c14a0148804425e13c4fb20d61cce69f53106da/packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f", size = 163950, upload-time = "2024-11-08T09:47:47.202Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/88/ef/eb23f262cca3c0c4eb7ab1933c3b1f03d021f2c48f54763065b6f0e321be/packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759", size = 65451, upload-time = "2024-11-08T09:47:44.722Z" }, @@ -47,7 +47,7 @@ wheels = [ [[package]] name = "pluggy" version = "1.5.0" -source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/96/2d/02d4312c973c6050a18b314a5ad0b3210edb65a906f868e31c111dede4a6/pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1", size = 67955, upload-time = "2024-04-20T21:34:42.531Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/88/5f/e351af9a41f866ac3f1fac4ca0613908d9a41741cfcf2228f4ad853b697d/pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669", size = 20556, upload-time = "2024-04-20T21:34:40.434Z" }, @@ -56,7 +56,7 @@ wheels = [ [[package]] name = "pygments" version = "2.20.0" -source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" }, @@ -65,7 +65,7 @@ wheels = [ [[package]] name = "pytest" version = "9.0.3" -source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, { name = "iniconfig" }, diff --git a/python/uv.lock b/python/uv.lock index db8db18521b..4e303f20437 100644 --- a/python/uv.lock +++ b/python/uv.lock @@ -5,7 +5,7 @@ requires-python = ">=3.10" [[package]] name = "alabaster" version = "1.0.0" -source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/a6/f8/d9c74d0daf3f742840fd818d69cfae176fa332022fd44e3469487d5a9420/alabaster-1.0.0.tar.gz", hash = "sha256:c00dca57bca26fa62a6d7d0a9fcce65f3e026e9bfe33e9c538fd3fbb2144fd9e", size = 24210, upload-time = "2024-07-26T18:15:03.762Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/7e/b3/6b4067be973ae96ba0d615946e314c5ae35f9f993eca561b356540bb0c2b/alabaster-1.0.0-py3-none-any.whl", hash = "sha256:fc6786402dc3fcb2de3cabd5fe455a2db534b371124f1f21de8731783dec828b", size = 13929, upload-time = "2024-07-26T18:15:02.05Z" }, @@ -14,7 +14,7 @@ wheels = [ [[package]] name = "babel" version = "2.17.0" -source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/7d/6b/d52e42361e1aa00709585ecc30b3f9684b3ab62530771402248b1b1d6240/babel-2.17.0.tar.gz", hash = "sha256:0c54cffb19f690cdcc52a3b50bcbf71e07a808d1c80d549f2459b9d2cf0afb9d", size = 9951852, upload-time = "2025-02-01T15:17:41.026Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/b7/b8/3fe70c75fe32afc4bb507f75563d39bc5642255d1d94f1f23604725780bf/babel-2.17.0-py3-none-any.whl", hash = "sha256:4d0b53093fdfb4b21c92b5213dba5a1b23885afa8383709427046b21c366e5f2", size = 10182537, upload-time = "2025-02-01T15:17:37.39Z" }, @@ -23,7 +23,7 @@ wheels = [ [[package]] name = "certifi" version = "2025.1.31" -source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/1c/ab/c9f1e32b7b1bf505bf26f0ef697775960db7932abeb7b516de930ba2705f/certifi-2025.1.31.tar.gz", hash = "sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651", size = 167577, upload-time = "2025-01-31T02:16:47.166Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/38/fc/bce832fd4fd99766c04d1ee0eead6b0ec6486fb100ae5e74c1d91292b982/certifi-2025.1.31-py3-none-any.whl", hash = "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe", size = 166393, upload-time = "2025-01-31T02:16:45.015Z" }, @@ -32,7 +32,7 @@ wheels = [ [[package]] name = "charset-normalizer" version = "3.4.1" -source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/16/b0/572805e227f01586461c80e0fd25d65a2115599cc9dad142fee4b747c357/charset_normalizer-3.4.1.tar.gz", hash = "sha256:44251f18cd68a75b56585dd00dae26183e102cd5e0f9f1466e6df5da2ed64ea3", size = 123188, upload-time = "2024-12-24T18:12:35.43Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/0d/58/5580c1716040bc89206c77d8f74418caf82ce519aae06450393ca73475d1/charset_normalizer-3.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:91b36a978b5ae0ee86c394f5a54d6ef44db1de0815eb43de826d41d21e4af3de", size = 198013, upload-time = "2024-12-24T18:09:43.671Z" }, @@ -93,7 +93,7 @@ wheels = [ [[package]] name = "colorama" version = "0.4.6" -source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, @@ -102,7 +102,7 @@ wheels = [ [[package]] name = "coverage" version = "7.6.12" -source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/0c/d6/2b53ab3ee99f2262e6f0b8369a43f6d66658eab45510331c0b3d5c8c4272/coverage-7.6.12.tar.gz", hash = "sha256:48cfc4641d95d34766ad41d9573cc0f22a48aa88d22657a1fe01dca0dbae4de2", size = 805941, upload-time = "2025-02-11T14:47:03.797Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/ba/67/81dc41ec8f548c365d04a29f1afd492d3176b372c33e47fa2a45a01dc13a/coverage-7.6.12-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:704c8c8c6ce6569286ae9622e534b4f5b9759b6f2cd643f1c1a61f666d534fe8", size = 208345, upload-time = "2025-02-11T14:44:51.83Z" }, @@ -194,7 +194,7 @@ dev = [ [[package]] name = "docutils" version = "0.21.2" -source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/ae/ed/aefcc8cd0ba62a0560c3c18c33925362d46c6075480bfa4df87b28e169a9/docutils-0.21.2.tar.gz", hash = "sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f", size = 2204444, upload-time = "2024-04-23T18:57:18.24Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/8f/d7/9322c609343d929e75e7e5e6255e614fcc67572cfd083959cdef3b7aad79/docutils-0.21.2-py3-none-any.whl", hash = "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2", size = 587408, upload-time = "2024-04-23T18:57:14.835Z" }, @@ -203,7 +203,7 @@ wheels = [ [[package]] name = "exceptiongroup" version = "1.2.2" -source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/09/35/2495c4ac46b980e4ca1f6ad6db102322ef3ad2410b79fdde159a4b0f3b92/exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc", size = 28883, upload-time = "2024-07-12T22:26:00.161Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/02/cc/b7e31358aac6ed1ef2bb790a9746ac2c69bcb3c8588b41616914eb106eaf/exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b", size = 16453, upload-time = "2024-07-12T22:25:58.476Z" }, @@ -212,7 +212,7 @@ wheels = [ [[package]] name = "idna" version = "3.15" -source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/82/77/7b3966d0b9d1d31a36ddf1746926a11dface89a83409bf1483f0237aa758/idna-3.15.tar.gz", hash = "sha256:ca962446ea538f7092a95e057da437618e886f4d349216d2b1e294abfdb65fdc", size = 199245, upload-time = "2026-05-12T22:45:57.011Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/d2/23/408243171aa9aaba178d3e2559159c24c1171a641aa83b67bdd3394ead8e/idna-3.15-py3-none-any.whl", hash = "sha256:048adeaf8c2d788c40fee287673ccaa74c24ffd8dcf09ffa555a2fbb59f10ac8", size = 72340, upload-time = "2026-05-12T22:45:55.733Z" }, @@ -221,7 +221,7 @@ wheels = [ [[package]] name = "imagesize" version = "1.4.1" -source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/a7/84/62473fb57d61e31fef6e36d64a179c8781605429fd927b5dd608c997be31/imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a", size = 1280026, upload-time = "2022-07-01T12:21:05.687Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/ff/62/85c4c919272577931d407be5ba5d71c20f0b616d31a0befe0ae45bb79abd/imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b", size = 8769, upload-time = "2022-07-01T12:21:02.467Z" }, @@ -230,7 +230,7 @@ wheels = [ [[package]] name = "iniconfig" version = "2.0.0" -source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/d7/4b/cbd8e699e64a6f16ca3a8220661b5f83792b3017d0f79807cb8708d33913/iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3", size = 4646, upload-time = "2023-01-07T11:08:11.254Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374", size = 5892, upload-time = "2023-01-07T11:08:09.864Z" }, @@ -239,7 +239,7 @@ wheels = [ [[package]] name = "jinja2" version = "3.1.6" -source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "markupsafe" }, ] @@ -251,7 +251,7 @@ wheels = [ [[package]] name = "markupsafe" version = "3.0.2" -source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/b2/97/5d42485e71dfc078108a86d6de8fa46db44a1a9295e89c5d6d4a06e23a62/markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0", size = 20537, upload-time = "2024-10-18T15:21:54.129Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/04/90/d08277ce111dd22f77149fd1a5d4653eeb3b3eaacbdfcbae5afb2600eebd/MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8", size = 14357, upload-time = "2024-10-18T15:20:51.44Z" }, @@ -309,7 +309,7 @@ wheels = [ [[package]] name = "nodeenv" version = "1.9.1" -source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/43/16/fc88b08840de0e0a72a2f9d8c6bae36be573e475a6326ae854bcc549fc45/nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f", size = 47437, upload-time = "2024-06-04T18:44:11.171Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/d2/1d/1b658dbd2b9fa9c4c9f32accbfc0205d532c8c6194dc0f2a4c0428e7128a/nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9", size = 22314, upload-time = "2024-06-04T18:44:08.352Z" }, @@ -318,7 +318,7 @@ wheels = [ [[package]] name = "packaging" version = "24.2" -source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/d0/63/68dbb6eb2de9cb10ee4c9c14a0148804425e13c4fb20d61cce69f53106da/packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f", size = 163950, upload-time = "2024-11-08T09:47:47.202Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/88/ef/eb23f262cca3c0c4eb7ab1933c3b1f03d021f2c48f54763065b6f0e321be/packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759", size = 65451, upload-time = "2024-11-08T09:47:44.722Z" }, @@ -327,7 +327,7 @@ wheels = [ [[package]] name = "pluggy" version = "1.5.0" -source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/96/2d/02d4312c973c6050a18b314a5ad0b3210edb65a906f868e31c111dede4a6/pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1", size = 67955, upload-time = "2024-04-20T21:34:42.531Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/88/5f/e351af9a41f866ac3f1fac4ca0613908d9a41741cfcf2228f4ad853b697d/pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669", size = 20556, upload-time = "2024-04-20T21:34:40.434Z" }, @@ -336,7 +336,7 @@ wheels = [ [[package]] name = "pygments" version = "2.20.0" -source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" }, @@ -345,7 +345,7 @@ wheels = [ [[package]] name = "pyright" version = "1.1.380" -source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "nodeenv" }, ] @@ -357,7 +357,7 @@ wheels = [ [[package]] name = "pytest" version = "9.0.3" -source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, @@ -375,7 +375,7 @@ wheels = [ [[package]] name = "pytest-cov" version = "5.0.0" -source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "coverage", extra = ["toml"] }, { name = "pytest" }, @@ -388,7 +388,7 @@ wheels = [ [[package]] name = "requests" version = "2.33.0" -source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "certifi" }, { name = "charset-normalizer" }, @@ -403,7 +403,7 @@ wheels = [ [[package]] name = "ruff" version = "0.9.1" -source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/67/3e/e89f736f01aa9517a97e2e7e0ce8d34a4d8207087b3cfdec95133fee13b5/ruff-0.9.1.tar.gz", hash = "sha256:fd2b25ecaf907d6458fa842675382c8597b3c746a2dde6717fe3415425df0c17", size = 3498844, upload-time = "2025-01-10T18:57:53.896Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/dc/05/c3a2e0feb3d5d394cdfd552de01df9d3ec8a3a3771bbff247fab7e668653/ruff-0.9.1-py3-none-linux_armv6l.whl", hash = "sha256:84330dda7abcc270e6055551aca93fdde1b0685fc4fd358f26410f9349cf1743", size = 10645241, upload-time = "2025-01-10T18:56:45.897Z" }, @@ -428,7 +428,7 @@ wheels = [ [[package]] name = "snowballstemmer" version = "2.2.0" -source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/44/7b/af302bebf22c749c56c9c3e8ae13190b5b5db37a33d9068652e8f73b7089/snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1", size = 86699, upload-time = "2021-11-16T18:38:38.009Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/ed/dc/c02e01294f7265e63a7315fe086dd1df7dacb9f840a804da846b96d01b96/snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a", size = 93002, upload-time = "2021-11-16T18:38:34.792Z" }, @@ -437,7 +437,7 @@ wheels = [ [[package]] name = "sphinx" version = "8.0.2" -source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "alabaster" }, { name = "babel" }, @@ -465,7 +465,7 @@ wheels = [ [[package]] name = "sphinxcontrib-applehelp" version = "2.0.0" -source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/ba/6e/b837e84a1a704953c62ef8776d45c3e8d759876b4a84fe14eba2859106fe/sphinxcontrib_applehelp-2.0.0.tar.gz", hash = "sha256:2f29ef331735ce958efa4734873f084941970894c6090408b079c61b2e1c06d1", size = 20053, upload-time = "2024-07-29T01:09:00.465Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/5d/85/9ebeae2f76e9e77b952f4b274c27238156eae7979c5421fba91a28f4970d/sphinxcontrib_applehelp-2.0.0-py3-none-any.whl", hash = "sha256:4cd3f0ec4ac5dd9c17ec65e9ab272c9b867ea77425228e68ecf08d6b28ddbdb5", size = 119300, upload-time = "2024-07-29T01:08:58.99Z" }, @@ -474,7 +474,7 @@ wheels = [ [[package]] name = "sphinxcontrib-devhelp" version = "2.0.0" -source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/f6/d2/5beee64d3e4e747f316bae86b55943f51e82bb86ecd325883ef65741e7da/sphinxcontrib_devhelp-2.0.0.tar.gz", hash = "sha256:411f5d96d445d1d73bb5d52133377b4248ec79db5c793ce7dbe59e074b4dd1ad", size = 12967, upload-time = "2024-07-29T01:09:23.417Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/35/7a/987e583882f985fe4d7323774889ec58049171828b58c2217e7f79cdf44e/sphinxcontrib_devhelp-2.0.0-py3-none-any.whl", hash = "sha256:aefb8b83854e4b0998877524d1029fd3e6879210422ee3780459e28a1f03a8a2", size = 82530, upload-time = "2024-07-29T01:09:21.945Z" }, @@ -483,7 +483,7 @@ wheels = [ [[package]] name = "sphinxcontrib-htmlhelp" version = "2.1.0" -source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/43/93/983afd9aa001e5201eab16b5a444ed5b9b0a7a010541e0ddfbbfd0b2470c/sphinxcontrib_htmlhelp-2.1.0.tar.gz", hash = "sha256:c9e2916ace8aad64cc13a0d233ee22317f2b9025b9cf3295249fa985cc7082e9", size = 22617, upload-time = "2024-07-29T01:09:37.889Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/0a/7b/18a8c0bcec9182c05a0b3ec2a776bba4ead82750a55ff798e8d406dae604/sphinxcontrib_htmlhelp-2.1.0-py3-none-any.whl", hash = "sha256:166759820b47002d22914d64a075ce08f4c46818e17cfc9470a9786b759b19f8", size = 98705, upload-time = "2024-07-29T01:09:36.407Z" }, @@ -492,7 +492,7 @@ wheels = [ [[package]] name = "sphinxcontrib-jsmath" version = "1.0.1" -source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/b2/e8/9ed3830aeed71f17c026a07a5097edcf44b692850ef215b161b8ad875729/sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8", size = 5787, upload-time = "2019-01-21T16:10:16.347Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/c2/42/4c8646762ee83602e3fb3fbe774c2fac12f317deb0b5dbeeedd2d3ba4b77/sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178", size = 5071, upload-time = "2019-01-21T16:10:14.333Z" }, @@ -501,7 +501,7 @@ wheels = [ [[package]] name = "sphinxcontrib-qthelp" version = "2.0.0" -source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/68/bc/9104308fc285eb3e0b31b67688235db556cd5b0ef31d96f30e45f2e51cae/sphinxcontrib_qthelp-2.0.0.tar.gz", hash = "sha256:4fe7d0ac8fc171045be623aba3e2a8f613f8682731f9153bb2e40ece16b9bbab", size = 17165, upload-time = "2024-07-29T01:09:56.435Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/27/83/859ecdd180cacc13b1f7e857abf8582a64552ea7a061057a6c716e790fce/sphinxcontrib_qthelp-2.0.0-py3-none-any.whl", hash = "sha256:b18a828cdba941ccd6ee8445dbe72ffa3ef8cbe7505d8cd1fa0d42d3f2d5f3eb", size = 88743, upload-time = "2024-07-29T01:09:54.885Z" }, @@ -510,7 +510,7 @@ wheels = [ [[package]] name = "sphinxcontrib-serializinghtml" version = "2.0.0" -source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/3b/44/6716b257b0aa6bfd51a1b31665d1c205fb12cb5ad56de752dfa15657de2f/sphinxcontrib_serializinghtml-2.0.0.tar.gz", hash = "sha256:e9d912827f872c029017a53f0ef2180b327c3f7fd23c87229f7a8e8b70031d4d", size = 16080, upload-time = "2024-07-29T01:10:09.332Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/52/a7/d2782e4e3f77c8450f727ba74a8f12756d5ba823d81b941f1b04da9d033a/sphinxcontrib_serializinghtml-2.0.0-py3-none-any.whl", hash = "sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331", size = 92072, upload-time = "2024-07-29T01:10:08.203Z" }, @@ -519,7 +519,7 @@ wheels = [ [[package]] name = "tomli" version = "2.2.1" -source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/18/87/302344fed471e44a87289cf4967697d07e532f2421fdaf868a303cbae4ff/tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff", size = 17175, upload-time = "2024-11-27T22:38:36.873Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/43/ca/75707e6efa2b37c77dadb324ae7d9571cb424e61ea73fad7c56c2d14527f/tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249", size = 131077, upload-time = "2024-11-27T22:37:54.956Z" }, @@ -558,7 +558,7 @@ wheels = [ [[package]] name = "typing-extensions" version = "4.12.2" -source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/df/db/f35a00659bc03fec321ba8bce9420de607a1d37f8342eee1863174c69557/typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8", size = 85321, upload-time = "2024-06-07T18:52:15.995Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/26/9f/ad63fc0248c5379346306f8668cda6e2e2e9c95e01216d2b8ffd9ff037d0/typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", size = 37438, upload-time = "2024-06-07T18:52:13.582Z" }, @@ -567,7 +567,7 @@ wheels = [ [[package]] name = "urllib3" version = "2.7.0" -source = { registry = "https://pypi-proxy.cloud.databricks.com/simple/" } +source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/53/0c/06f8b233b8fd13b9e5ee11424ef85419ba0d8ba0b3138bf360be2ff56953/urllib3-2.7.0.tar.gz", hash = "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c", size = 433602, upload-time = "2026-05-07T16:13:18.596Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/7f/3e/5db95bcf282c52709639744ca2a8b149baccf648e39c8cc87553df9eae0c/urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897", size = 131087, upload-time = "2026-05-07T16:13:17.151Z" }, From f0427e08dbb0571e48176ecdd809114353f9cdd3 Mon Sep 17 00:00:00 2001 From: Rada Kamysheva Date: Fri, 19 Jun 2026 13:12:45 +0000 Subject: [PATCH 17/17] job_runs: Surface run URL in bundle summary A run's URL needs both its run id and its parent job id. The run id is restored from state like any resource, but the job id in config comes from a ${resources.jobs.*.id} reference that is only resolved at deploy, so at read time it is 0 and the URL would render as jobs/0/runs/. Restore the run's resolved job_id from state at load time (same mechanism as id and the dashboard etag), then build the URL in JobRun.InitializeURL. --- .../bundle/resources/job_runs/basic/output.txt | 2 +- .../resources/job_runs/job_parameters/output.txt | 2 +- .../bundle/resources/job_runs/redeploy/output.txt | 4 ++-- bundle/config/resources/job_run.go | 13 ++++++++++--- bundle/config/resources_test.go | 5 +++-- bundle/direct/dstate/state.go | 15 +++++++++++++++ bundle/statemgmt/resourcestate/resourcestate.go | 7 +++++++ bundle/statemgmt/state_load.go | 10 ++++++++++ libs/workspaceurls/urls.go | 9 +++++++++ libs/workspaceurls/urls_test.go | 8 ++++++++ 10 files changed, 66 insertions(+), 9 deletions(-) diff --git a/acceptance/bundle/resources/job_runs/basic/output.txt b/acceptance/bundle/resources/job_runs/basic/output.txt index d00f7b26559..d9618704d01 100644 --- a/acceptance/bundle/resources/job_runs/basic/output.txt +++ b/acceptance/bundle/resources/job_runs/basic/output.txt @@ -56,7 +56,7 @@ Resources: Job Runs: my_run: Name: - URL: (not deployed) + URL: [DATABRICKS_URL]/jobs/[MY_JOB_ID]/runs/[MY_RUN_ID]?w=[NUMID] Jobs: my_job: Name: my-job diff --git a/acceptance/bundle/resources/job_runs/job_parameters/output.txt b/acceptance/bundle/resources/job_runs/job_parameters/output.txt index 5b32916f588..bcf3f21e017 100644 --- a/acceptance/bundle/resources/job_runs/job_parameters/output.txt +++ b/acceptance/bundle/resources/job_runs/job_parameters/output.txt @@ -32,7 +32,7 @@ Resources: Job Runs: my_run: Name: - URL: (not deployed) + URL: [DATABRICKS_URL]/jobs/[NUMID]/runs/[NUMID]?w=[NUMID] Jobs: my_job: Name: my-job diff --git a/acceptance/bundle/resources/job_runs/redeploy/output.txt b/acceptance/bundle/resources/job_runs/redeploy/output.txt index 7d6c45f74b4..d7f711c93b0 100644 --- a/acceptance/bundle/resources/job_runs/redeploy/output.txt +++ b/acceptance/bundle/resources/job_runs/redeploy/output.txt @@ -19,7 +19,7 @@ Resources: Job Runs: my_run: Name: - URL: (not deployed) + URL: [DATABRICKS_URL]/jobs/[MY_JOB_ID]/runs/[NUMID]?w=[NUMID] Jobs: my_job: Name: my-job @@ -62,7 +62,7 @@ Resources: Job Runs: my_run: Name: - URL: (not deployed) + URL: [DATABRICKS_URL]/jobs/[MY_JOB_ID]/runs/[NUMID]?w=[NUMID] Jobs: my_job: Name: my-job diff --git a/bundle/config/resources/job_run.go b/bundle/config/resources/job_run.go index 51a8310c636..24927653310 100644 --- a/bundle/config/resources/job_run.go +++ b/bundle/config/resources/job_run.go @@ -6,6 +6,7 @@ import ( "strconv" "github.com/databricks/cli/libs/log" + "github.com/databricks/cli/libs/workspaceurls" "github.com/databricks/databricks-sdk-go" "github.com/databricks/databricks-sdk-go/marshal" "github.com/databricks/databricks-sdk-go/service/jobs" @@ -73,7 +74,13 @@ func (r *JobRun) GetURL() string { return r.URL } -// InitializeURL is a no-op for now: surfacing a stable run URL is deferred to a -// later milestone. -func (r *JobRun) InitializeURL(_ url.URL) { +// InitializeURL sets the run's workspace URL once both IDs that address it are +// known. Before deploy neither is populated: the run id is backfilled from +// state and the job id may still be an unresolved ${resources.jobs.*.id} +// reference, so we skip rather than emit a broken jobs/0 URL. +func (r *JobRun) InitializeURL(baseURL url.URL) { + if r.ID == "" || r.JobId == 0 { + return + } + r.URL = workspaceurls.JobRunURL(baseURL, strconv.FormatInt(r.JobId, 10), r.ID) } diff --git a/bundle/config/resources_test.go b/bundle/config/resources_test.go index f23c349035a..978d5799f45 100644 --- a/bundle/config/resources_test.go +++ b/bundle/config/resources_test.go @@ -125,8 +125,9 @@ func TestBundleResourcePluralNamesResolveInWorkspaceURLs(t *testing.T) { // Resources that intentionally have no workspace URL. noURL := map[string]bool{ "external_locations": true, - // A job run has no stable workspace URL yet; surfacing one is deferred - // to a later milestone (see JobRun.InitializeURL). + // A job run does have a workspace URL, but it's addressed by two IDs + // (job + run) so it can't be expressed as a single-ID pattern here; it's + // built in JobRun.InitializeURL via workspaceurls.JobRunURL instead. "job_runs": true, "postgres_branches": true, "postgres_databases": true, diff --git a/bundle/direct/dstate/state.go b/bundle/direct/dstate/state.go index 0bf50809e16..3ce7769370d 100644 --- a/bundle/direct/dstate/state.go +++ b/bundle/direct/dstate/state.go @@ -468,9 +468,24 @@ func ExportStateFromData(data Database) resourcestate.ExportedResourcesMap { } } + // Extract the resolved job_id for job runs. A run's URL needs its parent + // job id, which in config is a ${resources.jobs.*.id} reference that is + // only resolved at deploy; restoring the deployed value lets read-only + // commands build the run URL. + var jobID int64 + if strings.Contains(key, ".job_runs.") && len(entry.State) > 0 { + var holder struct { + JobID int64 `json:"job_id"` + } + if err := json.Unmarshal(entry.State, &holder); err == nil { + jobID = holder.JobID + } + } + result[key] = resourcestate.ResourceState{ ID: entry.ID, ETag: etag, + JobID: jobID, StateSizeBytes: len(entry.State), } } diff --git a/bundle/statemgmt/resourcestate/resourcestate.go b/bundle/statemgmt/resourcestate/resourcestate.go index ec98f1bc827..4bd5d4eb15e 100644 --- a/bundle/statemgmt/resourcestate/resourcestate.go +++ b/bundle/statemgmt/resourcestate/resourcestate.go @@ -8,6 +8,13 @@ type ResourceState struct { // For dashboards ETag string + // For job_runs: the resolved job_id the run was launched against. A run's + // URL needs its parent job id, but in config that comes from a + // ${resources.jobs.*.id} reference that is only resolved at deploy, so at + // read time (e.g. bundle summary) it reads 0. We carry the deployed value + // here so it can be restored into config at load time. + JobID int64 + // Size in bytes of the resource's serialized state blob. Populated by the // direct engine (len of the JSON stored in resources.json) for deploy // telemetry; left zero by the terraform path. diff --git a/bundle/statemgmt/state_load.go b/bundle/statemgmt/state_load.go index 573c69126c2..02f5664021d 100644 --- a/bundle/statemgmt/state_load.go +++ b/bundle/statemgmt/state_load.go @@ -131,6 +131,16 @@ func StateToBundle(ctx context.Context, state ExportedResourcesMap, config *conf if err != nil { return dyn.InvalidValue, err } + + // A run's job_id in config is a ${resources.jobs.*.id} reference + // that is only resolved at deploy, so at read time it is 0. + // Restore the deployed value so the run URL can be built. + if groupName == "job_runs" && attrs.JobID != 0 { + v, err = dyn.SetByPath(v, dyn.Path{dyn.Key("resources"), dyn.Key(groupName), dyn.Key(resourceName), dyn.Key("job_id")}, dyn.V(attrs.JobID)) + if err != nil { + return dyn.InvalidValue, err + } + } } } diff --git a/libs/workspaceurls/urls.go b/libs/workspaceurls/urls.go index f599139e340..54b6da9bda1 100644 --- a/libs/workspaceurls/urls.go +++ b/libs/workspaceurls/urls.go @@ -81,6 +81,15 @@ func JobRunPath(jobID, runID string) string { return fmt.Sprintf("jobs/%s/runs/%s", jobID, runID) } +// JobRunURL constructs a workspace URL for a job run from a base URL, job ID, +// and run ID. Unlike ResourceURL it takes two IDs because a run is addressed by +// both its parent job and the run itself, so it can't be expressed as a single +// entry in resourceURLPatterns. +func JobRunURL(baseURL url.URL, jobID, runID string) string { + baseURL.Path = JobRunPath(jobID, runID) + return baseURL.String() +} + // ResourceURL constructs a workspace URL for a named resource type and ID. func ResourceURL(baseURL url.URL, resourceType, id string) string { resourceType = resolveAlias(resourceType) diff --git a/libs/workspaceurls/urls_test.go b/libs/workspaceurls/urls_test.go index 683b9c470e7..e39d28d9aaf 100644 --- a/libs/workspaceurls/urls_test.go +++ b/libs/workspaceurls/urls_test.go @@ -35,6 +35,14 @@ func TestJobRunPath(t *testing.T) { assert.Equal(t, "jobs/123/runs/456", JobRunPath("123", "456")) } +func TestJobRunURL(t *testing.T) { + base := url.URL{Scheme: "https", Host: "host.com"} + assert.Equal(t, "https://host.com/jobs/123/runs/456", JobRunURL(base, "123", "456")) + + withWorkspace := url.URL{Scheme: "https", Host: "host.com", RawQuery: "w=789"} + assert.Equal(t, "https://host.com/jobs/123/runs/456?w=789", JobRunURL(withWorkspace, "123", "456")) +} + func TestResourceTypes(t *testing.T) { types := ResourceTypes() assert.NotEmpty(t, types)