Repository: score-spec/score-compose
Pull request #284 (2025-04-01 13:02:29)

Postgres-instance provisioner added
## Description
A new provisioner, `postgres-instance`, has been added. It is similar to the `postgres` provisioner but differs in key aspects:

- Unlike the `postgres` provisioner, `postgres-instance` does not provide `database/name` as an output.

- It operates without shared resources (local )

rabelmervin: Hi @chris-stephenson  Apologies for pushing the previous commit without properly addressing the issue. Thanks for your review 

Patch:
diff --git a/.github/workflows/dependabot-auto-merge.yaml b/.github/workflows/dependabot-auto-merge.yaml
new file mode 100644
index 0000000..3f6a2a1
--- /dev/null
+++ b/.github/workflows/dependabot-auto-merge.yaml
@@ -0,0 +1,20 @@
+name: Dependabot auto-merge
+on: pull_request
+permissions:
+  contents: write
+  pull-requests: write
+jobs:
+  dependabot-auto-merge:
+    runs-on: ubuntu-latest
+    if: ${{ github.actor == 'dependabot[bot]' && !github.event.pull_request.auto_merge }}
+    steps:
+      - name: Approve a PR
+        run: gh pr review --approve "$PR_URL"
+        env:
+          PR_URL: ${{github.event.pull_request.html_url}}
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+      - name: Enable auto-merge for Dependabot PRs
+        run: gh pr merge --auto --squash "$PR_URL"
+        env:
+          PR_URL: ${{github.event.pull_request.html_url}}
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml
index 4663ae6..2bc4b84 100644
--- a/.github/workflows/scorecard.yml
+++ b/.github/workflows/scorecard.yml
@@ -68,6 +68,6 @@ jobs:
       # Upload the results to GitHub's code scanning dashboard (optional).
       # Commenting out will disable upload of results to your repo's Code Scanning dashboard
       - name: "Upload to code-scanning"
-        uses: github/codeql-action/upload-sarif@1b549b9259bda1cb5ddde3b41741a82a2d15a841 # v3.28.13
+        uses: github/codeql-action/upload-sarif@45775bd8235c68ba998cffa5171334d58593da47 # v3.28.15
         with:
           sarif_file: results.sarif
diff --git a/Dockerfile b/Dockerfile
index a77b823..a315eeb 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,4 +1,4 @@
-FROM golang:1.24.1-alpine@sha256:43c094ad24b6ac0546c62193baeb3e6e49ce14d3250845d166c77c25f64b0386 AS builder
+FROM golang:1.24.2-alpine@sha256:7772cb5322baa875edd74705556d08f0eeca7b9c4b5367754ce3f2f00041ccee AS builder
 
 ARG VERSION=0.0.0
 
diff --git a/go.mod b/go.mod
index b16237c..163303c 100644
--- a/go.mod
+++ b/go.mod
@@ -5,10 +5,9 @@ go 1.24.1
 require (
 	dario.cat/mergo v1.0.1
 	github.com/Masterminds/sprig/v3 v3.3.0
-	github.com/compose-spec/compose-go/v2 v2.4.9
+	github.com/compose-spec/compose-go/v2 v2.6.0
 	github.com/mitchellh/mapstructure v1.5.0
-	github.com/olekukonko/tablewriter v0.0.5
-	github.com/score-spec/score-go v1.9.5
+	github.com/score-spec/score-go v1.9.6
 	github.com/spf13/cobra v1.9.1
 	github.com/spf13/pflag v1.0.6
 	github.com/stretchr/testify v1.10.0
@@ -31,6 +30,7 @@ require (
 	github.com/mattn/go-shellwords v1.0.12 // indirect
 	github.com/mitchellh/copystructure v1.2.0 // indirect
 	github.com/mitchellh/reflectwalk v1.0.2 // indirect
+	github.com/olekukonko/tablewriter v0.0.5 // indirect
 	github.com/opencontainers/go-digest v1.0.0 // indirect
 	github.com/opencontainers/image-spec v1.1.1 // indirect
 	github.com/pmezard/go-difflib v1.0.0 // indirect
@@ -47,7 +47,6 @@ require (
 	github.com/xeipuuv/gojsonschema v1.2.0 // indirect
 	github.com/xhit/go-str2duration/v2 v2.1.0 // indirect
 	golang.org/x/crypto v0.36.0 // indirect
-	golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 // indirect
 	golang.org/x/sync v0.12.0 // indirect
 	golang.org/x/sys v0.31.0 // indirect
 	gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
diff --git a/go.sum b/go.sum
index b93f18a..615b0e5 100644
--- a/go.sum
+++ b/go.sum
@@ -6,8 +6,8 @@ github.com/Masterminds/semver/v3 v3.3.1 h1:QtNSWtVZ3nBfk8mAOu/B6v7FMJ+NHTIgUPi7r
 github.com/Masterminds/semver/v3 v3.3.1/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
 github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs=
 github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0=
-github.com/compose-spec/compose-go/v2 v2.4.9 h1:2K4TDw+1ba2idiR6empXHKRXvWYpnvAKoNQy93/sSOs=
-github.com/compose-spec/compose-go/v2 v2.4.9/go.mod h1:6k5l/0TxCg0/2uLEhRVEsoBWBprS2uvZi32J7xub3lo=
+github.com/compose-spec/compose-go/v2 v2.6.0 h1:/+oBD2ixSENOeN/TlJqWZmUak0xM8A7J08w/z661Wd4=
+github.com/compose-spec/compose-go/v2 v2.6.0/go.mod h1:vPlkN0i+0LjLf9rv52lodNMUTJF5YHVfHVGLLIP67NA=
 github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
@@ -61,8 +61,8 @@ github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/f
 github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
 github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 h1:lZUw3E0/J3roVtGQ+SCrUrg3ON6NgVqpn3+iol9aGu4=
 github.com/santhosh-tekuri/jsonschema/v5 v5.3.1/go.mod h1:uToXkOrWAZ6/Oc07xWQrPOhJotwFIyu2bBVN41fcDUY=
-github.com/score-spec/score-go v1.9.5 h1:BkZCCf0s4YVYWR6WL4D57P5PT9XxVmfWpNw/rC01750=
-github.com/score-spec/score-go v1.9.5/go.mod h1:hbWRzCHVEyxZP2UhD2nkhTEMRFZZob/uczCnUDl0enI=
+github.com/score-spec/score-go v1.9.6 h1:9VtqDrngMo7zrlKod6QN8XSZuw4JSvukybY+9Y/hcx0=
+github.com/score-spec/score-go v1.9.6/go.mod h1:/VXZ/6T3Pozoerxn6MBOfpEJi/YFGREYqmzwJ4a7HPs=
 github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=
 github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
 github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
@@ -99,8 +99,6 @@ github.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8
 github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU=
 golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
 golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
-golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 h1:nDVHiLt8aIbd/VzvPWN6kSOPE7+F/fNFDSXLVYkE/Iw=
-golang.org/x/exp v0.0.0-20250305212735-054e65f0b394/go.mod h1:sIifuuw/Yco/y6yb6+bDNfyeQ/MdPUy/hKEMYQV17cM=
 golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
 golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
 golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
diff --git a/internal/command/default.provisioners.yaml b/internal/command/default.provisioners.yaml
index dd5a8b3..8ac172a 100644
--- a/internal/command/default.provisioners.yaml
+++ b/internal/command/default.provisioners.yaml
@@ -216,6 +216,66 @@
     - username
     - password
 
+
+- uri: template://default-provisioners/postgres-instance
+ 
+  type: postgres-instance
+  description: Provisions a dedicated Postgres instance
+  # Init template has the random service name and password if needed later
+  init: |
+    randomServiceName: pg-{{ randAlphaNum 6 }}
+    randomDatabase: db-{{ randAlpha 8 }}
+    randomUsername: user-{{ randAlpha 8 }}
+    randomPassword: {{ randAlphaNum 16 | quote }}
+    sk: default-provisioners-postgres-instance
+    publishPort: {{ dig "annotations" "compose.score.dev/publish-port" "0" .Metadata | quote }}
+  # The state for each database resource is a unique db name and credentials
+  state: |
+    serviceName: {{ dig "serviceName" .Init.randomServiceName .State | quote }}
+    database: "postgres"
+    username: "postgres"
+    password: {{ dig "password" .Init.randomPassword .State | quote }}
+  # The outputs are the core database outputs. We output both name and database for broader compatibility.
+  outputs: |
+    host: {{ .State.serviceName }}
+    port: 5432
+    username: postgres
+    password: {{ .State.password }}
+  # Ensure the data volume exists
+  volumes: |
+    {{ .State.serviceName }}-data:
+      driver: local
+  # Create 2 services, the first is the database itself, the second is the init container which runs the scripts
+  services: |
+    {{ .State.serviceName }}:
+      image: mirror.gcr.io/postgres:17-alpine
+      restart: always
+      environment:
+        POSTGRES_USER: postgres
+        POSTGRES_PASSWORD: {{ .State.password | quote }}
+      {{ if ne .Init.publishPort "0" }}
+      ports:
+      - target: 5432
+        published: {{ .Init.publishPort }}
+      {{ end }}
+      volumes:
+      - type: volume
+        source: {{ .State.serviceName }}-data
+        target: /var/lib/postgresql/data
+      healthcheck:
+        test: ["CMD", "pg_isready", "-U", "postgres"]
+      
+  info_logs: |
+    - "{{.Uid}}: To connect to postgres, enter password {{ .State.password | squote }} at: \"docker run -it --network {{ .ComposeProjectName }}_default --rm postgres:17-alpine psql -h {{ .State.serviceName }} -U {{ .State.username }} --dbname {{ .State.database }}\""
+    {{ if ne .Init.publishPort "0" }}
+    - "{{.Uid}}: Or connect your postgres client to \"postgres://{{ .State.username }}:{{ .State.password }}@localhost:{{ .Init.publishPort }}/{{ .State.database }}\""
+    {{ end }}
+  expected_outputs:
+    - host
+    - port
+    - username
+    - password   
+
 # This resource provides a minio based S3 bucket with AWS-style credentials.
 # This provides some common and well known outputs that can be used with any generic AWS s3 client.
 # If the provider has a publish port annotation, it can expose a management port on the local network for debugging and
diff --git a/internal/command/init.go b/internal/command/init.go
index 9d43cf6..8b66d3f 100644
--- a/internal/command/init.go
+++ b/internal/command/init.go
@@ -69,11 +69,12 @@ service:
 
 resources: {}
 `
-	initCmdFileFlag          = "file"
-	initCmdFileProjectFlag   = "project"
-	initCmdFileNoSampleFlag  = "no-sample"
-	initCmdProvisionerFlag   = "provisioners"
-	initCmdPatchTemplateFlag = "patch-templates"
+	initCmdFileFlag                  = "file"
+	initCmdFileProjectFlag           = "project"
+	initCmdFileNoSampleFlag          = "no-sample"
+	initCmdProvisionerFlag           = "provisioners"
+	initCmdPatchTemplateFlag         = "patch-templates"
+	initCmdNoDefaultProvisionersFlag = "no-default-provisioners"
 )
 
 //go:embed default.provisioners.yaml
@@ -208,21 +209,34 @@ URI Retrieval:
 			}
 
 			// create and write the default provisioners file if it doesn't already exist
-			dst := "zz-default" + loader.DefaultSuffix
-			if f, err := os.Stat(filepath.Join(sd.Path, "99-default"+loader.DefaultSuffix)); err == nil {
-				slog.Info(fmt.Sprintf("Default provisioners yaml file '%s' already exists, not overwriting it", f.Name()))
-			} else if f, err := os.OpenFile(filepath.Join(sd.Path, dst), os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0644); err != nil {
-				if !errors.Is(err, os.ErrExist) {
-					return fmt.Errorf("failed to open default provisioners for writing: %w", err)
+			disableDefaultProvisioners, err := cmd.Flags().GetBool(initCmdNoDefaultProvisionersFlag)
+			if err != nil {
+				return fmt.Errorf("failed to parse --%s flag: %w", initCmdNoDefaultProvisionersFlag, err)
+			}
+
+			if !disableDefaultProvisioners {
+				defaultProvisioners := filepath.Join(sd.Path, "zz-default.provisioners.yaml")
+
+				if _, err := os.Stat(defaultProvisioners); err != nil {
+					if !errors.Is(err, os.ErrNotExist) {
+						return fmt.Errorf("failed to check for existing default provisioners file: %w", err)
+					}
+
+					f, err := os.OpenFile(defaultProvisioners, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0644)
+					if err != nil {
+						return fmt.Errorf("failed to create default provisioners file: %w", err)
+					}
+					defer f.Close()
+
+					slog.Info("Writing default provisioners file", "path", defaultProvisioners)
+					if _, err := f.WriteString(defaultProvisionersContent); err != nil {
+						return fmt.Errorf("failed to write default provisioners content: %w", err)
+					}
+				} else {
+					slog.Info("Default provisioners file already exists, skipping", "path", defaultProvisioners)
 				}
-				slog.Info(fmt.Sprintf("Default provisioners yaml file '%s' already exists, not overwriting it", dst))
 			} else {
-				defer f.Close()
-				slog.Info(fmt.Sprintf("Writing default provisioners yaml file '%s'", dst))
-				if _, err = f.WriteString(defaultProvisionersContent); err != nil {
-					return fmt.Errorf("failed to write provisioners: %w", err)
-				}
-				_ = f.Close()
+				slog.Info("Skipping default provisioners due to --no-default-provisioners flag")
 			}
 		}
 
@@ -270,7 +284,7 @@ URI Retrieval:
 			slog.Debug(fmt.Sprintf("Successfully loaded %d resource provisioners", len(provs)))
 		}
 
-		slog.Info(fmt.Sprintf("Read more about the Score specification at https://docs.score.dev/docs/"))
+		slog.Info("Read more about the Score specification at https://docs.score.dev/docs/")
 
 		return nil
 	},
@@ -282,6 +296,7 @@ func init() {
 	initCmd.Flags().Bool(initCmdFileNoSampleFlag, false, "Disable generation of the sample score file")
 	initCmd.Flags().StringArray(initCmdProvisionerFlag, nil, "Provisioner files to install. May be specified multiple times. Supports URI retrieval.")
 	initCmd.Flags().StringArray(initCmdPatchTemplateFlag, nil, "Patching template files to include. May be specified multiple times. Supports URI retrieval.")
+	initCmd.Flags().Bool(initCmdNoDefaultProvisionersFlag, false, "Disable generation of the default provisioners file")
 
 	rootCmd.AddCommand(initCmd)
 }
diff --git a/internal/command/provisioners.go b/internal/command/provisioners.go
index eb99b85..fd15a95 100644
--- a/internal/command/provisioners.go
+++ b/internal/command/provisioners.go
@@ -26,7 +26,7 @@ import (
 	"github.com/score-spec/score-compose/internal/project"
 	"github.com/score-spec/score-compose/internal/provisioners"
 	"github.com/score-spec/score-compose/internal/provisioners/loader"
-	"github.com/score-spec/score-compose/internal/util"
+	"github.com/score-spec/score-go/formatter"
 )
 
 var (
@@ -72,7 +72,7 @@ func listProvisioners(cmd *cobra.Command, args []string) error {
 }
 
 func displayProvisioners(loadedProvisioners []provisioners.Provisioner, outputFormat string) error {
-	var outputFormatter util.OutputFormatter
+	var outputFormatter formatter.OutputFormatter
 	sortedProvisioners := sortProvisionersByType(loadedProvisioners)
 
 	switch outputFormat {
@@ -94,7 +94,7 @@ func displayProvisioners(loadedProvisioners []provisioners.Provisioner, outputFo
 				Description: provisioner.Description(),
 			})
 		}
-		outputFormatter = &util.JSONOutputFormatter[[]jsonData]{Data: outputs}
+		outputFormatter = &formatter.JSONOutputFormatter[[]jsonData]{Data: outputs}
 	default:
 		rows := [][]string{}
 
@@ -102,7 +102,7 @@ func displayProvisioners(loadedProvisioners []provisioners.Provisioner, outputFo
 			rows = append(rows, []string{provisioner.Type(), provisioner.Class(), strings.Join(provisioner.Params(), ", "), strings.Join(provisioner.Outputs(), ", "), provisioner.Description()})
 		}
 		headers := []string{"Type", "Class", "Params", "Outputs", "Description"}
-		outputFormatter = &util.TableOutputFormatter{
+		outputFormatter = &formatter.TableOutputFormatter{
 			Headers: headers,
 			Rows:    rows,
 		}
diff --git a/internal/command/resources.go b/internal/command/resources.go
index 0de495e..78f38eb 100644
--- a/internal/command/resources.go
+++ b/internal/command/resources.go
@@ -22,11 +22,11 @@ import (
 	"text/template"
 
 	"github.com/Masterminds/sprig/v3"
+	"github.com/score-spec/score-go/formatter"
 	"github.com/score-spec/score-go/framework"
 	"github.com/spf13/cobra"
 
 	"github.com/score-spec/score-compose/internal/project"
-	"github.com/score-spec/score-compose/internal/util"
 )
 
 const (
@@ -122,12 +122,12 @@ func getResourceOutputsKeys(uid framework.ResourceUid, state *project.State) ([]
 
 func displayResourcesOutputs(outputs map[string]interface{}, cmd *cobra.Command) error {
 	outputFormat := cmd.Flags().Lookup(getOutputsCmdFormatFlag).Value.String()
-	var outputFormatter util.OutputFormatter
+	var outputFormatter formatter.OutputFormatter
 	switch outputFormat {
 	case "json":
-		outputFormatter = &util.JSONOutputFormatter[map[string]interface{}]{Data: outputs, Out: cmd.OutOrStdout()}
+		outputFormatter = &formatter.JSONOutputFormatter[map[string]interface{}]{Data: outputs, Out: cmd.OutOrStdout()}
 	case "yaml":
-		outputFormatter = &util.YAMLOutputFormatter[map[string]interface{}]{Data: outputs, Out: cmd.OutOrStdout()}
+		outputFormatter = &formatter.YAMLOutputFormatter[map[string]interface{}]{Data: outputs, Out: cmd.OutOrStdout()}
 	default:
 		// ensure there is a new line at the end if one is not already present
 		if !strings.HasSuffix(outputFormat, "\n") {
@@ -148,7 +148,7 @@ func displayResourcesOutputs(outputs map[string]interface{}, cmd *cobra.Command)
 
 func displayResourcesList(resources []framework.ResourceUid, state project.State, cmd *cobra.Command) error {
 	outputFormat := cmd.Flag("format").Value.String()
-	var outputFormatter util.OutputFormatter
+	var outputFormatter formatter.OutputFormatter
 
 	switch outputFormat {
 	case "json":
@@ -168,7 +168,7 @@ func displayResourcesList(resources []framework.ResourceUid, state project.State
 				Outputs: keys,
 			})
 		}
-		outputFormatter = &util.JSONOutputFormatter[[]jsonData]{Data: outputs, Out: cmd.OutOrStdout()}
+		outputFormatter = &formatter.JSONOutputFormatter[[]jsonData]{Data: outputs, Out: cmd.OutOrStdout()}
 	default:
 		var rows [][]string
 		for _, resource := range resources {
@@ -179,7 +179,7 @@ func displayResourcesList(resources []framework.ResourceUid, state project.State
 			row := []string{string(resource), strings.Join(keys, ", ")}
 			rows = append(rows, row)
 		}
-		outputFormatter = &util.TableOutputFormatter{
+		outputFormatter = &formatter.TableOutputFormatter{
 			Headers: []string{"UID", "Outputs"},
 			Rows:    rows,
 			Out:     cmd.OutOrStdout(),
diff --git a/internal/util/output_format.go b/internal/util/output_format.go
deleted file mode 100644
index c7e9676..0000000
--- a/internal/util/output_format.go
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright 2024 Humanitec
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package util
-
-import (
-	"encoding/json"
-	"io"
-	"os"
-
-	"github.com/olekukonko/tablewriter"
-	"gopkg.in/yaml.v3"
-)
-
-type OutputFormatter interface {
-	Display() error
-}
-
-type JSONOutputFormatter[T any] struct {
-	Data T
-	Out  io.Writer
-}
-
-type YAMLOutputFormatter[T any] struct {
-	Data T
-	Out  io.Writer
-}
-
-type TableOutputFormatter struct {
-	Headers []string
-	Rows    [][]string
-	Out     io.Writer
-}
-
-func (t *TableOutputFormatter) Display() error {
-	// Default to stdout if no output is provided
-	if t.Out == nil {
-		t.Out = os.Stdout
-	}
-	table := tablewriter.NewWriter(t.Out)
-	table.SetHeader(t.Headers)
-	table.AppendBulk(t.Rows)
-	table.SetAutoWrapText(false)
-	table.SetRowLine(true)
-	table.SetCenterSeparator("+")
-	table.SetColumnSeparator("|")
-	table.SetRowSeparator("-")
-	table.Render()
-	return nil
-}
-
-func (j *JSONOutputFormatter[T]) Display() error {
-	// Default to stdout if no output is provided
-	if j.Out == nil {
-		j.Out = os.Stdout
-	}
-	encoder := json.NewEncoder(j.Out)
-	encoder.SetIndent("", "  ")
-	if err := encoder.Encode(j.Data); err != nil {
-		return err
-	}
-	return nil
-}
-
-func (y *YAMLOutputFormatter[T]) Display() error {
-	// Default to stdout if no output is provided
-	if y.Out == nil {
-		y.Out = os.Stdout
-	}
-
-	encoder := yaml.NewEncoder(y.Out)
-	if err := encoder.Encode(y.Data); err != nil {
-		return err
-	}
-	return nil
-}


Test patch:
diff --git a/internal/command/init_test.go b/internal/command/init_test.go
index a4bf411..3d920ee 100644
--- a/internal/command/init_test.go
+++ b/internal/command/init_test.go
@@ -88,6 +88,7 @@ URI Retrieval:
 Flags:
   -f, --file string                   The score file to initialize (default "./score.yaml")
   -h, --help                          help for init
+      --no-default-provisioners       Disable generation of the default provisioners file
       --no-sample                     Disable generation of the sample score file
       --patch-templates stringArray   Patching template files to include. May be specified multiple times. Supports URI retrieval.
   -p, --project string                Set the name of the docker compose project (defaults to the current directory name)