Skip to content

test(e2e): build stack binaries once per run via TestMain (RIG-2738) - #668

Open
rigel-mintaka wants to merge 1 commit into
mainfrom
compass/rig-2738-testmain-build-once
Open

test(e2e): build stack binaries once per run via TestMain (RIG-2738)#668
rigel-mintaka wants to merge 1 commit into
mainfrom
compass/rig-2738-testmain-build-once

Conversation

@rigel-mintaka

@rigel-mintaka rigel-mintaka commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

What

Build the three stack child binaries (compass-postgres, compass-server, compass-runner) once per e2e run via a package TestMain, instead of rebuilding them on every NewFixture.

RIG-2738 mechanical lever L1.

Why

The dogfood-e2e suite stands up ~11 fixtures per run (10 podman-tagged tests, TestLegSixTeardownIdempotence calls NewFixture twice). Each NewFixture ran buildBinariesFromModuleRoot, which invoked go build three times into a throwaway t.TempDir33 go build invocations into 11 dirs per run, all producing identical binaries.

The binaries never differ across fixtures in a run, so one build serves the whole suite. TestMain compiles them once into a single dir and exports it on PATH for the run; NewFixture no longer builds anything.

How

  • New go/e2e/main_test.go (//go:build podman) with TestMain: builds once (guarded by podmanUsable() so a container-less sandbox still skips-and-exits without building), sets PATH process-wide, runs, cleans up the shared bin dir after.
  • buildBinariesFromModuleRoot(t) → t-free buildStackBinaries() (string, error), moved into main_test.go; the per-fixture build + t.Setenv("PATH", ...) dropped from NewFixture.

Behaviour-preserving. The ProcessSupervisor still resolves each child by bare name via exec.LookPath against the same PATH entry — only the build count changes (33 → 3 per run). The suite is serial (no t.Parallel, go test default), so one shared bin dir has no cross-test coupling beyond the PATH every fixture already set identically.

Why TestMain is //go:build podman

TestMain governs the whole package's test lifecycle, and go/e2e carries a deliberately untagged hermetic lane (cannedmodel_test.go) that runs under a plain go test with no container and no stack. Tagging TestMain podman keeps it out of that build, so the hermetic lane keeps Go's default TestMain and never triggers a stack-binary build. Verified: go vet ./e2e/ (untagged) and go vet -tags podman ./e2e/ both clean.

Scope

L1 only. The dominant levers — a shared long-lived stack across legs (kills ~11 cold container boots) and a shared external postgres (kills ~11 initdbs) — are the RIG-2742 harness-consolidation design, not this PR (see the profiling on RIG-2738 comment-877222b7 and the grounding on RIG-2742 comment-0586f7af). Keeping the topology change in one place.

Test

Ran the full podman suite locally (CGO_ENABLED=1 go test -tags podman -race -v -timeout 20m ./e2e/...): 9 of 11 podman legs PASS off the once-built TestMain binaries — confirming the build-once mechanism serves every fixture correctly. Two legs (TestLegFivePersistAndResume, TestLegSixTeardownIdempotence) failed on RemoveAgentWorkspace RPC: context deadline exceeded — a container-teardown timeout, a path this change does not touch (the documented cold-rootless-podman contention class), because this dev box was running the whole agent wave against one shared podman engine under -race.

Verified that's environmental, not this change: both legs PASS in isolation on unmodified main (ok, exit 0 — LegFive 90.7s / LegSix 78.9s) AND PASS in isolation on this branch (ok, exit 0 — LegFive 56.3s / LegSix 60.5s). Same binaries, no teardown timeout when the podman engine isn't contended. CI runs dogfood-e2e in a dedicated privileged container with no competing wave, matching the isolated (green) case.

RIG-2738

The e2e fixture rebuilt the three stack child binaries (compass-postgres,
compass-server, compass-runner) on every NewFixture call — 11 stand-ups per
suite run, so 33 go-build invocations into 11 throwaway temp dirs. The binaries
are identical across every fixture in a run, so hoist the build into a package
TestMain that compiles them once into one shared dir and exports it on PATH for
the whole run. NewFixture now just prepends that shared dir.

Behaviour-preserving: the ProcessSupervisor still resolves each child by bare
name via exec.LookPath against the same PATH entry; only the build count
changes (33 -> 3 per run). Serial suite, one shared dir, no cross-test coupling
beyond the already-shared PATH the fixtures all set identically.

RIG-2738 mechanical lever L1. Shared-stack + shared-external-PG levers (L2/L3)
are the RIG-2742 harness-consolidation design, not this PR.

Co-authored-by: Matt Wilkinson <matt@rigel.build>
@linear-code

linear-code Bot commented Aug 27, 2026

Copy link
Copy Markdown

RIG-2738

@github-actions

Copy link
Copy Markdown

Compass engineering docs preview: https://compass-rig-2738-testmain-bu.compass-eng-docs.pages.dev

Deployed from compass/rig-2738-testmain-build-once at 898f484.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant