Skip to content

Commit 364ed55

Browse files
Bill LeoutsakosBill Leoutsakos
authored andcommitted
fix(pi): recreate closed update PRs
1 parent 2f04077 commit 364ed55

3 files changed

Lines changed: 42 additions & 7 deletions

File tree

apps/docs/content/docs/en/workflows/blocks/pi.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ Update PR uses the same disposable authoring sandbox and host-controlled PR oper
6161
- Requires sandbox execution and **your own provider API key (BYOK)**.
6262
- Needs the same **GitHub token permissions as Create PR**: permission to clone, push, and create or update a pull request.
6363
- Never creates, rebases, merges, or force-pushes the branch. If another commit reaches the branch while Pi is working, the push fails rather than overwriting it.
64-
- Finds the exact open same-repository PR whose head is the target branch. One match is updated; no open match—including when an earlier PR was closed—creates a new PR after authoring; multiple open matches fail as ambiguous. A discovered PR that closes, moves, or no longer matches during validation aborts safely.
64+
- Finds the exact open same-repository PR whose head is the target branch and checks again after authoring. One match is updated; no open match—including when an earlier or preflight PR was closed—creates a new PR; multiple open matches fail as ambiguous.
6565
- When explicitly set, **Base Branch**, **PR Title**, **PR Body**, and **PR State** update the existing PR. Blank metadata preserves it. A newly created PR uses generated metadata and the repository default base when those fields are blank.
6666
- A no-change authoring pass still creates or updates the PR. A rejected initial push stops the run before any PR mutation or Babysit continuation.
6767
- The deliverable is the updated branch and its PR — read `prUrl`, `branch`, `changedFiles`, and `diff`.

apps/sim/executor/handlers/pi/cloud-backend.test.ts

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,11 @@ function mockExistingBranchPullRequest(): void {
108108
output: { items: [{ number: 7 }], count: 1 },
109109
})
110110
.mockResolvedValueOnce(existingPullRequestOutput())
111+
.mockResolvedValueOnce({
112+
success: true,
113+
output: { items: [{ number: 7 }], count: 1 },
114+
})
115+
.mockResolvedValueOnce(existingPullRequestOutput())
111116
}
112117

113118
describe('runCloudPi', () => {
@@ -798,11 +803,16 @@ describe('runCloudPi', () => {
798803
})
799804

800805
it('fails when a second PR for the branch appears during authoring', async () => {
801-
mockExistingBranchPullRequest()
802-
mockExecuteTool.mockResolvedValueOnce({
803-
success: true,
804-
output: { items: [{ number: 7 }, { number: 8 }], count: 2 },
805-
})
806+
mockExecuteTool
807+
.mockResolvedValueOnce({
808+
success: true,
809+
output: { items: [{ number: 7 }], count: 1 },
810+
})
811+
.mockResolvedValueOnce(existingPullRequestOutput())
812+
.mockResolvedValueOnce({
813+
success: true,
814+
output: { items: [{ number: 7 }, { number: 8 }], count: 2 },
815+
})
806816

807817
await expect(runCloudBranchPi(branchParams(), { onEvent: vi.fn() })).rejects.toThrow(
808818
/multiple open pull requests/
@@ -813,6 +823,32 @@ describe('runCloudPi', () => {
813823
expect(mockRunBabysit).not.toHaveBeenCalled()
814824
})
815825

826+
it('creates a replacement when the preflight PR is no longer open after authoring', async () => {
827+
mockExecuteTool
828+
.mockResolvedValueOnce({
829+
success: true,
830+
output: { items: [{ number: 7 }], count: 1 },
831+
})
832+
.mockResolvedValueOnce(existingPullRequestOutput())
833+
.mockResolvedValueOnce({
834+
success: true,
835+
output: { items: [], count: 0 },
836+
})
837+
838+
const result = await runCloudBranchPi(branchParams(), { onEvent: vi.fn() })
839+
840+
expect(mockExecuteTool).toHaveBeenCalledWith(
841+
'github_create_pr',
842+
expect.objectContaining({
843+
head: 'feature/existing',
844+
base: 'main',
845+
draft: true,
846+
}),
847+
{ signal: undefined }
848+
)
849+
expect(result.prUrl).toBe('https://github.com/octo/demo/pull/1')
850+
})
851+
816852
it('does not claim a push happened when no-op authoring is followed by a PR error', async () => {
817853
mockRun.mockImplementation((command: string) => {
818854
if (command.includes('git clone')) {

apps/sim/executor/handlers/pi/cloud-backend.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,6 @@ async function ensureUpdatePullRequest(
309309
if (currentPullRequest && currentPullRequest.pullNumber !== existingPullRequest.pullNumber) {
310310
throw new Error(`The open pull request for branch ${branch} changed during authoring`)
311311
}
312-
return updatePullRequest(params, existingPullRequest, secrets, signal)
313312
}
314313
if (currentPullRequest) {
315314
return updatePullRequest(params, currentPullRequest, secrets, signal)

0 commit comments

Comments
 (0)