Skip to content

Commit e82bea2

Browse files
authored
Mcp/deploy cmd (#4042)
## Changes Added combined deploy command simplifying agents workflow ## Why Agents won't skip validation step or get confused between bundle deploy and bundle run "resource name" ## Tests <!-- How have you tested the changes? --> <!-- If your PR needs to be included in the release notes for next release, add a separate entry in NEXT_CHANGELOG.md as part of your PR. -->
1 parent 496a104 commit e82bea2

File tree

2 files changed

+132
-0
lines changed

2 files changed

+132
-0
lines changed
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
package mcp
2+
3+
import (
4+
"context"
5+
"errors"
6+
"fmt"
7+
8+
"github.com/databricks/cli/bundle"
9+
"github.com/databricks/cli/bundle/resources"
10+
"github.com/databricks/cli/bundle/run"
11+
"github.com/databricks/cli/cmd/bundle/utils"
12+
"github.com/databricks/cli/cmd/root"
13+
"github.com/databricks/cli/experimental/apps-mcp/lib/validation"
14+
"github.com/databricks/cli/libs/cmdio"
15+
"github.com/databricks/cli/libs/log"
16+
"github.com/spf13/cobra"
17+
)
18+
19+
func newDeployCmd() *cobra.Command {
20+
cmd := &cobra.Command{
21+
Use: "deploy",
22+
Short: "Validate, deploy bundle, and run app",
23+
Long: `Validate, deploy bundle, and run app.
24+
25+
This command runs a complete deployment pipeline:
26+
1. Validates the Node.js project (npm install, build, typecheck, test)
27+
2. Deploys the bundle to the workspace
28+
3. Runs the app defined in the bundle
29+
30+
The command will stop immediately if any step fails.`,
31+
Args: root.NoArgs,
32+
RunE: deployRun,
33+
}
34+
35+
// Add --var flag required by ProcessBundle
36+
cmd.Flags().StringSlice("var", []string{}, `set values for variables defined in bundle config. Example: --var="foo=bar"`)
37+
38+
return cmd
39+
}
40+
41+
func deployRun(cmd *cobra.Command, args []string) error {
42+
ctx := cmd.Context()
43+
44+
log.Infof(ctx, "Running Node.js validation...")
45+
validator := &validation.ValidationNodeJs{}
46+
result, err := validator.Validate(ctx, ".")
47+
if err != nil {
48+
return fmt.Errorf("validation error: %w", err)
49+
}
50+
51+
cmdio.LogString(ctx, result.String())
52+
53+
if !result.Success {
54+
return errors.New("validation failed")
55+
}
56+
log.Infof(ctx, "Validation passed")
57+
58+
log.Infof(ctx, "Deploying bundle...")
59+
b, err := utils.ProcessBundle(cmd, utils.ProcessOptions{
60+
AlwaysPull: true,
61+
FastValidate: true,
62+
Build: true,
63+
Deploy: true,
64+
})
65+
if err != nil {
66+
return fmt.Errorf("deploy failed: %w", err)
67+
}
68+
log.Infof(ctx, "Deploy completed")
69+
70+
appKey, err := detectApp(b)
71+
if err != nil {
72+
return err
73+
}
74+
75+
log.Infof(ctx, "Running app: %s", appKey)
76+
err = runApp(ctx, b, appKey)
77+
if err != nil {
78+
return fmt.Errorf("failed to run app: %w", err)
79+
}
80+
81+
return nil
82+
}
83+
84+
// detectApp finds the single app in the bundle configuration.
85+
func detectApp(b *bundle.Bundle) (string, error) {
86+
apps := b.Config.Resources.Apps
87+
88+
if len(apps) == 0 {
89+
return "", errors.New("no apps found in bundle configuration")
90+
}
91+
92+
if len(apps) > 1 {
93+
return "", errors.New("multiple apps found in bundle, cannot auto-detect")
94+
}
95+
96+
// Get the single app key
97+
for key := range apps {
98+
return key, nil
99+
}
100+
101+
return "", errors.New("unexpected error detecting app")
102+
}
103+
104+
// runApp runs the specified app using the runner interface.
105+
func runApp(ctx context.Context, b *bundle.Bundle, appKey string) error {
106+
ref, err := resources.Lookup(b, appKey, run.IsRunnable)
107+
if err != nil {
108+
return fmt.Errorf("failed to lookup app: %w", err)
109+
}
110+
111+
runner, err := run.ToRunner(b, ref)
112+
if err != nil {
113+
return fmt.Errorf("failed to create runner: %w", err)
114+
}
115+
116+
output, err := runner.Run(ctx, &run.Options{})
117+
if err != nil {
118+
return fmt.Errorf("failed to run app: %w", err)
119+
}
120+
121+
// Log output
122+
if output != nil {
123+
resultString, err := output.String()
124+
if err != nil {
125+
return err
126+
}
127+
log.Infof(ctx, "App output: %s", resultString)
128+
}
129+
130+
return nil
131+
}

experimental/apps-mcp/cmd/tools.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ func newToolsCmd() *cobra.Command {
1515
cmd.AddCommand(newDiscoverSchemaCmd())
1616
cmd.AddCommand(newInitTemplateCmd())
1717
cmd.AddCommand(newValidateCmd())
18+
cmd.AddCommand(newDeployCmd())
1819

1920
return cmd
2021
}

0 commit comments

Comments
 (0)