From 2a846409aa8df01c7a2d39f0b3b1240245391bb9 Mon Sep 17 00:00:00 2001 From: Sylvester Damgaard Date: Thu, 27 Aug 2026 14:55:56 +0200 Subject: [PATCH 1/2] test(cmd): reset cobra flags between runs so -count is usable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These tests drive the shared global rootCmd, and cobra flag values are sticky: once "version --short" has run, --short stays set on that command, so a later plain "version" printed only the number. Within one run the subtests happened to be ordered such that this never showed; under -count=2 four tests fail. That made -count unusable for this package — and a test that only passes in one particular order is a test that can hide a real regression just as easily. Flags are now reset to their defaults before each execution. Pre-existing: v2.5.1 fails the same way. --- cmd/cbox-init/cmd_test.go | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/cmd/cbox-init/cmd_test.go b/cmd/cbox-init/cmd_test.go index ad898a0..0a9c22b 100644 --- a/cmd/cbox-init/cmd_test.go +++ b/cmd/cbox-init/cmd_test.go @@ -20,6 +20,7 @@ import ( "github.com/cboxdk/init/internal/process" "github.com/cboxdk/init/internal/scaffold" "github.com/spf13/cobra" + "github.com/spf13/pflag" ) // captureOutput captures stdout and stderr during function execution @@ -540,8 +541,36 @@ func TestGlobalConfigFlag(t *testing.T) { // Helper functions for test execution // executeCommandCapture executes a cobra command and captures real stdout/stderr +// resetCommandFlags restores every flag in the command tree to its default. +// +// These tests drive the SHARED global rootCmd, and cobra flag values are sticky: +// once "version --short" has run, the --short flag stays set on that command, so +// a later plain "version" printed only the number. Within a single run the +// subtests happened to be ordered such that this never showed; under -count=2 +// (or any reordering) it fails, which made -count unusable for this package and +// could equally hide a real regression. +func resetCommandFlags(cmd *cobra.Command) { + cmd.Flags().VisitAll(func(f *pflag.Flag) { + if f.Changed { + _ = f.Value.Set(f.DefValue) + f.Changed = false + } + }) + cmd.PersistentFlags().VisitAll(func(f *pflag.Flag) { + if f.Changed { + _ = f.Value.Set(f.DefValue) + f.Changed = false + } + }) + + for _, sub := range cmd.Commands() { + resetCommandFlags(sub) + } +} + func executeCommandCapture(t *testing.T, cmd *cobra.Command, args ...string) string { t.Helper() + resetCommandFlags(cmd) var output string stdout, stderr := captureOutput(func() { cmd.SetArgs(args) @@ -554,6 +583,7 @@ func executeCommandCapture(t *testing.T, cmd *cobra.Command, args ...string) str // executeCommandCaptureWithError executes a cobra command and returns captured output and error func executeCommandCaptureWithError(cmd *cobra.Command, args ...string) (string, error) { + resetCommandFlags(cmd) var cmdErr error stdout, stderr := captureOutput(func() { cmd.SetArgs(args) @@ -575,6 +605,8 @@ func executeCommand(t *testing.T, cmd *cobra.Command, args ...string) string { // executeCommandWithError executes a cobra command and returns stdout and error func executeCommandWithError(cmd *cobra.Command, args ...string) (string, error) { + resetCommandFlags(cmd) + // Create buffers for output stdout := new(bytes.Buffer) stderr := new(bytes.Buffer) From 8efea88144824a9045ccaa41d686a76736ec80ed Mon Sep 17 00:00:00 2001 From: Sylvester Damgaard Date: Thu, 27 Aug 2026 15:15:18 +0200 Subject: [PATCH 2/2] build: promote pflag to a direct dependency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The flag-reset helper imports pflag directly (cobra's FlagSet.VisitAll takes a *pflag.Flag), so go.mod and the SBOM record it as direct rather than indirect. No new module enters the graph — cobra already pulled it in. --- go.mod | 2 +- sbom.json | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index e763c0a..dff64c3 100644 --- a/go.mod +++ b/go.mod @@ -18,6 +18,7 @@ require ( github.com/robfig/cron/v3 v3.0.1 github.com/shirou/gopsutil/v4 v4.26.7 github.com/spf13/cobra v1.10.2 + github.com/spf13/pflag v1.0.9 go.opentelemetry.io/otel v1.45.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.45.0 go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.45.0 @@ -62,7 +63,6 @@ require ( github.com/prometheus/common v0.70.1 // indirect github.com/prometheus/procfs v0.21.1 // indirect github.com/rivo/uniseg v0.4.7 // indirect - github.com/spf13/pflag v1.0.9 // indirect github.com/tklauser/go-sysconf v0.3.16 // indirect github.com/tklauser/numcpus v0.11.0 // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect diff --git a/sbom.json b/sbom.json index e82f7e8..4b46105 100644 --- a/sbom.json +++ b/sbom.json @@ -1619,6 +1619,7 @@ "pkg:golang/github.com/robfig/cron/v3@v3.0.1?type=module", "pkg:golang/github.com/shirou/gopsutil/v4@v4.26.7?type=module", "pkg:golang/github.com/spf13/cobra@v1.10.2?type=module", + "pkg:golang/github.com/spf13/pflag@v1.0.9?type=module", "pkg:golang/go.opentelemetry.io/otel@v1.45.0?type=module", "pkg:golang/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc@v1.45.0?type=module", "pkg:golang/go.opentelemetry.io/otel/exporters/stdout/stdouttrace@v1.45.0?type=module",