77 "os"
88 "path/filepath"
99
10+ mcp "github.com/databricks/cli/experimental/apps-mcp/lib"
11+ "github.com/databricks/cli/experimental/apps-mcp/lib/sandbox"
12+ "github.com/databricks/cli/experimental/apps-mcp/lib/sandbox/dagger"
1013 "github.com/databricks/cli/experimental/apps-mcp/lib/sandbox/local"
1114 "github.com/databricks/cli/libs/log"
1215)
@@ -44,7 +47,7 @@ func (p *Provider) Validate(ctx context.Context, args *ValidateArgs) (*ValidateR
4447 valConfig := p .config .Validation
4548 if valConfig .Command != "" {
4649 log .Infof (ctx , "using custom validation command: command=%s" , valConfig .Command )
47- validation = NewValidationCmd (valConfig .Command , "" )
50+ validation = NewValidationCmd (valConfig .Command , valConfig . DockerImage )
4851 }
4952 }
5053
@@ -53,12 +56,45 @@ func (p *Provider) Validate(ctx context.Context, args *ValidateArgs) (*ValidateR
5356 validation = NewValidationTRPC ()
5457 }
5558
56- log .Info (ctx , "using local sandbox for validation" )
57- sb , err := p .createLocalSandbox (workDir )
58- if err != nil {
59- return nil , fmt .Errorf ("failed to create local sandbox: %w" , err )
59+ validationCfg := p .config .Validation
60+ if validationCfg == nil {
61+ validationCfg = & mcp.ValidationConfig {}
62+ validationCfg .SetDefaults ()
63+ } else {
64+ validationCfg .SetDefaults ()
65+ }
66+
67+ var sb sandbox.Sandbox
68+ var sandboxType string
69+ if validationCfg .UseDagger {
70+ log .Info (ctx , "attempting to create Dagger sandbox" )
71+ daggerSb , err := p .createDaggerSandbox (ctx , workDir , validationCfg )
72+ if err != nil {
73+ log .Warnf (ctx , "failed to create Dagger sandbox, falling back to local: error=%s" , err .Error ())
74+ sb , err = p .createLocalSandbox (workDir )
75+ if err != nil {
76+ return nil , fmt .Errorf ("failed to create local sandbox: %w" , err )
77+ }
78+ sandboxType = "local"
79+ } else {
80+ sb = daggerSb
81+ sandboxType = "dagger"
82+ }
83+ } else {
84+ log .Info (ctx , "using local sandbox" )
85+ sb , err = p .createLocalSandbox (workDir )
86+ if err != nil {
87+ return nil , fmt .Errorf ("failed to create local sandbox: %w" , err )
88+ }
89+ sandboxType = "local"
90+ }
91+
92+ // Log which sandbox is being used for transparency
93+ if sandboxType == "dagger" {
94+ log .Info (ctx , "✓ Using Dagger sandbox for validation (containerized, isolated environment)" )
95+ } else {
96+ log .Info (ctx , "Using local sandbox for validation (host filesystem)" )
6097 }
61- sandboxType := "local"
6298
6399 defer func () {
64100 if closeErr := sb .Close (); closeErr != nil {
@@ -101,7 +137,62 @@ func (p *Provider) Validate(ctx context.Context, args *ValidateArgs) (*ValidateR
101137 return result , nil
102138}
103139
104- func (p * Provider ) createLocalSandbox (workDir string ) (* local.LocalSandbox , error ) {
140+ func (p * Provider ) createDaggerSandbox (ctx context.Context , workDir string , cfg * mcp.ValidationConfig ) (sandbox.Sandbox , error ) {
141+ log .Infof (ctx , "creating Dagger sandbox: image=%s, timeout=%d, workDir=%s" ,
142+ cfg .DockerImage , cfg .Timeout , workDir )
143+
144+ sb , err := dagger .NewDaggerSandbox (ctx , dagger.Config {
145+ Image : cfg .DockerImage ,
146+ ExecuteTimeout : cfg .Timeout ,
147+ BaseDir : "/workspace" ,
148+ })
149+ if err != nil {
150+ log .Errorf (ctx , "failed to create Dagger sandbox: error=%s, image=%s" ,
151+ err .Error (), cfg .DockerImage )
152+ return nil , err
153+ }
154+
155+ log .Debug (ctx , "propagating environment variables" )
156+ if err := p .propagateEnvironment (sb ); err != nil {
157+ log .Errorf (ctx , "failed to propagate environment: error=%s" , err .Error ())
158+ sb .Close ()
159+ return nil , fmt .Errorf ("failed to set environment: %w" , err )
160+ }
161+
162+ log .Debugf (ctx , "syncing files from host to container: workDir=%s" , workDir )
163+ if err := sb .RefreshFromHost (ctx , workDir , "/workspace" ); err != nil {
164+ log .Errorf (ctx , "failed to sync files: error=%s" , err .Error ())
165+ sb .Close ()
166+ return nil , fmt .Errorf ("failed to sync files: %w" , err )
167+ }
168+
169+ log .Info (ctx , "Dagger sandbox created successfully" )
170+ return sb , nil
171+ }
172+
173+ func (p * Provider ) createLocalSandbox (workDir string ) (sandbox.Sandbox , error ) {
105174 log .Infof (p .ctx , "creating local sandbox: workDir=%s" , workDir )
106175 return local .NewLocalSandbox (workDir )
107176}
177+
178+ func (p * Provider ) propagateEnvironment (sb sandbox.Sandbox ) error {
179+ daggerSb , ok := sb .(* dagger.DaggerSandbox )
180+ if ! ok {
181+ return nil
182+ }
183+
184+ envVars := []string {
185+ "DATABRICKS_HOST" ,
186+ "DATABRICKS_TOKEN" ,
187+ "DATABRICKS_WAREHOUSE_ID" ,
188+ }
189+
190+ for _ , key := range envVars {
191+ if value := os .Getenv (key ); value != "" {
192+ daggerSb .WithEnv (key , value )
193+ log .Debugf (p .ctx , "propagated environment variable: key=%s" , key )
194+ }
195+ }
196+
197+ return nil
198+ }
0 commit comments