Skip to content

Support GitHub stacks in Delivery - #363

Merged
mira-2026 merged 8 commits into
mainfrom
fix/delivery-stacked-prs
Jul 30, 2026
Merged

Support GitHub stacks in Delivery#363
mira-2026 merged 8 commits into
mainfrom
fix/delivery-stacked-prs

Conversation

@mira-2026

Copy link
Copy Markdown
Collaborator

Summary

  • show every open pull request in Delivery, group GitHub stack members bottom-to-top, and identify linear unlinked chains as stack candidates
  • create GitHub stacks from validated existing chains and merge through any selected layer with GitHub's asynchronous stack merge API
  • bind merge and PR-dev actions to the exact confirmed head SHA, validate every included layer, and require every included PR-dev author to be trusted
  • clean only worktrees and managed dev data for PRs that GitHub confirms merged; retain upper, dirty, queued, failed, and unconfirmed worktrees
  • guard ordinary merge/reject/update flows from mutating stack members or open stack candidates

Delivery behavior

  • selecting a middle layer submits that layer plus every open layer below it; selecting the top submits the full remaining stack
  • direct stack merges use squash and can continue into the existing deploy flow
  • merge-queued stacks retain every worktree and do not auto-deploy; Delivery tells the operator to deploy latest main after the queue finishes
  • Run in dev is available for eligible GitHub stack and candidate layers at the selected exact SHA, with the included downstack layers shown in the confirmation
  • Reject remains available for standalone PRs; stack and candidate members explain why restructuring/unstacking is required first

Verification

  • bun run format:check
  • bun run lint
  • bun run build
  • 170 backend tests across the four changed backend test files
  • 124 frontend tests across the four changed frontend test files
  • live read-only REST and GraphQL checks confirmed GitHub stack access and metadata for stack #360

Closes #386

@mira-2026
mira-2026 requested a review from rajohan as a code owner July 30, 2026 16:56
@mira-2026 mira-2026 added status: needs-review Ready for human or agent review type: feature Adds user-visible functionality area: ops Operational actions, deploys, services, backups, and health area: frontend Frontend UI, client state, routing, and browser behavior area: backend Backend API, server routes, services, and integrations labels Jul 30, 2026
@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@mira-2026, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 40 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e95e6d5c-888a-4ea9-b52b-9ad08ce48407

📥 Commits

Reviewing files that changed from the base of the PR and between f6f7226 and a7c7c06.

📒 Files selected for processing (4)
  • backend/src/services/pullRequests.ts
  • backend/test/serviceBehavior.test.ts
  • frontend/src/pages/Delivery.tsx
  • frontend/src/test/pageBehavior.test.tsx
📝 Walkthrough

Summary by CodeRabbit

  • New Features
    • Added API support to create GitHub pull request stacks and to run stack-aware merge workflows.
    • Delivery now surfaces GitHub stack candidates and grouped native stacks, including stack badges and included preview layer messaging.
  • Bug Fixes
    • Hardened validation for stack creation, approval, and preview start.
    • Approval and preview/merge actions now require exact head SHA verification (and stack head expectations for native stack merges) to prevent unsafe or stale operations.
    • Preview start now rejects missing/invalid expected head details with a clear error.

Walkthrough

This change adds native and candidate pull-request stack support across contracts, backend services, routes, workers, frontend hooks, and the Delivery UI. Preview and merge actions now require exact head SHAs, with stack creation, scoped previews, stack-aware merges, guardrails, cleanup results, and expanded tests.

Changes

Pull request contracts and preview scoping

Layer / File(s) Summary
Stack contracts and preview validation
contracts/delivery.ts, backend/src/services/pullRequestPreviewHost.ts, backend/src/services/pullRequestPreviews.ts, backend/src/services/pullRequests.ts
Adds stack schemas, scoped preview candidates, main-root and author-list validation, stack-aware listing, and expected-head checks before preview jobs are queued.

Backend stack execution

Layer / File(s) Summary
Stack routes, merges, and worker actions
backend/src/routes/pullRequestRoutes.ts, backend/src/services/pullRequests.ts
Adds stack creation, asynchronous native stack merging, exact-head verification, stack guardrails, cleanup responses, and worker wiring.

Frontend Delivery workflows

Layer / File(s) Summary
Stack modeling and UI actions
frontend/src/components/features/delivery/pullRequestStacks.ts, frontend/src/hooks/*, frontend/src/pages/Delivery.tsx
Derives candidates, groups native stacks, adds stack creation hooks, sends exact-head mutations, and renders stack-aware actions and sections.

Validation coverage

Layer / File(s) Summary
Backend and frontend tests
backend/test/*, frontend/src/test/*
Covers contracts, preview conflicts, stack listing, stack creation, native merges, guardrails, UI actions, and cleanup outcomes.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Delivery
  participant Backend
  participant GitHub
  Delivery->>Backend: Send stack operation and exact head SHAs
  Backend->>GitHub: Validate refs and execute stack operation
  GitHub-->>Backend: Return stack or merge status
  Backend-->>Delivery: Return action message and cleanup results
Loading

Possibly related PRs

Suggested labels: type: security

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the main change: adding GitHub stack support to Delivery.
Description check ✅ Passed It covers summary, delivery behavior, and verification, and is mostly complete even though some checklist sections are not filled in.
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.

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.

@codecov

codecov Bot commented Jul 30, 2026

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🧹 Nitpick comments (4)
backend/src/services/pullRequests.ts (3)

1026-1037: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

previewEligible is now computed in two places with different rules.

normalizePullRequest still derives previewEligible from pr.baseRefName === DEFAULT_BASE and a single-author check, while applyPullRequestPreviewEligibility recomputes it scope-aware for both list paths. Single-PR responses (e.g. approvePullRequestReview, updatePullRequestBranch) only get the former, so a stacked PR is reported previewEligible: false until the next list refresh. Consider dropping the field from normalizePullRequest and making the scope-aware helper the single source of truth.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/src/services/pullRequests.ts` around lines 1026 - 1037, Remove the
duplicated previewEligible calculation from normalizePullRequest, including its
single-author/base checks, and rely on applyPullRequestPreviewEligibility as the
sole source of truth. Ensure both list and single-PR response paths invoke the
scope-aware helper so stacked PRs receive consistent eligibility immediately.

1165-1184: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Recomputes the whole chain index once per pull request.

pullRequestPreviewScope rebuilds childrenByBase and re-walks candidate chains on every call, and this maps over all PRs — quadratic-to-cubic in the open PR count on a cached-but-hot listing path. Consider building the base→children index (and the resolved linear chains) once and passing it into the scope resolver.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/src/services/pullRequests.ts` around lines 1165 - 1184, Update
applyPullRequestPreviewEligibility and pullRequestPreviewScope so the
base-to-children index and resolved linear chains are built once per
pull-request collection, then reused for every mapped pull request. Pass the
shared index/chain data into the scope resolution instead of rebuilding and
re-walking it for each pull request, while preserving the existing eligibility
checks and results.

3926-4004: 🩺 Stability & Availability | 🔵 Trivial

Confirm the operational recovery path for a merged-but-unconfirmed stack.

When GitHub reports merged but a member doesn't confirm as MERGED, this throws 409 after the merge has already landed — worktrees are retained (good), but syncMain never runs, so the production checkout stays behind with no automatic reconciliation. Worth ensuring there's alerting or a manual runbook step for this state.

Also applies to: 4028-4046

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/src/services/pullRequests.ts` around lines 3926 - 4004, Update the
unconfirmedPullRequests error path in the stack merge flow to emit an actionable
alert containing the affected PRs and retained-worktree state, while preserving
the 409 response and cleanup behavior. Ensure the alert or associated
operational guidance directs operators to run syncMain to reconcile the
production checkout after the merge has landed.
backend/test/serviceBehavior.test.ts (1)

378-395: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

No coverage for the pending polling path.

asyncResult only ever produces merged, enqueued, or failed, so mergePullRequestStack's poll loop — the uuid requirement, the STACK_MERGE_TIMEOUT_MS deadline, the abort checks, and the follow-up merge-async/{uuid} GET — is never exercised. A fake that returns pending with a uuid on the PUT and merged on the first poll would cover the loop cheaply.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/test/serviceBehavior.test.ts` around lines 378 - 395, Extend the
asyncResult setup in the relevant mergePullRequestStack test to support a
pending response with a uuid on the initial PUT, then return merged for the
first merge-async/{uuid} poll. Exercise the pending polling path, including the
uuid-based follow-up GET, while preserving existing merged, enqueued, and failed
scenarios.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/src/services/pullRequests.ts`:
- Around line 3724-3772: Update the stack merge flow around
runGhJsonWithResultBody and the polling loop so the initiating merge-async
request can run for at least STACK_MERGE_TIMEOUT_MS, preventing its hardcoded
shorter timeout from abandoning an accepted merge. Preserve the existing UUID
polling behavior, and before surfacing timeout or abort failures from the
initiation or polling stages, attempt the available stack-state
read/reconciliation path so an in-flight merge can be observed.
- Around line 4122-4126: Update approvePullRequestReview around
requirePullRequestStack and validateDashboardPrForReviewApproval so
non-main-based PRs that are valid standalone linear-stack candidates can proceed
through review approval without requiring native stack registration; otherwise
replace the merge-oriented error with a review-specific message while preserving
validation for genuinely unsupported PR shapes.
- Around line 1457-1479: Replace prose-based capability detection in
isGitHubStackApiUnavailable with structured HTTP/status or capability metadata
tied specifically to the stack API, preventing unrelated 404 errors from
bypassing stack-aware guards. Also update isStackGraphqlMetadataUnavailable to
classify unsupported stack fields using GraphQL error type/extensions rather
than fragment-matcher text; apply these changes at
backend/src/services/pullRequests.ts lines 1457-1479 and 1858-1866.

In `@backend/test/pullRequestPreview.test.ts`:
- Around line 1127-1143: Await every asynchronous assertion: in
backend/test/pullRequestPreview.test.ts lines 1127-1143, await all three
prepareAndStartPullRequestPreview resolves/rejects expectations; in
backend/test/serviceBehavior.test.ts lines 3813-3818, await both
createPullRequestStack rejection assertions; and in
backend/test/serviceBehavior.test.ts lines 4616-4618, await the
approvePullRequest(6, …) rejection assertion.

In `@backend/test/serviceBehavior.test.ts`:
- Around line 4616-4618: Await the rejects assertion for approvePullRequest in
the relevant test so the test runner observes and fails on an unexpected
rejection or resolved promise; preserve the existing error-message expectation.

In `@frontend/src/test/frontendBehavior.test.tsx`:
- Around line 5222-5227: Await the resolves assertion for
createStack.result.current.mutateAsync in the stack creation test so promise
rejection or payload assertion failures are observed before the test completes.
Keep the existing toMatchObject expectation unchanged.

---

Nitpick comments:
In `@backend/src/services/pullRequests.ts`:
- Around line 1026-1037: Remove the duplicated previewEligible calculation from
normalizePullRequest, including its single-author/base checks, and rely on
applyPullRequestPreviewEligibility as the sole source of truth. Ensure both list
and single-PR response paths invoke the scope-aware helper so stacked PRs
receive consistent eligibility immediately.
- Around line 1165-1184: Update applyPullRequestPreviewEligibility and
pullRequestPreviewScope so the base-to-children index and resolved linear chains
are built once per pull-request collection, then reused for every mapped pull
request. Pass the shared index/chain data into the scope resolution instead of
rebuilding and re-walking it for each pull request, while preserving the
existing eligibility checks and results.
- Around line 3926-4004: Update the unconfirmedPullRequests error path in the
stack merge flow to emit an actionable alert containing the affected PRs and
retained-worktree state, while preserving the 409 response and cleanup behavior.
Ensure the alert or associated operational guidance directs operators to run
syncMain to reconcile the production checkout after the merge has landed.

In `@backend/test/serviceBehavior.test.ts`:
- Around line 378-395: Extend the asyncResult setup in the relevant
mergePullRequestStack test to support a pending response with a uuid on the
initial PUT, then return merged for the first merge-async/{uuid} poll. Exercise
the pending polling path, including the uuid-based follow-up GET, while
preserving existing merged, enqueued, and failed scenarios.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: a244022f-7201-415c-acd4-fc4363943677

📥 Commits

Reviewing files that changed from the base of the PR and between e50b738 and dbf01c5.

📒 Files selected for processing (17)
  • backend/src/routes/pullRequestRoutes.ts
  • backend/src/services/pullRequestPreviewHost.ts
  • backend/src/services/pullRequestPreviews.ts
  • backend/src/services/pullRequests.ts
  • backend/test/pullRequestPreview.test.ts
  • backend/test/routeAndServiceBehavior.test.ts
  • backend/test/serviceBehavior.test.ts
  • backend/test/utilityBehavior.test.ts
  • contracts/delivery.ts
  • frontend/src/components/features/delivery/pullRequestStacks.ts
  • frontend/src/hooks/index.ts
  • frontend/src/hooks/useDelivery.ts
  • frontend/src/pages/Delivery.tsx
  • frontend/src/test/contracts.test.ts
  • frontend/src/test/frontendBehavior.test.tsx
  • frontend/src/test/pageBehavior.test.tsx
  • frontend/src/test/pullRequestStacks.test.ts
📜 Review details
🔇 Additional comments (48)
frontend/src/components/features/delivery/pullRequestStacks.ts (3)

24-72: LGTM!

Also applies to: 79-92


100-115: LGTM!


117-155: LGTM!

frontend/src/hooks/index.ts (1)

63-63: LGTM!

frontend/src/hooks/useDelivery.ts (3)

106-120: LGTM!

Also applies to: 127-133, 211-219, 313-327, 347-357


376-385: LGTM!


493-499: LGTM!

frontend/src/pages/Delivery.tsx (6)

27-33: LGTM!

Also applies to: 45-45, 67-76, 90-90, 101-101, 523-545, 562-600, 616-629, 716-723


863-879: LGTM!


886-943: LGTM!

Also applies to: 957-967, 1007-1016


1216-1256: LGTM!

Also applies to: 1324-1349


1532-1677: LGTM!

Also applies to: 1701-1733


1166-1173: 🩺 Stability & Availability

No change needed. stackCandidateEntry exists only for unlinked GitHub stack candidates created in Delivery, and those always satisfy pullRequest.stack !== undefined, so they route through pullRequestPreviewScope/validatePullRequestPreviewScope rather than this unstacked branch.

			> Likely an incorrect or invalid review comment.
frontend/src/test/contracts.test.ts (1)

13-17: LGTM!

Also applies to: 174-205

frontend/src/test/frontendBehavior.test.tsx (1)

143-143: LGTM!

Also applies to: 5095-5106, 5182-5184, 5216-5220, 5265-5268

frontend/src/test/pageBehavior.test.tsx (1)

1893-1893: LGTM!

Also applies to: 1997-2001, 3156-3456, 3647-3649, 3761-3763, 3800-3801

frontend/src/test/pullRequestStacks.test.ts (1)

11-29: LGTM!

Also applies to: 32-64, 66-115

contracts/delivery.ts (6)

36-48: LGTM!


76-88: LGTM!

Also applies to: 102-102


266-275: LGTM!


284-297: LGTM!


313-322: LGTM!

Also applies to: 362-367, 386-406, 465-502


147-157: 🗄️ Data Integrity & Integration

Confirm the async merge queue payload shape with GitHub.

The private-preview merge-async/merge-queue response shape and whether every terminal state includes details.message should be checked before keeping details.message required and status as this closed picklist.

backend/src/services/pullRequestPreviewHost.ts (1)

78-81: LGTM! The empty-array guard correctly closes the vacuous .some hole, and isPullRequestPreviewAuthorAllowed already rejects undefined logins.

Also applies to: 1584-1601

backend/src/services/pullRequestPreviews.ts (3)

23-24: LGTM!

Also applies to: 70-90


100-110: LGTM!


283-301: LGTM! Pinning the queued payload to the confirmed SHA (rather than re-deriving it at execution time) is the right call.

Also applies to: 330-330

backend/src/services/pullRequests.ts (11)

7-20: LGTM!

Also applies to: 108-150, 188-189


1048-1111: LGTM! The fan-out/cycle guards and the "selected must be the top of the returned scope" check both look correct.


1120-1163: LGTM!


1191-1218: LGTM! Dropping the base=main filter is required for scope derivation to see child PRs.

Also applies to: 1263-1263


1383-1408: LGTM! Requiring a schema-valid status before treating a non-zero exit as a result keeps genuine HTTP error bodies on the failure path.


1416-1455: LGTM!

Also applies to: 1487-1556


1761-1851: LGTM! Reattaching pr.stack after the pr view refetch is correct, since that command exposes no stack field.

Also applies to: 1872-1908


1916-2010: LGTM! Validation order (duplicates → existence → already-stacked → main-rooted bottom → contiguous base/head chain) is sound, and the 404→409 mapping gives a usable message when stacks aren't enabled.


2074-2083: LGTM! Using a state-only fetch for lifecycle checks avoids the full pr view payload.

Also applies to: 2095-2095, 2258-2275, 2306-2328


3794-3921: LGTM! Re-fetching every included member and comparing against the stack resource's head.sha before merging closes the stale-page window properly.


4060-4101: LGTM! Re-validating expectedHeadSha and the stack payload at the job-execution boundary is the right defense for persisted payloads.

Also applies to: 4160-4160, 4195-4195, 4278-4299, 4309-4331, 4404-4410

backend/src/routes/pullRequestRoutes.ts (1)

14-16: LGTM! Dropping the request.body ? … : {} fallback on approve is necessary now that expectedHeadSha is required, and the 400 path is covered by tests.

Also applies to: 43-43, 128-171, 238-255

backend/test/pullRequestPreview.test.ts (1)

66-81: LGTM!

Also applies to: 196-196, 732-735, 1185-1185, 1197-1212, 1294-1294, 1309-1309, 1361-1364, 1457-1479

backend/test/routeAndServiceBehavior.test.ts (1)

3271-3281: LGTM!

backend/test/serviceBehavior.test.ts (6)

35-35: LGTM! The baseRefName: "main" guard is a nice regression lock on the removed base filter.

Also applies to: 206-213


229-280: LGTM! Padding positionals with set -- "$@" "" "" "" "" is the right fix for set -u under $3/$4 comparisons.

Also applies to: 288-288


306-377: LGTM! The per-scenario closedNumber/unconfirmedNumber knobs keep the guardrail tests readable.

Also applies to: 396-696


2904-2906: LGTM! Asserting canReviewerApprove: true on PR #4 (base ready, stack base main) pins the new normalization precisely.

Also applies to: 3721-3754, 3764-3812


3984-4005: LGTM! Asserting --match-head-commit in the recorded gh command locks the server-side precondition, not just the client intent.

Also applies to: 4066-4102


4132-4453: LGTM! Asserting the absence of worktree remove and fetch --prune origin for the queued/failed/unconfirmed paths is exactly the right way to pin the retention guarantee.

Also applies to: 4503-4505

backend/test/utilityBehavior.test.ts (1)

8-8: LGTM! String(number).repeat(40).slice(0, 40) reliably yields a hex-valid 40-char SHA for any PR number.

Also applies to: 66-66, 115-134, 153-190, 196-229, 914-917

Comment thread backend/src/services/pullRequests.ts
Comment thread backend/src/services/pullRequests.ts
Comment thread backend/src/services/pullRequests.ts Outdated
Comment thread backend/test/pullRequestPreview.test.ts Outdated
Comment thread backend/test/serviceBehavior.test.ts Outdated
Comment thread frontend/src/test/frontendBehavior.test.tsx Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: dbf01c51ba

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread backend/src/services/pullRequests.ts
@mira-2026

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown
✅ 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.

@mira-2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (1)
backend/src/services/pullRequests.ts (1)

1518-1521: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Centralize the stacks endpoint construction.

The repos/{owner}/{name}/stacks path is now built in three places (findPullRequestStack, createPullRequestStack at Line 2113, and isGitHubStackApiUnavailable). Since the detector matches on exact endpoint identity, any future path drift in one caller silently disables the capability fallback rather than failing loudly.

♻️ Suggested helper
function pullRequestStacksEndpoint(): string {
    const repo = parseRepoParts(DASHBOARD_REPO);
    return `repos/${repo.owner}/${repo.name}/stacks`;
}

Then use pullRequestStacksEndpoint() in all three sites, appending the query string in findPullRequestStack.

Also applies to: 1553-1561

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/src/services/pullRequests.ts` around lines 1518 - 1521, Centralize
construction of the GitHub stacks endpoint in a shared pullRequestStacksEndpoint
helper using the existing repository parsing logic. Update findPullRequestStack
to append its pull_request and per_page query parameters to that helper result,
and replace the duplicated endpoint construction in createPullRequestStack and
isGitHubStackApiUnavailable so all three callers use the same path identity.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/src/services/pullRequests.ts`:
- Around line 1982-1993: Update supportsPullRequestStackGraphqlMetadata to fail
closed by catching introspection errors and returning false, allowing
listDashboardPullRequests to continue without optional stack metadata. Cache the
successful or failed capability result so the GraphQL probe runs only once per
process (or use an established short-TTL mechanism), and reuse that cached value
for subsequent listings.
- Line 3856: Move the deadline initialization in the stack merge flow so the
full STACK_MERGE_TIMEOUT_MS polling budget begins after the merge-async
initiation returns pending, while preserving the returned uuid polling behavior.
Update the related deadline handling in the initiation and polling logic around
the merge request, without changing reconciliation behavior for already-merged
stacks.
- Around line 3895-3907: Update the pending-result validation condition to
compare expected_head_sha, merge_action, and merge_method only when each field
is not undefined. Preserve the 409 error for defined values that conflict with
expectedHeadSha, "default", or "squash", respectively.

---

Nitpick comments:
In `@backend/src/services/pullRequests.ts`:
- Around line 1518-1521: Centralize construction of the GitHub stacks endpoint
in a shared pullRequestStacksEndpoint helper using the existing repository
parsing logic. Update findPullRequestStack to append its pull_request and
per_page query parameters to that helper result, and replace the duplicated
endpoint construction in createPullRequestStack and isGitHubStackApiUnavailable
so all three callers use the same path identity.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: c589fcab-7626-4b5c-b93d-8af57527737b

📥 Commits

Reviewing files that changed from the base of the PR and between dbf01c5 and a320156.

📒 Files selected for processing (5)
  • backend/src/services/pullRequests.ts
  • backend/test/pullRequestPreview.test.ts
  • backend/test/serviceBehavior.test.ts
  • backend/test/utilityBehavior.test.ts
  • frontend/src/test/frontendBehavior.test.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • frontend/src/test/frontendBehavior.test.tsx
📜 Review details
🧰 Additional context used
🪛 OpenGrep (1.26.0)
backend/src/services/pullRequests.ts

[ERROR] 1419-1419: Dynamic command passed to child_process.exec/execSync. Use child_process.execFile or spawn with an argument array instead.

(coderabbit.command-injection.exec-js)

🔇 Additional comments (14)
backend/test/pullRequestPreview.test.ts (1)

52-52: LGTM!

Also applies to: 191-203, 1128-1153, 1204-1204, 1458-1489

backend/test/serviceBehavior.test.ts (2)

19-19: LGTM!

Also applies to: 206-216, 232-249, 364-601, 660-800, 802-941


4032-4033: LGTM!

Also applies to: 4059-4096, 4098-4156, 4158-4225, 4406-4406, 4508-4511, 4601-4702, 4897-4897, 5046-5071, 5134-5158

backend/src/services/pullRequests.ts (10)

1032-1102: LGTM!


1104-1132: LGTM!


1186-1210: LGTM!


1402-1429: LGTM!


1431-1469: LGTM!

Also applies to: 1479-1491


2107-2140: LGTM!


2450-2470: LGTM!


3951-3973: LGTM!


4001-4109: LGTM!

Also applies to: 4110-4200, 4222-4243


4316-4382: LGTM!

Also applies to: 4390-4413

backend/test/utilityBehavior.test.ts (1)

183-183: LGTM!

Also applies to: 224-227

Comment thread backend/src/services/pullRequests.ts
Comment thread backend/src/services/pullRequests.ts Outdated
Comment thread backend/src/services/pullRequests.ts

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a320156d49

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread frontend/src/pages/Delivery.tsx
Comment thread backend/src/services/pullRequests.ts
Comment thread backend/src/services/pullRequests.ts Outdated
Comment thread backend/src/services/pullRequests.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cd2f8f3d2d

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread backend/src/services/pullRequests.ts
@mira-2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0e6a010c47

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread backend/src/services/pullRequests.ts
@mira-2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 364c2bc716

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread frontend/src/components/features/delivery/pullRequestStacks.ts

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 957042fe46

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread backend/src/services/pullRequests.ts
Comment thread frontend/src/pages/Delivery.tsx
Comment thread backend/src/services/pullRequests.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f6f7226f91

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread backend/src/services/pullRequests.ts Outdated
@mira-2026
mira-2026 merged commit 893087e into main Jul 30, 2026
7 checks passed
@mira-2026
mira-2026 deleted the fix/delivery-stacked-prs branch July 30, 2026 21:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: backend Backend API, server routes, services, and integrations area: frontend Frontend UI, client state, routing, and browser behavior area: ops Operational actions, deploys, services, backups, and health status: needs-review Ready for human or agent review type: feature Adds user-visible functionality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants