Skip to content

Commit 8310cd3

Browse files
committed
convert appkit template to bundle init
1 parent ac2a4b4 commit 8310cd3

File tree

96 files changed

+101
-239
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

96 files changed

+101
-239
lines changed

experimental/apps-mcp/lib/providers/io/format.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,17 @@ import (
99
func formatScaffoldResult(result *ScaffoldResult) string {
1010
return fmt.Sprintf(
1111
"Successfully scaffolded %s template to %s\n\n"+
12-
"Files copied: %d\n\n"+
1312
"Template: %s\n\n"+
13+
"App name: %s\n\n"+
14+
"IMPORTANT: run `cd %s && npm install > /dev/null 2>&1` to install dependencies.\n\n"+
1415
"It is recomended to run the app in the background immediately after scaffolding using `npm install && npm run dev`. Then directly open http://localhost:8000 in the browser so the user can follow the progress.\n\n"+
1516
"IMPORTANT: Make sure to read %s before proceeding with the project!!!\n\n",
1617
result.TemplateName,
1718
result.WorkDir,
18-
result.FilesCopied,
1919
result.TemplateName,
20-
filepath.Join(result.WorkDir, "CLAUDE.md"),
20+
result.AppName,
21+
result.AppName,
22+
filepath.Join(result.WorkDir, result.AppName, "CLAUDE.md"),
2123
)
2224
}
2325

experimental/apps-mcp/lib/providers/io/provider.go

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import (
77
mcpsdk "github.com/databricks/cli/experimental/apps-mcp/lib/mcp"
88
"github.com/databricks/cli/experimental/apps-mcp/lib/providers"
99
"github.com/databricks/cli/experimental/apps-mcp/lib/session"
10-
"github.com/databricks/cli/experimental/apps-mcp/lib/templates"
1110
"github.com/databricks/cli/libs/log"
1211
)
1312

@@ -21,19 +20,17 @@ func init() {
2120

2221
// Provider implements the I/O provider for scaffolding and validation
2322
type Provider struct {
24-
config *mcp.IoConfig
25-
session *session.Session
26-
ctx context.Context
27-
defaultTemplate templates.Template
23+
config *mcp.IoConfig
24+
session *session.Session
25+
ctx context.Context
2826
}
2927

3028
// NewProvider creates a new I/O provider
3129
func NewProvider(ctx context.Context, cfg *mcp.IoConfig, sess *session.Session) (*Provider, error) {
3230
return &Provider{
33-
config: cfg,
34-
session: sess,
35-
ctx: ctx,
36-
defaultTemplate: templates.GetAppKitTemplate(),
31+
config: cfg,
32+
session: sess,
33+
ctx: ctx,
3734
}, nil
3835
}
3936

@@ -50,7 +47,7 @@ func (p *Provider) RegisterTools(server *mcpsdk.Server) error {
5047
type ScaffoldInput struct {
5148
WorkDir string `json:"work_dir" jsonschema:"required" jsonschema_description:"Absolute path to the work directory"`
5249
AppName string `json:"app_name" jsonschema:"required" jsonschema_description:"Name of the app (alphanumeric and dash characters only)"`
53-
AppDescription string `json:"app_description,omitempty" jsonschema_description:"Description of the app (max 100 characters)"`
50+
AppDescription string `json:"app_description" jsonschema:"required" jsonschema_description:"Description of the app (max 100 characters)"`
5451
}
5552

5653
mcpsdk.AddTool(server,
Lines changed: 51 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,28 @@
11
package io
22

33
import (
4-
"bytes"
54
"context"
5+
"encoding/json"
66
"errors"
77
"fmt"
88
"io/fs"
9+
"os"
10+
"os/exec"
911
"path/filepath"
1012
"regexp"
1113
"strings"
12-
"text/template"
1314

1415
"github.com/databricks/cli/experimental/apps-mcp/lib/middlewares"
15-
"github.com/databricks/cli/experimental/apps-mcp/lib/templates"
1616
"github.com/databricks/cli/libs/filer"
1717
"github.com/databricks/cli/libs/log"
1818
)
1919

20+
const (
21+
defaultTemplateRepo = "https://github.com/databricks/cli"
22+
defaultTemplateDir = "experimental/apps-mcp/templates/appkit"
23+
defaultTemplateTag = "main"
24+
)
25+
2026
// ScaffoldArgs contains arguments for scaffolding operation
2127
type ScaffoldArgs struct {
2228
WorkDir string `json:"work_dir"`
@@ -26,10 +32,9 @@ type ScaffoldArgs struct {
2632

2733
// ScaffoldResult contains the result of a scaffold operation
2834
type ScaffoldResult struct {
29-
FilesCopied int `json:"files_copied"`
30-
WorkDir string `json:"work_dir"`
31-
TemplateName string `json:"template_name"`
32-
TemplateDescription string `json:"template_description"`
35+
WorkDir string `json:"work_dir"`
36+
TemplateName string `json:"template_name"`
37+
AppName string `json:"app_name"`
3338
}
3439

3540
// Scaffold copies template files to the work directory
@@ -93,84 +98,60 @@ func (p *Provider) Scaffold(ctx context.Context, args *ScaffoldArgs) (*ScaffoldR
9398
return nil, fmt.Errorf("failed to create directory: %w", err)
9499
}
95100

96-
// Get template
97-
tmpl := p.getTemplate()
98-
files, err := tmpl.Files()
99-
if err != nil {
100-
return nil, fmt.Errorf("failed to read template: %w", err)
101-
}
102-
103101
// Get template data
104102
warehouseID, err := middlewares.GetWarehouseID(ctx)
105103
if err != nil {
106104
return nil, fmt.Errorf("failed to get warehouse ID: %w", err)
107105
}
108106
host := middlewares.MustGetDatabricksClient(ctx).Config.Host
109107

110-
templateData := map[string]string{
111-
"WarehouseID": warehouseID,
112-
"WorkspaceURL": host,
113-
"AppName": normalizedAppName,
114-
"AppDescription": args.AppDescription,
108+
// create temp config file with parameters
109+
configMap := map[string]string{
110+
"project_name": normalizedAppName,
111+
"sql_warehouse_id": warehouseID,
112+
"app_description": args.AppDescription,
113+
"workspace_host": host,
115114
}
116115

117-
// Copy files
118-
filesCopied := 0
119-
for path, content := range files {
120-
// Check if there's a corresponding .tmpl file for this path
121-
tmplPath := path + ".tmpl"
122-
if _, hasTmpl := files[tmplPath]; hasTmpl {
123-
// Skip this file, the .tmpl version will be processed instead
124-
continue
125-
}
126-
127-
// Determine final path and content
128-
var finalPath string
129-
var finalContent string
130-
if strings.HasSuffix(path, ".tmpl") {
131-
// This is a template file, process it
132-
finalPath = strings.TrimSuffix(path, ".tmpl")
133-
134-
// Parse and execute the template
135-
t, err := template.New(path).Parse(content)
136-
if err != nil {
137-
return nil, fmt.Errorf("failed to parse template %s: %w", path, err)
138-
}
116+
configBytes, err := json.Marshal(configMap)
117+
if err != nil {
118+
return nil, fmt.Errorf("marshal config: %w", err)
119+
}
139120

140-
var buf bytes.Buffer
141-
if err := t.Execute(&buf, templateData); err != nil {
142-
return nil, fmt.Errorf("failed to execute template %s: %w", path, err)
143-
}
144-
finalContent = buf.String()
145-
} else {
146-
// Regular file, use as-is
147-
finalPath = path
148-
finalContent = content
149-
}
121+
tmpFile, err := os.CreateTemp("", "mcp-template-config-*.json")
122+
if err != nil {
123+
return nil, fmt.Errorf("create temp config file: %w", err)
124+
}
125+
defer os.Remove(tmpFile.Name())
150126

151-
// filer.Write handles creating parent directories if requested
152-
if err := f.Write(ctx, finalPath, bytes.NewReader([]byte(finalContent)), filer.CreateParentDirectories); err != nil {
153-
return nil, fmt.Errorf("failed to write %s: %w", finalPath, err)
154-
}
127+
if _, err := tmpFile.Write(configBytes); err != nil {
128+
return nil, fmt.Errorf("write config file: %w", err)
129+
}
130+
if err := tmpFile.Close(); err != nil {
131+
return nil, fmt.Errorf("close config file: %w", err)
132+
}
155133

156-
filesCopied++
134+
// Invoke databricks CLI to initialize the bundle
135+
cmd := exec.CommandContext(ctx, os.Args[0], "bundle", "init",
136+
defaultTemplateRepo,
137+
"--template-dir", defaultTemplateDir,
138+
"--tag", defaultTemplateTag,
139+
"--config-file", tmpFile.Name(),
140+
"--output-dir", workDir,
141+
)
142+
cmd.Env = append(os.Environ(), "DATABRICKS_HOST="+host, "DATABRICKS_BUNDLE_ENGINE=direct-exp")
143+
144+
output, err := cmd.CombinedOutput()
145+
if err != nil {
146+
return nil, fmt.Errorf("databricks bundle init failed: %w\nOutput: %s", err, string(output))
157147
}
158148

159-
log.Infof(ctx, "scaffolded project (template=%s, work_dir=%s, files=%d)",
160-
tmpl.Name(), workDir, filesCopied)
149+
log.Infof(ctx, "scaffolded project (template=%s, work_dir=%s)",
150+
defaultTemplateRepo+"/"+defaultTemplateDir, workDir)
161151

162152
return &ScaffoldResult{
163-
FilesCopied: filesCopied,
164-
WorkDir: workDir,
165-
TemplateName: tmpl.Name(),
166-
TemplateDescription: tmpl.Description(),
153+
WorkDir: workDir,
154+
TemplateName: defaultTemplateRepo + "/" + defaultTemplateDir,
155+
AppName: args.AppName,
167156
}, nil
168157
}
169-
170-
func (p *Provider) getTemplate() templates.Template {
171-
// TODO: Support custom templates by checking p.config.Template.Path
172-
// and loading from filesystem. Not yet implemented.
173-
174-
// Default to AppKit template
175-
return p.defaultTemplate
176-
}

experimental/apps-mcp/lib/templates/appkit/.env.tmpl

Lines changed: 0 additions & 5 deletions
This file was deleted.

experimental/apps-mcp/lib/templates/appkit/databricks.yml

Lines changed: 0 additions & 49 deletions
This file was deleted.

experimental/apps-mcp/lib/templates/embed.go

Lines changed: 0 additions & 18 deletions
This file was deleted.

experimental/apps-mcp/lib/templates/template.go

Lines changed: 0 additions & 75 deletions
This file was deleted.
File renamed without changes.

0 commit comments

Comments
 (0)