Skip to content

test(testcontainers): hoist container boot off the test timer - #4686

Merged
nicktrn merged 3 commits into
ci/prepull-list-driftfrom
test/hoist-container-boot-off-test-timer
Aug 19, 2026
Merged

test(testcontainers): hoist container boot off the test timer#4686
nicktrn merged 3 commits into
ci/prepull-list-driftfrom
test/hoist-container-boot-off-test-timer

Conversation

@nicktrn

@nicktrn nicktrn commented Aug 18, 2026

Copy link
Copy Markdown
Collaborator

What

The one-off worker container boot is billed to whichever test resolves the fixture first. This moves it into a beforeAll with its own timeout.

Why

vitest runs the fixture chain inside the test timer:

// @vitest/runner 4.1.7
setFn(task, withTimeout(...withFixtures(handler)..., timeout, ...))

There is no fixtureTimeout. So booting Postgres (plus CREATE DATABASE, schema push, ClickHouse and Redis) lands on the first test and consumes a budget sized for test work.

That is why losing the image pre-pull on fork PRs was fatal rather than merely slower: the extra ~10s crossed the 60s cap. Since fork time is roughly internal + 10s and forks exceed 60s, internal runs were already clearing that cap by under 10s — a latent flake regardless of forks.

How

withWarmup wraps each fixture family and lazily registers a beforeAll on first touch, with its own generous timeout. Registration is lazy so only files that actually use a family pay for it — @internal/testcontainers is imported by hundreds of test files, many of which only need Redis. It registers once per file, since isolate gives each file a fresh module registry.

Eight families are wrapped. isolatedRedisTest, replicationContainerTest and postgresAndRedisTest are deliberately untouched: they use per-test containers by design, so there is no one-off boot to hoist.

No test file or CI changes, and it applies to every package using these fixtures.

Verification

Proven by mutation. src/warmup.test.ts runs container tests under a deliberately tight cap:

Result
with the warm-up passes
warm-up neutered fails, Test timed out

It is kept as a regression test — without it, unwrapping a fixture would break nothing visibly.

triggerFailedTask.call.test.ts, one of the five shard casualties, passes locally in 20.4s.

Also here

@internal/testcontainers had no test script, so turbo run test --filter "@internal/*" skipped the package and its existing heteroDedicated.test.ts never ran in CI. Adding the script (matching the sibling packages') runs both files; verified green through turbo exactly as CI invokes it.

@changeset-bot

changeset-bot Bot commented Aug 18, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: cca8aea

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai

coderabbitai Bot commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e6116a22-769d-4de8-8ec5-358c180d9d67

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

The testcontainers package now uses withWarmup to lazily register guarded beforeAll hooks for worker-scoped PostgreSQL, Redis, ClickHouse, MinIO, and combined fixtures. Existing per-test isolation and reset behavior remains configured. The package test command disables file-level parallelism. A warmup test suite verifies Prisma queries in the first and subsequent tests.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely identifies the main change: moving container boot outside the test timer.
Description check ✅ Passed The description clearly covers the change, rationale, implementation, and verification, although it does not use every template heading.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch test/hoist-container-boot-off-test-timer

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@nicktrn nicktrn self-assigned this Aug 18, 2026
Vitest bills fixture setup to the first test's testTimeout - the fixture
chain runs inside the test timer - so the one-off worker container boot
landed on whichever test resolved it first and consumed a budget sized
for test work.

On fork PRs, which get no secrets and so skip the CI image pre-pull, that
added ~10s and pushed five webapp shards past their 60s cap. Internal
runs cleared it by under 10s, so it was a latent flake there too.

Registering the boot as a beforeAll with its own timeout moves it off the
test clock. Registration is lazy, so only files that actually touch a
fixture family pay for it, and happens once per file since isolate gives
each file a fresh module registry.
@nicktrn
nicktrn force-pushed the test/hoist-container-boot-off-test-timer branch from 000782b to 8aa5670 Compare August 18, 2026 23:14
@nicktrn

nicktrn commented Aug 18, 2026

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 18, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@nicktrn

nicktrn commented Aug 18, 2026

Copy link
Copy Markdown
Collaborator Author

/devin review

@devin-ai-integration

Copy link
Copy Markdown
Contributor

Starting Devin Review.

Open in Devin Review

coderabbitai[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 2 new potential issues.

Open in Devin Review

Comment thread internal-packages/testcontainers/src/index.ts
Comment thread internal-packages/testcontainers/src/index.ts
@nicktrn
nicktrn merged commit b939045 into main Aug 19, 2026
53 checks passed
@nicktrn
nicktrn deleted the test/hoist-container-boot-off-test-timer branch August 19, 2026 07:40
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.

2 participants