From 0a781ec754d1bbdb7d078e3fed4d694d459e5cb0 Mon Sep 17 00:00:00 2001 From: TangoEnSkai <21152231+TangoEnSkai@users.noreply.github.com> Date: Fri, 28 Aug 2026 01:36:26 +0900 Subject: [PATCH] Fix bundle template directory symlink error --- .nextchanges/bundles/template-directory-symlink.md | 1 + .../databricks_template_schema.json | 3 +++ .../symlinked-directory/input.json | 1 + .../symlinked-directory/out.test.toml | 2 ++ .../symlinked-directory/output.txt | 5 +++++ .../templates-machinery/symlinked-directory/script | 5 +++++ .../template/shared/file.txt.tmpl | 1 + .../symlinked-directory/test.toml | 1 + libs/template/renderer.go | 14 ++++++++++++-- libs/template/renderer_test.go | 13 +++++++++++++ 10 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 .nextchanges/bundles/template-directory-symlink.md create mode 100644 acceptance/bundle/templates-machinery/symlinked-directory/databricks_template_schema.json create mode 100644 acceptance/bundle/templates-machinery/symlinked-directory/input.json create mode 100644 acceptance/bundle/templates-machinery/symlinked-directory/out.test.toml create mode 100644 acceptance/bundle/templates-machinery/symlinked-directory/output.txt create mode 100644 acceptance/bundle/templates-machinery/symlinked-directory/script create mode 100644 acceptance/bundle/templates-machinery/symlinked-directory/template/shared/file.txt.tmpl create mode 100644 acceptance/bundle/templates-machinery/symlinked-directory/test.toml diff --git a/.nextchanges/bundles/template-directory-symlink.md b/.nextchanges/bundles/template-directory-symlink.md new file mode 100644 index 00000000000..502d1f921d0 --- /dev/null +++ b/.nextchanges/bundles/template-directory-symlink.md @@ -0,0 +1 @@ +Improved the error for unsupported symlinked directories in bundle templates and prevented partial output. diff --git a/acceptance/bundle/templates-machinery/symlinked-directory/databricks_template_schema.json b/acceptance/bundle/templates-machinery/symlinked-directory/databricks_template_schema.json new file mode 100644 index 00000000000..d5b0514b649 --- /dev/null +++ b/acceptance/bundle/templates-machinery/symlinked-directory/databricks_template_schema.json @@ -0,0 +1,3 @@ +{ + "properties": {} +} diff --git a/acceptance/bundle/templates-machinery/symlinked-directory/input.json b/acceptance/bundle/templates-machinery/symlinked-directory/input.json new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/acceptance/bundle/templates-machinery/symlinked-directory/input.json @@ -0,0 +1 @@ +{} diff --git a/acceptance/bundle/templates-machinery/symlinked-directory/out.test.toml b/acceptance/bundle/templates-machinery/symlinked-directory/out.test.toml new file mode 100644 index 00000000000..98ea5040486 --- /dev/null +++ b/acceptance/bundle/templates-machinery/symlinked-directory/out.test.toml @@ -0,0 +1,2 @@ +Cloud = false +EnvMatrix.DATABRICKS_BUNDLE_ENGINE = ["terraform", "direct"] diff --git a/acceptance/bundle/templates-machinery/symlinked-directory/output.txt b/acceptance/bundle/templates-machinery/symlinked-directory/output.txt new file mode 100644 index 00000000000..56095295ef1 --- /dev/null +++ b/acceptance/bundle/templates-machinery/symlinked-directory/output.txt @@ -0,0 +1,5 @@ + +>>> musterr [CLI] bundle init . --config-file input.json --output-dir output +Error: symlinked directories are not supported in templates: linked_dir + +>>> find.py ^output/linked_dir --expect 0 diff --git a/acceptance/bundle/templates-machinery/symlinked-directory/script b/acceptance/bundle/templates-machinery/symlinked-directory/script new file mode 100644 index 00000000000..cf16ebfbcc1 --- /dev/null +++ b/acceptance/bundle/templates-machinery/symlinked-directory/script @@ -0,0 +1,5 @@ +ln -s shared template/linked_dir + +trace musterr $CLI bundle init . --config-file input.json --output-dir output +trace find.py '^output/linked_dir' --expect 0 +rm -rf output diff --git a/acceptance/bundle/templates-machinery/symlinked-directory/template/shared/file.txt.tmpl b/acceptance/bundle/templates-machinery/symlinked-directory/template/shared/file.txt.tmpl new file mode 100644 index 00000000000..ce013625030 --- /dev/null +++ b/acceptance/bundle/templates-machinery/symlinked-directory/template/shared/file.txt.tmpl @@ -0,0 +1 @@ +hello diff --git a/acceptance/bundle/templates-machinery/symlinked-directory/test.toml b/acceptance/bundle/templates-machinery/symlinked-directory/test.toml new file mode 100644 index 00000000000..92d0068b88b --- /dev/null +++ b/acceptance/bundle/templates-machinery/symlinked-directory/test.toml @@ -0,0 +1 @@ +Ignore = ["template/linked_dir"] diff --git a/libs/template/renderer.go b/libs/template/renderer.go index cce0861c0d2..9bd453a6212 100644 --- a/libs/template/renderer.go +++ b/libs/template/renderer.go @@ -305,14 +305,24 @@ func (r *renderer) walk() error { return cmp.Compare(a.Name(), b.Name()) }) for _, entry := range entries { + entryPath := path.Join(currentDirectory, entry.Name()) + if entry.Type()&fs.ModeSymlink != 0 { + info, err := fs.Stat(r.srcFS, entryPath) + if err != nil { + return err + } + if info.IsDir() { + return fmt.Errorf("symlinked directories are not supported in templates: %s", entryPath) + } + } if entry.IsDir() { // Add to slice, for BFS traversal - directories = append(directories, path.Join(currentDirectory, entry.Name())) + directories = append(directories, entryPath) continue } // Generate in memory representation of file - f, err := r.computeFile(path.Join(currentDirectory, entry.Name())) + f, err := r.computeFile(entryPath) if err != nil { return err } diff --git a/libs/template/renderer_test.go b/libs/template/renderer_test.go index 837584c452a..2ce2e523d67 100644 --- a/libs/template/renderer_test.go +++ b/libs/template/renderer_test.go @@ -577,6 +577,19 @@ func TestRendererNonTemplatesAreCreatedAsCopyFiles(t *testing.T) { assert.Equal(t, "not-a-template", r.files[0].RelPath()) } +func TestRendererRejectsSymlinkedDirectories(t *testing.T) { + ctx := cmdctx.SetWorkspaceClient(t.Context(), nil) + templateDir := t.TempDir() + require.NoError(t, os.Mkdir(filepath.Join(templateDir, "shared"), 0o755)) + require.NoError(t, os.Symlink("shared", filepath.Join(templateDir, "linked_dir"))) + + r, err := newRenderer(ctx, nil, nil, os.DirFS(templateDir), ".", "library") + require.NoError(t, err) + + err = r.walk() + assert.EqualError(t, err, "symlinked directories are not supported in templates: linked_dir") +} + func TestRendererFileTreeRendering(t *testing.T) { ctx := t.Context() ctx = cmdctx.SetWorkspaceClient(ctx, nil)