Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 30 additions & 32 deletions app/api/webhooks/github/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,41 +107,39 @@ export async function POST(request: NextRequest) {
} = body;

const [owner, repoName] = repo?.split("/");
// trigger pr summary immediately after
if (action === "opened") {
await generatePullRequestSummary(
owner,
repoName,
prNumber,
pull_request?.title,
pull_request?.body,
body?.installation?.id,
pull_request?.base?.sha,
pull_request?.head?.sha,
pull_request?.changed_files,
pull_request?.additions,
pull_request?.deletions
)
.then(() =>
console.log(`Summary completed for: ${repo} #${prNumber}`)
)
.catch((error) =>
console.error(
`Summarization failed for repo: ${repo} #${prNumber}: `,
error
)
);
}
// Trigger AI review when PR is opened or updated
if (action === "opened" || action === "synchronized") {
await reviewPullRequest(owner, repoName, prNumber)
.then(() => console.log(`Review completed for: ${repo} #${prNumber}`))
.catch((error) =>
console.error(
`Review failed for repo: ${repo} #${prNumber}: `,
error
)
try {
await generatePullRequestSummary(
owner,
repoName,
prNumber,
pull_request?.title,
pull_request?.body,
body?.installation?.id,
pull_request?.base?.sha,
pull_request?.head?.sha,
pull_request?.changed_files,
pull_request?.additions,
pull_request?.deletions
);
console.log(`Summary completed for: ${repo} #${prNumber}`);
} catch (error) {
console.error(
`Summarization failed for repo: ${repo} #${prNumber}: `,
error
);
}

try {
await reviewPullRequest(owner, repoName, prNumber);
console.log(`Review completed for: ${repo} #${prNumber}`);
} catch (error) {
console.error(
`Review failed for repo: ${repo} #${prNumber}: `,
error
);
}
}
Comment on lines 111 to 143
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# Search for rate limiting, deduplication, and idempotency patterns
rg -n 'rateLimit|debounce|throttle|idempotency|dedup|concurrency' --type ts --type js

Repository: afuhflynn/code-reverb

Length of output: 884


🏁 Script executed:

# Check for Inngest event definitions and handlers related to PR summary and review
rg -n 'pr\.summary|pr\.review|pullRequest.*summary|pullRequest.*review' --type ts --type js

Repository: afuhflynn/code-reverb

Length of output: 1157


🏁 Script executed:

# Look for the Inngest function definitions
fd -t f -e ts -e js 'inngest' | head -20

Repository: afuhflynn/code-reverb

Length of output: 79


🏁 Script executed:

# Check the structure of the repository to understand the architecture
git ls-files | grep -E '(inngest|event|webhook)' | head -30

Repository: afuhflynn/code-reverb

Length of output: 216


🏁 Script executed:

# Read the webhook handler to check for deduplication logic
cat -n app/api/webhooks/github/route.ts | head -160

Repository: afuhflynn/code-reverb

Length of output: 6005


🏁 Script executed:

# Read the Inngest functions to see concurrency and event handling
cat -n inngest/functions/index.ts | sed -n '320,430p'

Repository: afuhflynn/code-reverb

Length of output: 3799


🏁 Script executed:

# Check lib/inngest.ts to understand the setup
cat -n lib/inngest.ts

Repository: afuhflynn/code-reverb

Length of output: 246


🏁 Script executed:

# Read lib/ai/actions/index.ts to see how events are triggered
cat -n lib/ai/actions/index.ts | sed -n '1,100p'

Repository: afuhflynn/code-reverb

Length of output: 3152


🏁 Script executed:

# Look for the generatePullRequestSummary and reviewPullRequest functions
rg -n -A 15 'export.*generatePullRequestSummary|export.*reviewPullRequest' lib/ai/actions/index.ts

Repository: afuhflynn/code-reverb

Length of output: 874


🏁 Script executed:

# Read the full generatePullRequestSummary function
cat -n lib/ai/actions/index.ts | sed -n '139,250p'

Repository: afuhflynn/code-reverb

Length of output: 1977


Concurrent execution recommended for independent operations.

The triggering on "synchronized" is intentional and processed through Inngest with concurrency limits (summarize-pr: 20, generate-review: 5). However, you're making sequential API calls in the webhook handler — consider parallelizing these with Promise.all() since they're independent operations:

if (action === "opened" || action === "synchronized") {
  await Promise.all([
    generatePullRequestSummary(...).catch(error => 
      console.error(`Summarization failed for repo: ${repo} #${prNumber}: `, error)
    ),
    reviewPullRequest(...).catch(error =>
      console.error(`Review failed for repo: ${repo} #${prNumber}: `, error)
    ),
  ]);
}

Also add webhook deduplication to handle GitHub's redelivery mechanism (webhook events can be redelivered). Consider tracking X-GitHub-Delivery header or adding idempotency keys to Inngest events to prevent duplicate processing.

🤖 Prompt for AI Agents
In app/api/webhooks/github/route.ts around lines 111 to 143 you run
generatePullRequestSummary and reviewPullRequest sequentially; make them run in
parallel with Promise.all to improve throughput and reduce latency, wrapping
each call with its own catch so one failure doesn’t block the other and logging
errors as before; additionally add webhook deduplication by reading the
X-GitHub-Delivery header (or generating an idempotency key) and checking/storing
that ID (or passing it to Inngest as an idempotency key) so redelivered events
are ignored or de-duplicated.

}

Expand Down