diff --git a/.nextchanges/cli/apps-run-local-absolute-entry-point.md b/.nextchanges/cli/apps-run-local-absolute-entry-point.md new file mode 100644 index 00000000000..39e5f2aa429 --- /dev/null +++ b/.nextchanges/cli/apps-run-local-absolute-entry-point.md @@ -0,0 +1 @@ +* Fix `apps run-local --entry-point` failing with absolute paths to the app spec file. ([#6918](https://github.com/databricks/cli/pull/6918)) diff --git a/libs/apps/runlocal/spec.go b/libs/apps/runlocal/spec.go index 7aebadfc029..72f8a089c4e 100644 --- a/libs/apps/runlocal/spec.go +++ b/libs/apps/runlocal/spec.go @@ -36,8 +36,12 @@ func (a *AppSpec) GetFileName() string { func ReadAppSpecFile(config *Config) (*AppSpec, error) { spec := &AppSpec{config: config} for _, file := range config.AppSpecFiles { + // An absolute entry point is used verbatim; relative names resolve under AppPath. + if !filepath.IsAbs(file) { + file = filepath.Join(config.AppPath, file) + } // Read the yaml file - yamlFile, err := os.ReadFile(filepath.Join(config.AppPath, file)) + yamlFile, err := os.ReadFile(file) if errors.Is(err, fs.ErrNotExist) { continue } diff --git a/libs/apps/runlocal/spec_test.go b/libs/apps/runlocal/spec_test.go index f4218c09e41..c274ba72729 100644 --- a/libs/apps/runlocal/spec_test.go +++ b/libs/apps/runlocal/spec_test.go @@ -2,12 +2,44 @@ package runlocal import ( "context" + "os" + "path/filepath" "testing" "github.com/databricks/cli/libs/env" "github.com/stretchr/testify/require" ) +func TestReadAppSpecFile(t *testing.T) { + appDir := t.TempDir() + specDir := t.TempDir() + + specYAML := "command:\n - python\n - app.py\n" + require.NoError(t, os.WriteFile(filepath.Join(appDir, "app.yml"), []byte(specYAML), 0o644)) + // Absolute spec lives outside the app dir so the test proves the + // path is used verbatim instead of joined with AppPath. + absSpec := filepath.Join(specDir, "custom.yml") + require.NoError(t, os.WriteFile(absSpec, []byte(specYAML), 0o644)) + + t.Run("relative path", func(t *testing.T) { + spec, err := ReadAppSpecFile(&Config{AppPath: appDir, AppSpecFiles: []string{"app.yml"}}) + require.NoError(t, err) + require.Equal(t, []string{"python", "app.py"}, spec.Command) + }) + + t.Run("absolute path", func(t *testing.T) { + spec, err := ReadAppSpecFile(&Config{AppPath: appDir, AppSpecFiles: []string{absSpec}}) + require.NoError(t, err) + require.Equal(t, []string{"python", "app.py"}, spec.Command) + }) + + t.Run("missing file returns empty spec", func(t *testing.T) { + spec, err := ReadAppSpecFile(&Config{AppPath: appDir, AppSpecFiles: []string{"does-not-exist.yml"}}) + require.NoError(t, err) + require.Empty(t, spec.Command) + }) +} + func TestAppSpecLoadEnvVars(t *testing.T) { tempDir := t.TempDir() config := &Config{