From 58176bf82db3d5216c1dbd15a5dd1b0a571067c3 Mon Sep 17 00:00:00 2001 From: Atila Fassina Date: Fri, 13 Nov 2026 08:33:22 +0100 Subject: [PATCH 1/3] Add --skip-examples to databricks apps init (LA-2397) Passes the flag to the template as `skipExamples`, so templates can gate their placeholder files on `{{if not .skipExamples}}`. The AppKit template uses it (databricks/appkit#734) to leave out config/queries/*.sql and server/example.test.ts. Without the flag the key is false and behavior is unchanged. Files that render empty are already skipped and empty directories removed, so config/queries/ disappears when all its queries are gated. Co-authored-by: Isaac --- .nextchanges/cli/apps-init-skip-examples.md | 1 + cmd/apps/init.go | 9 +++ cmd/apps/init_test.go | 74 +++++++++++++++++++++ 3 files changed, 84 insertions(+) create mode 100644 .nextchanges/cli/apps-init-skip-examples.md diff --git a/.nextchanges/cli/apps-init-skip-examples.md b/.nextchanges/cli/apps-init-skip-examples.md new file mode 100644 index 00000000000..518522e3678 --- /dev/null +++ b/.nextchanges/cli/apps-init-skip-examples.md @@ -0,0 +1 @@ +* Add `--skip-examples` to `databricks apps init` to leave out the template's example files (sample SQL queries and the example test). diff --git a/cmd/apps/init.go b/cmd/apps/init.go index 7ba36f79999..5104ee04c30 100644 --- a/cmd/apps/init.go +++ b/cmd/apps/init.go @@ -97,6 +97,7 @@ func newInitCmd() *cobra.Command { setValues []string autoApprove bool skipInstall bool + skipExamples bool packageManager string authMode string ) @@ -191,6 +192,7 @@ Environment variables: setValues: setValues, autoApprove: autoApprove, skipInstall: skipInstall, + skipExamples: skipExamples, packageManager: packageManager, packageManagerChanged: cmd.Flags().Changed("package-manager"), authMode: authMode, @@ -215,6 +217,7 @@ Environment variables: cmd.Flags().BoolVar(&autoApprove, "auto-approve", false, "Skip confirmation prompts for optional resources. Optional resources are only configured when their values are provided via --set.") cmd.Flags().StringVar(&authMode, "auth-mode", "", "Default resource auth mode: obo (on behalf of the user) or sp (service principal). With obo, resources that cannot be accessed on behalf of the user use sp. Prompts if not provided in interactive mode, otherwise sp.") cmd.Flags().BoolVar(&skipInstall, "skip-install", false, "Skip installing project dependencies (e.g. npm install / uv sync). Cannot be combined with --run.") + cmd.Flags().BoolVar(&skipExamples, "skip-examples", false, "Leave out the template's example files (sample SQL queries and the example test) that a real app replaces") cmd.Flags().StringVar(&packageManager, "package-manager", "", "Node.js package manager (pnpm, npm; default: inferred from template)") return cmd @@ -243,6 +246,7 @@ type createOptions struct { setValues []string // --set plugin.resourceKey.field=value pairs autoApprove bool skipInstall bool + skipExamples bool packageManager string packageManagerChanged bool authMode string // --auth-mode default for all resources @@ -527,6 +531,9 @@ type templateVars struct { DotEnv dotEnvVars AppEnv string PackageManager string + // SkipExamples is set by --skip-examples. Templates leave their example + // files out when it is true; a missing key (older CLIs) keeps them. + SkipExamples bool // Plugins maps plugin name to its metadata // Missing keys return nil, enabling {{if .plugins.analytics}} conditionals. Plugins map[string]*pluginVar @@ -1807,6 +1814,7 @@ func runCreate(ctx context.Context, opts createOptions) (runErr error) { }, AppEnv: generator.GenerateAppEnv(selectedPluginList, genConfig), PackageManager: selectedManager.Name, + SkipExamples: opts.skipExamples, Plugins: plugins, } @@ -2271,6 +2279,7 @@ func templateData(vars templateVars) map[string]any { "appDescription": vars.AppDescription, "workspaceHost": vars.WorkspaceHost, "packageManager": vars.PackageManager, + "skipExamples": vars.SkipExamples, "bundle": map[string]any{ "variables": vars.Bundle.Variables, "resources": vars.Bundle.Resources, diff --git a/cmd/apps/init_test.go b/cmd/apps/init_test.go index 013e3a9253a..dfadc30d8cd 100644 --- a/cmd/apps/init_test.go +++ b/cmd/apps/init_test.go @@ -5,6 +5,7 @@ import ( "encoding/json" "errors" "flag" + "fmt" "io" "io/fs" "os" @@ -273,6 +274,24 @@ func TestPackageManagerTemplateVariable(t *testing.T) { } } +func TestSkipExamplesTemplateVariable(t *testing.T) { + ctx := t.Context() + input := "{{if not .skipExamples}}x{{end}}" + for _, tt := range []struct { + skipExamples bool + expected string + }{ + {false, "x"}, + {true, ""}, + } { + vars := testVars() + vars.SkipExamples = tt.skipExamples + result, err := executeTemplate(ctx, "test.sql", []byte(input), vars) + require.NoError(t, err) + assert.Equal(t, tt.expected, string(result), "skipExamples=%v", tt.skipExamples) + } +} + func TestExecuteTemplateInvalidSyntaxReturnsOriginal(t *testing.T) { ctx := t.Context() vars := templateVars{ProjectName: "my-app"} @@ -1342,6 +1361,61 @@ func TestInitCmd_SkipInstallFlagRegistered(t *testing.T) { assert.Equal(t, "false", flag.DefValue) } +func TestInitCmd_SkipExamplesFlagRegistered(t *testing.T) { + cmd := newInitCmd() + flag := cmd.Flags().Lookup("skip-examples") + require.NotNil(t, flag) + assert.Equal(t, "false", flag.DefValue) +} + +// TestRunCreateSkipExamples scaffolds a template whose example files are +// gated on {{if not .skipExamples}}. With --skip-examples they render empty, +// so they are not written and config/queries/ is removed once it is empty. +func TestRunCreateSkipExamples(t *testing.T) { + src := t.TempDir() + files := map[string]string{ + "appkit.plugins.json": `{"plugins":{}}`, + "README.md": "# {{.projectName}}\n", + "config/queries/hello_world.sql": "{{if not .skipExamples -}}\nSELECT 1\n{{- end}}\n", + "server/server.ts": "export {};\n", + "server/example.test.ts": "{{if not .skipExamples -}}\ntest('x', () => {});\n{{- end}}\n", + } + for name, content := range files { + path := filepath.Join(src, filepath.FromSlash(name)) + require.NoError(t, os.MkdirAll(filepath.Dir(path), 0o755)) + require.NoError(t, os.WriteFile(path, []byte(content), 0o644)) + } + + for _, skipExamples := range []bool{false, true} { + t.Run(fmt.Sprintf("skipExamples=%v", skipExamples), func(t *testing.T) { + output := t.TempDir() + ctx := cmdctx.SetWorkspaceClient(cmdio.MockDiscard(t.Context()), nil) + err := runCreate(ctx, createOptions{ + templatePath: src, + name: "test-app", + nameProvided: true, + outputDir: output, + skipInstall: true, + skipExamples: skipExamples, + }) + require.NoError(t, err) + + app := filepath.Join(output, "test-app") + assert.FileExists(t, filepath.Join(app, "README.md")) + assert.FileExists(t, filepath.Join(app, "server", "server.ts")) + if skipExamples { + assert.NoDirExists(t, filepath.Join(app, "config")) + assert.NoFileExists(t, filepath.Join(app, "server", "example.test.ts")) + return + } + got, err := os.ReadFile(filepath.Join(app, "config", "queries", "hello_world.sql")) + require.NoError(t, err) + assert.Equal(t, "SELECT 1\n", string(got)) + assert.FileExists(t, filepath.Join(app, "server", "example.test.ts")) + }) + } +} + func TestPrependInstall(t *testing.T) { tests := []struct { name string From 0ebc7fd0d5ba97bcd0b99d092a0c21d18b184b06 Mon Sep 17 00:00:00 2001 From: Atila Fassina Date: Fri, 13 Nov 2026 09:26:55 +0100 Subject: [PATCH 2/3] Link PR in changelog fragment Co-authored-by: Isaac --- .nextchanges/cli/apps-init-skip-examples.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.nextchanges/cli/apps-init-skip-examples.md b/.nextchanges/cli/apps-init-skip-examples.md index 518522e3678..99210ff923c 100644 --- a/.nextchanges/cli/apps-init-skip-examples.md +++ b/.nextchanges/cli/apps-init-skip-examples.md @@ -1 +1 @@ -* Add `--skip-examples` to `databricks apps init` to leave out the template's example files (sample SQL queries and the example test). +* Add `--skip-examples` to `databricks apps init` to leave out the template's example files (sample SQL queries and the example test) ([#7591](https://github.com/databricks/cli/pull/7591)). ([#7591](https://github.com/databricks/cli/pull/7591)) From bce7741f0b3aa444f1e9f9a585a2a5194bb393ea Mon Sep 17 00:00:00 2001 From: Atila Fassina Date: Fri, 13 Nov 2026 09:27:22 +0100 Subject: [PATCH 3/3] Fix PR link placement in changelog fragment Co-authored-by: Isaac --- .nextchanges/cli/apps-init-skip-examples.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.nextchanges/cli/apps-init-skip-examples.md b/.nextchanges/cli/apps-init-skip-examples.md index 99210ff923c..f32feffb074 100644 --- a/.nextchanges/cli/apps-init-skip-examples.md +++ b/.nextchanges/cli/apps-init-skip-examples.md @@ -1 +1 @@ -* Add `--skip-examples` to `databricks apps init` to leave out the template's example files (sample SQL queries and the example test) ([#7591](https://github.com/databricks/cli/pull/7591)). ([#7591](https://github.com/databricks/cli/pull/7591)) +* Add `--skip-examples` to `databricks apps init` to leave out the template's example files (sample SQL queries and the example test). ([#7591](https://github.com/databricks/cli/pull/7591))