diff --git a/NEXT_CHANGELOG.md b/NEXT_CHANGELOG.md index 0db4b902e1..7c419b8c69 100644 --- a/NEXT_CHANGELOG.md +++ b/NEXT_CHANGELOG.md @@ -7,6 +7,7 @@ ### CLI ### Bundles +* Fix script output dropping last line without trailing newline ([#4995](https://github.com/databricks/cli/pull/4995)) ### Dependency updates diff --git a/acceptance/bundle/scripts/no-trailing-newline/databricks.yml b/acceptance/bundle/scripts/no-trailing-newline/databricks.yml new file mode 100644 index 0000000000..3f4116151d --- /dev/null +++ b/acceptance/bundle/scripts/no-trailing-newline/databricks.yml @@ -0,0 +1,6 @@ +bundle: + name: scripts_no_trailing_newline + +experimental: + scripts: + preinit: "python3 ./myscript.py" diff --git a/acceptance/bundle/scripts/no-trailing-newline/myscript.py b/acceptance/bundle/scripts/no-trailing-newline/myscript.py new file mode 100644 index 0000000000..c8937dbf85 --- /dev/null +++ b/acceptance/bundle/scripts/no-trailing-newline/myscript.py @@ -0,0 +1,5 @@ +import sys + +sys.stdout.write("line 1\n") +sys.stdout.write("line 2\n") +sys.stdout.write("line without newline") diff --git a/acceptance/bundle/scripts/no-trailing-newline/out.test.toml b/acceptance/bundle/scripts/no-trailing-newline/out.test.toml new file mode 100644 index 0000000000..d560f1de04 --- /dev/null +++ b/acceptance/bundle/scripts/no-trailing-newline/out.test.toml @@ -0,0 +1,5 @@ +Local = true +Cloud = false + +[EnvMatrix] + DATABRICKS_BUNDLE_ENGINE = ["terraform", "direct"] diff --git a/acceptance/bundle/scripts/no-trailing-newline/output.txt b/acceptance/bundle/scripts/no-trailing-newline/output.txt new file mode 100644 index 0000000000..49ccb79237 --- /dev/null +++ b/acceptance/bundle/scripts/no-trailing-newline/output.txt @@ -0,0 +1,13 @@ + +>>> [CLI] bundle validate +Executing 'preinit' script +line 1 +line 2 +line without newline +Name: scripts_no_trailing_newline +Target: default +Workspace: + User: [USERNAME] + Path: /Workspace/Users/[USERNAME]/.bundle/scripts_no_trailing_newline/default + +Validation OK! diff --git a/acceptance/bundle/scripts/no-trailing-newline/script b/acceptance/bundle/scripts/no-trailing-newline/script new file mode 100644 index 0000000000..5350876150 --- /dev/null +++ b/acceptance/bundle/scripts/no-trailing-newline/script @@ -0,0 +1 @@ +trace $CLI bundle validate diff --git a/bundle/scripts/scripts.go b/bundle/scripts/scripts.go index cca380129a..29cef46041 100644 --- a/bundle/scripts/scripts.go +++ b/bundle/scripts/scripts.go @@ -51,10 +51,14 @@ func (m *script) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnostics { cmdio.LogString(ctx, fmt.Sprintf("Executing '%s' script", m.scriptHook)) reader := bufio.NewReader(out) - line, err := reader.ReadString('\n') - for err == nil { - cmdio.LogString(ctx, strings.TrimSpace(line)) - line, err = reader.ReadString('\n') + for { + line, err := reader.ReadString('\n') + if line != "" { + cmdio.LogString(ctx, strings.TrimSpace(line)) + } + if err != nil { + break + } } err = cmd.Wait() diff --git a/bundle/scripts/scripts_test.go b/bundle/scripts/scripts_test.go new file mode 100644 index 0000000000..38941fc798 --- /dev/null +++ b/bundle/scripts/scripts_test.go @@ -0,0 +1,50 @@ +package scripts_test + +import ( + "runtime" + "testing" + + "github.com/databricks/cli/bundle" + "github.com/databricks/cli/bundle/config" + "github.com/databricks/cli/bundle/scripts" + "github.com/databricks/cli/libs/cmdio" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestExecuteOutputWithoutTrailingNewline(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skip("skipping on windows") + } + + dir := t.TempDir() + b := &bundle.Bundle{ + BundleRootPath: dir, + Config: config.Root{ + Experimental: &config.Experimental{ + Scripts: map[config.ScriptHook]config.Command{ + config.ScriptPreInit: "printf 'line1\nline2\nlast line without newline'", + }, + }, + }, + } + + ctx, stderr := cmdio.NewTestContextWithStderr(t.Context()) + diags := bundle.Apply(ctx, b, scripts.Execute(config.ScriptPreInit)) + require.NoError(t, diags.Error()) + + output := stderr.String() + assert.Contains(t, output, "line1") + assert.Contains(t, output, "line2") + assert.Contains(t, output, "last line without newline") +} + +func TestExecuteNoScript(t *testing.T) { + b := &bundle.Bundle{ + Config: config.Root{}, + } + + ctx, _ := cmdio.NewTestContextWithStderr(t.Context()) + diags := bundle.Apply(ctx, b, scripts.Execute(config.ScriptPreInit)) + require.NoError(t, diags.Error()) +}