diff --git a/pkg/cli/runner_guard_activation_gate_test.go b/pkg/cli/runner_guard_activation_gate_test.go index 4f9c158038d..0aa8db797e2 100644 --- a/pkg/cli/runner_guard_activation_gate_test.go +++ b/pkg/cli/runner_guard_activation_gate_test.go @@ -92,6 +92,7 @@ func writeWorkflow(t *testing.T, gitRoot string, name string, content string) { } func TestTrustedActivationGatedJobs(t *testing.T) { + t.Parallel() t.Run("gates propagate through the needs graph", func(t *testing.T) { gitRoot := t.TempDir() writeWorkflow(t, gitRoot, "gated.lock.yml", gatedWorkflow) @@ -133,6 +134,7 @@ func TestTrustedActivationGatedJobs(t *testing.T) { } func TestFilterRunnerGuardFindings(t *testing.T) { + t.Parallel() gitRoot := t.TempDir() writeWorkflow(t, gitRoot, "gated.lock.yml", gatedWorkflow) writeWorkflow(t, gitRoot, "ungated.lock.yml", ungatedWorkflow) @@ -156,6 +158,7 @@ func TestFilterRunnerGuardFindings(t *testing.T) { } func TestFilterRunnerGuardFindingsKeepsFindingsForUnresolvableFiles(t *testing.T) { + t.Parallel() gitRoot := t.TempDir() findings := []runnerGuardFinding{ @@ -167,6 +170,7 @@ func TestFilterRunnerGuardFindingsKeepsFindingsForUnresolvableFiles(t *testing.T } func TestJobNeeds(t *testing.T) { + t.Parallel() assert.Equal(t, []string{"a"}, jobNeeds("a")) assert.Equal(t, []string{"a", "b"}, jobNeeds([]any{"a", "b", 42})) assert.Equal(t, []string{"a"}, jobNeeds([]string{"a"})) @@ -174,6 +178,7 @@ func TestJobNeeds(t *testing.T) { } func TestHasWorkflowRunActorAllowlistCheck(t *testing.T) { + t.Parallel() assert.True(t, hasWorkflowRunActorAllowlistCheck("${{ github.event.workflow_run.event == 'workflow_dispatch' && contains(fromJSON('[\"owner\"]'), github.event.workflow_run.actor.login) }}")) assert.True(t, hasWorkflowRunActorAllowlistCheck("${{ github.event.workflow_run.event == 'workflow_dispatch' && !contains(fromJSON('[\"blocked\"]'), github.event.workflow_run.actor.login) && contains(fromJSON('[\"owner\"]'), github.event.workflow_run.actor.login) }}")) assert.False(t, hasWorkflowRunActorAllowlistCheck("${{ github.event.workflow_run.event == 'workflow_dispatch' && !contains(fromJSON('[\"owner\"]'), github.event.workflow_run.actor.login) }}")) diff --git a/pkg/cli/runner_guard_copilot_allow_tool_test.go b/pkg/cli/runner_guard_copilot_allow_tool_test.go index f002fcaa906..50b5b380566 100644 --- a/pkg/cli/runner_guard_copilot_allow_tool_test.go +++ b/pkg/cli/runner_guard_copilot_allow_tool_test.go @@ -36,6 +36,7 @@ jobs: ` func TestFilterCopilotLocalAllowToolFindings(t *testing.T) { + t.Parallel() gitRoot := t.TempDir() writeWorkflow(t, gitRoot, "visual-regression-checker.lock.yml", copilotLocalAllowToolWorkflow) lines := strings.Split(copilotLocalAllowToolWorkflow, "\n") @@ -70,6 +71,7 @@ func TestFilterCopilotLocalAllowToolFindings(t *testing.T) { } func TestFilterCopilotLocalAllowToolFindingsKeepsNonLocalAllowToolContext(t *testing.T) { + t.Parallel() const workflow = ` name: Suspicious Tool jobs: @@ -94,6 +96,7 @@ jobs: } func TestFindingInCopilotLocalCurlAllowTool(t *testing.T) { + t.Parallel() lines := strings.Split(copilotLocalAllowToolWorkflow, "\n") assert.True(t, findingInCopilotLocalCurlAllowTool(lines, lineContaining(t, lines, "Execute GitHub Copilot CLI"))) @@ -105,6 +108,7 @@ func TestFindingInCopilotLocalCurlAllowTool(t *testing.T) { } func TestIsLocalCurlAllowToolArgumentLine(t *testing.T) { + t.Parallel() assert.True(t, isLocalCurlAllowToolArgumentLine(`"$GH_AW_NODE_EXEC" copilot_harness.cjs copilot --allow-tool 'shell(curl http://host.docker.internal:*)' --allow-tool 'shell(curl http://localhost:*)'`)) assert.False(t, isLocalCurlAllowToolArgumentLine(`"$GH_AW_NODE_EXEC" copilot_harness.cjs copilot --allow-tool 'shell(curl http://localhost:*)' --allow-tool 'shell(curl https://evil.example.com)'`)) assert.False(t, isLocalCurlAllowToolArgumentLine(`curl -fsSL http://localhost:4321/collect -d "secret=$SECRET_TOKEN"`)) @@ -113,6 +117,7 @@ func TestIsLocalCurlAllowToolArgumentLine(t *testing.T) { } func TestFindingInCopilotLocalCurlAllowToolKeepsExecutableCurlInStep(t *testing.T) { + t.Parallel() const workflow = ` jobs: agent: @@ -129,6 +134,7 @@ jobs: } func TestCurlAllowToolCommentHost(t *testing.T) { + t.Parallel() tests := []struct { line string wantHost string diff --git a/pkg/cli/runner_guard_gvisor_exfiltration_test.go b/pkg/cli/runner_guard_gvisor_exfiltration_test.go index cd38e39e4f1..02ad22eb3b2 100644 --- a/pkg/cli/runner_guard_gvisor_exfiltration_test.go +++ b/pkg/cli/runner_guard_gvisor_exfiltration_test.go @@ -34,6 +34,7 @@ jobs: ` func TestFilterGvisorInstallFindings(t *testing.T) { + t.Parallel() gitRoot := t.TempDir() writeWorkflow(t, gitRoot, "sandbox.lock.yml", gvisorWorkflow) @@ -56,6 +57,7 @@ func TestFilterGvisorInstallFindings(t *testing.T) { } func TestFilterGvisorInstallFindingsKeepsFindingsForUnresolvableFiles(t *testing.T) { + t.Parallel() gitRoot := t.TempDir() findings := []runnerGuardFinding{ @@ -67,6 +69,7 @@ func TestFilterGvisorInstallFindingsKeepsFindingsForUnresolvableFiles(t *testing } func TestFindingInGvisorInstallStep(t *testing.T) { + t.Parallel() lines := []string{ "jobs:", // 1 " agent:", // 2 @@ -100,6 +103,7 @@ func TestFindingInGvisorInstallStep(t *testing.T) { } func TestReadWorkflowLines(t *testing.T) { + t.Parallel() assert.Nil(t, readWorkflowLines("")) assert.Nil(t, readWorkflowLines(filepath.Join(t.TempDir(), "missing.lock.yml"))) } diff --git a/pkg/cli/runner_guard_inline_ignore_test.go b/pkg/cli/runner_guard_inline_ignore_test.go index 320d19ad37f..ce8420203ba 100644 --- a/pkg/cli/runner_guard_inline_ignore_test.go +++ b/pkg/cli/runner_guard_inline_ignore_test.go @@ -28,6 +28,7 @@ jobs: ` func TestFilterRunnerGuardIgnoredFindings(t *testing.T) { + t.Parallel() gitRoot := t.TempDir() writeWorkflow(t, gitRoot, "inline-ignore.lock.yml", inlineIgnoreWorkflow) @@ -46,6 +47,7 @@ func TestFilterRunnerGuardIgnoredFindings(t *testing.T) { } func TestFilterGeneratedSafeOutputPermissionFindings(t *testing.T) { + t.Parallel() gitRoot := t.TempDir() writeWorkflow(t, gitRoot, "generated.lock.yml", "# To regenerate this workflow, run:\n# gh aw compile\njobs:\n safe_outputs:\n") writeWorkflow(t, gitRoot, "user-workflow.yml", "jobs:\n safe_outputs:\n") @@ -66,6 +68,7 @@ func TestFilterGeneratedSafeOutputPermissionFindings(t *testing.T) { } func TestHasRunnerGuardInlineIgnore(t *testing.T) { + t.Parallel() lines := []string{ " - name: Public index request", // 1 " run: |", // 2 @@ -81,6 +84,7 @@ func TestHasRunnerGuardInlineIgnore(t *testing.T) { } func TestHasRunnerGuardInlineIgnoreAllowsNearbyGeneratedLineOffsets(t *testing.T) { + t.Parallel() lines := []string{ " - name: Configure host", // 1 " run: |", // 2 diff --git a/pkg/cli/runner_guard_test.go b/pkg/cli/runner_guard_test.go index 602da4a5ffc..794c37eddaf 100644 --- a/pkg/cli/runner_guard_test.go +++ b/pkg/cli/runner_guard_test.go @@ -356,6 +356,7 @@ func TestRunnerGuardPathTraversalGuard(t *testing.T) { } func TestBuildRunnerGuardContainerScanPath(t *testing.T) { + t.Parallel() tests := []struct { name string scanPath string @@ -385,6 +386,7 @@ func TestBuildRunnerGuardContainerScanPath(t *testing.T) { } func TestRunnerGuardDockerArgsPreservesDynamicValuesAsArguments(t *testing.T) { + t.Parallel() volumeMount := "/tmp/checkout with spaces:/workdir" containerScanPath := "./--help" @@ -404,6 +406,7 @@ func TestRunnerGuardDockerArgsPreservesDynamicValuesAsArguments(t *testing.T) { } func TestRunnerGuardDockerArgsShellEscapesBangInPaths(t *testing.T) { + t.Parallel() volumeMount := "/tmp/repo!42:/workdir" containerScanPath := "./path!subdir" @@ -415,6 +418,7 @@ func TestRunnerGuardDockerArgsShellEscapesBangInPaths(t *testing.T) { } func TestRunRunnerGuardOnDirectoryRejectsPathsOutsideRepo(t *testing.T) { + t.Parallel() outsideDir := filepath.Join(t.TempDir(), "outside") require.NoError(t, os.MkdirAll(outsideDir, 0o755)) diff --git a/pkg/cli/secret_set_command_test.go b/pkg/cli/secret_set_command_test.go index 5bc8edc3d13..eb269f2dd39 100644 --- a/pkg/cli/secret_set_command_test.go +++ b/pkg/cli/secret_set_command_test.go @@ -66,6 +66,7 @@ func TestResolveSecretValueForSet(t *testing.T) { } func TestEncryptWithPublicKey(t *testing.T) { + t.Parallel() // Valid 32-byte public key in base64 validKey := "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNERUY=" plaintext := "my-secret-value" @@ -86,6 +87,7 @@ func TestEncryptWithPublicKey(t *testing.T) { } func TestEncryptWithPublicKeyInvalidKey(t *testing.T) { + t.Parallel() tests := []struct { name string key string @@ -120,6 +122,7 @@ func TestEncryptWithPublicKeyInvalidKey(t *testing.T) { } func TestEncryptWithPublicKeyEmptyPlaintext(t *testing.T) { + t.Parallel() validKey := "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNERUY=" encrypted, err := encryptWithPublicKey(validKey, "") if err != nil { @@ -135,6 +138,7 @@ func TestEncryptWithPublicKeyEmptyPlaintext(t *testing.T) { } func TestEncryptDecryptRoundTrip(t *testing.T) { + t.Parallel() // Generate a real key pair for testing pub, priv, err := box.GenerateKey(rand.Reader) if err != nil { @@ -168,6 +172,7 @@ func TestEncryptDecryptRoundTrip(t *testing.T) { } func TestSecretSetClientOptions(t *testing.T) { + t.Parallel() t.Run("defaults include timeout", func(t *testing.T) { opts := secretSetClientOptions("") if opts.Host != "" { diff --git a/pkg/cli/secrets_command_test.go b/pkg/cli/secrets_command_test.go index e31ee607373..f3d2051d6fc 100644 --- a/pkg/cli/secrets_command_test.go +++ b/pkg/cli/secrets_command_test.go @@ -12,6 +12,7 @@ import ( ) func TestNewSecretsCommand(t *testing.T) { + t.Parallel() cmd := NewSecretsCommand() require.NotNil(t, cmd, "NewSecretsCommand should not return nil") @@ -41,6 +42,7 @@ func TestNewSecretsCommand(t *testing.T) { } func TestSecretsCommandHelp(t *testing.T) { + t.Parallel() cmd := NewSecretsCommand() // Verify RunE returns help when command is run without subcommand @@ -49,6 +51,7 @@ func TestSecretsCommandHelp(t *testing.T) { } func TestSecretsCommandStructure(t *testing.T) { + t.Parallel() tests := []struct { name string expectedUse string @@ -72,6 +75,7 @@ func TestSecretsCommandStructure(t *testing.T) { } func TestSecretsBootstrapEngineFlagUsage(t *testing.T) { + t.Parallel() cmd := NewSecretsCommand() var bootstrapCmd *cobra.Command @@ -95,6 +99,7 @@ func TestSecretsBootstrapEngineFlagUsage(t *testing.T) { } func TestSecretsCommandUnknownSubcommandReturnsError(t *testing.T) { + t.Parallel() cmd := NewSecretsCommand() cmd.SetOut(io.Discard) cmd.SetErr(io.Discard) diff --git a/pkg/cli/secrets_test.go b/pkg/cli/secrets_test.go index 209d4fd8f33..1712787b525 100644 --- a/pkg/cli/secrets_test.go +++ b/pkg/cli/secrets_test.go @@ -11,6 +11,7 @@ import ( ) func TestExtractSecretName(t *testing.T) { + t.Parallel() tests := []struct { name string value string @@ -59,6 +60,7 @@ func TestExtractSecretName(t *testing.T) { } func TestExtractSecretsFromConfig(t *testing.T) { + t.Parallel() tests := []struct { name string config parser.RegistryMCPServerConfig diff --git a/pkg/cli/security_regression_test.go b/pkg/cli/security_regression_test.go index 5264a664cd9..5e5cef713bf 100644 --- a/pkg/cli/security_regression_test.go +++ b/pkg/cli/security_regression_test.go @@ -19,6 +19,7 @@ import ( // TestSecurityCLICommandInjectionPrevention validates that CLI commands // properly sanitize inputs to prevent command injection. func TestSecurityCLICommandInjectionPrevention(t *testing.T) { + t.Parallel() tests := []struct { name string workflowName string @@ -90,6 +91,7 @@ func TestSecurityCLICommandInjectionPrevention(t *testing.T) { // TestSecurityCLIPathSanitization validates that file paths are properly // sanitized to prevent path traversal attacks. func TestSecurityCLIPathSanitization(t *testing.T) { + t.Parallel() tests := []struct { name string inputPath string @@ -184,6 +186,7 @@ func TestSecurityCLIPathSanitization(t *testing.T) { // TestSecurityCLIUnsafeFlagCombinations validates that certain flag // combinations that could be dangerous are handled properly. func TestSecurityCLIUnsafeFlagCombinations(t *testing.T) { + t.Parallel() tests := []struct { name string config CompileConfig @@ -239,6 +242,7 @@ func TestSecurityCLIUnsafeFlagCombinations(t *testing.T) { // TestSecurityCLIInputSizeLimits validates that excessively large inputs // are handled properly without causing DoS. func TestSecurityCLIInputSizeLimits(t *testing.T) { + t.Parallel() tests := []struct { name string contentFunc func() string @@ -382,6 +386,7 @@ func TestSecurityCLIEnvironmentVariableSanitization(t *testing.T) { // TestSecurityCLIWorkflowFileValidation validates that workflow files are // properly validated before compilation. func TestSecurityCLIWorkflowFileValidation(t *testing.T) { + t.Parallel() tests := []struct { name string workflow string @@ -476,6 +481,7 @@ Test content.`, // TestSecurityCLIOutputDirectorySafety validates that output directories // are properly validated to prevent writing to unsafe locations. func TestSecurityCLIOutputDirectorySafety(t *testing.T) { + t.Parallel() tests := []struct { name string outputDir string diff --git a/pkg/cli/semver_precise_test.go b/pkg/cli/semver_precise_test.go index 9b192f449c8..86eccc1575d 100644 --- a/pkg/cli/semver_precise_test.go +++ b/pkg/cli/semver_precise_test.go @@ -13,6 +13,7 @@ import ( ) func TestIsPreciseVersion(t *testing.T) { + t.Parallel() tests := []struct { name string version string @@ -95,6 +96,7 @@ func TestIsPreciseVersion(t *testing.T) { } func TestPreciseVersionPreference(t *testing.T) { + t.Parallel() // Tests that when comparing equivalent versions, imprecise tags (major-only or // major.minor) are not considered precise, while full three-component versions are. // This follows GitHub Actions convention of distinguishing major version pins diff --git a/pkg/cli/semver_test.go b/pkg/cli/semver_test.go index 6056f8e1775..244c09388ae 100644 --- a/pkg/cli/semver_test.go +++ b/pkg/cli/semver_test.go @@ -10,6 +10,7 @@ import ( ) func TestIsSemanticVersionTag(t *testing.T) { + t.Parallel() tests := []struct { name string ref string @@ -38,6 +39,7 @@ func TestIsSemanticVersionTag(t *testing.T) { } func TestParseVersion(t *testing.T) { + t.Parallel() tests := []struct { name string input string @@ -137,6 +139,7 @@ func TestParseVersion(t *testing.T) { } func TestVersionIsNewer(t *testing.T) { + t.Parallel() tests := []struct { name string version string diff --git a/pkg/cli/setup_cli_action_integration_test.go b/pkg/cli/setup_cli_action_integration_test.go index d422ec555ac..ea4a9e155e0 100644 --- a/pkg/cli/setup_cli_action_integration_test.go +++ b/pkg/cli/setup_cli_action_integration_test.go @@ -12,6 +12,7 @@ import ( // TestSetupCLIAction tests the setup-cli action's generated install scripts. func TestSetupCLIAction(t *testing.T) { + t.Parallel() // Get project root wd, err := os.Getwd() if err != nil { @@ -177,6 +178,7 @@ func TestSetupCLIAction(t *testing.T) { // TestSetupCLIActionYAML tests the action.yml file structure func TestSetupCLIActionYAML(t *testing.T) { + t.Parallel() wd, err := os.Getwd() if err != nil { t.Fatalf("Failed to get working directory: %v", err) diff --git a/pkg/cli/setup_command_test.go b/pkg/cli/setup_command_test.go index 2f07169f1e5..b1302063a27 100644 --- a/pkg/cli/setup_command_test.go +++ b/pkg/cli/setup_command_test.go @@ -16,6 +16,7 @@ import ( ) func TestRunSetupAuthWithRuntime(t *testing.T) { + t.Parallel() called := 0 err := runSetupAuthWithRuntime(SetupAuthOptions{Ctx: context.Background()}, setupRepositoryRuntime{ checkAuth: func(context.Context) error { @@ -40,6 +41,7 @@ func TestRunSetupAuthWithRuntime_JSONOutput(t *testing.T) { } func TestRunSetupRepositoryCheck_AttachedCheckout(t *testing.T) { + t.Parallel() repoDir := initBootstrapGitRepo(t) err := runSetupRepositoryCheckWithRuntime(normalizeSetupRepositoryCheckOptions(SetupRepositoryCheckOptions{ Ctx: context.Background(), @@ -88,6 +90,7 @@ func TestRunSetupRepositoryCheck_JSONOutput(t *testing.T) { } func TestRunSetupRepositoryCheck_EnforcesOwnerTypeRequirement(t *testing.T) { + t.Parallel() repoDir := initBootstrapGitRepo(t) err := runSetupRepositoryCheckWithRuntime(normalizeSetupRepositoryCheckOptions(SetupRepositoryCheckOptions{ Ctx: context.Background(), @@ -106,6 +109,7 @@ func TestRunSetupRepositoryCheck_EnforcesOwnerTypeRequirement(t *testing.T) { } func TestRunSetupRepositoryCheck_RequiresExistingRepository(t *testing.T) { + t.Parallel() err := runSetupRepositoryCheckWithRuntime(normalizeSetupRepositoryCheckOptions(SetupRepositoryCheckOptions{ Ctx: context.Background(), Repo: "octo/platform-ops", @@ -119,6 +123,7 @@ func TestRunSetupRepositoryCheck_RequiresExistingRepository(t *testing.T) { } func TestRunSetupRepositoryCheck_PropagatesCleanWorktreeError(t *testing.T) { + t.Parallel() repoDir := initBootstrapGitRepo(t) wantErr := errors.New("working directory has uncommitted changes, please commit or stash them first") @@ -142,6 +147,7 @@ func TestRunSetupRepositoryCheck_PropagatesCleanWorktreeError(t *testing.T) { } func TestRunSetupRepositoryCheck_RejectsNonExistentNestedCheckoutPath(t *testing.T) { + t.Parallel() parentRepoDir := initBootstrapGitRepo(t) nestedDir := filepath.Join(parentRepoDir, "new-checkout") @@ -205,6 +211,7 @@ exit 1 } func TestRunSetupRepositoryCheck_AcceptsCaseInsensitiveSlugMatch(t *testing.T) { + t.Parallel() repoDir := initBootstrapGitRepo(t) err := runSetupRepositoryCheckWithRuntime(normalizeSetupRepositoryCheckOptions(SetupRepositoryCheckOptions{ Ctx: context.Background(), @@ -221,6 +228,7 @@ func TestRunSetupRepositoryCheck_AcceptsCaseInsensitiveSlugMatch(t *testing.T) { } func TestValidateSetupRepositoryCheckOptions_RejectsEmptyRepoComponents(t *testing.T) { + t.Parallel() tests := []SetupRepositoryCheckOptions{ {Repo: "/"}, {Repo: "/repo"}, diff --git a/pkg/cli/shell_completion_test.go b/pkg/cli/shell_completion_test.go index 9df6911c622..90a12a2a861 100644 --- a/pkg/cli/shell_completion_test.go +++ b/pkg/cli/shell_completion_test.go @@ -173,6 +173,7 @@ func TestDetectShellPrioritizesVersionVariable(t *testing.T) { } func TestShellTypeString(t *testing.T) { + t.Parallel() tests := []struct { shellType ShellType expected string @@ -416,6 +417,7 @@ func TestUninstallShellCompletion(t *testing.T) { } func TestValidateRcPath(t *testing.T) { + t.Parallel() t.Run("returns cleaned path for absolute path", func(t *testing.T) { homeDir := t.TempDir() cleanPath, err := validateRcPath("bashrc", filepath.Join(homeDir, ".", ".bashrc")) diff --git a/pkg/cli/shellcheck_test.go b/pkg/cli/shellcheck_test.go index 3722e707319..19bdab0a553 100644 --- a/pkg/cli/shellcheck_test.go +++ b/pkg/cli/shellcheck_test.go @@ -17,6 +17,7 @@ import ( // TestIsShellcheckableShell tests the shell filter. func TestIsShellcheckableShell(t *testing.T) { + t.Parallel() t.Run("empty shell defaults to bash", func(t *testing.T) { assert.True(t, isShellcheckableShell("")) }) @@ -45,6 +46,7 @@ func TestIsShellcheckableShell(t *testing.T) { // TestShellcheckShell verifies the --shell= argument selection. func TestShellcheckShell(t *testing.T) { + t.Parallel() assert.Equal(t, "bash", shellcheckShell("")) assert.Equal(t, "bash", shellcheckShell("bash")) assert.Equal(t, "sh", shellcheckShell("sh")) @@ -54,6 +56,7 @@ func TestShellcheckShell(t *testing.T) { // TestExtractRunStepsFromLockFile tests YAML parsing and step extraction. func TestExtractRunStepsFromLockFile(t *testing.T) { + t.Parallel() t.Run("extracts bash and sh steps", func(t *testing.T) { content := ` jobs: @@ -215,6 +218,7 @@ jobs: // TestSanitizeGHAExpressions verifies that ${{ ... }} expressions are replaced // with a shell-safe placeholder before shellcheck runs. func TestSanitizeGHAExpressions(t *testing.T) { + t.Parallel() t.Run("replaces simple expression", func(t *testing.T) { assert.Equal(t, `echo __GHA_EXPR__`, sanitizeGHAExpressions(`echo ${{ github.actor }}`)) }) @@ -241,6 +245,7 @@ func TestSanitizeGHAExpressions(t *testing.T) { // TestStepLabel tests the diagnostic label helper. func TestStepLabel(t *testing.T) { + t.Parallel() t.Run("includes step name when set", func(t *testing.T) { info := runStepInfo{Name: "my step", LockFile: "/a/b/foo.lock.yml"} label := stepLabel(info) @@ -256,6 +261,7 @@ func TestStepLabel(t *testing.T) { // TestDefaultIgnoreCodes verifies the well-known false-positive codes are present. func TestDefaultIgnoreCodes(t *testing.T) { + t.Parallel() assert.Contains(t, shellcheckDefaultIgnoreCodes, "SC2016") assert.Contains(t, shellcheckDefaultIgnoreCodes, "SC1090") assert.Contains(t, shellcheckDefaultIgnoreCodes, "SC1091") @@ -279,6 +285,7 @@ func TestRunShellcheckOnLockFilesSkipsWhenUnavailable(t *testing.T) { // TestRunShellcheckOnLockFilesEmpty returns nil for an empty list. func TestRunShellcheckOnLockFilesEmpty(t *testing.T) { + t.Parallel() err := runShellcheckOnLockFiles(context.Background(), nil, false, false) assert.NoError(t, err) } diff --git a/pkg/cli/signal_aware_poll_test.go b/pkg/cli/signal_aware_poll_test.go index da9c4713a1b..8747b63a29b 100644 --- a/pkg/cli/signal_aware_poll_test.go +++ b/pkg/cli/signal_aware_poll_test.go @@ -10,6 +10,7 @@ import ( ) func TestPollWithSignalHandling_Success(t *testing.T) { + t.Parallel() callCount := 0 err := PollWithSignalHandling(PollOptions{ PollInterval: 10 * time.Millisecond, @@ -34,6 +35,7 @@ func TestPollWithSignalHandling_Success(t *testing.T) { } func TestPollWithSignalHandling_Failure(t *testing.T) { + t.Parallel() expectedErr := errors.New("poll failed") err := PollWithSignalHandling(PollOptions{ PollInterval: 10 * time.Millisecond, @@ -54,6 +56,7 @@ func TestPollWithSignalHandling_Failure(t *testing.T) { } func TestPollWithSignalHandling_Timeout(t *testing.T) { + t.Parallel() err := PollWithSignalHandling(PollOptions{ PollInterval: 50 * time.Millisecond, Timeout: 100 * time.Millisecond, @@ -73,6 +76,7 @@ func TestPollWithSignalHandling_Timeout(t *testing.T) { } func TestPollWithSignalHandling_ImmediateSuccess(t *testing.T) { + t.Parallel() callCount := 0 err := PollWithSignalHandling(PollOptions{ PollInterval: 10 * time.Millisecond, @@ -94,6 +98,7 @@ func TestPollWithSignalHandling_ImmediateSuccess(t *testing.T) { } func TestPollWithSignalHandling_SignalInterruption(t *testing.T) { + t.Parallel() // Note: This test is challenging because PollWithSignalHandling creates its own // signal handler. We verify the behavior indirectly by checking that the function // structure supports signal handling (which is covered by the other tests). @@ -109,6 +114,7 @@ func TestPollWithSignalHandling_SignalInterruption(t *testing.T) { // TestPollWithSignalHandling_ContextCancellation verifies that PollWithSignalHandling // returns ErrInterrupted when the context is cancelled, enabling proper Ctrl-C propagation. func TestPollWithSignalHandling_ContextCancellation(t *testing.T) { + t.Parallel() ctx, cancel := context.WithCancel(context.Background()) pollStarted := make(chan struct{}) @@ -143,6 +149,7 @@ func TestPollWithSignalHandling_ContextCancellation(t *testing.T) { // TestPollWithSignalHandling_AlreadyCancelledContext verifies that PollWithSignalHandling // returns ErrInterrupted immediately when given an already-cancelled context. func TestPollWithSignalHandling_AlreadyCancelledContext(t *testing.T) { + t.Parallel() ctx, cancel := context.WithCancel(context.Background()) cancel() // cancel before starting diff --git a/pkg/cli/smoke_copilot_aoai_workflow_contract_test.go b/pkg/cli/smoke_copilot_aoai_workflow_contract_test.go index fc36960f5d5..eb072aad3d0 100644 --- a/pkg/cli/smoke_copilot_aoai_workflow_contract_test.go +++ b/pkg/cli/smoke_copilot_aoai_workflow_contract_test.go @@ -17,6 +17,7 @@ import ( // haiku-printer without the required `message` input, hard-failing the // safe_outputs job after an otherwise successful (and expensive) run. func TestSmokeCopilotAOAIWorkflowDispatchContract(t *testing.T) { + t.Parallel() repoRoot, err := gitutil.FindGitRoot() if err != nil { t.Skipf("Skipping test: not in a git repository: %v", err) diff --git a/pkg/cli/spec_github_url_test.go b/pkg/cli/spec_github_url_test.go index 5873eddfcfc..c6798c7c57b 100644 --- a/pkg/cli/spec_github_url_test.go +++ b/pkg/cli/spec_github_url_test.go @@ -8,6 +8,7 @@ import ( // TestParseGitHubURL tests the parseGitHubURL function directly func TestParseGitHubURL(t *testing.T) { + t.Parallel() tests := []struct { name string url string diff --git a/pkg/cli/spec_manifest_source_test.go b/pkg/cli/spec_manifest_source_test.go index 3043c07e161..5ea0a31f4ee 100644 --- a/pkg/cli/spec_manifest_source_test.go +++ b/pkg/cli/spec_manifest_source_test.go @@ -5,6 +5,7 @@ package cli import "testing" func TestBuildSourceStringWithCommitSHA_ManifestSource(t *testing.T) { + t.Parallel() workflow := &WorkflowSpec{ RepoSpec: RepoSpec{ RepoSlug: "owner/repo", @@ -23,6 +24,7 @@ func TestBuildSourceStringWithCommitSHA_ManifestSource(t *testing.T) { } func TestBuildSourceStringWithCommitSHA_ManifestSourceRoot(t *testing.T) { + t.Parallel() workflow := &WorkflowSpec{ RepoSpec: RepoSpec{ RepoSlug: "owner/repo", @@ -40,6 +42,7 @@ func TestBuildSourceStringWithCommitSHA_ManifestSourceRoot(t *testing.T) { } func TestParseManifestSourceSpec(t *testing.T) { + t.Parallel() tests := []struct { source string wantManifest bool diff --git a/pkg/cli/spec_test.go b/pkg/cli/spec_test.go index b53bdda5438..a54b81b8977 100644 --- a/pkg/cli/spec_test.go +++ b/pkg/cli/spec_test.go @@ -15,6 +15,7 @@ import ( // TestSpec_PublicAPI_ValidateWorkflowName validates the documented behavior. // Spec: empty names and names with invalid characters return errors. func TestSpec_PublicAPI_ValidateWorkflowName(t *testing.T) { + t.Parallel() tests := []struct { name string input string @@ -42,6 +43,7 @@ func TestSpec_PublicAPI_ValidateWorkflowName(t *testing.T) { // TestSpec_PublicAPI_IsCommitSHA validates that IsCommitSHA returns true only for 40-char hex strings. // Spec: "Returns true if the string is a full Git commit SHA" func TestSpec_PublicAPI_IsCommitSHA(t *testing.T) { + t.Parallel() tests := []struct { name string version string @@ -69,6 +71,7 @@ func TestSpec_PublicAPI_IsCommitSHA(t *testing.T) { // TestSpec_PublicAPI_GetVersion validates that GetVersion returns a non-empty string. // Spec: "Returns the current CLI version" func TestSpec_PublicAPI_GetVersion(t *testing.T) { + t.Parallel() version := cli.GetVersion() assert.NotEmpty(t, version, "GetVersion should return a non-empty version string") } @@ -86,6 +89,7 @@ func TestSpec_PublicAPI_SetVersionInfo(t *testing.T) { // TestSpec_PublicAPI_IsRunningInCI validates that IsRunningInCI returns a bool without panicking. // Spec: "Detects CI environment" func TestSpec_PublicAPI_IsRunningInCI(t *testing.T) { + t.Parallel() result := cli.IsRunningInCI() _ = result // result is environment-dependent; ensure no panic } @@ -93,6 +97,7 @@ func TestSpec_PublicAPI_IsRunningInCI(t *testing.T) { // TestSpec_Types_ShellType validates the documented ShellType string alias and its constants. // Spec: ShellType string alias with values "bash", "zsh", "fish", "powershell", "unknown" func TestSpec_Types_ShellType(t *testing.T) { + t.Parallel() assert.Equal(t, cli.ShellBash, cli.ShellType("bash"), "ShellBash constant should be \"bash\"") assert.Equal(t, cli.ShellZsh, cli.ShellType("zsh"), "ShellZsh constant should be \"zsh\"") assert.Equal(t, cli.ShellFish, cli.ShellType("fish"), "ShellFish constant should be \"fish\"") @@ -103,6 +108,7 @@ func TestSpec_Types_ShellType(t *testing.T) { // TestSpec_PublicAPI_DetectShell validates DetectShell returns one of the documented ShellType values. // Spec: "Detects the user's current shell" func TestSpec_PublicAPI_DetectShell(t *testing.T) { + t.Parallel() shell := cli.DetectShell() validShells := []cli.ShellType{cli.ShellBash, cli.ShellZsh, cli.ShellFish, cli.ShellPowerShell, cli.ShellUnknown} assert.Contains(t, validShells, shell, "DetectShell should return one of the documented ShellType values") @@ -111,6 +117,7 @@ func TestSpec_PublicAPI_DetectShell(t *testing.T) { // TestSpec_PublicAPI_ValidEngineNames validates the documented function returns a non-empty list. // Spec: "Returns the supported engine names for shell completion" func TestSpec_PublicAPI_ValidEngineNames(t *testing.T) { + t.Parallel() engines := cli.ValidEngineNames() assert.NotEmpty(t, engines, "ValidEngineNames should return at least one engine name") for _, name := range engines { @@ -121,6 +128,7 @@ func TestSpec_PublicAPI_ValidEngineNames(t *testing.T) { // TestSpec_PublicAPI_ValidArtifactSetNames validates the documented function returns known artifact sets. // Spec: "Returns the valid artifact set name strings" func TestSpec_PublicAPI_ValidArtifactSetNames(t *testing.T) { + t.Parallel() names := cli.ValidArtifactSetNames() assert.NotEmpty(t, names, "ValidArtifactSetNames should return a non-empty list") assert.Contains(t, names, "all", "ValidArtifactSetNames should include \"all\"") @@ -129,6 +137,7 @@ func TestSpec_PublicAPI_ValidArtifactSetNames(t *testing.T) { // TestSpec_PublicAPI_ValidateArtifactSets validates known and unknown artifact sets. // Spec: "Validates that all provided artifact set names are known" func TestSpec_PublicAPI_ValidateArtifactSets(t *testing.T) { + t.Parallel() t.Run("known artifact set returns no error", func(t *testing.T) { err := cli.ValidateArtifactSets([]string{"all"}) require.NoError(t, err, "ValidateArtifactSets should not error for known set \"all\"") @@ -148,6 +157,7 @@ func TestSpec_PublicAPI_ValidateArtifactSets(t *testing.T) { // TestSpec_PublicAPI_ExtractWorkflowDescription validates extraction of the description field. // Spec: "Extracts the description field from workflow markdown content" func TestSpec_PublicAPI_ExtractWorkflowDescription(t *testing.T) { + t.Parallel() tests := []struct { name string content string @@ -181,6 +191,7 @@ func TestSpec_PublicAPI_ExtractWorkflowDescription(t *testing.T) { // TestSpec_PublicAPI_ExtractWorkflowEngine validates extraction of the engine field. // Spec: "Extracts the engine field from workflow markdown content" func TestSpec_PublicAPI_ExtractWorkflowEngine(t *testing.T) { + t.Parallel() tests := []struct { name string content string @@ -209,6 +220,7 @@ func TestSpec_PublicAPI_ExtractWorkflowEngine(t *testing.T) { // TestSpec_PublicAPI_ExtractWorkflowPrivate validates extraction of the private flag. // Spec: "Returns true if the workflow is marked private" func TestSpec_PublicAPI_ExtractWorkflowPrivate(t *testing.T) { + t.Parallel() tests := []struct { name string content string diff --git a/pkg/cli/staged_filtering_test.go b/pkg/cli/staged_filtering_test.go index b328794dea3..1d9577ac7be 100644 --- a/pkg/cli/staged_filtering_test.go +++ b/pkg/cli/staged_filtering_test.go @@ -12,6 +12,7 @@ import ( ) func TestParseAwInfo(t *testing.T) { + t.Parallel() // Create a temporary directory for test files tmpDir := testutil.TempDir(t, "test-*") diff --git a/pkg/cli/stats_helpers_test.go b/pkg/cli/stats_helpers_test.go index d2be5926fbd..09ed9236764 100644 --- a/pkg/cli/stats_helpers_test.go +++ b/pkg/cli/stats_helpers_test.go @@ -9,6 +9,7 @@ import ( ) func TestSafePercent(t *testing.T) { + t.Parallel() assert.InDelta(t, 0.0, safePercent(1, 0), 1e-12, "zero total") assert.InDelta(t, 0.0, safePercent(0, 4), 1e-12, "zero part") assert.InDelta(t, 25.0, safePercent(1, 4), 1e-12, "percentage") diff --git a/pkg/cli/status_command_test.go b/pkg/cli/status_command_test.go index bfeff9be7a9..cf375ec67f1 100644 --- a/pkg/cli/status_command_test.go +++ b/pkg/cli/status_command_test.go @@ -50,6 +50,7 @@ func TestStatusWorkflows_JSONOutput(t *testing.T) { } func TestWorkflowStatus_JSONMarshaling(t *testing.T) { + t.Parallel() // Test that WorkflowStatus can be marshaled to JSON status := WorkflowStatus{ WorkflowListItem: WorkflowListItem{ @@ -297,6 +298,7 @@ func TestStatusCommand_JSONOutputIncludesOnField(t *testing.T) { // TestWorkflowStatus_ConsoleRendering tests that WorkflowStatus uses console.RenderStruct correctly func TestWorkflowStatus_ConsoleRendering(t *testing.T) { + t.Parallel() // Create test data statuses := []WorkflowStatus{ { @@ -357,6 +359,7 @@ func TestWorkflowStatus_ConsoleRendering(t *testing.T) { // TestWorkflowStatus_JSONMarshalingWithRunStatus tests that RunStatus and RunConclusion are included in JSON output func TestWorkflowStatus_JSONMarshalingWithRunStatus(t *testing.T) { + t.Parallel() // Test that WorkflowStatus with run status can be marshaled to JSON status := WorkflowStatus{ WorkflowListItem: WorkflowListItem{ @@ -391,6 +394,7 @@ func TestWorkflowStatus_JSONMarshalingWithRunStatus(t *testing.T) { // TestWorkflowStatus_JSONMarshalingWithEmptyRunStatus tests that empty RunStatus and RunConclusion are omitted func TestWorkflowStatus_JSONMarshalingWithEmptyRunStatus(t *testing.T) { + t.Parallel() // Test that WorkflowStatus without run status omits those fields status := WorkflowStatus{ WorkflowListItem: WorkflowListItem{ @@ -424,6 +428,7 @@ func TestWorkflowStatus_JSONMarshalingWithEmptyRunStatus(t *testing.T) { // TestWorkflowStatus_JSONMarshalingWithLabels tests that labels are included in JSON output func TestWorkflowStatus_JSONMarshalingWithLabels(t *testing.T) { + t.Parallel() // Test that WorkflowStatus with labels can be marshaled to JSON status := WorkflowStatus{ WorkflowListItem: WorkflowListItem{ @@ -466,6 +471,7 @@ func TestWorkflowStatus_JSONMarshalingWithLabels(t *testing.T) { // TestWorkflowStatus_JSONMarshalingWithEmptyLabels tests that empty labels are omitted func TestWorkflowStatus_JSONMarshalingWithEmptyLabels(t *testing.T) { + t.Parallel() // Test that WorkflowStatus without labels omits the field status := WorkflowStatus{ WorkflowListItem: WorkflowListItem{ @@ -496,6 +502,7 @@ func TestWorkflowStatus_JSONMarshalingWithEmptyLabels(t *testing.T) { // TestWorkflowStatus_ConsoleRenderingWithRunStatus tests that RunStatus and RunConclusion are rendered when present func TestWorkflowStatus_ConsoleRenderingWithRunStatus(t *testing.T) { + t.Parallel() // Create test data with run status statuses := []WorkflowStatus{ { diff --git a/pkg/cli/status_compiled_test.go b/pkg/cli/status_compiled_test.go index 3f3d3868658..bda0f294a3d 100644 --- a/pkg/cli/status_compiled_test.go +++ b/pkg/cli/status_compiled_test.go @@ -13,6 +13,7 @@ import ( ) func TestIsCompiledUpToDate(t *testing.T) { + t.Parallel() tmpDir := t.TempDir() // Minimal valid workflow markdown diff --git a/pkg/cli/status_dependency_tree_test.go b/pkg/cli/status_dependency_tree_test.go index dfc35e1495d..15b3175c092 100644 --- a/pkg/cli/status_dependency_tree_test.go +++ b/pkg/cli/status_dependency_tree_test.go @@ -9,6 +9,7 @@ import ( ) func TestExtractWorkflowDependencies(t *testing.T) { + t.Parallel() frontmatter := map[string]any{ "imports": []any{ "shared/base.md#section", @@ -34,6 +35,7 @@ func TestExtractWorkflowDependencies(t *testing.T) { } func TestExtractWorkflowDependencies_ImportsObjectAW(t *testing.T) { + t.Parallel() frontmatter := map[string]any{ "imports": map[string]any{ "aw": []any{ @@ -50,6 +52,7 @@ func TestExtractWorkflowDependencies_ImportsObjectAW(t *testing.T) { } func TestRenderWorkflowDependencyTree(t *testing.T) { + t.Parallel() statuses := []WorkflowStatus{ { WorkflowListItem: WorkflowListItem{Workflow: "main-workflow"}, @@ -65,6 +68,7 @@ func TestRenderWorkflowDependencyTree(t *testing.T) { } func TestRenderWorkflowDependencyTree_Empty(t *testing.T) { + t.Parallel() statuses := []WorkflowStatus{{WorkflowListItem: WorkflowListItem{Workflow: "standalone"}}} assert.Empty(t, renderWorkflowDependencyTree(statuses), "dependency tree should be empty when no dependencies exist") }