From 6267f3b7f5f6e65c2f2dc1374c3d69547e8dc7b6 Mon Sep 17 00:00:00 2001 From: Steve Yegge Date: Wed, 3 Dec 2025 18:30:53 -0800 Subject: [PATCH] fix: add test parallelism and increase Windows CI timeout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Increase Windows test timeout from 20m to 30m - Add -parallel=4 flag to allow concurrent test execution - Add t.Parallel() to safe table-driven tests in validate_test.go, autoimport_test.go, and sync_test.go This should prevent the Windows CI timeout caused by the cumulative runtime of cmd/bd tests exceeding 20 minutes. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .github/workflows/ci.yml | 2 +- cmd/bd/autoimport_test.go | 3 +++ cmd/bd/sync_test.go | 13 +++++++++++++ cmd/bd/validate_test.go | 7 +++++++ 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dd1fc756..22a7eea9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -71,7 +71,7 @@ jobs: run: go build -v ./cmd/bd - name: Test - run: go test -v -short -timeout=20m ./... + run: go test -v -short -timeout=30m -parallel=4 ./... lint: name: Lint diff --git a/cmd/bd/autoimport_test.go b/cmd/bd/autoimport_test.go index b1fb9de4..c30a4f0c 100644 --- a/cmd/bd/autoimport_test.go +++ b/cmd/bd/autoimport_test.go @@ -283,6 +283,7 @@ func TestCheckGitForIssues_NoBeadsDir(t *testing.T) { } func TestBoolToFlag(t *testing.T) { + t.Parallel() tests := []struct { name string condition bool @@ -296,7 +297,9 @@ func TestBoolToFlag(t *testing.T) { } for _, tt := range tests { + tt := tt // capture range variable t.Run(tt.name, func(t *testing.T) { + t.Parallel() got := boolToFlag(tt.condition, tt.flag) if got != tt.want { t.Errorf("boolToFlag(%v, %q) = %q, want %q", tt.condition, tt.flag, got, tt.want) diff --git a/cmd/bd/sync_test.go b/cmd/bd/sync_test.go index 6a95efd9..5285b7db 100644 --- a/cmd/bd/sync_test.go +++ b/cmd/bd/sync_test.go @@ -141,6 +141,7 @@ func TestGitCommit_AutoMessage(t *testing.T) { } func TestCountIssuesInJSONL_NonExistent(t *testing.T) { + t.Parallel() count, err := countIssuesInJSONL("/nonexistent/path.jsonl") if err == nil { t.Error("expected error for nonexistent file") @@ -151,6 +152,7 @@ func TestCountIssuesInJSONL_NonExistent(t *testing.T) { } func TestCountIssuesInJSONL_EmptyFile(t *testing.T) { + t.Parallel() tmpDir := t.TempDir() jsonlPath := filepath.Join(tmpDir, "empty.jsonl") os.WriteFile(jsonlPath, []byte(""), 0644) @@ -165,6 +167,7 @@ func TestCountIssuesInJSONL_EmptyFile(t *testing.T) { } func TestCountIssuesInJSONL_MultipleIssues(t *testing.T) { + t.Parallel() tmpDir := t.TempDir() jsonlPath := filepath.Join(tmpDir, "issues.jsonl") content := `{"id":"bd-1"} @@ -183,6 +186,7 @@ func TestCountIssuesInJSONL_MultipleIssues(t *testing.T) { } func TestCountIssuesInJSONL_WithMalformedLines(t *testing.T) { + t.Parallel() tmpDir := t.TempDir() jsonlPath := filepath.Join(tmpDir, "mixed.jsonl") content := `{"id":"bd-1"} @@ -797,6 +801,7 @@ func TestMaybeAutoCompactDeletions_BelowThreshold(t *testing.T) { } func TestSanitizeJSONLWithDeletions_NoDeletions(t *testing.T) { + t.Parallel() tmpDir := t.TempDir() beadsDir := filepath.Join(tmpDir, ".beads") os.MkdirAll(beadsDir, 0755) @@ -825,6 +830,7 @@ func TestSanitizeJSONLWithDeletions_NoDeletions(t *testing.T) { } func TestSanitizeJSONLWithDeletions_EmptyDeletions(t *testing.T) { + t.Parallel() tmpDir := t.TempDir() beadsDir := filepath.Join(tmpDir, ".beads") os.MkdirAll(beadsDir, 0755) @@ -848,6 +854,7 @@ func TestSanitizeJSONLWithDeletions_EmptyDeletions(t *testing.T) { } func TestSanitizeJSONLWithDeletions_RemovesDeletedIssues(t *testing.T) { + t.Parallel() tmpDir := t.TempDir() beadsDir := filepath.Join(tmpDir, ".beads") os.MkdirAll(beadsDir, 0755) @@ -911,6 +918,7 @@ func TestSanitizeJSONLWithDeletions_RemovesDeletedIssues(t *testing.T) { } func TestSanitizeJSONLWithDeletions_NoMatchingDeletions(t *testing.T) { + t.Parallel() tmpDir := t.TempDir() beadsDir := filepath.Join(tmpDir, ".beads") os.MkdirAll(beadsDir, 0755) @@ -947,6 +955,7 @@ func TestSanitizeJSONLWithDeletions_NoMatchingDeletions(t *testing.T) { } func TestSanitizeJSONLWithDeletions_PreservesMalformedLines(t *testing.T) { + t.Parallel() tmpDir := t.TempDir() beadsDir := filepath.Join(tmpDir, ".beads") os.MkdirAll(beadsDir, 0755) @@ -987,6 +996,7 @@ this is not valid json } func TestSanitizeJSONLWithDeletions_NonexistentJSONL(t *testing.T) { + t.Parallel() tmpDir := t.TempDir() beadsDir := filepath.Join(tmpDir, ".beads") os.MkdirAll(beadsDir, 0755) @@ -1110,6 +1120,7 @@ func TestHashBasedStalenessDetection_bd_f2f(t *testing.T) { // to prevent creating incorrect deletion records for locally-created beads. // See: https://github.com/steveyegge/beads/issues/417 func TestResolveNoGitHistoryForFromMain(t *testing.T) { + t.Parallel() tests := []struct { name string fromMain bool @@ -1143,7 +1154,9 @@ func TestResolveNoGitHistoryForFromMain(t *testing.T) { } for _, tt := range tests { + tt := tt // capture range variable t.Run(tt.name, func(t *testing.T) { + t.Parallel() got := resolveNoGitHistoryForFromMain(tt.fromMain, tt.noGitHistory) if got != tt.want { t.Errorf("resolveNoGitHistoryForFromMain(%v, %v) = %v, want %v", diff --git a/cmd/bd/validate_test.go b/cmd/bd/validate_test.go index e041e765..8e53ac46 100644 --- a/cmd/bd/validate_test.go +++ b/cmd/bd/validate_test.go @@ -9,6 +9,7 @@ import ( ) func TestParseChecks(t *testing.T) { + t.Parallel() tests := []struct { name string input string @@ -63,7 +64,9 @@ func TestParseChecks(t *testing.T) { } for _, tt := range tests { + tt := tt // capture range variable t.Run(tt.name, func(t *testing.T) { + t.Parallel() got, err := parseChecks(tt.input) if tt.wantError { if err == nil { @@ -88,6 +91,7 @@ func TestParseChecks(t *testing.T) { } func TestValidationResultsHasFailures(t *testing.T) { + t.Parallel() tests := []struct { name string checks map[string]checkResult @@ -125,7 +129,9 @@ func TestValidationResultsHasFailures(t *testing.T) { } for _, tt := range tests { + tt := tt // capture range variable t.Run(tt.name, func(t *testing.T) { + t.Parallel() r := &validationResults{checks: tt.checks} got := r.hasFailures() if got != tt.want { @@ -136,6 +142,7 @@ func TestValidationResultsHasFailures(t *testing.T) { } func TestValidationResultsToJSON(t *testing.T) { + t.Parallel() r := &validationResults{ checks: map[string]checkResult{ "orphans": {