From 92129374dd2896cfa8346a0870ac5b7b8357558f Mon Sep 17 00:00:00 2001 From: Kit Patella Date: Fri, 8 Nov 2024 14:25:43 -0800 Subject: [PATCH 01/10] make sure we render tables on stdout Signed-off-by: Kit Patella --- src/cmd/connect.go | 7 ++++--- src/cmd/dev.go | 13 +++---------- src/cmd/package.go | 16 ++++++++-------- src/cmd/root.go | 2 ++ 4 files changed, 17 insertions(+), 21 deletions(-) diff --git a/src/cmd/connect.go b/src/cmd/connect.go index 358a9e1ac3..3f1608a8b9 100644 --- a/src/cmd/connect.go +++ b/src/cmd/connect.go @@ -7,6 +7,7 @@ package cmd import ( "fmt" + "github.com/pterm/pterm" "github.com/spf13/cobra" "github.com/zarf-dev/zarf/src/config/lang" @@ -97,9 +98,9 @@ var connectListCmd = &cobra.Command{ if err != nil { return err } - // HACK: Re-initializing PTerm with a stderr writer isn't great, but it lets us render these - // tables for backwards compatibility - message.InitializePTerm(logger.DestinationDefault) + // HACK(mkcp): Setting a PTerm global isn't ideal or thread-safe. However, it lets us render even when message + // is disabled. + pterm.SetDefaultOutput(OutputWriter) message.PrintConnectStringTable(connections) return nil }, diff --git a/src/cmd/dev.go b/src/cmd/dev.go index e8bffd57c0..adc6fb07a0 100644 --- a/src/cmd/dev.go +++ b/src/cmd/dev.go @@ -65,6 +65,9 @@ var devDeployCmd = &cobra.Command{ err = pkgClient.DevDeploy(cmd.Context()) var lintErr *lint.LintError if errors.As(err, &lintErr) { + // TODO(mkcp): This is not thread safe at all. If we intend to keep using message we should have functions + // that can take a writer. + pterm.SetDefaultOutput(OutputWriter) common.PrintFindings(lintErr) } if err != nil { @@ -260,11 +263,6 @@ var devFindImagesCmd = &cobra.Command{ var lintErr *lint.LintError if errors.As(err, &lintErr) { - // HACK(mkcp): Re-initializing PTerm with a stderr writer isn't great, but it lets us render these lint - // tables below for backwards compatibility - if logger.Enabled(cmd.Context()) { - message.InitializePTerm(logger.DestinationDefault) - } common.PrintFindings(lintErr) } if err != nil { @@ -311,11 +309,6 @@ var devLintCmd = &cobra.Command{ err := lint.Validate(cmd.Context(), pkgConfig.CreateOpts.BaseDir, pkgConfig.CreateOpts.Flavor, pkgConfig.CreateOpts.SetVariables) var lintErr *lint.LintError if errors.As(err, &lintErr) { - // HACK(mkcp): Re-initializing PTerm with a stderr writer isn't great, but it lets us render these lint - // tables below for backwards compatibility - if logger.Enabled(cmd.Context()) { - message.InitializePTerm(logger.DestinationDefault) - } common.PrintFindings(lintErr) // Do not return an error if the findings are all warnings. if lintErr.OnlyWarnings() { diff --git a/src/cmd/package.go b/src/cmd/package.go index c0d441a0f0..305985511e 100644 --- a/src/cmd/package.go +++ b/src/cmd/package.go @@ -14,10 +14,9 @@ import ( "runtime" "strings" - "github.com/zarf-dev/zarf/src/pkg/logger" - "github.com/AlecAivazis/survey/v2" "github.com/defenseunicorns/pkg/helpers/v2" + "github.com/pterm/pterm" "github.com/spf13/cobra" "github.com/spf13/viper" "oras.land/oras-go/v2/registry" @@ -29,6 +28,7 @@ import ( "github.com/zarf-dev/zarf/src/internal/packager2" "github.com/zarf-dev/zarf/src/pkg/cluster" "github.com/zarf-dev/zarf/src/pkg/lint" + "github.com/zarf-dev/zarf/src/pkg/logger" "github.com/zarf-dev/zarf/src/pkg/message" "github.com/zarf-dev/zarf/src/pkg/packager" "github.com/zarf-dev/zarf/src/pkg/packager/filters" @@ -235,9 +235,9 @@ var packageInspectCmd = &cobra.Command{ if err != nil { return fmt.Errorf("failed to inspect package: %w", err) } - // HACK(mkcp): This init call ensures we still can still print Yaml when message is disabled. Remove when we - // release structured logged and don't have to disable message globally in pre-run. - message.InitializePTerm(logger.DestinationDefault) + // HACK(mkcp): Setting a PTerm global isn't ideal or thread-safe. However, it lets us render even when message + // is disabled. + pterm.SetDefaultOutput(OutputWriter) err = utils.ColorPrintYAML(output, nil, false) if err != nil { return err @@ -281,9 +281,9 @@ var packageListCmd = &cobra.Command{ // NOTE(mkcp): Renders table with message. header := []string{"Package", "Version", "Components"} - // HACK(mkcp): Similar to `package inspect`, we do want to use message here but we have to make sure our feature - // flagging doesn't disable this. Nothing happens after this so it's safe, but still very hacky. - message.InitializePTerm(logger.DestinationDefault) + // HACK(mkcp): Setting a PTerm global isn't ideal or thread-safe. However, it lets us render even when message + // is disabled. + pterm.SetDefaultOutput(OutputWriter) message.Table(header, packageData) // Print out any unmarshalling errors diff --git a/src/cmd/root.go b/src/cmd/root.go index 5acfc9c278..1f26b748cd 100644 --- a/src/cmd/root.go +++ b/src/cmd/root.go @@ -40,6 +40,8 @@ var ( SkipLogFile bool // NoColor is a flag to disable colors in output NoColor bool + // OutputWriter provides a default writer to Stdout for user-facing command output + OutputWriter = os.Stdout ) var rootCmd = &cobra.Command{ From 174645810624849be35e16db453cf90fa74a0720 Mon Sep 17 00:00:00 2001 From: Kit Patella Date: Fri, 8 Nov 2024 15:14:59 -0800 Subject: [PATCH 02/10] make table writes to stdout reversible Signed-off-by: Kit Patella --- src/cmd/common/table.go | 14 +++++++++++++- src/cmd/connect.go | 4 ---- src/cmd/dev.go | 3 --- src/cmd/package.go | 3 --- src/pkg/message/connect.go | 7 +++++++ src/pkg/message/message.go | 6 +++++- src/pkg/utils/yaml.go | 5 +++++ 7 files changed, 30 insertions(+), 12 deletions(-) diff --git a/src/cmd/common/table.go b/src/cmd/common/table.go index ee5f9ee190..6ae9772be8 100644 --- a/src/cmd/common/table.go +++ b/src/cmd/common/table.go @@ -5,15 +5,19 @@ package common import ( "fmt" + "os" "path/filepath" "github.com/defenseunicorns/pkg/helpers/v2" "github.com/fatih/color" - + "github.com/pterm/pterm" "github.com/zarf-dev/zarf/src/pkg/lint" "github.com/zarf-dev/zarf/src/pkg/message" ) +// OutputWriter provides a writer to stdout for user-focused output +var OutputWriter = os.Stdout + // PrintFindings prints the findings in the LintError as a table. func PrintFindings(lintErr *lint.LintError) { mapOfFindingsByPath := lint.GroupFindingsByPath(lintErr.Findings, lintErr.PackageName) @@ -40,8 +44,16 @@ func PrintFindings(lintErr *lint.LintError) { } else { packagePathFromUser = filepath.Join(lintErr.BaseDir, findings[0].PackagePathOverride) } + + // Print table to our OutputWriter + // HACK(mkcp): Setting a PTerm global isn't ideal or thread-safe. However, it lets us render even when message + // is disabled. + lastWriter := pterm.Info.Writer + message.InitializePTerm(OutputWriter) message.Notef("Linting package %q at %s", findings[0].PackageNameOverride, packagePathFromUser) message.Table([]string{"Type", "Path", "Message"}, lintData) + // Reset pterm output + message.InitializePTerm(lastWriter) } } diff --git a/src/cmd/connect.go b/src/cmd/connect.go index 3f1608a8b9..9a7a13a241 100644 --- a/src/cmd/connect.go +++ b/src/cmd/connect.go @@ -7,7 +7,6 @@ package cmd import ( "fmt" - "github.com/pterm/pterm" "github.com/spf13/cobra" "github.com/zarf-dev/zarf/src/config/lang" @@ -98,9 +97,6 @@ var connectListCmd = &cobra.Command{ if err != nil { return err } - // HACK(mkcp): Setting a PTerm global isn't ideal or thread-safe. However, it lets us render even when message - // is disabled. - pterm.SetDefaultOutput(OutputWriter) message.PrintConnectStringTable(connections) return nil }, diff --git a/src/cmd/dev.go b/src/cmd/dev.go index adc6fb07a0..5c95922b6f 100644 --- a/src/cmd/dev.go +++ b/src/cmd/dev.go @@ -65,9 +65,6 @@ var devDeployCmd = &cobra.Command{ err = pkgClient.DevDeploy(cmd.Context()) var lintErr *lint.LintError if errors.As(err, &lintErr) { - // TODO(mkcp): This is not thread safe at all. If we intend to keep using message we should have functions - // that can take a writer. - pterm.SetDefaultOutput(OutputWriter) common.PrintFindings(lintErr) } if err != nil { diff --git a/src/cmd/package.go b/src/cmd/package.go index 305985511e..08e49212e2 100644 --- a/src/cmd/package.go +++ b/src/cmd/package.go @@ -235,9 +235,6 @@ var packageInspectCmd = &cobra.Command{ if err != nil { return fmt.Errorf("failed to inspect package: %w", err) } - // HACK(mkcp): Setting a PTerm global isn't ideal or thread-safe. However, it lets us render even when message - // is disabled. - pterm.SetDefaultOutput(OutputWriter) err = utils.ColorPrintYAML(output, nil, false) if err != nil { return err diff --git a/src/pkg/message/connect.go b/src/pkg/message/connect.go index 499a9e3602..cd00c8f5cc 100644 --- a/src/pkg/message/connect.go +++ b/src/pkg/message/connect.go @@ -6,7 +6,9 @@ package message import ( "fmt" + "os" + "github.com/pterm/pterm" "github.com/zarf-dev/zarf/src/types" ) @@ -20,8 +22,13 @@ func PrintConnectStringTable(connectStrings types.ConnectStrings) { connectData = append(connectData, []string{name, connect.Description}) } + // HACK(mkcp): Setting a PTerm global during runtime isn't ideal or thread-safe. However, it lets us render + // even when message is disabled. + lastWriter := pterm.Info.Writer + InitializePTerm(os.Stdout) // Create the table output with the data header := []string{"Connect Command", "Description"} Table(header, connectData) + InitializePTerm(lastWriter) } } diff --git a/src/pkg/message/message.go b/src/pkg/message/message.go index 0eea8b326c..a1f39eb7fc 100644 --- a/src/pkg/message/message.go +++ b/src/pkg/message/message.go @@ -69,9 +69,13 @@ func InitializePTerm(w io.Writer) { Text: " ERROR:", Style: pterm.NewStyle(pterm.BgLightRed, pterm.FgBlack), } - pterm.Info.Prefix = pterm.Prefix{ + + // HACK(mkcp): Unforgivable hack to set a writer directly on Info's prefixprinter so we can retrieve it elsewhere. + info := pterm.Info + info.Prefix = pterm.Prefix{ Text: " •", } + pterm.Info = *info.WithWriter(w) pterm.SetDefaultOutput(w) } diff --git a/src/pkg/utils/yaml.go b/src/pkg/utils/yaml.go index e0b8a3e953..920520312b 100644 --- a/src/pkg/utils/yaml.go +++ b/src/pkg/utils/yaml.go @@ -103,8 +103,13 @@ func ColorPrintYAML(data any, hints map[string]string, spaceRootLists bool) erro outputYAML = ansiRegex.ReplaceAllString(outputYAML, "") } + // HACK(mkcp): Setting a PTerm global isn't ideal or thread-safe. However, it lets us render even when message + // is disabled. + lastWriter := pterm.Info.Writer + message.InitializePTerm(os.Stdout) pterm.Println() pterm.Println(outputYAML) + message.InitializePTerm(lastWriter) return nil } From f0238a04ba318a636f325e0389677e3641def8ed Mon Sep 17 00:00:00 2001 From: Kit Patella Date: Fri, 8 Nov 2024 15:27:11 -0800 Subject: [PATCH 03/10] store PTermWriter in message rather than relying on some Pterm info jank Signed-off-by: Kit Patella --- src/cmd/common/table.go | 3 +-- src/cmd/package.go | 9 +++++---- src/pkg/message/connect.go | 3 +-- src/pkg/message/message.go | 17 ++++++++++++----- src/pkg/utils/yaml.go | 6 +++--- 5 files changed, 22 insertions(+), 16 deletions(-) diff --git a/src/cmd/common/table.go b/src/cmd/common/table.go index 6ae9772be8..6cedaa783d 100644 --- a/src/cmd/common/table.go +++ b/src/cmd/common/table.go @@ -10,7 +10,6 @@ import ( "github.com/defenseunicorns/pkg/helpers/v2" "github.com/fatih/color" - "github.com/pterm/pterm" "github.com/zarf-dev/zarf/src/pkg/lint" "github.com/zarf-dev/zarf/src/pkg/message" ) @@ -48,7 +47,7 @@ func PrintFindings(lintErr *lint.LintError) { // Print table to our OutputWriter // HACK(mkcp): Setting a PTerm global isn't ideal or thread-safe. However, it lets us render even when message // is disabled. - lastWriter := pterm.Info.Writer + lastWriter := *message.PTermWriter.Load() message.InitializePTerm(OutputWriter) message.Notef("Linting package %q at %s", findings[0].PackageNameOverride, packagePathFromUser) message.Table([]string{"Type", "Path", "Message"}, lintData) diff --git a/src/cmd/package.go b/src/cmd/package.go index 08e49212e2..2f10d6397c 100644 --- a/src/cmd/package.go +++ b/src/cmd/package.go @@ -16,7 +16,6 @@ import ( "github.com/AlecAivazis/survey/v2" "github.com/defenseunicorns/pkg/helpers/v2" - "github.com/pterm/pterm" "github.com/spf13/cobra" "github.com/spf13/viper" "oras.land/oras-go/v2/registry" @@ -278,10 +277,12 @@ var packageListCmd = &cobra.Command{ // NOTE(mkcp): Renders table with message. header := []string{"Package", "Version", "Components"} - // HACK(mkcp): Setting a PTerm global isn't ideal or thread-safe. However, it lets us render even when message - // is disabled. - pterm.SetDefaultOutput(OutputWriter) + // HACK(mkcp): Re-initializing PTerm globally isn't ideal or thread-safe. However, it lets us render even when + // message is disabled. + lastWriter := *message.PTermWriter.Load() + message.InitializePTerm(OutputWriter) message.Table(header, packageData) + message.InitializePTerm(lastWriter) // Print out any unmarshalling errors if err != nil { diff --git a/src/pkg/message/connect.go b/src/pkg/message/connect.go index cd00c8f5cc..c64f8dc0d6 100644 --- a/src/pkg/message/connect.go +++ b/src/pkg/message/connect.go @@ -8,7 +8,6 @@ import ( "fmt" "os" - "github.com/pterm/pterm" "github.com/zarf-dev/zarf/src/types" ) @@ -24,7 +23,7 @@ func PrintConnectStringTable(connectStrings types.ConnectStrings) { // HACK(mkcp): Setting a PTerm global during runtime isn't ideal or thread-safe. However, it lets us render // even when message is disabled. - lastWriter := pterm.Info.Writer + lastWriter := *PTermWriter.Load() InitializePTerm(os.Stdout) // Create the table output with the data header := []string{"Connect Command", "Description"} diff --git a/src/pkg/message/message.go b/src/pkg/message/message.go index a1f39eb7fc..46ea2e242f 100644 --- a/src/pkg/message/message.go +++ b/src/pkg/message/message.go @@ -9,6 +9,7 @@ import ( "io" "os" "strings" + "sync/atomic" "time" "github.com/defenseunicorns/pkg/helpers/v2" @@ -45,6 +46,12 @@ var logLevel = InfoLevel // logFile acts as a buffer for logFile generation var logFile *PausableWriter +// PTermWriter is an unholy hack that allows us to retrieve the writer passed into InitializePTerm. Under no +// circumstances should this be considered stable or supported. It's only purpose is so we change the writer to +// Stdout for specific logs, then back to its original intended value that we set at the start of the command. +// It should be replaced by something threadsafe as soon as possible. Blame mkcp for this contraption. +var PTermWriter atomic.Pointer[io.Writer] + // DebugWriter represents a writer interface that writes to message.Debug type DebugWriter struct{} @@ -69,13 +76,13 @@ func InitializePTerm(w io.Writer) { Text: " ERROR:", Style: pterm.NewStyle(pterm.BgLightRed, pterm.FgBlack), } - - // HACK(mkcp): Unforgivable hack to set a writer directly on Info's prefixprinter so we can retrieve it elsewhere. - info := pterm.Info - info.Prefix = pterm.Prefix{ + pterm.Info.Prefix = pterm.Prefix{ Text: " •", } - pterm.Info = *info.WithWriter(w) + + // HACK(mkcp): See the comments on the var above but this should not be used for anything other than its intended + // use and should be removed as soon as possible. + PTermWriter.Store(&w) pterm.SetDefaultOutput(w) } diff --git a/src/pkg/utils/yaml.go b/src/pkg/utils/yaml.go index 920520312b..5bf0f1cf9c 100644 --- a/src/pkg/utils/yaml.go +++ b/src/pkg/utils/yaml.go @@ -103,9 +103,9 @@ func ColorPrintYAML(data any, hints map[string]string, spaceRootLists bool) erro outputYAML = ansiRegex.ReplaceAllString(outputYAML, "") } - // HACK(mkcp): Setting a PTerm global isn't ideal or thread-safe. However, it lets us render even when message - // is disabled. - lastWriter := pterm.Info.Writer + // HACK(mkcp): Re-initializing a PTerm global isn't ideal or thread-safe. However, it lets us render even when + // message is disabled. + lastWriter := *message.PTermWriter.Load() message.InitializePTerm(os.Stdout) pterm.Println() pterm.Println(outputYAML) From dbe02e9a0d1ed53e90888a42bd36257e655ee939 Mon Sep 17 00:00:00 2001 From: Kit Patella Date: Thu, 21 Nov 2024 10:44:02 -0800 Subject: [PATCH 04/10] remove global re-init hack for Stdout message prints using functions with writers instead Signed-off-by: Kit Patella --- src/cmd/common/table.go | 8 +----- src/cmd/package.go | 8 +----- src/pkg/message/connect.go | 8 +----- src/pkg/message/credentials.go | 2 +- src/pkg/message/message.go | 47 +++++++++++++++++----------------- src/pkg/utils/yaml.go | 9 ++----- 6 files changed, 29 insertions(+), 53 deletions(-) diff --git a/src/cmd/common/table.go b/src/cmd/common/table.go index 6cedaa783d..72211bd3cd 100644 --- a/src/cmd/common/table.go +++ b/src/cmd/common/table.go @@ -45,14 +45,8 @@ func PrintFindings(lintErr *lint.LintError) { } // Print table to our OutputWriter - // HACK(mkcp): Setting a PTerm global isn't ideal or thread-safe. However, it lets us render even when message - // is disabled. - lastWriter := *message.PTermWriter.Load() - message.InitializePTerm(OutputWriter) message.Notef("Linting package %q at %s", findings[0].PackageNameOverride, packagePathFromUser) - message.Table([]string{"Type", "Path", "Message"}, lintData) - // Reset pterm output - message.InitializePTerm(lastWriter) + message.TableWithWriter(OutputWriter, []string{"Type", "Path", "Message"}, lintData) } } diff --git a/src/cmd/package.go b/src/cmd/package.go index 2f10d6397c..09f14b4a1f 100644 --- a/src/cmd/package.go +++ b/src/cmd/package.go @@ -275,14 +275,8 @@ var packageListCmd = &cobra.Command{ }) } - // NOTE(mkcp): Renders table with message. header := []string{"Package", "Version", "Components"} - // HACK(mkcp): Re-initializing PTerm globally isn't ideal or thread-safe. However, it lets us render even when - // message is disabled. - lastWriter := *message.PTermWriter.Load() - message.InitializePTerm(OutputWriter) - message.Table(header, packageData) - message.InitializePTerm(lastWriter) + message.TableWithWriter(message.OutputWriter, header, packageData) // Print out any unmarshalling errors if err != nil { diff --git a/src/pkg/message/connect.go b/src/pkg/message/connect.go index c64f8dc0d6..755ccf764a 100644 --- a/src/pkg/message/connect.go +++ b/src/pkg/message/connect.go @@ -6,7 +6,6 @@ package message import ( "fmt" - "os" "github.com/zarf-dev/zarf/src/types" ) @@ -21,13 +20,8 @@ func PrintConnectStringTable(connectStrings types.ConnectStrings) { connectData = append(connectData, []string{name, connect.Description}) } - // HACK(mkcp): Setting a PTerm global during runtime isn't ideal or thread-safe. However, it lets us render - // even when message is disabled. - lastWriter := *PTermWriter.Load() - InitializePTerm(os.Stdout) // Create the table output with the data header := []string{"Connect Command", "Description"} - Table(header, connectData) - InitializePTerm(lastWriter) + TableWithWriter(OutputWriter, header, connectData) } } diff --git a/src/pkg/message/credentials.go b/src/pkg/message/credentials.go index 998fa41283..42f472c62b 100644 --- a/src/pkg/message/credentials.go +++ b/src/pkg/message/credentials.go @@ -55,7 +55,7 @@ func PrintCredentialTable(state *types.ZarfState, componentsToDeploy []types.Dep if len(loginData) > 0 { header := []string{"Application", "Username", "Password", "Connect", "Get-Creds Key"} - Table(header, loginData) + TableWithWriter(OutputWriter, header, loginData) } } diff --git a/src/pkg/message/message.go b/src/pkg/message/message.go index 46ea2e242f..22d49df673 100644 --- a/src/pkg/message/message.go +++ b/src/pkg/message/message.go @@ -9,7 +9,6 @@ import ( "io" "os" "strings" - "sync/atomic" "time" "github.com/defenseunicorns/pkg/helpers/v2" @@ -34,23 +33,18 @@ const ( TermWidth = 100 ) -// NoProgress tracks whether spinner/progress bars show updates. -var NoProgress bool - -// RuleLine creates a line of ━ as wide as the terminal -var RuleLine = strings.Repeat("━", TermWidth) - -// logLevel holds the pterm compatible log level integer -var logLevel = InfoLevel - -// logFile acts as a buffer for logFile generation -var logFile *PausableWriter - -// PTermWriter is an unholy hack that allows us to retrieve the writer passed into InitializePTerm. Under no -// circumstances should this be considered stable or supported. It's only purpose is so we change the writer to -// Stdout for specific logs, then back to its original intended value that we set at the start of the command. -// It should be replaced by something threadsafe as soon as possible. Blame mkcp for this contraption. -var PTermWriter atomic.Pointer[io.Writer] +var ( + // NoProgress tracks whether spinner/progress bars show updates. + NoProgress bool + // RuleLine creates a line of ━ as wide as the terminal + RuleLine = strings.Repeat("━", TermWidth) + // OutputWriter provides a default writer to Stdout for user-focused output like tables and yaml + OutputWriter = os.Stdout + // logLevel holds the pterm compatible log level integer + logLevel = InfoLevel + // logFile acts as a buffer for logFile generation + logFile *PausableWriter +) // DebugWriter represents a writer interface that writes to message.Debug type DebugWriter struct{} @@ -80,10 +74,6 @@ func InitializePTerm(w io.Writer) { Text: " •", } - // HACK(mkcp): See the comments on the var above but this should not be used for anything other than its intended - // use and should be removed as soon as possible. - PTermWriter.Store(&w) - pterm.SetDefaultOutput(w) } @@ -260,6 +250,11 @@ func Paragraphn(n int, format string, a ...any) string { // Table prints a padded table containing the specified header and data func Table(header []string, data [][]string) { + TableWithWriter(nil, header, data) +} + +// TableWithWriter prints a padded table containing the specified header and data to the optional writer. +func TableWithWriter(writer io.Writer, header []string, data [][]string) { pterm.Println() // To avoid side effects make copies of the header and data before adding padding @@ -282,8 +277,12 @@ func Table(header []string, data [][]string) { table = append(table, pterm.TableData{row}...) } - //nolint:errcheck // never returns an error - pterm.DefaultTable.WithHasHeader().WithData(table).Render() + // Use DefaultTable writer if none is provided + tPrinter := pterm.DefaultTable + if writer != nil { + tPrinter.Writer = writer + } + _ = tPrinter.WithHasHeader().WithData(table).Render() //nolint:errcheck } func debugPrinter(offset int, a ...any) { diff --git a/src/pkg/utils/yaml.go b/src/pkg/utils/yaml.go index 5bf0f1cf9c..1c19f070b5 100644 --- a/src/pkg/utils/yaml.go +++ b/src/pkg/utils/yaml.go @@ -103,13 +103,8 @@ func ColorPrintYAML(data any, hints map[string]string, spaceRootLists bool) erro outputYAML = ansiRegex.ReplaceAllString(outputYAML, "") } - // HACK(mkcp): Re-initializing a PTerm global isn't ideal or thread-safe. However, it lets us render even when - // message is disabled. - lastWriter := *message.PTermWriter.Load() - message.InitializePTerm(os.Stdout) - pterm.Println() - pterm.Println(outputYAML) - message.InitializePTerm(lastWriter) + content := strings.Join([]string{"\n", outputYAML}, "") + pterm.Fprintln(message.OutputWriter, content) return nil } From 5b580a19d014714bd9dc432ec472a0d60a3eb316 Mon Sep 17 00:00:00 2001 From: Kit Patella Date: Thu, 21 Nov 2024 11:50:10 -0800 Subject: [PATCH 05/10] fix variables test to check stdout instead of stderr Signed-off-by: Kit Patella --- src/test/e2e/24_variables_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/e2e/24_variables_test.go b/src/test/e2e/24_variables_test.go index b583a314d4..255988d4f8 100644 --- a/src/test/e2e/24_variables_test.go +++ b/src/test/e2e/24_variables_test.go @@ -58,11 +58,11 @@ func TestVariables(t *testing.T) { stdOut, stdErr, err = e2e.Zarf(t, "package", "deploy", path, "--confirm", "--set", "SITE_NAME=Lula Web", "--set", "AWS_REGION=unicorn-land", "-l", "trace") require.NoError(t, err, stdOut, stdErr) // Verify that the variables were shown to the user in the formats we expect - require.Contains(t, stdErr, "currently set to 'Defense Unicorns' (default)") - require.Contains(t, stdErr, "currently set to 'Lula Web'") - require.Contains(t, stdErr, "currently set to '**sanitized**'") + require.Contains(t, stdOut, "currently set to 'Defense Unicorns' (default)") + require.Contains(t, stdOut, "currently set to 'Lula Web'") + require.Contains(t, stdOut, "currently set to '**sanitized**'") // Verify that the sensitive variable 'unicorn-land' was not printed to the screen - require.NotContains(t, stdErr, "unicorn-land") + require.NotContains(t, stdOut, "unicorn-land") logText := e2e.GetLogFileContents(t, e2e.StripMessageFormatting(stdErr)) // Verify that the sensitive variable 'unicorn-land' was not included in the log From 0095e728b7e57ebbd7f230e6e7ff6c72690b83c5 Mon Sep 17 00:00:00 2001 From: Kit Patella Date: Thu, 21 Nov 2024 14:00:54 -0800 Subject: [PATCH 06/10] 06_create_sbom should see if stdout contains ref, not that it is only ref now Signed-off-by: Kit Patella --- src/test/e2e/06_create_sbom_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/e2e/06_create_sbom_test.go b/src/test/e2e/06_create_sbom_test.go index 9426a21d4c..d8e9d5eabc 100644 --- a/src/test/e2e/06_create_sbom_test.go +++ b/src/test/e2e/06_create_sbom_test.go @@ -55,7 +55,7 @@ func TestCreateSBOM(t *testing.T) { stdOut, _, err := e2e.Zarf(t, "package", "inspect", tarPath, "--list-images") require.NoError(t, err) - require.Equal(t, "- ghcr.io/zarf-dev/doom-game:0.0.1\n", stdOut) + require.Contains(t, stdOut, "- ghcr.io/zarf-dev/doom-game:0.0.1\n") // Pull the current zarf binary version to find the corresponding init package version, _, err := e2e.Zarf(t, "version") From 36ab5632232ff28d87304b6bd009763716891b14 Mon Sep 17 00:00:00 2001 From: Kit Patella Date: Thu, 21 Nov 2024 14:21:49 -0800 Subject: [PATCH 07/10] 25_helm check stdout not srderr for package deploy Signed-off-by: Kit Patella --- src/test/e2e/25_helm_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/e2e/25_helm_test.go b/src/test/e2e/25_helm_test.go index a741c000ac..933fda4eb7 100644 --- a/src/test/e2e/25_helm_test.go +++ b/src/test/e2e/25_helm_test.go @@ -96,8 +96,8 @@ func testHelmChartsExample(t *testing.T) { helmChartsPkg := filepath.Join("build", fmt.Sprintf("zarf-package-helm-charts-%s-0.0.1.tar.zst", e2e.Arch)) stdOut, stdErr, err = e2e.Zarf(t, "package", "deploy", helmChartsPkg, "--confirm") require.NoError(t, err, stdOut, stdErr) - require.Contains(t, string(stdErr), "registryOverrides", "registry overrides was not saved to build data") - require.Contains(t, string(stdErr), "docker.io", "docker.io not found in registry overrides") + require.Contains(t, stdOut, "registryOverrides", "registry overrides was not saved to build data") + require.Contains(t, stdOut, "docker.io", "docker.io not found in registry overrides") // Remove the example package. stdOut, stdErr, err = e2e.Zarf(t, "package", "remove", "helm-charts", "--confirm") From 3de93268f5e104db84ed3d39a80e1c560a1556d8 Mon Sep 17 00:00:00 2001 From: Kit Patella Date: Thu, 5 Dec 2024 09:21:38 -0800 Subject: [PATCH 08/10] fix some tests that were checking for content on stderr Signed-off-by: Kit Patella --- src/test/e2e/09_component_compose_test.go | 22 ++++++++--------- src/test/e2e/12_lint_test.go | 29 ++++++++++++----------- 2 files changed, 26 insertions(+), 25 deletions(-) diff --git a/src/test/e2e/09_component_compose_test.go b/src/test/e2e/09_component_compose_test.go index 8c369feab9..925a5b1b28 100644 --- a/src/test/e2e/09_component_compose_test.go +++ b/src/test/e2e/09_component_compose_test.go @@ -45,7 +45,7 @@ func (suite *CompositionSuite) TearDownSuite() { func (suite *CompositionSuite) Test_0_ComposabilityExample() { suite.T().Log("E2E: Package Compose Example") - _, stdErr, err := e2e.Zarf(suite.T(), "package", "create", composeExample, "-o", "build", "--no-color", "--confirm") + stdOut, _, err := e2e.Zarf(suite.T(), "package", "create", composeExample, "-o", "build", "--no-color", "--confirm") suite.NoError(err) // Ensure that common names merge @@ -57,10 +57,10 @@ func (suite *CompositionSuite) Test_0_ComposabilityExample() { - ../dos-games/manifests/deployment.yaml - ../dos-games/manifests/service.yaml - quake-service.yaml`) - suite.Contains(stdErr, manifests) + suite.Contains(stdOut, manifests) // Ensure that the action was appended - suite.Contains(stdErr, ` + suite.Contains(stdOut, ` - ghcr.io/zarf-dev/doom-game:0.0.1 actions: onDeploy: @@ -71,13 +71,13 @@ func (suite *CompositionSuite) Test_0_ComposabilityExample() { func (suite *CompositionSuite) Test_1_FullComposability() { suite.T().Log("E2E: Full Package Compose") - _, stdErr, err := e2e.Zarf(suite.T(), "package", "create", composeTest, "-o", "build", "--no-color", "--confirm") + stdOut, _, err := e2e.Zarf(suite.T(), "package", "create", composeTest, "-o", "build", "--no-color", "--confirm") suite.NoError(err) // Ensure that names merge and that composition is added appropriately // Check metadata - suite.Contains(stdErr, ` + suite.Contains(stdOut, ` - name: test-compose-package description: A contrived example for podinfo using many Zarf primitives for compose testing required: true @@ -86,7 +86,7 @@ func (suite *CompositionSuite) Test_1_FullComposability() { `) // Check files - suite.Contains(stdErr, e2e.NormalizeYAMLFilenames(` + suite.Contains(stdOut, e2e.NormalizeYAMLFilenames(` files: - source: files/coffee-ipsum.txt target: coffee-ipsum.txt @@ -95,7 +95,7 @@ func (suite *CompositionSuite) Test_1_FullComposability() { `)) // Check charts - suite.Contains(stdErr, e2e.NormalizeYAMLFilenames(` + suite.Contains(stdOut, e2e.NormalizeYAMLFilenames(` charts: - name: podinfo-compose version: 6.4.0 @@ -115,7 +115,7 @@ func (suite *CompositionSuite) Test_1_FullComposability() { `)) // Check manifests - suite.Contains(stdErr, e2e.NormalizeYAMLFilenames(` + suite.Contains(stdOut, e2e.NormalizeYAMLFilenames(` manifests: - name: connect-service namespace: podinfo-override @@ -134,7 +134,7 @@ func (suite *CompositionSuite) Test_1_FullComposability() { `)) // Check images + repos - suite.Contains(stdErr, ` + suite.Contains(stdOut, ` images: - ghcr.io/stefanprodan/podinfo:6.4.0 - ghcr.io/stefanprodan/podinfo:6.4.1 @@ -144,7 +144,7 @@ func (suite *CompositionSuite) Test_1_FullComposability() { `) // Check dataInjections - suite.Contains(stdErr, ` + suite.Contains(stdOut, ` dataInjections: - source: files target: @@ -161,7 +161,7 @@ func (suite *CompositionSuite) Test_1_FullComposability() { `) // Check actions - suite.Contains(stdErr, ` + suite.Contains(stdOut, ` actions: onCreate: before: diff --git a/src/test/e2e/12_lint_test.go b/src/test/e2e/12_lint_test.go index 2c77b14056..6f6ffbf26c 100644 --- a/src/test/e2e/12_lint_test.go +++ b/src/test/e2e/12_lint_test.go @@ -31,31 +31,32 @@ func TestLint(t *testing.T) { configPath := filepath.Join(testPackagePath, "zarf-config.toml") osSetErr := os.Setenv("ZARF_CONFIG", configPath) require.NoError(t, osSetErr, "Unable to set ZARF_CONFIG") - _, stderr, err := e2e.Zarf(t, "dev", "lint", testPackagePath, "-f", "good-flavor") + stdOut, stdErr, err := e2e.Zarf(t, "dev", "lint", testPackagePath, "-f", "good-flavor") osUnsetErr := os.Unsetenv("ZARF_CONFIG") require.NoError(t, osUnsetErr, "Unable to cleanup ZARF_CONFIG") require.Error(t, err, "Require an exit code since there was warnings / errors") - strippedStderr := e2e.StripMessageFormatting(stderr) + strippedStdOut := e2e.StripMessageFormatting(stdOut) + strippedStdErr := e2e.StripMessageFormatting(stdErr) key := "WHATEVER_IMAGE" - require.Contains(t, strippedStderr, lang.UnsetVarLintWarning) - require.Contains(t, strippedStderr, fmt.Sprintf(lang.PkgValidateTemplateDeprecation, key, key, key)) - require.Contains(t, strippedStderr, ".components.[2].repos.[0] | Unpinned repository") - require.Contains(t, strippedStderr, ".metadata | Additional property description1 is not allowed") - require.Contains(t, strippedStderr, ".components.[0].import | Additional property not-path is not allowed") + require.Contains(t, strippedStdOut, lang.UnsetVarLintWarning) + require.Contains(t, strippedStdOut, fmt.Sprintf(lang.PkgValidateTemplateDeprecation, key, key, key)) + require.Contains(t, strippedStdOut, ".components.[2].repos.[0] | Unpinned repository") + require.Contains(t, strippedStdOut, ".metadata | Additional property description1 is not allowed") + require.Contains(t, strippedStdOut, ".components.[0].import | Additional property not-path is not allowed") // Testing the import / compose on lint is working - require.Contains(t, strippedStderr, ".components.[1].images.[0] | Image not pinned with digest - registry.com:9001/whatever/image:latest") + require.Contains(t, strippedStdOut, ".components.[1].images.[0] | Image not pinned with digest - registry.com:9001/whatever/image:latest") // Testing import / compose + variables are working - require.Contains(t, strippedStderr, ".components.[2].images.[3] | Image not pinned with digest - busybox:latest") + require.Contains(t, strippedStdOut, ".components.[2].images.[3] | Image not pinned with digest - busybox:latest") // Testing OCI imports get linted - require.Contains(t, strippedStderr, ".components.[0].images.[0] | Image not pinned with digest - ghcr.io/zarf-dev/doom-game:0.0.1") + require.Contains(t, strippedStdOut, ".components.[0].images.[0] | Image not pinned with digest - ghcr.io/zarf-dev/doom-game:0.0.1") // Check flavors - require.NotContains(t, strippedStderr, "image-in-bad-flavor-component:unpinned") - require.Contains(t, strippedStderr, "image-in-good-flavor-component:unpinned") + require.NotContains(t, strippedStdOut, "image-in-bad-flavor-component:unpinned") + require.Contains(t, strippedStdOut, "image-in-good-flavor-component:unpinned") // Check reported filepaths - require.Contains(t, strippedStderr, "Linting package \"dos-games\" at oci://ghcr.io/zarf-dev/packages/dos-games:1.1.0") - require.Contains(t, strippedStderr, fmt.Sprintf("Linting package \"lint\" at %s", testPackagePath)) + require.Contains(t, strippedStdErr, "Linting package \"dos-games\" at oci://ghcr.io/zarf-dev/packages/dos-games:1.1.0") + require.Contains(t, strippedStdErr, fmt.Sprintf("Linting package \"lint\" at %s", testPackagePath)) }) } From e9cdc84e1d2cfdbe255183738733c52a536729d8 Mon Sep 17 00:00:00 2001 From: Kit Patella Date: Thu, 5 Dec 2024 09:33:54 -0800 Subject: [PATCH 09/10] check stdout for oci_compose test Signed-off-by: Kit Patella --- src/test/e2e/14_oci_compose_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/e2e/14_oci_compose_test.go b/src/test/e2e/14_oci_compose_test.go index 3f8c0a452b..81fdd8c2d5 100644 --- a/src/test/e2e/14_oci_compose_test.go +++ b/src/test/e2e/14_oci_compose_test.go @@ -100,7 +100,7 @@ func (suite *PublishCopySkeletonSuite) Test_1_Compose_Everything_Inception() { _, _, err = e2e.Zarf(suite.T(), "package", "create", importception, "-o", "build", "--plain-http", "--confirm") suite.NoError(err) - _, stdErr, err := e2e.Zarf(suite.T(), "package", "inspect", importEverythingPath) + stdOut, _, err := e2e.Zarf(suite.T(), "package", "inspect", importEverythingPath) suite.NoError(err) targets := []string{ @@ -109,7 +109,7 @@ func (suite *PublishCopySkeletonSuite) Test_1_Compose_Everything_Inception() { } for _, target := range targets { - suite.Contains(stdErr, target) + suite.Contains(stdOut, target) } } From cd1a23fb72bbb3b650f3ced20361c93a2a463d30 Mon Sep 17 00:00:00 2001 From: Kit Patella Date: Thu, 5 Dec 2024 10:50:53 -0800 Subject: [PATCH 10/10] import component tests from main Signed-off-by: Kit Patella --- src/test/e2e/09_component_compose_test.go | 204 +++++++++++----------- 1 file changed, 98 insertions(+), 106 deletions(-) diff --git a/src/test/e2e/09_component_compose_test.go b/src/test/e2e/09_component_compose_test.go index 925a5b1b28..0ff078f393 100644 --- a/src/test/e2e/09_component_compose_test.go +++ b/src/test/e2e/09_component_compose_test.go @@ -5,97 +5,116 @@ package test import ( + "context" "fmt" - "os" "path/filepath" + "runtime" "testing" + goyaml "github.com/goccy/go-yaml" "github.com/stretchr/testify/require" - "github.com/stretchr/testify/suite" -) - -type CompositionSuite struct { - suite.Suite - *require.Assertions -} -var ( - composeExample = filepath.Join("examples", "composable-packages") - composeExamplePath string - composeTest = filepath.Join("src", "test", "packages", "09-composable-packages") - composeTestPath string - composeTestBadLocalOS = filepath.Join("src", "test", "packages", "09-composable-packages", "bad-local-os") + layout2 "github.com/zarf-dev/zarf/src/internal/packager2/layout" ) -func (suite *CompositionSuite) SetupSuite() { - suite.Assertions = require.New(suite.T()) +func TestComposabilityExample(t *testing.T) { + t.Parallel() - // Setup the package paths after e2e has been initialized - composeExamplePath = filepath.Join("build", fmt.Sprintf("zarf-package-composable-packages-%s.tar.zst", e2e.Arch)) - composeTestPath = filepath.Join("build", fmt.Sprintf("zarf-package-test-compose-package-%s.tar.zst", e2e.Arch)) -} + // Skip for Windows until path separators in packages are standardized. + if runtime.GOOS == "windows" { + t.SkipNow() + } -func (suite *CompositionSuite) TearDownSuite() { - err := os.RemoveAll(composeExamplePath) - suite.NoError(err) - err = os.RemoveAll(composeTestPath) - suite.NoError(err) -} + tmpDir := t.TempDir() + composeExample := filepath.Join("examples", "composable-packages") + _, _, err := e2e.Zarf(t, "package", "create", composeExample, "-o", tmpDir, "--no-color", "--confirm", "--zarf-cache", tmpDir) + require.NoError(t, err) -func (suite *CompositionSuite) Test_0_ComposabilityExample() { - suite.T().Log("E2E: Package Compose Example") + tarPath := filepath.Join(tmpDir, fmt.Sprintf("zarf-package-composable-packages-%s.tar.zst", e2e.Arch)) + pkgLayout, err := layout2.LoadFromTar(context.Background(), tarPath, layout2.PackageLayoutOptions{}) + require.NoError(t, err) - stdOut, _, err := e2e.Zarf(suite.T(), "package", "create", composeExample, "-o", "build", "--no-color", "--confirm") - suite.NoError(err) + require.Len(t, pkgLayout.Pkg.Components, 2) + b, err := goyaml.Marshal(pkgLayout.Pkg.Components) + require.NoError(t, err) - // Ensure that common names merge - manifests := e2e.NormalizeYAMLFilenames(` + expectedYaml := fmt.Sprintf(`- name: local-games-path + description: Example of a local composed package with a unique description for this component + required: true manifests: - name: multi-games namespace: dos-games files: - ../dos-games/manifests/deployment.yaml - ../dos-games/manifests/service.yaml - - quake-service.yaml`) - suite.Contains(stdOut, manifests) - - // Ensure that the action was appended - suite.Contains(stdOut, ` + - quake-service.yaml + images: + - ghcr.io/zarf-dev/doom-game:0.0.1 +- name: oci-games-url + manifests: + - name: multi-games + namespace: dos-games + files: + - ../../../../../../..%s/oci/dirs/9ece174e362633b637e3c6b554b70f7d009d0a27107bee822336fdf2ce9a9def/manifests/multi-games-0.yaml + - ../../../../../../..%s/oci/dirs/9ece174e362633b637e3c6b554b70f7d009d0a27107bee822336fdf2ce9a9def/manifests/multi-games-1.yaml + images: - ghcr.io/zarf-dev/doom-game:0.0.1 actions: onDeploy: before: - - cmd: ./zarf tools kubectl get -n dos-games deployment -o jsonpath={.items[0].metadata.creationTimestamp}`) + - cmd: ./zarf tools kubectl get -n dos-games deployment -o jsonpath={.items[0].metadata.creationTimestamp} + after: + - wait: + cluster: + kind: deployment + name: game + namespace: dos-games + condition: available +`, tmpDir, tmpDir) + require.YAMLEq(t, expectedYaml, string(b)) } -func (suite *CompositionSuite) Test_1_FullComposability() { - suite.T().Log("E2E: Full Package Compose") +func TestFullComposability(t *testing.T) { + t.Parallel() + + // Skip for Windows until path separators in packages are standardized. + if runtime.GOOS == "windows" { + t.SkipNow() + } + + tmpDir := t.TempDir() + composeTest := filepath.Join("src", "test", "packages", "09-composable-packages") + _, _, err := e2e.Zarf(t, "package", "create", composeTest, "-o", tmpDir, "--no-color", "--confirm") + require.NoError(t, err) - stdOut, _, err := e2e.Zarf(suite.T(), "package", "create", composeTest, "-o", "build", "--no-color", "--confirm") - suite.NoError(err) + tarPath := filepath.Join(tmpDir, fmt.Sprintf("zarf-package-test-compose-package-%s-0.0.1.tar.zst", e2e.Arch)) + pkgLayout, err := layout2.LoadFromTar(context.Background(), tarPath, layout2.PackageLayoutOptions{}) + require.NoError(t, err) - // Ensure that names merge and that composition is added appropriately + require.Len(t, pkgLayout.Pkg.Components, 1) + b, err := goyaml.Marshal(pkgLayout.Pkg.Components) + require.NoError(t, err) - // Check metadata - suite.Contains(stdOut, ` -- name: test-compose-package + expectedYaml := `- name: test-compose-package description: A contrived example for podinfo using many Zarf primitives for compose testing required: true only: localOS: linux -`) - - // Check files - suite.Contains(stdOut, e2e.NormalizeYAMLFilenames(` - files: - - source: files/coffee-ipsum.txt - target: coffee-ipsum.txt - - source: files/coffee-ipsum.txt - target: coffee-ipsum.txt -`)) - - // Check charts - suite.Contains(stdOut, e2e.NormalizeYAMLFilenames(` + manifests: + - name: connect-service + namespace: podinfo-override + files: + - files/service.yaml + - files/service.yaml + kustomizations: + - files + - files + - name: connect-service-two + namespace: podinfo-compose-two + files: + - files/service.yaml + kustomizations: + - files charts: - name: podinfo-compose version: 6.4.0 @@ -112,39 +131,6 @@ func (suite *CompositionSuite) Test_1_FullComposability() { releaseName: podinfo-compose-two valuesFiles: - files/test-values.yaml -`)) - - // Check manifests - suite.Contains(stdOut, e2e.NormalizeYAMLFilenames(` - manifests: - - name: connect-service - namespace: podinfo-override - files: - - files/service.yaml - - files/service.yaml - kustomizations: - - files - - files - - name: connect-service-two - namespace: podinfo-compose-two - files: - - files/service.yaml - kustomizations: - - files -`)) - - // Check images + repos - suite.Contains(stdOut, ` - images: - - ghcr.io/stefanprodan/podinfo:6.4.0 - - ghcr.io/stefanprodan/podinfo:6.4.1 - repos: - - https://github.com/zarf-dev/zarf-public-test.git - - https://github.com/zarf-dev/zarf-public-test.git@refs/heads/dragons -`) - - // Check dataInjections - suite.Contains(stdOut, ` dataInjections: - source: files target: @@ -158,10 +144,17 @@ func (suite *CompositionSuite) Test_1_FullComposability() { selector: app.kubernetes.io/name=podinfo-compose container: podinfo path: /home/app/service.yaml -`) - - // Check actions - suite.Contains(stdOut, ` + files: + - source: files/coffee-ipsum.txt + target: coffee-ipsum.txt + - source: files/coffee-ipsum.txt + target: coffee-ipsum.txt + images: + - ghcr.io/stefanprodan/podinfo:6.4.0 + - ghcr.io/stefanprodan/podinfo:6.4.1 + repos: + - https://github.com/zarf-dev/zarf-public-test.git + - https://github.com/zarf-dev/zarf-public-test.git@refs/heads/dragons actions: onCreate: before: @@ -177,17 +170,16 @@ func (suite *CompositionSuite) Test_1_FullComposability() { kind: deployment name: podinfo-compose-two namespace: podinfo-compose-two - condition: available`) + condition: available +` + require.YAMLEq(t, expectedYaml, string(b)) } -func (suite *CompositionSuite) Test_2_ComposabilityBadLocalOS() { - suite.T().Log("E2E: Package Compose Example") - - _, stdErr, err := e2e.Zarf(suite.T(), "package", "create", composeTestBadLocalOS, "-o", "build", "--no-color", "--confirm") - suite.Error(err) - suite.Contains(e2e.StripMessageFormatting(stdErr), "\"only.localOS\" \"linux\" cannot be redefined as \"windows\" during compose") -} +func TestComposabilityBadLocalOS(t *testing.T) { + t.Parallel() -func TestCompositionSuite(t *testing.T) { - suite.Run(t, new(CompositionSuite)) + composeTestBadLocalOS := filepath.Join("src", "test", "packages", "09-composable-packages", "bad-local-os") + _, stdErr, err := e2e.Zarf(t, "package", "create", composeTestBadLocalOS, "-o", "build", "--no-color", "--confirm") + require.Error(t, err) + require.Contains(t, e2e.StripMessageFormatting(stdErr), "\"only.localOS\" \"linux\" cannot be redefined as \"windows\" during compose") }