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
536 lines
19 KiB
TypeScript
536 lines
19 KiB
TypeScript
import fs from "node:fs"
|
||
import path, { dirname } from "node:path"
|
||
import { fileURLToPath } from "node:url"
|
||
import { PrCommentFields } from "./create-pr-from-diffcontents.js"
|
||
import { OptimizationReview } from "../OptimizationReview.js"
|
||
|
||
export function generateOptimizationReviewTemplate(optimizationReview: string): string {
|
||
// Return empty string if optimizationReview is empty
|
||
if (!optimizationReview || optimizationReview === "") {
|
||
return ""
|
||
}
|
||
|
||
// Determine review rating level and color based on optimizationReview parameter
|
||
let review_rating: string
|
||
let color: string
|
||
|
||
switch (optimizationReview.toLowerCase()) {
|
||
case "high":
|
||
review_rating = "high"
|
||
color = "green"
|
||
break
|
||
case "medium":
|
||
review_rating = "medium"
|
||
color = "blue"
|
||
break
|
||
case "low":
|
||
review_rating = "low"
|
||
color = "yellow"
|
||
break
|
||
default:
|
||
// Default to low if unrecognized value
|
||
review_rating = "low"
|
||
color = "yellow"
|
||
}
|
||
|
||
// Generate the badge link with appropriate impact and color
|
||
const badgeUrl = `https://img.shields.io/badge/🎯_Optimization_Quality-${review_rating}-${color}`
|
||
|
||
return `\n`
|
||
}
|
||
|
||
// Helper function to create invisible HTML metadata
|
||
export function buildOptimizationMetadata(fields: PrCommentFields, trace_id: string): string {
|
||
const metadata: {
|
||
trace_id: string
|
||
function: string
|
||
file: string
|
||
speedup_pct: string
|
||
speedup_x: string
|
||
original_runtime: string
|
||
best_runtime: string
|
||
optimization_type: string
|
||
timestamp: string
|
||
version: string
|
||
original_async_throughput?: string
|
||
best_async_throughput?: string
|
||
} = {
|
||
trace_id,
|
||
function: fields.function_name,
|
||
file: fields.file_path,
|
||
speedup_pct: fields.speedup_pct,
|
||
speedup_x: fields.speedup_x,
|
||
original_runtime: fields.original_runtime,
|
||
best_runtime: fields.best_runtime,
|
||
optimization_type: fields.optimization_explanation
|
||
? fields.optimization_explanation.toLowerCase().includes("loop")
|
||
? "loop"
|
||
: fields.optimization_explanation.toLowerCase().includes("memory")
|
||
? "memory"
|
||
: fields.optimization_explanation.toLowerCase().includes("algorithm")
|
||
? "algorithm"
|
||
: "general"
|
||
: "general",
|
||
timestamp: new Date().toISOString(),
|
||
version: "1.0",
|
||
}
|
||
|
||
// Include throughput data for async functions
|
||
if (fields.original_async_throughput && fields.best_async_throughput) {
|
||
metadata.original_async_throughput = fields.original_async_throughput
|
||
metadata.best_async_throughput = fields.best_async_throughput
|
||
}
|
||
|
||
return `<!-- CODEFLASH_OPTIMIZATION: ${JSON.stringify(metadata)} -->`
|
||
}
|
||
|
||
const __filename = fileURLToPath(import.meta.url)
|
||
const __dirname = dirname(__filename)
|
||
|
||
// moving it to lazy load the files
|
||
let _PR_HEADER_TEMPLATE: string | undefined
|
||
let _PR_REVIEW_HEADER_TEMPLATE: string | undefined
|
||
let _PR_DETAILS_TEMPLATE: string | undefined
|
||
let _PR_DETAILS_TEMPLATE_COLLAPSED: string | undefined
|
||
let _PR_TEST_REPORT_TEMPLATE: string | undefined
|
||
let _PR_BENCHMARK_INFO_TEMPLATE: string | undefined
|
||
|
||
const getPrHeaderTemplate = (): string => {
|
||
if (_PR_HEADER_TEMPLATE === undefined) {
|
||
_PR_HEADER_TEMPLATE = fs.readFileSync(
|
||
path.join(__dirname, "optimization_results_header.md"),
|
||
"utf8",
|
||
)
|
||
}
|
||
return _PR_HEADER_TEMPLATE
|
||
}
|
||
|
||
const getPrReviewHeaderTemplate = (): string => {
|
||
if (_PR_REVIEW_HEADER_TEMPLATE === undefined) {
|
||
_PR_REVIEW_HEADER_TEMPLATE = fs.readFileSync(
|
||
path.join(__dirname, "optimization_results_review_header.md"),
|
||
"utf8",
|
||
)
|
||
}
|
||
return _PR_REVIEW_HEADER_TEMPLATE
|
||
}
|
||
|
||
const getPrDetailsTemplate = (): string => {
|
||
if (_PR_DETAILS_TEMPLATE === undefined) {
|
||
_PR_DETAILS_TEMPLATE = fs.readFileSync(
|
||
path.join(__dirname, "optimization_results_details.md"),
|
||
"utf8",
|
||
)
|
||
}
|
||
return _PR_DETAILS_TEMPLATE
|
||
}
|
||
|
||
const getPrDetailsTemplateCollapsed = (): string => {
|
||
if (_PR_DETAILS_TEMPLATE_COLLAPSED === undefined) {
|
||
_PR_DETAILS_TEMPLATE_COLLAPSED = fs.readFileSync(
|
||
path.join(__dirname, "optimization_results_details_collapsed.md"),
|
||
"utf8",
|
||
)
|
||
}
|
||
return _PR_DETAILS_TEMPLATE_COLLAPSED
|
||
}
|
||
|
||
const getPrTestReportTemplate = (): string => {
|
||
if (_PR_TEST_REPORT_TEMPLATE === undefined) {
|
||
_PR_TEST_REPORT_TEMPLATE = fs.readFileSync(
|
||
path.join(__dirname, "optimization_results_test_report.md"),
|
||
"utf8",
|
||
)
|
||
}
|
||
return _PR_TEST_REPORT_TEMPLATE
|
||
}
|
||
|
||
const getPrBenchmarkInfoTemplate = (): string => {
|
||
if (_PR_BENCHMARK_INFO_TEMPLATE === undefined) {
|
||
_PR_BENCHMARK_INFO_TEMPLATE = fs.readFileSync(
|
||
path.join(__dirname, "optimization_results_benchmark_info.md"),
|
||
"utf8",
|
||
)
|
||
}
|
||
return _PR_BENCHMARK_INFO_TEMPLATE
|
||
}
|
||
|
||
const summaryLinesRegex = new RegExp(
|
||
/####\s*(?:📄|⚡️Codeflash found)?\s*([\d,]+(?:\.\d+)?)%\s*\(([\d,.]+)x\)\s*speedup for\s*[*_]*`([^`]+)`[*_]*(?:\s*in\s*`([^`]+)`)?/g,
|
||
)
|
||
|
||
type ReportTable = Record<
|
||
string,
|
||
{
|
||
passed: number
|
||
failed: number
|
||
}
|
||
>
|
||
|
||
export function buildPrCommentBody(
|
||
prCommentFields: PrCommentFields,
|
||
existingTests: any,
|
||
generatedTests: any,
|
||
coverage_message: string,
|
||
newBranchName: string,
|
||
replayTests: any,
|
||
concolicTests: any,
|
||
trace_id: string,
|
||
options: {
|
||
isUnifiedReview?: boolean
|
||
includeHeader?: boolean
|
||
isCollapsed?: boolean
|
||
} = { isUnifiedReview: false, includeHeader: true, isCollapsed: false },
|
||
): string {
|
||
const { isUnifiedReview, includeHeader, isCollapsed } = options
|
||
// Build benchmark info if available
|
||
const benchmarkInfo =
|
||
prCommentFields.benchmark_details && prCommentFields.benchmark_details.length > 0
|
||
? buildBenchmarkInfo(prCommentFields)
|
||
: ""
|
||
return (
|
||
`${buildOptimizationMetadata(prCommentFields, trace_id)}\n${
|
||
includeHeader ? `#### ⚡️ Codeflash found optimizations for this PR\n` : ""
|
||
}${buildResultHeader(prCommentFields, isUnifiedReview)}\n${
|
||
benchmarkInfo ? `${benchmarkInfo}\n` : ""
|
||
}${buildResultDetails(prCommentFields, isCollapsed)}\n` +
|
||
`${buildResultTestReport(
|
||
prCommentFields,
|
||
existingTests,
|
||
generatedTests,
|
||
coverage_message,
|
||
replayTests,
|
||
concolicTests,
|
||
)}\n` +
|
||
`${buildMergeBranchMsg(newBranchName)}\n`
|
||
)
|
||
}
|
||
|
||
export function buildMergeBranchMsg(newBranchName: string): string {
|
||
if (newBranchName?.length > 0) {
|
||
return `To test or edit this optimization locally ` + `\`git merge ${newBranchName}\`\n\n`
|
||
}
|
||
return ""
|
||
}
|
||
|
||
export function buildBenchmarkInfo(fields: PrCommentFields): string {
|
||
if (!fields.benchmark_details || fields.benchmark_details.length === 0) {
|
||
return ""
|
||
}
|
||
|
||
// Separate benchmarks into improved and degraded categories
|
||
const improvedBenchmarks = fields.benchmark_details.filter(detail => detail.speedup_percent > 0)
|
||
const degradedBenchmarks = fields.benchmark_details.filter(detail => detail.speedup_percent <= 0)
|
||
|
||
// Build improved benchmarks table if there are any
|
||
let improvedBenchmarkInfo = ""
|
||
if (improvedBenchmarks.length > 0) {
|
||
improvedBenchmarkInfo = "\n\n"
|
||
improvedBenchmarkInfo +=
|
||
"| Benchmark File :: Function | Original Runtime | Expected New Runtime | Speedup |\n"
|
||
improvedBenchmarkInfo += "| :--- | ---: | ---: | ---: |\n"
|
||
|
||
for (const detail of improvedBenchmarks) {
|
||
const benchmarkName = `${detail.benchmark_name}::${detail.test_function}`
|
||
improvedBenchmarkInfo += `| ${benchmarkName} | ${detail.original_timing} | ${detail.expected_new_timing} | **${detail.speedup_percent.toFixed(2)}%** |\n`
|
||
}
|
||
}
|
||
|
||
// Build degraded benchmarks table if there are any
|
||
let degradedBenchmarkInfo = ""
|
||
if (degradedBenchmarks.length > 0) {
|
||
degradedBenchmarkInfo = "\n\n"
|
||
degradedBenchmarkInfo +=
|
||
"| Benchmark File :: Function | Original Runtime | Expected New Runtime | Slowdown |\n"
|
||
degradedBenchmarkInfo += "| :--- | ---: | ---: | ---: |\n"
|
||
|
||
for (const detail of degradedBenchmarks) {
|
||
const benchmarkName = `${detail.benchmark_name}::${detail.test_function}`
|
||
// Use absolute value to show slowdown as a positive percentage
|
||
const slowdownPercent = Math.abs(detail.speedup_percent)
|
||
degradedBenchmarkInfo += `| ${benchmarkName} | ${detail.original_timing} | ${detail.expected_new_timing} | **${slowdownPercent.toFixed(2)}%** |\n`
|
||
}
|
||
}
|
||
|
||
// Replace placeholders in template
|
||
let result = getPrBenchmarkInfoTemplate()
|
||
|
||
// Replace improved benchmark info or remove the section if no improvements
|
||
if (improvedBenchmarks.length > 0) {
|
||
result = result.replace(/\{benchmark_info_improved\}/g, improvedBenchmarkInfo)
|
||
} else {
|
||
// Remove the entire improved section including header
|
||
result = result.replace(
|
||
/###\s+⚡️\s+This change will improve the performance of the following benchmarks:[\s\S]*?\{benchmark_info_improved\}\s*/g,
|
||
"",
|
||
)
|
||
}
|
||
// Replace degraded benchmark info or remove the section if no degradations
|
||
if (degradedBenchmarks.length > 0) {
|
||
result = result.replace(/\{benchmark_info_degraded\}/g, degradedBenchmarkInfo)
|
||
} else {
|
||
// Remove the entire degraded section including header
|
||
result = result.replace(
|
||
/###\s+🔻\s+This change will degrade the performance of the following benchmarks:[\s\S]*?\{benchmark_info_degraded\}\s*/g,
|
||
"",
|
||
)
|
||
}
|
||
return result
|
||
}
|
||
|
||
// Update the buildResultHeader function to use the new benchmark info function
|
||
export function buildResultHeader(fields: PrCommentFields, isUnifiedReview?: boolean): string {
|
||
const template = isUnifiedReview ? getPrReviewHeaderTemplate() : getPrHeaderTemplate()
|
||
|
||
return template
|
||
.replace(/\{best_runtime}/g, fields.best_runtime)
|
||
.replace(/\{original_runtime}/g, fields.original_runtime)
|
||
.replace(/\{function_name}/g, fields.function_name)
|
||
.replace(/\{file_path}/g, fields.file_path)
|
||
.replace(/\{speedup_x}/g, fields.speedup_x)
|
||
.replace(/\{speedup_pct}/g, fields.speedup_pct)
|
||
.replace(/\{num_runs}/g, fields.loop_count)
|
||
}
|
||
|
||
export function buildResultDetails(fields: PrCommentFields, isCollapsed: boolean = false): string {
|
||
return isCollapsed
|
||
? `${getPrDetailsTemplateCollapsed().replace(
|
||
/\{optimization_explanation}/g,
|
||
fields.optimization_explanation,
|
||
)}\n`
|
||
: `${getPrDetailsTemplate().replace(
|
||
/\{optimization_explanation}/g,
|
||
fields.optimization_explanation,
|
||
)}\n`
|
||
}
|
||
export function buildResultFooter(newBranchName: string): string {
|
||
return (
|
||
`To edit these changes ` +
|
||
`\`git checkout ${newBranchName}\` and push.\n\n` +
|
||
`[](https://codeflash.ai)`
|
||
)
|
||
}
|
||
|
||
export function buildResultTestReport(
|
||
fields: PrCommentFields,
|
||
existingTests: string,
|
||
generatedTests: string,
|
||
coverage_message: string,
|
||
replayTests: string,
|
||
concolicTests: string,
|
||
): string {
|
||
const reportTableDict: ReportTable = fields.report_table
|
||
|
||
let reportTableMd: string = ""
|
||
// Initialize the Markdown table
|
||
reportTableMd += "| Test | Status |\n"
|
||
reportTableMd += "| --------------------------- | ----------------- |\n"
|
||
|
||
// Loop through each test type and construct the table rows
|
||
for (const [testType, { passed = 0, failed = 0 }] of Object.entries(reportTableDict)) {
|
||
if (testType.includes("🎨")) {
|
||
continue
|
||
}
|
||
let status = ""
|
||
let detailsNote = ""
|
||
|
||
// Determine the status based on passed counts
|
||
if (passed > 0) {
|
||
status = `✅ **${passed} Passed**`
|
||
} else {
|
||
status = "🔘 **None Found**"
|
||
}
|
||
|
||
// If there are details, note that they are available below
|
||
if (passed > 0 && (testType.includes("Existing") || testType.includes("Generated"))) {
|
||
detailsNote = "See below"
|
||
} else {
|
||
detailsNote = ""
|
||
}
|
||
|
||
// Add the row to the Markdown table
|
||
reportTableMd += `| ${testType} | ${status} |\n`
|
||
}
|
||
reportTableMd += `|📊 Tests Coverage | ${coverage_message} |\n`
|
||
|
||
// Add detailed test outputs below the table
|
||
for (const [testType, { passed = 0, failed = 0 }] of Object.entries(reportTableDict)) {
|
||
// Only include details for Existing and Generated tests with results
|
||
if (
|
||
passed > 0 &&
|
||
(testType.includes("Existing") ||
|
||
testType.includes("Generated") ||
|
||
testType.includes("Replay") ||
|
||
testType.includes("Concolic"))
|
||
) {
|
||
// Add a heading for the test type details
|
||
reportTableMd += `<details>\n`
|
||
|
||
// Extract emoji if present at the start, then format as "[emoji] Click to see [name]"
|
||
const emojiMatch = /^(\p{Emoji_Presentation}|\p{Emoji}\uFE0F?)/u.exec(testType)
|
||
if (emojiMatch) {
|
||
const emoji = emojiMatch[0]
|
||
const testName = testType.slice(emoji.length).trim()
|
||
reportTableMd += `<summary>${emoji} Click to see ${testName}</summary>\n\n`
|
||
} else {
|
||
reportTableMd += `<summary>Click to see ${testType}</summary>\n\n`
|
||
}
|
||
|
||
// Include the relevant test code
|
||
if (testType.includes("Existing")) {
|
||
reportTableMd += existingTests.trim()
|
||
reportTableMd += "\n"
|
||
} else if (testType.includes("Replay")) {
|
||
reportTableMd += replayTests.trim()
|
||
reportTableMd += "\n"
|
||
} else if (testType.includes("Concolic")) {
|
||
reportTableMd += concolicTests.trim()
|
||
reportTableMd += "\n"
|
||
} else if (testType.includes("Generated")) {
|
||
const trimmedGeneratedTests = generatedTests.trim()
|
||
// Check if generatedTests already contains backticks
|
||
if (!trimmedGeneratedTests.includes("`")) {
|
||
// Wrap in Python markdown block
|
||
reportTableMd += `\`\`\`python\n${trimmedGeneratedTests}\n\`\`\``
|
||
} else {
|
||
reportTableMd += trimmedGeneratedTests
|
||
}
|
||
reportTableMd += "\n"
|
||
} else {
|
||
reportTableMd += "_No additional details available._\n"
|
||
}
|
||
|
||
reportTableMd += `\n</details>\n\n`
|
||
}
|
||
}
|
||
|
||
// Add the final markdown content (e.g., the feedback section)
|
||
const finalMarkdown = reportTableMd
|
||
|
||
return getPrTestReportTemplate().replace(/\{report_table}/g, finalMarkdown)
|
||
}
|
||
|
||
// Enhanced parser that supports both metadata and legacy regex parsing
|
||
export function parseAndCreateOptimizationsDict(
|
||
prBody: string,
|
||
prComments: Array<{ body: string }>,
|
||
): Record<string, Set<string>> {
|
||
const optimizations: Record<string, Set<string>> = {}
|
||
const textsToParse = [prBody, ...prComments.map(comment => comment.body)]
|
||
|
||
// New metadata regex for HTML comments
|
||
const metadataRegex = /<!--\s*CODEFLASH_OPTIMIZATION:\s*({.*?})\s*-->/g
|
||
|
||
for (const text of textsToParse) {
|
||
// First, try to parse new metadata format
|
||
let metadataMatch
|
||
while ((metadataMatch = metadataRegex.exec(text)) !== null) {
|
||
try {
|
||
const metadata = JSON.parse(metadataMatch[1])
|
||
const functionName = metadata.function
|
||
const filePath = metadata.file
|
||
|
||
if (functionName && filePath) {
|
||
optimizations[filePath] ||= new Set()
|
||
optimizations[filePath].add(functionName)
|
||
}
|
||
} catch (e) {
|
||
console.warn("Failed to parse optimization metadata:", metadataMatch[1])
|
||
}
|
||
}
|
||
|
||
// Fallback to legacy regex parsing for backward compatibility
|
||
let legacyMatch
|
||
while ((legacyMatch = summaryLinesRegex.exec(text)) !== null) {
|
||
const functionName = legacyMatch[3]
|
||
const filePath = legacyMatch[4]
|
||
|
||
if (functionName && filePath) {
|
||
optimizations[filePath] ||= new Set()
|
||
optimizations[filePath].add(functionName)
|
||
}
|
||
}
|
||
}
|
||
|
||
return optimizations
|
||
}
|
||
|
||
// Helper function to extract rich metadata from comments (future use)
|
||
export function parseOptimizationMetadata(
|
||
prBody: string,
|
||
prComments: Array<{ body: string }>,
|
||
): Array<{
|
||
function: string
|
||
file: string
|
||
speedup_pct: string
|
||
speedup_x: string
|
||
original_runtime: string
|
||
best_runtime: string
|
||
optimization_type: string
|
||
timestamp: string
|
||
version: string
|
||
}> {
|
||
const optimizations = []
|
||
const textsToParse = [prBody, ...prComments.map(comment => comment.body)]
|
||
const metadataRegex = /<!--\s*CODEFLASH_OPTIMIZATION:\s*({.*?})\s*-->/g
|
||
|
||
for (const text of textsToParse) {
|
||
let match
|
||
while ((match = metadataRegex.exec(text)) !== null) {
|
||
try {
|
||
const metadata = JSON.parse(match[1])
|
||
optimizations.push(metadata)
|
||
} catch (e) {
|
||
console.warn("Failed to parse optimization metadata:", match[1])
|
||
}
|
||
}
|
||
}
|
||
|
||
return optimizations
|
||
}
|
||
|
||
export function buildDependentPrTitle(
|
||
functionName: string,
|
||
speedupPct: string,
|
||
speedupX: string,
|
||
pullNumber: number,
|
||
baseBranch: string,
|
||
): string {
|
||
return `${buildPrTitle(functionName, speedupPct, speedupX)} in PR #${pullNumber} (\`${baseBranch}\`)`
|
||
}
|
||
|
||
export function buildPrTitle(functionName: string, speedupPct: string, speedupX: string): string {
|
||
const type = functionName.includes(".") ? "method" : "function"
|
||
let speedupValue = 0
|
||
if (speedupPct.includes("%")) {
|
||
speedupValue = parseInt(speedupPct.replace("%", ""))
|
||
}
|
||
// hide percent over 1000
|
||
const speed = speedupValue > 1000 ? speedupX : speedupPct
|
||
return `⚡️ Speed up ${type} \`${functionName}\` by ${speed}`
|
||
}
|
||
|
||
export function originalPRComment(
|
||
prCommentFields: PrCommentFields,
|
||
newPrNumber: string,
|
||
baseBranch: string,
|
||
optimizationReview: string,
|
||
): string {
|
||
const prCommentHeader = buildResultHeader(prCommentFields)
|
||
let optReviewBadge = generateOptimizationReviewTemplate(optimizationReview)
|
||
optReviewBadge &&= `\n\n${optReviewBadge}\n`
|
||
const isMediumReview = optimizationReview === OptimizationReview.MEDIUM
|
||
const reviewSection = isMediumReview
|
||
? `#### A new Optimization Review has been created.\n\n🔗 [Review here](https://app.codeflash.ai/review-optimizations/${newPrNumber})`
|
||
: `#### A dependent PR with the suggested changes has been created. Please review:\n\n- ### #${newPrNumber}`
|
||
return `
|
||
#### ⚡️ Codeflash found optimizations for this PR
|
||
${prCommentHeader}
|
||
${reviewSection}
|
||
${
|
||
!isMediumReview
|
||
? `If you approve, it will be merged into this PR (branch \`${baseBranch}\`).
|
||
`
|
||
: ""
|
||
}${optReviewBadge}`
|
||
}
|