Skip to content

Commit 6a7b273

Browse files
authored
Render deployment_id and version_id in bundle summary (#5638)
## Changes `bundle summary` now surfaces the bundle's deployment metadata service identifiers — `deployment_id` and the current `version_id` — when the deployment metadata service is in use (managed state + direct engine). They appear as a `Deployment:` section in text output and as a top-level `deployment` object in `--output json`. Non-DMS summaries are unchanged. `version_id` isn't known to a read-only command, so summary fetches the latest `last_version_id` from the deployment record via `GetDeployment`. ## Why The in-workspace DABs UI needs the bundle-level `deployment_id` + `version_id` to link to the deployment metadata page. Until now these were only resolved internally (`b.DeploymentID`) or stamped per-resource for the jobs UI — no command exposed the bundle's own identifiers. This stacks on the DMS branch (#4856). ## Tests Extended the `bundle/dms/plan-and-summary` acceptance test to cover both the text `Deployment:` block and the `bundle summary -o json` `deployment` object.
1 parent 78efc31 commit 6a7b273

5 files changed

Lines changed: 111 additions & 6 deletions

File tree

acceptance/bundle/dms/plan-and-summary/output.txt

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,21 @@ Target: default
1515
Workspace:
1616
User: [USERNAME]
1717
Path: /Workspace/Users/[USERNAME]/.bundle/plan-summary-test/default
18+
Deployment:
19+
ID: [UUID]
20+
Version: 1
1821
Resources:
1922
Jobs:
2023
test_job:
2124
Name: test-job
2225
URL: [DATABRICKS_URL]/jobs/[NUMID]?w=[NUMID]
2326

27+
>>> [CLI] bundle summary -o json
28+
{
29+
"deployment_id": "[UUID]",
30+
"version_id": "1"
31+
}
32+
2433
>>> print_requests.py --get //bundle ^//workspace-files ^//import-file
2534
{
2635
"method": "POST",
@@ -103,3 +112,19 @@ Resources:
103112
},
104113
"body": null
105114
}
115+
{
116+
"method": "GET",
117+
"path": "/api/2.0/bundle/deployments/[UUID]"
118+
}
119+
{
120+
"method": "GET",
121+
"path": "/api/2.0/bundle/deployments/[UUID]/resources",
122+
"q": {
123+
"page_size": "1000"
124+
},
125+
"body": null
126+
}
127+
{
128+
"method": "GET",
129+
"path": "/api/2.0/bundle/deployments/[UUID]"
130+
}

acceptance/bundle/dms/plan-and-summary/script

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ trace $CLI bundle plan
77
# Summary should show the deployment ID and read state from DMS.
88
trace $CLI bundle summary
99

10+
# Summary in JSON mode exposes the deployment metadata for programmatic use.
11+
trace $CLI bundle summary -o json | jq .deployment
12+
1013
# Print metadata service requests from plan and summary.
1114
# Both should include ListResources calls.
1215
trace print_requests.py --get //bundle ^//workspace-files ^//import-file

bundle/render/render_text_output.go

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,13 @@ const resourcesTemplate = `Resources:
4545
{{- end }}
4646
`
4747

48+
const deploymentTemplate = `Deployment:
49+
ID: {{ .DeploymentId | bold }}
50+
{{- if .VersionId }}
51+
Version: {{ .VersionId | bold }}
52+
{{- end }}
53+
`
54+
4855
type ResourceGroup struct {
4956
GroupName string
5057
Resources []ResourceInfo
@@ -136,14 +143,20 @@ func RenderDiagnosticsSummary(ctx context.Context, out io.Writer, b *bundle.Bund
136143
return nil
137144
}
138145

139-
func RenderSummary(ctx context.Context, out io.Writer, b *bundle.Bundle) error {
146+
func RenderSummary(ctx context.Context, out io.Writer, b *bundle.Bundle, deploymentID, versionID string) error {
140147
if b == nil {
141148
return nil
142149
}
143150
if err := renderSummaryHeaderTemplate(ctx, out, b); err != nil {
144151
return err
145152
}
146153

154+
if deploymentID != "" {
155+
if err := renderDeploymentTemplate(ctx, out, deploymentID, versionID); err != nil {
156+
return fmt.Errorf("failed to render deployment template: %w", err)
157+
}
158+
}
159+
147160
var resourceGroups []ResourceGroup
148161

149162
for _, group := range b.Config.Resources.AllResources() {
@@ -171,6 +184,16 @@ func RenderSummary(ctx context.Context, out io.Writer, b *bundle.Bundle) error {
171184
return nil
172185
}
173186

187+
// renderDeploymentTemplate renders the bundle's deployment metadata service
188+
// identifiers (deployment_id and the current version_id).
189+
func renderDeploymentTemplate(ctx context.Context, out io.Writer, deploymentID, versionID string) error {
190+
t := template.Must(template.New("deployment").Funcs(cmdio.RenderFuncMap(ctx)).Parse(deploymentTemplate))
191+
return t.Execute(out, map[string]any{
192+
"DeploymentId": deploymentID,
193+
"VersionId": versionID,
194+
})
195+
}
196+
174197
// Helper function to sort and render resource groups using the template
175198
func renderResourcesTemplate(ctx context.Context, out io.Writer, resourceGroups []ResourceGroup) error {
176199
// Sort everything to ensure consistent output

bundle/render/render_text_output_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ func TestRenderSummary(t *testing.T) {
340340
}
341341

342342
writer := &bytes.Buffer{}
343-
err := RenderSummary(ctx, writer, b)
343+
err := RenderSummary(ctx, writer, b, "", "")
344344
require.NoError(t, err)
345345

346346
expectedSummary := `Name: test-bundle

cmd/bundle/summary.go

Lines changed: 58 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
11
package bundle
22

33
import (
4+
"context"
5+
"encoding/json"
6+
"fmt"
7+
48
"github.com/databricks/cli/bundle"
59
"github.com/databricks/cli/bundle/render"
610
"github.com/databricks/cli/cmd/bundle/utils"
711
"github.com/databricks/cli/cmd/root"
812
"github.com/databricks/cli/libs/flags"
913
"github.com/databricks/cli/libs/logdiag"
14+
"github.com/databricks/cli/libs/tmpdms"
1015
"github.com/spf13/cobra"
1116
)
1217

@@ -51,11 +56,60 @@ Useful after deployment to see what was created and where to find it.`,
5156
}
5257

5358
func showSummary(cmd *cobra.Command, b *bundle.Bundle) error {
54-
if root.OutputType(cmd) == flags.OutputText {
55-
return render.RenderSummary(cmd.Context(), cmd.OutOrStdout(), b)
59+
ctx := cmd.Context()
60+
61+
// When the deployment metadata service is in use, surface the bundle's
62+
// deployment_id and current version_id so callers (e.g. the workspace UI)
63+
// can link to the deployment metadata. Both are empty otherwise.
64+
versionID, err := currentDeploymentVersion(ctx, b)
65+
if err != nil {
66+
return err
67+
}
68+
69+
switch root.OutputType(cmd) {
70+
case flags.OutputText:
71+
return render.RenderSummary(ctx, cmd.OutOrStdout(), b, b.DeploymentID, versionID)
72+
case flags.OutputJSON:
73+
return renderSummaryJSON(cmd, b, versionID)
74+
}
75+
return nil
76+
}
77+
78+
// currentDeploymentVersion returns the latest version_id recorded for the
79+
// bundle's deployment, or "" when the deployment metadata service is not in use.
80+
func currentDeploymentVersion(ctx context.Context, b *bundle.Bundle) (string, error) {
81+
if b.DeploymentID == "" {
82+
return "", nil
83+
}
84+
svc, err := tmpdms.NewDeploymentMetadataAPI(b.WorkspaceClient(ctx))
85+
if err != nil {
86+
return "", fmt.Errorf("failed to create metadata service client: %w", err)
87+
}
88+
dep, err := svc.GetDeployment(ctx, tmpdms.GetDeploymentRequest{DeploymentID: b.DeploymentID})
89+
if err != nil {
90+
return "", fmt.Errorf("failed to get deployment: %w", err)
91+
}
92+
return dep.LastVersionID, nil
93+
}
94+
95+
// renderSummaryJSON marshals the bundle configuration and, when the deployment
96+
// metadata service is in use, adds a top-level "deployment" object carrying the
97+
// deployment_id and version_id.
98+
func renderSummaryJSON(cmd *cobra.Command, b *bundle.Bundle, versionID string) error {
99+
value := b.Config.Value().AsAny()
100+
if b.DeploymentID != "" {
101+
// The config root is always a mapping for a loaded bundle.
102+
value.(map[string]any)["deployment"] = map[string]string{
103+
"deployment_id": b.DeploymentID,
104+
"version_id": versionID,
105+
}
56106
}
57-
if root.OutputType(cmd) == flags.OutputJSON {
58-
return renderJsonOutput(cmd, b)
107+
buf, err := json.MarshalIndent(value, "", " ")
108+
if err != nil {
109+
return err
59110
}
111+
out := cmd.OutOrStdout()
112+
_, _ = out.Write(buf)
113+
_, _ = out.Write([]byte{'\n'})
60114
return nil
61115
}

0 commit comments

Comments
 (0)