Skip to content

test(repo): fix e2e port races and name storage crash-test stalls - #7504

Merged
jgoux merged 6 commits into
developfrom
avallete/flaky-fixes-2026-11-05
Nov 5, 2026
Merged

jgoux merged 6 commits into
developfrom
avallete/flaky-fixes-2026-11-05

Conversation

@avallete

@avallete avallete commented Nov 5, 2026 •

Copy link
Copy Markdown
Member

TL;DR

Fixes an e2e port race and adds named per-phase deadlines to a test whose stall cause is still unknown. The sso list flake originally in this PR is already fixed on develop by #7502.

  • status e2e › reports a running local stack… failed with Kong's host port address already in use. The e2e helper picked ports by binding port 0 and releasing it, so they came from the kernel's ephemeral range, where an outbound connection on the runner could take one before Docker published it. Ports now come from 1024–9999, below both the stack's own allocation ranges (10000 and up, see packages/stack/src/Ports.ts) and the OS ephemeral ranges, so neither a concurrent stack-mode e2e nor an outbound connection can claim a probed port. Each port is probed on 0.0.0.0, as Docker binds it, and on 127.0.0.1, because macOS lets a wildcard bind succeed over a loopback-only listener. Ports stay partitioned per e2e worker.
  • DockerDatabaseStorage › keeps the prior marker decodable when a real kill lands… hit the 20s test timeout and the failure didn't say which step hung. Each remaining phase (helper image, prepare, PG_VERSION seed, killed writer exit and pipe close, markInitialized retry, both cleanups) now fails with a PhaseStallError naming the phase, well before the test timeout. This is diagnostic-only; the next failure will name the phase to fix.

ref

spotted in:

…e clock

The stalled-list test advanced the TestClock in fixed steps right after forking
the command. When the command's setup took longer than those steps, the request
timeout was scheduled after the clock had already moved, and the test hung until
the real test timeout. The mock now signals each stalled attempt and the test
advances the clock only after that attempt is in flight.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MBEk1JxfLqmcaNWvN6MRyG
The e2e helper picked stack ports by binding port 0 and releasing it. Those
ports come from the kernel's ephemeral range, so an outbound connection on the
runner could take one before Docker published it, failing the stack start with
`address already in use`. Ports now come from a fixed range below the Linux and
macOS ephemeral ranges, probed on every interface as Docker binds them, and
still partitioned per e2e worker.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MBEk1JxfLqmcaNWvN6MRyG
The kill-between-staging-and-publishing test hit the 20s test timeout without
saying which step hung; only the writer's readiness had its own deadline. Each
remaining phase (helper image, prepare, PG_VERSION seed, killed writer exit and
pipe close, markInitialized retry, and both cleanups) now fails with a tagged
error naming the phase well before the test timeout.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MBEk1JxfLqmcaNWvN6MRyG
@avallete
avallete requested a review from a team as a code owner November 5, 2026 07:46
@avallete
avallete requested a review from Coly010 November 5, 2026 07:46

avallete commented Nov 5, 2026

Copy link
Copy Markdown
Member Author

/ai-review


Generated by Claude Code

@avallete avallete added the run-flaky-check Run the flaky-test check on this PR label Nov 5, 2026 — with Claude
@github-actions github-actions Bot removed the run-flaky-check Run the flaky-test check on this PR label Nov 5, 2026
@github-actions

github-actions Bot commented Nov 5, 2026

Copy link
Copy Markdown
Contributor

CLI benchmark (Lightweight Commands): no changes found

Commit 2582905 against develop at 95e86b3 · 10 runs each · report only, never blocks merging

Command Workload Before After Change
supabase --version version 259 ms 272 ms no real change
supabase --help help 256 ms 252 ms no real change
supabase init init 234 ms 226 ms no real change
supabase migration new bench migration-new 232 ms 230 ms no real change
supabase gen types --lang typescript --project-id replayfixtureprojref gen-types 257 ms 244 ms no real change (-5%, within normal variation)
supabase projects list projects-list 249 ms 245 ms no real change
supabase functions list --project-ref replayfixtureprojref functions-list 248 ms 259 ms no real change

API calls: unchanged for all 7 commands.

Binary size: 134.6 MB, unchanged.

Details: timing ranges, API calls per command, slowest phases

Timing ranges

Command Workload Before range After range Change Verdict
supabase --version version 224-292 ms 250-293 ms +12 ms (+5%) within noise
supabase --help help 230-286 ms 221-295 ms -4 ms (-2%) within noise
supabase init init 188-252 ms 200-249 ms -8 ms (-3%) within noise
supabase migration new bench migration-new 206-274 ms 201-260 ms -3 ms (-1%) within noise
supabase gen types --lang typescript --project-id replayfixtureprojref gen-types 217-295 ms 231-302 ms -13 ms (-5%) within noise
supabase projects list projects-list 213-291 ms 216-271 ms -4 ms (-2%) within noise
supabase functions list --project-ref replayfixtureprojref functions-list 210-275 ms 219-289 ms +11 ms (+4%) within noise

API calls per command

Command Workload Before After Endpoint changes
supabase --version version 0 0
supabase --help help 0 0
supabase init init 0 0
supabase migration new bench migration-new 0 0
supabase gen types --lang typescript --project-id replayfixtureprojref gen-types 2 2
supabase projects list projects-list 1 1
supabase functions list --project-ref replayfixtureprojref functions-list 2 2

Slowest phases

No command moved beyond noise, so there are no phase deltas.

Workflow run

Comment /bench to run the lightweight benchmark (this comment) again on the latest commit, or /bench full to also run the integration-heavy benchmark, which posts in its own comment.

@github-actions github-actions 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.

Superseded by a newer AI review

🤖 AI Review

Reviewed both independent reviews and all three changed files. Claude's finding is refuted: duplicate port draws are possible, but current callers of that helper start only PostgreSQL; full-stack tests use the allocator that deduplicates. No confirmed defects found. Tests were not run because dependencies are absent.

Findings

No issues found.

Refuted findings (kept for transparency, not posted as review comments)
  • apps/cli/tests/helpers/cli.ts:332 (test-flakiness): Independent random draws without deduplication in makeTempStackProjectEffect can assign the same port to multiple services, producing Docker address-in-use failures with roughly 5% probability per project when four workers run.
    Refuted: The duplicate-draw observation is correct, but the claimed test failures do not follow from current callers. The only consumers are db/start/start.e2e.test.ts and gen/types/types.e2e.test.ts. The former invokes db start at lines 24-28, whose implementation starts only the database using values.dbPort (command-internal/db-bootstrap/start-local-database.ts:247-270). Local typegen overwrites the generated config and starts bare PostgreSQL using only project.ports.dbPort (types.e2e.test.ts:333-335), publishing only that port at lines 226-234; remote typegen starts no local services. Full-stack tests instead call overrideStackPorts, which explicitly rejects duplicate allocations (tests/helpers/cli.ts:354-368). Thus approximately 5% describes any duplicate among 18 draws, including unused values, rather than an address-in-use failure probability.

Stats

Claude findings: 1 · Codex findings: 0 · Confirmed: 0 · Refuted: 1 · Uncertain: 0


Models: claude-opus-5-5 + gpt-6.1-sol · Trigger: auto · Workflow run

This review runs once per PR. A maintainer can request another with a /ai-review comment.

Each pick drew a fresh random start in the fixed range, so the many ports a
temp stack project allocates at once could repeat within a worker's slot. The
picker now walks the range from one random start per worker.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MBEk1JxfLqmcaNWvN6MRyG
@github-actions

github-actions Bot commented Nov 5, 2026

Copy link
Copy Markdown
Contributor

Flaky test check: ✅ no flaky tests

Commit 4bcfe2efdec4 · focused ×10 (5 executions each), 90 tests · integration ×10, 6738 tests · unit ×10, 9444 tests · workflow run

Each execution is a separate Vitest process; Where lists failing runs, as run.iteration for suites executed more than once per run. The full data is in the flaky-check-report artifact.

@github-actions github-actions 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.

Superseded by a newer AI review

🤖 AI Review

Verified all three findings. Refuted the claimed port-collision flake for current callers. Confirmed overly restrictive phase deadlines and, with corrected reasoning, cleanup paths that can outlast their deadlines.

Findings

Severity Location Category Sources Claim
🟡 MINOR packages/stack/src/storage/DockerDatabaseStorage.integration.test.ts:1153 test-flakiness claude The diagnostic phase deadlines introduce failures for successful Docker operations that exceed five seconds but would fit within the overall test budget. Cleanup deadline failures also become defects instead of being ignored.
🟡 MINOR packages/stack/src/storage/DockerDatabaseStorage.integration.test.ts:1155 test-reliability codex The destroyData cleanup deadline can still wait indefinitely without reporting its phase because the storage implementation explicitly masks interruption during helper removal.
Refuted findings (kept for transparency, not posted as review comments)
  • apps/cli/tests/helpers/cli.ts:336 (test-flakiness): Independent random port picks without deduplication cause approximately 4.7% of stack setups to receive duplicate service ports and fail when Docker publishes them.
    Refuted: Duplicate picks are possible, but the claimed failure does not follow for current callers. The db-start test starts only PostgreSQL; db-bootstrap/postgres.service.ts:320 publishes only db.port. The typegen test rewrites the configuration and starts PostgreSQL using only project.ports.dbPort at types.e2e.test.ts:333-335; its other caller exercises a remote project. Full-stack configurations use overrideStackPortsEffect, which deduplicates assignments at cli.ts:354-368. The birthday calculation therefore does not establish the claimed setup failure rate.

Stats

Claude findings: 2 · Codex findings: 1 · Confirmed: 2 · Refuted: 1 · Uncertain: 0


Models: claude-opus-5-5 + gpt-6.1-sol · Trigger: manual · Workflow run

This review runs once per PR. A maintainer can request another with a /ai-review comment.

jgoux added 2 commits November 5, 2026 09:46
…es-2026-11-05

# Conflicts:
#	apps/cli/src/commands/sso/list/list.integration.test.ts
The fixed 20000-32767 range was the stack's public auto-port range, so a
concurrent stack-mode e2e could bind a port another worker had probed but
not yet published. Ports now come from 1024-9999, below both stack ranges
and the OS ephemeral ranges, and are also probed on loopback because macOS
lets a wildcard bind succeed over a loopback-only listener.
@jgoux

jgoux commented Nov 5, 2026

Copy link
Copy Markdown
Contributor

/ai-review

@jgoux jgoux changed the title test(repo): fix 3 flaky tests in sso list, e2e ports and storage crash-safety test(repo): fix e2e port races and name storage crash-test stalls Nov 5, 2026

@github-actions github-actions 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.

🤖 AI Review

Verified all five findings against the code: four confirmed and one refuted. Confirmed concerns cover duplicate concurrent port allocations, missing IPv6 probes, cleanup deadlines introducing failures, and phase budgets exceeding the test timeout. The claim that cleanup deadlines inherit finalizer uninterruptibility is refuted by the bundled Effect implementation and a controlled reproduction. No released CLI behavior changes.

Findings

Severity Location Category Sources Claim
🟡 MINOR packages/stack/src/storage/DockerDatabaseStorage.integration.test.ts:1155 test-reliability claude The new five-second cleanup deadlines can turn otherwise passing tests into failures when best-effort Docker cleanup is merely slow. Effect.ignore precedes the deadline, so it does not swallow PhaseStallError, which Effect.orDie converts into a defect.
🟡 MINOR packages/stack/src/storage/DockerDatabaseStorage.integration.test.ts:1129 test-reliability claude The sequential phase budgets exceed the unchanged 20-second test timeout, so slow earlier phases can leave a later phase hitting the generic test timeout before its named deadline. The individual deadlines also reject some executions that previously completed within the overall timeout.
🟡 MINOR apps/cli/tests/helpers/cli.ts:348 test-reliability claude The allocator checks only IPv4, so an IPv6-only listener can occupy a selected port and cause Docker's subsequent publication to fail on hosts where Docker also publishes over IPv6.
🟡 MINOR apps/cli/tests/helpers/cli.ts:343 concurrency codex Concurrent allocations can return the same port because retries ignore advances made to the shared cursor.
Refuted findings (kept for transparency, not posted as review comments)
  • packages/stack/src/storage/DockerDatabaseStorage.integration.test.ts:1155 (error-handling): The cleanup deadlines cannot reliably terminate stalled cleanup because they inherit the finalizer's uninterruptible status.
    Refuted: The unchanged Effect implementation bundled in packages/stack/src/functions/generated/serve-main-bundle.ts:3 implements timeoutOrElse through a race whose child fibers start interruptible rather than inheriting the parent's status. A reproduction using that runtime and the same finalizer pipeline interrupted a 200ms cleanup and returned the deadline defect after 22ms. Explicitly uninterruptible operations such as DockerDatabaseStorage.ts:753-774 can still delay cancellation, but finalizer inheritance does not disable these deadlines.

Stats

Claude findings: 3 · Codex findings: 2 · Confirmed: 4 · Refuted: 1 · Uncertain: 0


Models: claude-opus-5-5 + gpt-6.1-sol · Trigger: manual · Workflow run

This review runs once per PR. A maintainer can request another with a /ai-review comment.

Comment thread apps/cli/tests/helpers/cli.ts Resolved
Comment thread apps/cli/tests/helpers/cli.ts Resolved
@jgoux
jgoux added this pull request to the merge queue Nov 5, 2026
Merged via the queue into develop with commit deccf04 Nov 5, 2026
74 checks passed
@jgoux
jgoux deleted the avallete/flaky-fixes-2026-11-05 branch November 5, 2026 09:48
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.

3 participants