Skip to content

fix(cli): serialize local start and stop per project (CLI-2875) - #7372

Open
jgoux wants to merge 2 commits into
developfrom
juliengoux/cli-2875-supabase-cli-21220-prunes-local-docker-network-before
Open

jgoux wants to merge 2 commits into
developfrom
juliengoux/cli-2875-supabase-cli-21220-prunes-local-docker-network-before

Conversation

@jgoux

@jgoux jgoux commented Oct 28, 2026

Copy link
Copy Markdown
Contributor

Addresses #7339

Problem

Between start creating a project's Docker network and attaching its first container, the network has no endpoints. Any project-label-filtered docker network prune that lands in that window removes it, and start then fails with network supabase_network_<id> not found. Within one invocation every prune runs before bring-up (stopped-stack recovery) or after it stops (rollback), so the prune in the report most likely came from an overlapping lifecycle command on the same project: an earlier start still rolling back, a stop, stop --all, or a db start rollback.

Change

  • start, db start (including the declarative auto-start), and stop hold a cross-process lifecycle lock under $SUPABASE_HOME/locks:
    • a per-project lock keyed by the project's Docker label, so checkouts sharing a project_id serialize and different projects still run in parallel;
    • a gate every per-project command holds shared and stop --all holds exclusively.
  • The lock is taken before the first Docker probe and released after any rollback, outside the rollback region, so a waiting command never rolls back another command's resources.
  • A blocked command prints one waiting line to stderr and fails with an actionable error after 10 minutes; waiting is interruptible.
  • @supabase/stack gains holdSharedLock / holdExclusiveLock next to holdLock.
  • The ensureNetwork doc comment no longer claims the network cannot be removed mid-run.

Limitations

Older CLI binaries, raw docker commands, a different SUPABASE_HOME, and projects sharing a custom --network-id do not participate, and stop --all is not queued ahead of a stream of single-project commands (documented in start's SIDE_EFFECTS.md). db reset and the shadow database still create their network without the lock; that is a separate follow-up.

A concurrent `stop`, `stop --all`, or rollback could prune a project's
Docker network between `start` creating it and attaching the first
container, failing `start` with "network ... not found".

`start`, `db start` (including declarative auto-start), and `stop` now
hold a cross-process lifecycle lock under `$SUPABASE_HOME/locks`: a
per-project lock keyed by the project's Docker label, behind a shared
gate that `stop --all` takes exclusively. A blocked command prints one
waiting line and gives up after 10 minutes.
@jgoux
jgoux requested a review from a team as a code owner October 28, 2026 13:08
@jgoux jgoux self-assigned this Oct 28, 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 three Claude findings and confirmed them as nits: one misleading waiting message and two documentation gaps. Codex reported no findings. No functional defect was established. Tests were not run; dependencies are absent from the checkout.

Findings

Severity Location Category Sources Claim
⚪ NIT apps/cli/src/command-internal/project-lifecycle-lock.ts:131 ux claude When stop --all blocks the shared gate, the waiting message describes project-specific contention, while the eventual timeout correctly identifies an all-projects stop.
⚪ NIT apps/cli/src/commands/start/SIDE_EFFECTS.md:231 documentation claude The start, db start, and stop exit-code tables document ProjectLifecycleLockBusyError but omit the new ProjectLifecycleLockIoError failure.
⚪ NIT packages/stack/src/effect.ts:92 documentation claude The isLockBusy documentation mentions only holdLock even though the helper also classifies failures from holdSharedLock and holdExclusiveLock.

Stats

Claude findings: 3 · Codex findings: 0 · Confirmed: 3 · Refuted: 0 · 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.

Comment thread apps/cli/src/command-internal/project-lifecycle-lock.ts Outdated
Comment thread apps/cli/src/commands/start/SIDE_EFFECTS.md Outdated
Comment thread packages/stack/src/effect.ts

This branch has not been deployed

No deployments
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