fix(worktree): bound git ops and always clear the setup spinner#3051
Conversation
|
React Doctor found no issues in the changed files. 🎉 Reviewed by React Doctor for commit |
|
Address Greptile review on #3051: - spawnWorktreeAdd / runPostCheckoutHook: after the timeout SIGKILLs the process, the `close` handler fires with code=null and settled a second time, producing a misleading "exited with code null" error that clobbered the real timeout message. Add a `settled` guard so the timeout result wins and later events are ignored. - taskCreationSaga.test.ts: fold the two "clears provisioning on success/failure" cases into a single it.each, matching the repo's parameterised-test convention while keeping the happy-path connect assertion. Generated-By: PostHog Code Task-Id: f3c8da8b-fc20-47bc-becd-575128b4b70f
#3054 added kill-timeouts to `git worktree add` and the post-checkout hook, and #3053 restructured the saga to clear the provisioning spinner and keep the task for retry when provisioning fails. Both landed on main and supersede the worktree-add/hook-timeout and spinner-clearing parts of this PR, so those are dropped here. The one hang path neither covered is the `git fetch` that precedes worktree creation — the trigger both fixes cited. It still runs unbounded inside the per-repo write lock, so a blocked fetch (network stall, unreachable remote) never settles, the lock is never released, and every later worktree creation for that repo queues behind it forever. Bound the two fetch call sites (resolveFreshBaseRef and createWorktreeForRemoteBranch) with a timeout. The fetch runs through simple-git rather than a raw spawn, so it can't use armProcessTimeout; instead it aborts via the AbortSignal executeWrite already forwards to its scoped git client, which kills the fetch subprocess and releases the write lock. On timeout the trunk path degrades to the local ref and the remote-branch path fails with a retryable error, rather than hanging.
1f7bfe7 to
6ba7c6e
Compare
Problem
Some tasks get stuck forever on the "Setting up worktree…" spinner with no error. Two independent causes:
Unbounded git ops under the write lock (the real hang). Every new local task runs
WorktreeManager.createWorktree({ fetchBeforeCreate: true }), which doesgit fetch origin <branch>insideGitOperationManager.executeWrite. If that fetch blocks (network stall, a credential helper waiting on stdin, an auth prompt) the operation promise never settles, so thefinally { releaseWrite() }never runs — the per-repo write lock is held forever and every subsequent worktree creation for that repo queues behind it. One bad fetch strands many tasks. The rawgit worktree addand post-checkout hook spawns likewise had no timeout.Leaked spinner on failure.
TaskCreationSagacallssetProvisioningActivebefore the worktree step but only callsclearProvisioningon the happy path. TheSagabase class catches any thrown step, rolls back, and returns{success:false}without ever reaching the clear — so even once a hang becomes an error, the spinner stays up.Changes
packages/git/src/worktree.tsspawnWorktreeAdd: kill + reject on a 60s timeout.runPostCheckoutHook: kill + resolve a non-fatal warning on a 120s timeout.fetchRefWithTimeouthelper: wraps the fetch in anAbortController(60s) and threads the signal throughexecuteWrite, which aborts the git subprocess and releases the write lock. Used byresolveFreshBaseRef(default new-task path) andcreateWorktreeForRemoteBranch.packages/core/src/task-detail/taskCreationSaga.ts: wrap the saga body intry/finallysoclearProvisioningalways runs, tearing down the spinner and letting the existing error toast inuseTaskCreationsurface. Removes the now-redundant mid-flow clear.Testing
pnpm --filter @posthog/core test taskCreationSaga— 16 pass, incl. two new cases assertingclearProvisioningfires on both the worktree failure and happy paths.pnpm --filter @posthog/git test worktree— 59 pass; fetch paths now route throughfetchRefWithTimeout(incl. the existing unreachable-remote fallback and remote-branch fetch cases).@posthog/gittypechecks clean.Created with PostHog Code