From fe56e2fe0157e08278819bb6455c0528fd9b94a2 Mon Sep 17 00:00:00 2001 From: Mathias Date: Thu, 11 Jun 2026 07:26:33 +0200 Subject: [PATCH] test: make embedded-postgres per-process so concurrent CI runs don't collide MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A push to main and its version tag fire two CI runs for the same commit. Both ran `go test ./...`, which starts embedded-postgres on a FIXED port (54329/54330) and a shared data dir. -p 1 serialises packages WITHIN a run, not across two concurrent runs — so when the two runs overlapped they collided on the port/data dir and BOTH failed the Lint/Test job (no image built). Prior commits passed only because their two runs happened not to overlap. Derive the port and runtime/data dirs from the PID; share only CachePath so the PG archive downloads once. Proven: two concurrent `go test` of the store package now both pass. Unblocks the v0.21.0 (Pillar A) build. Co-Authored-By: Claude Opus 4.8 (1M context) --- internal/adapters/store/store_test.go | 17 +++++++++++++++-- internal/web/handlers_test.go | 18 ++++++++++++++++-- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/internal/adapters/store/store_test.go b/internal/adapters/store/store_test.go index 06c6ff8..9a8f774 100644 --- a/internal/adapters/store/store_test.go +++ b/internal/adapters/store/store_test.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "os" + "path/filepath" "testing" embeddedpostgres "github.com/fergusstrange/embedded-postgres" @@ -24,11 +25,22 @@ var _ ports.Sink = (*store.Store)(nil) var dsn string func TestMain(m *testing.M) { - const port = 54329 + // Port + runtime/data dirs are per-process (PID-derived) so two concurrent + // `go test` invocations — e.g. a push-run and a tag-run firing together in CI — + // don't collide on a fixed port or a shared data dir (which silently failed + // both runs). CachePath is shared so the PG archive is downloaded once, not + // per process. Base 54000 keeps this package's range distinct from web's. + port := uint32(54000 + os.Getpid()%1000) dsn = fmt.Sprintf("postgres://postgres:postgres@localhost:%d/postgres?sslmode=disable", port) + rt := filepath.Join(os.TempDir(), fmt.Sprintf("tapir-epg-store-%d", os.Getpid())) pg := embeddedpostgres.NewDatabase( - embeddedpostgres.DefaultConfig().Port(port), + embeddedpostgres.DefaultConfig(). + Port(port). + RuntimePath(rt). + DataPath(filepath.Join(rt, "data")). + BinariesPath(filepath.Join(rt, "bin")). + CachePath(filepath.Join(os.TempDir(), "tapir-epg-cache")), ) if err := pg.Start(); err != nil { fmt.Fprintf(os.Stderr, "embedded-postgres start: %v\n", err) @@ -40,6 +52,7 @@ func TestMain(m *testing.M) { if err := pg.Stop(); err != nil { fmt.Fprintf(os.Stderr, "embedded-postgres stop: %v\n", err) } + _ = os.RemoveAll(rt) os.Exit(code) } diff --git a/internal/web/handlers_test.go b/internal/web/handlers_test.go index d1c6ecb..d36c183 100644 --- a/internal/web/handlers_test.go +++ b/internal/web/handlers_test.go @@ -7,6 +7,7 @@ import ( "net/http" "net/http/httptest" "os" + "path/filepath" "strings" "testing" "time" @@ -26,10 +27,22 @@ import ( var dsn string func TestMain(m *testing.M) { - const port = 54330 // distinct from the store package's embedded PG (54329) + // Per-process port + dirs so concurrent `go test` runs (e.g. a push-run and a + // tag-run in CI) never collide on a fixed port or shared data dir. Base 55000 + // keeps web's range distinct from the store package (54000). Shared CachePath + // downloads the PG archive once. + port := uint32(55000 + os.Getpid()%1000) dsn = fmt.Sprintf("postgres://postgres:postgres@localhost:%d/postgres?sslmode=disable", port) - pg := embeddedpostgres.NewDatabase(embeddedpostgres.DefaultConfig().Port(port)) + rt := filepath.Join(os.TempDir(), fmt.Sprintf("tapir-epg-web-%d", os.Getpid())) + pg := embeddedpostgres.NewDatabase( + embeddedpostgres.DefaultConfig(). + Port(port). + RuntimePath(rt). + DataPath(filepath.Join(rt, "data")). + BinariesPath(filepath.Join(rt, "bin")). + CachePath(filepath.Join(os.TempDir(), "tapir-epg-cache")), + ) if err := pg.Start(); err != nil { fmt.Fprintf(os.Stderr, "embedded-postgres start: %v\n", err) os.Exit(1) @@ -38,6 +51,7 @@ func TestMain(m *testing.M) { if err := pg.Stop(); err != nil { fmt.Fprintf(os.Stderr, "embedded-postgres stop: %v\n", err) } + _ = os.RemoveAll(rt) os.Exit(code) }