Skip to content
Merged
Show file tree
Hide file tree
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
1 change: 0 additions & 1 deletion app/api/webhooks/github/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,6 @@ export async function POST(request: NextRequest) {
prNumber,
pull_request?.title,
pull_request?.body,
body?.account.id,
body?.installation?.id,
pull_request?.base?.sha,
pull_request?.head?.sha,
Expand Down
17 changes: 15 additions & 2 deletions lib/ai/actions/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
"use server";

import { auth } from "@/lib/auth";
import { getPullRequestDiff } from "@/lib/github-utils/actions";
import { inngest } from "@/lib/inngest";
import { prisma } from "@/lib/prisma";
import { headers } from "next/headers";

export async function reviewPullRequest(
owner: string,
Expand Down Expand Up @@ -142,7 +144,6 @@ export async function generatePullRequestSummary(
prNumber: number,
title: string,
description: string,
accountId: number,
installationId: number,
baseSha: string,
headSha: string,
Expand All @@ -151,6 +152,18 @@ export async function generatePullRequestSummary(
deletions: number
) {
try {
const session = await auth.api.getSession({ headers: await headers() });

if (!session) throw new Error("Unauthorized");
const account = await prisma.account.findFirst({
where: {
userId: session.user.id,
providerId: "github",
},
});

if (!account?.accessToken) throw new Error("No GitHub access token found");
Comment on lines +155 to +165
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 | 🔴 Critical

Session-based auth breaks webhook-triggered calls.

According to the AI summary, this function is called from a webhook handler when a PR is opened. Webhook requests from GitHub are server-to-server calls that don't carry user session cookies. The auth.api.getSession() call will return null for all webhook-triggered invocations, causing every PR summary request to fail with "Unauthorized".

The previous design (passing accountId as a parameter) allowed the webhook handler to resolve the account from webhook payload data (e.g., installationId). Consider one of:

  1. Restore the accountId parameter for webhook contexts and keep session auth only for user-initiated calls.
  2. Resolve account from installationId within this function instead of relying on user session.
  3. Create separate functions for webhook-triggered vs. user-triggered flows.
🔎 Example: Resolve account from installationId instead
 export async function generatePullRequestSummary(
   owner: string,
   repoName: string,
   prNumber: number,
   title: string,
   description: string,
   installationId: number,
   baseSha: string,
   headSha: string,
   changedFiles: number,
   additions: number,
-  deletions: number
+  deletions: number,
+  accountId?: string // Optional: passed by webhook handler
 ) {
   try {
-    const session = await auth.api.getSession({ headers: await headers() });
-
-    if (!session) throw new Error("Unauthorized");
-    const account = await prisma.account.findFirst({
-      where: {
-        userId: session.user.id,
-        providerId: "github",
-      },
-    });
-
-    if (!account?.accessToken) throw new Error("No GitHub access token found");
+    let resolvedAccountId = accountId;
+    
+    // If no accountId provided, try to resolve from session (user-initiated)
+    if (!resolvedAccountId) {
+      const session = await auth.api.getSession({ headers: await headers() });
+      if (!session) throw new Error("Unauthorized");
+      
+      const account = await prisma.account.findFirst({
+        where: {
+          userId: session.user.id,
+          providerId: "github",
+        },
+      });
+      if (!account?.accessToken) throw new Error("No GitHub access token found");
+      resolvedAccountId = account.accountId;
+    }

     await inngest.send({
       name: "pr.summary.requested",
       data: {
         owner,
         repo: repoName,
         prNumber,
         title: title ?? "",
         description: description ?? "",
-        accountId: account.accountId,
+        accountId: resolvedAccountId,
         installationId: installationId ?? null,

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In lib/ai/actions/index.ts around lines 155-165, session-based auth via
auth.api.getSession() breaks webhook-triggered calls (no cookies) and causes
"Unauthorized"; restore support for an explicit accountId parameter (or
installationId) so the caller can pass the account context for server-to-server
webhooks, and keep the session-based path as a fallback: first try to use a
provided accountId/installationId to look up the account (resolve installationId
-> account if needed), and only if none provided, use auth.api.getSession() to
derive the user and then fetch the account; ensure error messages reflect which
lookup failed.


await inngest.send({
name: "pr.summary.requested",
data: {
Expand All @@ -159,7 +172,7 @@ export async function generatePullRequestSummary(
prNumber,
title: title ?? "",
description: description ?? "",
accountId,
accountId: account.accountId,
installationId: installationId ?? null,
baseSha,
headSha,
Expand Down