Skip to content

Commit d9d854f

Browse files
committed
migrate: compute depends_on from refs before resolving, restore --noplancheck
The refs map is shared with sv.Refs and gets mutated (entries deleted) during reference resolution. depends_on must be computed before that loop runs. Also restore --noplancheck as a no-op flag kept for backward compatibility (used by the invariant test suite for job_with_depends_on config). Co-authored-by: Isaac
1 parent 9ca01e7 commit d9d854f

1 file changed

Lines changed: 43 additions & 1 deletion

File tree

bundle/migrate/build_state.go

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,18 @@ import (
44
"context"
55
"fmt"
66
"maps"
7+
"slices"
78
"strings"
89

910
"github.com/databricks/cli/bundle/config"
1011
"github.com/databricks/cli/bundle/config/resources"
1112
"github.com/databricks/cli/bundle/deploy/terraform"
13+
"github.com/databricks/cli/bundle/deployplan"
1214
"github.com/databricks/cli/bundle/direct"
1315
"github.com/databricks/cli/bundle/direct/dresources"
1416
"github.com/databricks/cli/bundle/direct/dstate"
1517
"github.com/databricks/cli/libs/dyn"
18+
"github.com/databricks/cli/libs/dyn/dynvar"
1619
"github.com/databricks/cli/libs/log"
1720
"github.com/databricks/cli/libs/structs/structaccess"
1821
"github.com/databricks/cli/libs/structs/structpath"
@@ -120,6 +123,45 @@ func BuildStateFromTF(
120123

121124
sv := structvar.NewStructVar(newStateValue, refs)
122125

126+
// Compute depends_on from cross-resource references before resolving them
127+
// (resolution deletes entries from the refs map).
128+
// Same logic as makePlan in bundle/direct/bundle_plan.go.
129+
var dependsOn []deployplan.DependsOnEntry //nolint:prealloc
130+
for _, refTemplate := range refs {
131+
ref, ok := dynvar.NewRef(dyn.V(refTemplate))
132+
if !ok {
133+
continue
134+
}
135+
for _, targetPath := range ref.References() {
136+
targetPathParsed, err := dyn.NewPathFromString(targetPath)
137+
if err != nil {
138+
continue
139+
}
140+
targetNodeDP, _ := config.GetNodeAndType(targetPathParsed)
141+
targetNode := targetNodeDP.String()
142+
fullRef := "${" + targetPath + "}"
143+
found := false
144+
for _, dep := range dependsOn {
145+
if dep.Node == targetNode && dep.Label == fullRef {
146+
found = true
147+
break
148+
}
149+
}
150+
if !found {
151+
dependsOn = append(dependsOn, deployplan.DependsOnEntry{
152+
Node: targetNode,
153+
Label: fullRef,
154+
})
155+
}
156+
}
157+
}
158+
slices.SortFunc(dependsOn, func(a, b deployplan.DependsOnEntry) int {
159+
if a.Node != b.Node {
160+
return strings.Compare(a.Node, b.Node)
161+
}
162+
return strings.Compare(a.Label, b.Label)
163+
})
164+
123165
// Resolve each reference using TF state.
124166
// node format: "resources.<group>.<name>" or "resources.<group>.<name>.permissions"
125167
parts := strings.SplitN(node, ".", 4)
@@ -170,7 +212,7 @@ func BuildStateFromTF(
170212
}
171213
}
172214

173-
if err := stateDB.SaveState(node, idEntry.ID, sv.Value, nil); err != nil {
215+
if err := stateDB.SaveState(node, idEntry.ID, sv.Value, dependsOn); err != nil {
174216
return fmt.Errorf("%s: SaveState: %w", node, err)
175217
}
176218
}

0 commit comments

Comments
 (0)