mirror of
https://github.com/codeflash-ai/codeflash-internal.git
synced 2026-05-04 18:25:18 +00:00
## Summary - **Fix CI build failure**: Auth0Client crashes during Next.js prerendering when env vars aren't set. Returns a no-op stub (`getSession → null`) when domain is missing — semantically correct for static generation - **Lazy-load markdown libs (~260kb)**: ReactMarkdown, remarkGfm, and react-syntax-highlighter were eagerly imported in monaco-diff-viewer but only rendered when user expands "Generated Tests". Extracted into a dynamic component - **Parallelize repo detail query**: `getRepositoryById` ran the activity count sequentially after the repo lookup. Since `repoId` is already available, all three queries now run in parallel ## Test plan - [ ] CI `build` check passes (was failing since #2598) - [ ] Trace page still renders generated tests correctly when expanded - [ ] Repository detail page loads correctly with activity status
376 lines
12 KiB
TypeScript
376 lines
12 KiB
TypeScript
import { getInstallationOctokitByOwner, isUserCollaborator } from "../github/github-utils.js"
|
|
import { githubApp } from "../github/github-app.js"
|
|
import { Request, Response } from "express"
|
|
import { parseAndCreateOptimizationsDict } from "../github/pr-changes-utils.js"
|
|
import { posthog } from "../analytics.js"
|
|
import { userNickname } from "../auth0-mgmt.js"
|
|
import { logger } from "../utils/logger.js"
|
|
import {
|
|
missingRequiredFields,
|
|
unauthorized,
|
|
githubInstallationError,
|
|
githubNotCollaborator,
|
|
githubPrNotFound,
|
|
internalServerError,
|
|
} from "../exceptions/index.js"
|
|
|
|
// Dependencies interface for easier testing
|
|
export interface VerifyExistingOptimizationsDependencies {
|
|
getInstallationOctokitByOwner: typeof getInstallationOctokitByOwner
|
|
githubApp: typeof githubApp
|
|
parseAndCreateOptimizationsDict: typeof parseAndCreateOptimizationsDict
|
|
posthog: typeof posthog
|
|
userNickname: typeof userNickname
|
|
isUserCollaborator: typeof isUserCollaborator
|
|
}
|
|
|
|
// Default dependencies
|
|
let dependencies: VerifyExistingOptimizationsDependencies = {
|
|
getInstallationOctokitByOwner,
|
|
githubApp,
|
|
parseAndCreateOptimizationsDict,
|
|
posthog,
|
|
userNickname,
|
|
isUserCollaborator,
|
|
}
|
|
|
|
// For testing - allow dependency injection
|
|
export function setVerifyExistingOptimizationsDependencies(
|
|
deps: Partial<VerifyExistingOptimizationsDependencies>,
|
|
) {
|
|
dependencies = { ...dependencies, ...deps }
|
|
}
|
|
|
|
export function resetVerifyExistingOptimizationsDependencies() {
|
|
dependencies = {
|
|
getInstallationOctokitByOwner,
|
|
githubApp,
|
|
parseAndCreateOptimizationsDict,
|
|
posthog,
|
|
userNickname,
|
|
isUserCollaborator,
|
|
}
|
|
}
|
|
|
|
export async function verifyExistingOptimizations(req: Request, res: Response) {
|
|
try {
|
|
const { repo_owner, repo_name, pr_number } = req.body
|
|
const userId = (req as any).userId
|
|
|
|
logger.debug("Processing verify-existing-optimizations request", {
|
|
requestId: (req as any).requestId,
|
|
userId,
|
|
endpoint: "/cfapi/verify-existing-optimizations",
|
|
operation: "request_start",
|
|
repo_owner,
|
|
repo_name,
|
|
pr_number,
|
|
})
|
|
|
|
if (!repo_name || !repo_owner || !pr_number) {
|
|
throw missingRequiredFields("repo_name, repo_owner, pr_number")
|
|
}
|
|
|
|
const nickname: string | null = await dependencies.userNickname(userId)
|
|
if (nickname == null) {
|
|
throw unauthorized("")
|
|
}
|
|
|
|
const octokit = await dependencies.getInstallationOctokitByOwner(
|
|
dependencies.githubApp,
|
|
repo_owner,
|
|
repo_name,
|
|
userId,
|
|
)
|
|
if (octokit instanceof Error) {
|
|
throw githubInstallationError(octokit.message)
|
|
}
|
|
|
|
logger.info("Got installation Octokit for repository", {
|
|
requestId: (req as any).requestId,
|
|
userId,
|
|
endpoint: "/cfapi/verify-existing-optimizations",
|
|
operation: "octokit_installation",
|
|
repo_owner,
|
|
repo_name,
|
|
})
|
|
|
|
// Check collaborator status with error handling
|
|
try {
|
|
const isCollaborator = await dependencies.isUserCollaborator(
|
|
octokit,
|
|
repo_owner,
|
|
repo_name,
|
|
nickname,
|
|
)
|
|
if (!isCollaborator) {
|
|
// Emit human-readable console message for tests (using info for console.log output)
|
|
// Don't include userId in context to avoid logger appending " for user ..."
|
|
logger.info(`${nickname} is not a collaborator on ${repo_owner}/${repo_name}`, {
|
|
requestId: (req as any).requestId,
|
|
endpoint: "/cfapi/verify-existing-optimizations",
|
|
operation: "collaborator_verification",
|
|
repo_owner,
|
|
repo_name,
|
|
nickname,
|
|
})
|
|
throw githubNotCollaborator(`${repo_owner}/${repo_name}`)
|
|
}
|
|
} catch (error) {
|
|
if (error && typeof error === "object" && "getHttpStatus" in error) {
|
|
throw error
|
|
}
|
|
// Concatenate error in message for tests
|
|
logger.error(`Error checking collaborator status: ${error}`, {
|
|
requestId: (req as any).requestId,
|
|
userId,
|
|
endpoint: "/cfapi/verify-existing-optimizations",
|
|
operation: "collaborator_verification",
|
|
repo_owner,
|
|
repo_name,
|
|
nickname,
|
|
})
|
|
throw internalServerError("Failed to verify collaborator status")
|
|
}
|
|
|
|
// Get PR with specific 404 handling
|
|
// Note: GitHub returns 404 for both non-existent PRs and PRs the installation cannot access
|
|
let pr
|
|
try {
|
|
pr = await octokit.rest.pulls.get({
|
|
owner: repo_owner,
|
|
repo: repo_name,
|
|
pull_number: pr_number,
|
|
})
|
|
} catch (error: any) {
|
|
if (error.status === 404) {
|
|
// Log additional context to help diagnose permission vs not-found issues
|
|
logger.warn(
|
|
`PR #${pr_number} returned 404 in ${repo_owner}/${repo_name}. This could mean the PR doesn't exist, or the GitHub App installation doesn't have access to it.`,
|
|
{
|
|
requestId: (req as any).requestId,
|
|
userId,
|
|
endpoint: "/cfapi/verify-existing-optimizations",
|
|
operation: "pr_not_found_or_no_access",
|
|
repo_owner,
|
|
repo_name,
|
|
pr_number,
|
|
nickname,
|
|
errorMessage: error.message,
|
|
errorResponse: error.response?.data,
|
|
},
|
|
)
|
|
throw githubPrNotFound(
|
|
`#${pr_number} in ${repo_owner}/${repo_name}. If the PR exists, ensure the GitHub App installation has access to this repository.`,
|
|
)
|
|
}
|
|
// Handle 403 (Forbidden) as a permissions issue
|
|
if (error.status === 403) {
|
|
logger.warn(
|
|
`Access forbidden to PR #${pr_number} in ${repo_owner}/${repo_name}. The GitHub App installation may not have sufficient permissions.`,
|
|
{
|
|
requestId: (req as any).requestId,
|
|
userId,
|
|
endpoint: "/cfapi/verify-existing-optimizations",
|
|
operation: "pr_access_forbidden",
|
|
repo_owner,
|
|
repo_name,
|
|
pr_number,
|
|
nickname,
|
|
errorMessage: error.message,
|
|
},
|
|
)
|
|
throw githubInstallationError(
|
|
`Access forbidden to PR #${pr_number} in ${repo_owner}/${repo_name}. Please ensure the GitHub App has the necessary permissions.`,
|
|
)
|
|
}
|
|
throw error // Re-throw to be caught by global handler
|
|
}
|
|
|
|
// Get PR comments with error handling
|
|
let pr_messages
|
|
try {
|
|
pr_messages = await octokit.rest.issues.listComments({
|
|
owner: repo_owner,
|
|
repo: repo_name,
|
|
issue_number: pr_number,
|
|
})
|
|
} catch (error) {
|
|
// Pass error object for tests
|
|
logger.error(
|
|
"Error getting PR messages:",
|
|
{
|
|
requestId: (req as any).requestId,
|
|
userId,
|
|
endpoint: "/cfapi/verify-existing-optimizations",
|
|
operation: "get_pr_messages",
|
|
repo_owner,
|
|
repo_name,
|
|
pr_number,
|
|
},
|
|
undefined,
|
|
error as Error,
|
|
)
|
|
throw internalServerError(`Failed to retrieve PR comments for ${repo_owner}/${repo_name}`)
|
|
}
|
|
|
|
// Get PR reviews with error handling
|
|
let pr_reviews
|
|
try {
|
|
pr_reviews = await octokit.rest.pulls.listReviews({
|
|
owner: repo_owner,
|
|
repo: repo_name,
|
|
pull_number: pr_number,
|
|
})
|
|
} catch (error) {
|
|
// Pass error object for tests
|
|
logger.error(
|
|
"Error getting PR reviews:",
|
|
{
|
|
requestId: (req as any).requestId,
|
|
userId,
|
|
endpoint: "/cfapi/verify-existing-optimizations",
|
|
operation: "get_pr_reviews",
|
|
repo_owner,
|
|
repo_name,
|
|
pr_number,
|
|
},
|
|
undefined,
|
|
error as Error,
|
|
)
|
|
throw internalServerError(`Failed to retrieve PR reviews for ${repo_owner}/${repo_name}`)
|
|
}
|
|
|
|
const reviewBodies: Array<{ body: string }> = []
|
|
for (const review of pr_reviews.data) {
|
|
// Add the main review body if it exists
|
|
if (review.body) {
|
|
reviewBodies.push({ body: review.body })
|
|
}
|
|
|
|
// Get review comments for this specific review
|
|
try {
|
|
const reviewComments = await octokit.rest.pulls.listCommentsForReview({
|
|
owner: repo_owner,
|
|
repo: repo_name,
|
|
pull_number: pr_number,
|
|
review_id: review.id,
|
|
})
|
|
// Add each review comment body
|
|
for (const comment of reviewComments.data) {
|
|
if (comment.body) {
|
|
reviewBodies.push({ body: comment.body })
|
|
}
|
|
}
|
|
} catch (error) {
|
|
// Emit explicit console message for tests
|
|
logger.error(
|
|
`Error getting review comments for review ${review.id}:`,
|
|
{
|
|
requestId: (req as any).requestId,
|
|
userId,
|
|
endpoint: "/cfapi/verify-existing-optimizations",
|
|
operation: "get_review_comments",
|
|
repo_owner,
|
|
repo_name,
|
|
pr_number,
|
|
reviewId: review.id,
|
|
},
|
|
undefined,
|
|
error as Error,
|
|
)
|
|
// Continue with other reviews even if one fails
|
|
}
|
|
}
|
|
|
|
// Also get all review comments (not tied to a specific review)
|
|
try {
|
|
const allReviewComments = await octokit.rest.pulls.listReviewComments({
|
|
owner: repo_owner,
|
|
repo: repo_name,
|
|
pull_number: pr_number,
|
|
})
|
|
for (const comment of allReviewComments.data) {
|
|
if (comment.body) {
|
|
reviewBodies.push({ body: comment.body })
|
|
}
|
|
}
|
|
} catch (error) {
|
|
// Emit explicit console message for tests
|
|
logger.error(
|
|
"Error getting all review comments:",
|
|
{
|
|
requestId: (req as any).requestId,
|
|
userId,
|
|
endpoint: "/cfapi/verify-existing-optimizations",
|
|
operation: "get_all_review_comments",
|
|
repo_owner,
|
|
repo_name,
|
|
pr_number,
|
|
},
|
|
undefined,
|
|
error as Error,
|
|
)
|
|
// Continue even if this fails
|
|
}
|
|
|
|
const prBody = pr.data.body || ""
|
|
const validComments = pr_messages.data.filter(
|
|
(comment: { body?: string }) => comment.body !== undefined,
|
|
) as Array<{ body: string }>
|
|
const allComments = [...validComments, ...reviewBodies]
|
|
const optimizations_dict = dependencies.parseAndCreateOptimizationsDict(prBody, allComments)
|
|
|
|
if (Object.keys(optimizations_dict).length === 0) {
|
|
return res.status(200).json({ error: "No optimizations found for this PR" })
|
|
}
|
|
|
|
const response_dict: Record<string, string[]> = {}
|
|
for (const key in optimizations_dict) {
|
|
response_dict[key] = Array.from(optimizations_dict[key])
|
|
}
|
|
|
|
dependencies.posthog?.capture({
|
|
distinctId: userId,
|
|
event: `cfapi-github-pr-optimization`,
|
|
properties: {
|
|
repo_owner,
|
|
repo_name,
|
|
pr_number,
|
|
},
|
|
})
|
|
|
|
return res.status(200).json(response_dict)
|
|
} catch (error) {
|
|
// Re-throw AppExceptions to be handled by GlobalExceptionHandler
|
|
if (error && typeof error === "object" && "getHttpStatus" in error) {
|
|
throw error
|
|
}
|
|
|
|
// Emit specific console message expected by tests (stringified for single-arg output)
|
|
// Note: Error object is still passed for Sentry, but test mode outputs stringified version
|
|
// Use String(error) to match test expectation of ${error} format
|
|
const errorStr = String(error)
|
|
logger.errorWithSentry(
|
|
`Error in /cfapi/verify-existing-optimizations: ${errorStr}`,
|
|
{
|
|
requestId: (req as any).requestId,
|
|
userId: (req as any).userId,
|
|
endpoint: "/cfapi/verify-existing-optimizations",
|
|
operation: "verify_existing_optimizations",
|
|
},
|
|
{
|
|
repo_owner: req.body?.repo_owner,
|
|
repo_name: req.body?.repo_name,
|
|
pr_number: req.body?.pr_number,
|
|
},
|
|
error as Error,
|
|
)
|
|
|
|
if (error instanceof Error) {
|
|
throw internalServerError(`Error verifying existing optimizations: ${error.message}`)
|
|
} else {
|
|
throw internalServerError("Error verifying existing optimizations")
|
|
}
|
|
}
|
|
}
|