Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .agents/skills/bump-sdk/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ Decide with the user whether to keep the tagging-producer drift or restore those
The task ends with step 4 (`generate-clijson-post` runs `bump-sdk-post`) and ignores its error, so read the end of its output, or go on with step 4 directly.

**4. Regenerate everything downstream: `./task bump-sdk-post`.**
This is the whole mechanical part of the bump: `generate-check` (command stubs, refschema, schema, validation, direct-engine YAML, pydabs), then `test-update` for the acceptance goldens.
This is the whole mechanical part of the bump: `fix-sdk-field-copies` (complete reviewed direct-resource mappings), `generate-check` (command stubs, refschema, schema, validation, direct-engine YAML, pydabs), then `test-update` for the acceptance goldens.
Everything after it needs judgment.
Run directly, it fails on errors: `generate-refschema` and `test-update` build the CLI, so it fails while the bump still breaks compilation; fix that (step 5) and rerun the task.

Expand All @@ -67,7 +67,7 @@ Revert any golden change you can't attribute to the new SDK or spec.
**5. Handle SDK breaking changes.**
Read the SDK's `CHANGELOG.md` at the target version (in the module cache) to enumerate breaking changes before chasing compile errors.
A removed struct field that the CLI used (e.g. `jobs.AiRuntimeTask.CodeSourcePath`) should have its usage temporarily disabled with a comment noting it returns in a later SDK bump, not deleted outright.
A new struct field triggers an `exhaustruct` lint failure in `bundle/direct/dresources/*`. Run `./task lint` and (in case of issues) wire the field through `PrepareState` and `RemapState` when it exists on both the input and remote types.
A new struct field can trigger an `exhaustruct` lint failure in `bundle/direct/dresources/*`. `bump-sdk-post` first runs `fix-sdk-field-copies`, which adds missing same-name, same-JSON-name, identical-type copies only in literals explicitly annotated with `// sdk:copy-from source`. Existing assignments are preserved. Read `tools/sdkfieldcopies/README.md` for the reviewed scope and exclusions. Remaining fields still need judgment: run `./task lint`, review the fixer diagnostics, and wire the field through the appropriate mappings. Do not add zero values or annotations just to silence lint.
Where a remote is rebuilt by hand from a GET response (e.g. `makeJobRunRemote` maps `jobs.Run` into the `jobs.RunNow`-shaped `JobRunRemote`), copy the new field from the response if the response has it, and list it with the request-only zero values otherwise.
`job_runs.yml` must list every `jobs.RunNow` field under `ignore_remote_changes`; `TestJobRunIgnoresEveryRequestField` fails on a new one.
A field the new spec now annotates as output-only may already be emitted into `<resource_type>.generated.yml`, making the manual entry in `<resource_type>.yml` redundant; `TestResourcesYMLNoRedundantRules` catches this, so remove the manual entry.
Expand Down
8 changes: 7 additions & 1 deletion Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -962,14 +962,20 @@ tasks:
# then refresh the acceptance goldens. generate-clijson-post runs it last;
# run it directly to redo it, e.g. after hand fixes. generate-refschema and
# test-update build the CLI, so it fails while the bump breaks compilation
# (code using a removed SDK field). Those fixes, exhaustruct wiring and the
# (code using a removed SDK field). Unresolved field mappings and the
# changelog PR link stay manual (.agents/skills/bump-sdk).
bump-sdk-post:
desc: Regenerate everything downstream of an SDK bump and refresh acceptance goldens
cmds:
- task: fix-sdk-field-copies
- task: generate-check
- task: test-update

fix-sdk-field-copies:
desc: Complete explicitly annotated SDK field copies in direct resources
cmds:
- go run -C tools ./sdkfieldcopies -root ..

# Refreshes out.fields.txt, which records the field paths / types emitted by
# `bundle debug refschema` (see cmd/bundle/debug/refschema.go). It reflects
# over types reachable from bundle/, so any bundle change or SDK bump (go.mod
Expand Down
2 changes: 1 addition & 1 deletion bundle/direct/dresources/catalog.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func (*ResourceCatalog) PrepareState(input *resources.Catalog) *catalog.CreateCa
}

func (*ResourceCatalog) RemapState(info *catalog.CatalogInfo) *catalog.CreateCatalog {
return &catalog.CreateCatalog{
return &catalog.CreateCatalog{ // sdk:copy-from info
Comment: info.Comment,
ConnectionName: info.ConnectionName,
CustomMaxRetentionHours: info.CustomMaxRetentionHours,
Expand Down
6 changes: 3 additions & 3 deletions bundle/direct/dresources/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ func (r *ResourceCluster) PrepareState(input *resources.Cluster) *ClusterState {
// RemapState maps the remote ClusterRemote to ClusterState for diff comparison.
// Started is derived from cluster state so the planner can detect start/stop changes.
func (r *ResourceCluster) RemapState(input *ClusterRemote) *ClusterState {
spec := &ClusterState{
spec := &ClusterState{ // sdk:copy-from input
ApplyPolicyDefaultValues: input.ApplyPolicyDefaultValues,
Autoscale: input.Autoscale,
AutoterminationMinutes: input.AutoterminationMinutes,
Expand Down Expand Up @@ -428,7 +428,7 @@ func remoteClusterIsRunning(entry *PlanEntry) bool {
}

func makeCreateCluster(config *compute.ClusterSpec) compute.CreateCluster {
create := compute.CreateCluster{
create := compute.CreateCluster{ // sdk:copy-from config
ApplyPolicyDefaultValues: config.ApplyPolicyDefaultValues,
Autoscale: config.Autoscale,
AutoterminationMinutes: config.AutoterminationMinutes,
Expand Down Expand Up @@ -478,7 +478,7 @@ func makeCreateCluster(config *compute.ClusterSpec) compute.CreateCluster {
}

func makeEditCluster(id string, config *compute.ClusterSpec) compute.EditCluster {
edit := compute.EditCluster{
edit := compute.EditCluster{ // sdk:copy-from config
ClusterId: id,
ApplyPolicyDefaultValues: config.ApplyPolicyDefaultValues,
Autoscale: config.Autoscale,
Expand Down
4 changes: 2 additions & 2 deletions bundle/direct/dresources/cluster_policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func (*ResourceClusterPolicy) PrepareState(input *resources.ClusterPolicy) *comp
// RemapState copies the config fields shared by Policy and CreatePolicy;
// output-only fields (policy_id, created_at_timestamp, creator_user_name, is_default) are not in the state.
func (*ResourceClusterPolicy) RemapState(remote *compute.Policy) *compute.CreatePolicy {
return &compute.CreatePolicy{
return &compute.CreatePolicy{ // sdk:copy-from remote
Definition: remote.Definition,
Description: remote.Description,
Libraries: remote.Libraries,
Expand All @@ -58,7 +58,7 @@ func (r *ResourceClusterPolicy) DoCreate(ctx context.Context, config *compute.Cr
}

func (r *ResourceClusterPolicy) DoUpdate(ctx context.Context, id string, config *compute.CreatePolicy, _ *PlanEntry) (*compute.Policy, error) {
return nil, r.client.ClusterPolicies.Edit(ctx, compute.EditPolicy{
return nil, r.client.ClusterPolicies.Edit(ctx, compute.EditPolicy{ // sdk:copy-from config
PolicyId: id,
Name: config.Name,
Definition: config.Definition,
Expand Down
4 changes: 2 additions & 2 deletions bundle/direct/dresources/experiment.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func (*ResourceExperiment) New(client *databricks.WorkspaceClient) *ResourceExpe
}

func (*ResourceExperiment) PrepareState(input *resources.MlflowExperiment) *ml.CreateExperiment {
return &ml.CreateExperiment{
return &ml.CreateExperiment{ // sdk:copy-from input
Name: input.Name,
ArtifactLocation: input.ArtifactLocation,
Tags: input.Tags,
Expand All @@ -33,7 +33,7 @@ func (*ResourceExperiment) PrepareState(input *resources.MlflowExperiment) *ml.C
}

func (*ResourceExperiment) RemapState(experiment *ml.Experiment) *ml.CreateExperiment {
return &ml.CreateExperiment{
return &ml.CreateExperiment{ // sdk:copy-from experiment
Name: experiment.Name,
ArtifactLocation: experiment.ArtifactLocation,
Tags: experiment.Tags,
Expand Down
2 changes: 1 addition & 1 deletion bundle/direct/dresources/external_location.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func (*ResourceExternalLocation) PrepareState(input *resources.ExternalLocation)
}

func (*ResourceExternalLocation) RemapState(info *catalog.ExternalLocationInfo) *catalog.CreateExternalLocation {
return &catalog.CreateExternalLocation{
return &catalog.CreateExternalLocation{ // sdk:copy-from info
Comment: info.Comment,
CredentialName: info.CredentialName,
// Output-only fields mirrored into state to avoid churn in remapped config.
Expand Down
4 changes: 2 additions & 2 deletions bundle/direct/dresources/instance_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func (*ResourceInstancePool) PrepareState(input *resources.InstancePool) *comput
// RemapState copies the config fields shared by GetInstancePool and CreateInstancePool;
// output-only fields (state, stats, default_tags, instance_pool_id) are not in the state.
func (*ResourceInstancePool) RemapState(remote *compute.GetInstancePool) *compute.CreateInstancePool {
return &compute.CreateInstancePool{
return &compute.CreateInstancePool{ // sdk:copy-from remote
AwsAttributes: remote.AwsAttributes,
AzureAttributes: remote.AzureAttributes,
CustomTags: remote.CustomTags,
Expand Down Expand Up @@ -58,7 +58,7 @@ func (r *ResourceInstancePool) DoCreate(ctx context.Context, config *compute.Cre
}

func (r *ResourceInstancePool) DoUpdate(ctx context.Context, id string, config *compute.CreateInstancePool, _ *PlanEntry) (*compute.GetInstancePool, error) {
return nil, r.client.InstancePools.Edit(ctx, compute.EditInstancePool{
return nil, r.client.InstancePools.Edit(ctx, compute.EditInstancePool{ // sdk:copy-from config
InstancePoolId: id,
InstancePoolName: config.InstancePoolName,
NodeTypeId: config.NodeTypeId,
Expand Down
2 changes: 1 addition & 1 deletion bundle/direct/dresources/job.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ func (r *ResourceJob) DoDelete(ctx context.Context, id string, _ *jobs.JobSettin
func makeCreateJob(config jobs.JobSettings) (jobs.CreateJob, error) {
// Note, exhaustruct linter validates that all off CreateJob fields are initialized.
// We don't have linter that validates that all of config fields are used.
result := jobs.CreateJob{
result := jobs.CreateJob{ // sdk:copy-from config
AccessControlList: nil, // Not supported by DABs
BudgetPolicyId: config.BudgetPolicyId,
Continuous: config.Continuous,
Expand Down
2 changes: 1 addition & 1 deletion bundle/direct/dresources/job_run.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ func makeJobRunRemote(run *jobs.Run) *JobRunRemote {
jobParameters[p.Name] = p.Value
}
}
return &JobRunRemote{
return &JobRunRemote{ // sdk:copy-skip Parameter flattening and result-state reconstruction need manual mapping.
JobId: run.JobId,
JobParameters: jobParameters,
DurationTarget: run.DurationTarget,
Expand Down
2 changes: 1 addition & 1 deletion bundle/direct/dresources/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func (*ResourceMlflowModel) PrepareState(input *resources.MlflowModel) *ml.Creat
}

func (*ResourceMlflowModel) RemapState(output *MlflowModelRemote) *ml.CreateModelRequest {
return &ml.CreateModelRequest{
return &ml.CreateModelRequest{ // sdk:copy-from output
Name: output.Name,
Tags: output.Tags,
Description: output.Description,
Expand Down
6 changes: 3 additions & 3 deletions bundle/direct/dresources/model_serving_endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ func autoCaptureConfigOutputToInput(output *serving.AutoCaptureConfigOutput) *se
if output == nil {
return nil
}
return &serving.AutoCaptureConfigInput{
return &serving.AutoCaptureConfigInput{ // sdk:copy-from output
CatalogName: output.CatalogName,
SchemaName: output.SchemaName,
TableNamePrefix: output.TableNamePrefix,
Expand All @@ -57,7 +57,7 @@ func autoCaptureConfigOutputToInput(output *serving.AutoCaptureConfigOutput) *se
func servedEntitiesOutputToInput(output []serving.ServedEntityOutput) []serving.ServedEntityInput {
entities := make([]serving.ServedEntityInput, len(output))
for i, entity := range output {
entities[i] = serving.ServedEntityInput{
entities[i] = serving.ServedEntityInput{ // sdk:copy-from entity
EntityName: entity.EntityName,
EntityVersion: entity.EntityVersion,
EnvironmentVars: entity.EnvironmentVars,
Expand All @@ -84,7 +84,7 @@ func configOutputToInput(output *serving.EndpointCoreConfigOutput) *serving.Endp
if output == nil {
return nil
}
return &serving.EndpointCoreConfigInput{
return &serving.EndpointCoreConfigInput{ // sdk:copy-skip Nested conversions and deprecated fields need manual review.
AutoCaptureConfig: autoCaptureConfigOutputToInput(output.AutoCaptureConfig),
ServedEntities: servedEntitiesOutputToInput(output.ServedEntities),
ServedModels: nil,
Expand Down
4 changes: 2 additions & 2 deletions bundle/direct/dresources/pipeline.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ func makePipelineRemote(p *pipelines.GetPipelineResponse) *PipelineRemote {
var createPipeline pipelines.CreatePipeline
if p.Spec != nil {
spec := p.Spec
createPipeline = pipelines.CreatePipeline{
createPipeline = pipelines.CreatePipeline{ // sdk:copy-skip New fields need review to choose Spec or response-level sources.
// Note: AllowDuplicateNames and DryRun are not in PipelineSpec,
// they are request-only fields, so they stay at their zero values.
AllowDuplicateNames: false,
Expand Down Expand Up @@ -173,7 +173,7 @@ func (r *ResourcePipeline) DoUpdate(ctx context.Context, id string, config *Pipe
return nil, nil
}

request := pipelines.EditPipeline{
request := pipelines.EditPipeline{ // sdk:copy-from config
AllowDuplicateNames: config.AllowDuplicateNames,
BudgetPolicyId: config.BudgetPolicyId,
Catalog: config.Catalog,
Expand Down
2 changes: 1 addition & 1 deletion bundle/direct/dresources/quality_monitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func (*ResourceQualityMonitor) PrepareState(input *resources.QualityMonitor) *Qu

func (*ResourceQualityMonitor) RemapState(info *catalog.MonitorInfo) *QualityMonitorState {
return &QualityMonitorState{
CreateMonitor: catalog.CreateMonitor{
CreateMonitor: catalog.CreateMonitor{ // sdk:copy-from info
AssetsDir: info.AssetsDir,
BaselineTableName: info.BaselineTableName,
CustomMetrics: info.CustomMetrics,
Expand Down
2 changes: 1 addition & 1 deletion bundle/direct/dresources/registered_model.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func (*ResourceRegisteredModel) PrepareState(input *resources.RegisteredModel) *
}

func (*ResourceRegisteredModel) RemapState(model *catalog.RegisteredModelInfo) *catalog.CreateRegisteredModelRequest {
return &catalog.CreateRegisteredModelRequest{
return &catalog.CreateRegisteredModelRequest{ // sdk:copy-from model
CatalogName: model.CatalogName,
Comment: model.Comment,
Name: model.Name,
Expand Down
2 changes: 1 addition & 1 deletion bundle/direct/dresources/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func (*ResourceSchema) PrepareState(input *resources.Schema) *catalog.CreateSche
}

func (*ResourceSchema) RemapState(info *catalog.SchemaInfo) *catalog.CreateSchema {
return &catalog.CreateSchema{
return &catalog.CreateSchema{ // sdk:copy-from info
CatalogName: info.CatalogName,
Comment: info.Comment,
CustomMaxRetentionHours: info.CustomMaxRetentionHours,
Expand Down
4 changes: 2 additions & 2 deletions bundle/direct/dresources/secret_scope.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func (*ResourceSecretScope) New(client *databricks.WorkspaceClient) *ResourceSec
}

func (*ResourceSecretScope) PrepareState(input *resources.SecretScope) *SecretScopeConfig {
return &SecretScopeConfig{
return &SecretScopeConfig{ // sdk:copy-skip Response-to-request field renames need manual mapping.
Scope: input.Name,
ScopeBackendType: input.BackendType,
BackendAzureKeyvault: input.KeyvaultMetadata,
Expand All @@ -60,7 +60,7 @@ func (*ResourceSecretScope) PrepareState(input *resources.SecretScope) *SecretSc
}

func (*ResourceSecretScope) RemapState(remote *SecretScopeRemote) *SecretScopeConfig {
return &SecretScopeConfig{
return &SecretScopeConfig{ // sdk:copy-from remote
Scope: remote.Scope,
ScopeBackendType: remote.ScopeBackendType,
BackendAzureKeyvault: remote.BackendAzureKeyvault,
Expand Down
4 changes: 2 additions & 2 deletions bundle/direct/dresources/sql_warehouse.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ func (*ResourceSqlWarehouse) PrepareState(input *resources.SqlWarehouse) *SqlWar
// RemapState maps the remote SqlWarehouseRemote to SqlWarehouseState for diff comparison.
// Started is derived from warehouse state so the planner can detect start/stop changes.
func (*ResourceSqlWarehouse) RemapState(warehouse *SqlWarehouseRemote) *SqlWarehouseState {
return &SqlWarehouseState{
return &SqlWarehouseState{ // sdk:copy-from warehouse
AutoStopMins: warehouse.AutoStopMins,
Channel: warehouse.Channel,
ClusterSize: warehouse.ClusterSize,
Expand Down Expand Up @@ -137,7 +137,7 @@ func hasWarehouseChanges(entry *PlanEntry) bool {
func (r *ResourceSqlWarehouse) DoUpdate(ctx context.Context, id string, config *SqlWarehouseState, entry *PlanEntry) (*SqlWarehouseRemote, error) {
edited := hasWarehouseChanges(entry)
if edited {
request := sql.EditWarehouseRequest{
request := sql.EditWarehouseRequest{ // sdk:copy-from config
AutoStopMins: config.AutoStopMins,
Channel: config.Channel,
ClusterSize: config.ClusterSize,
Expand Down
2 changes: 1 addition & 1 deletion bundle/direct/dresources/vector_search_endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ func (*ResourceVectorSearchEndpoint) PrepareState(input *resources.VectorSearchE
}

func (*ResourceVectorSearchEndpoint) RemapState(remote *VectorSearchEndpointRemote) *vectorsearch.CreateEndpoint {
return &vectorsearch.CreateEndpoint{
return &vectorsearch.CreateEndpoint{ // sdk:copy-from remote
Name: remote.Name,
EndpointType: remote.EndpointType,
BudgetPolicyId: remote.BudgetPolicyId,
Expand Down
4 changes: 2 additions & 2 deletions bundle/direct/dresources/vector_search_index.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ func (*ResourceVectorSearchIndex) PrepareState(input *resources.VectorSearchInde
}

func (*ResourceVectorSearchIndex) RemapState(remote *VectorSearchIndexRemote) *VectorSearchIndexState {
state := &VectorSearchIndexState{
state := &VectorSearchIndexState{ // sdk:copy-from remote
DeltaSyncIndexSpec: nil, // need to remap below
DirectAccessIndexSpec: remote.DirectAccessIndexSpec,
IndexSubtype: remote.IndexSubtype,
Expand All @@ -93,7 +93,7 @@ func (*ResourceVectorSearchIndex) RemapState(remote *VectorSearchIndexRemote) *V
EndpointUuid: remote.EndpointUuid,
}
if remote.DeltaSyncIndexSpec != nil {
state.DeltaSyncIndexSpec = &vectorsearch.DeltaSyncVectorIndexSpecRequest{
state.DeltaSyncIndexSpec = &vectorsearch.DeltaSyncVectorIndexSpecRequest{ // sdk:copy-from remote.DeltaSyncIndexSpec
ColumnsToIndex: remote.DeltaSyncIndexSpec.ColumnsToIndex,
ColumnsToSync: remote.DeltaSyncIndexSpec.ColumnsToSync,
EmbeddingSourceColumns: remote.DeltaSyncIndexSpec.EmbeddingSourceColumns,
Expand Down
2 changes: 1 addition & 1 deletion bundle/direct/dresources/volume.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func (*ResourceVolume) PrepareState(input *resources.Volume) *catalog.CreateVolu
}

func (*ResourceVolume) RemapState(info *catalog.VolumeInfo) *catalog.CreateVolumeRequestContent {
return &catalog.CreateVolumeRequestContent{
return &catalog.CreateVolumeRequestContent{ // sdk:copy-from info
CatalogName: info.CatalogName,
Comment: info.Comment,
Name: info.Name,
Expand Down
2 changes: 1 addition & 1 deletion tools/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ toolchain go1.27.3
require (
github.com/stretchr/testify v1.12.1
golang.org/x/mod v0.41.0
golang.org/x/tools v0.50.0 // BSD-3-Clause
gopkg.in/yaml.v3 v3.0.1
)

Expand Down Expand Up @@ -220,7 +221,6 @@ require (
golang.org/x/telemetry v0.0.0-20260908163034-4bcc4b2ee518 // indirect
golang.org/x/term v0.39.0 // indirect
golang.org/x/text v0.41.0 // indirect
golang.org/x/tools v0.50.0 // indirect
golang.org/x/vuln v1.3.0 // indirect
google.golang.org/protobuf v1.36.12 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
Expand Down
5 changes: 5 additions & 0 deletions tools/sdkfieldcopies/NOTICE
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
This development tool uses the following open source project, licensed under the BSD (3-clause) license:

golang.org/x/tools - https://github.com/golang/tools
Copyright 2009 The Go Authors.
License - https://github.com/golang/tools/blob/master/LICENSE
Loading
Loading