mirror of
https://github.com/codeflash-ai/codeflash-internal.git
synced 2026-05-04 18:25:18 +00:00
### **PR Type** - Enhancement ___ ### **Description** - Add pre-commit hook integration and formatting commands - Introduce lint-staged and simple-git-hooks into package scripts - Update prettier configuration and ignore files for consistency - Refresh dependency lock files with new tooling entries ___ ### **Changes walkthrough** 📝 <table><thead><tr><th></th><th align="left">Relevant files</th></tr></thead><tbody><tr><td><strong>Dependencies</strong></td><td><details><summary>2 files</summary><table> <tr> <td><strong>package-lock.json</strong><dd><code>Update dependency lock with new tooling entries</code> </dd></td> <td><a href="https://github.com/codeflash-ai/codeflash-internal/pull/1499/files#diff-54c17cef859f033fc84a59da2e977235ebc494943710c25d132e310ec500c5ef">+754/-2</a> </td> </tr> <tr> <td><strong>package-lock.json</strong><dd><code>Refresh package lock with lint and formatting tools</code> </dd></td> <td><a href="https://github.com/codeflash-ai/codeflash-internal/pull/1499/files#diff-75446c74353509ca0232d6a1350aef075ced8f72bd568e9bafa09cf255683142">+743/-0</a> </td> </tr> </table></details></td></tr><tr><td><strong>Configuration changes</strong></td><td><details><summary>4 files</summary><table> <tr> <td><strong>package.json</strong><dd><code>Add formatting, lint and pre-commit hook scripts</code> </dd></td> <td><a href="https://github.com/codeflash-ai/codeflash-internal/pull/1499/files#diff-4edec169b0f8d3312edaf35b5cc8521fe1edfa163ce174f60eff51906896601f">+34/-17</a> </td> </tr> <tr> <td><strong>package.json</strong><dd><code>Introduce formatting commands and pre-commit hooks</code> </dd></td> <td><a href="https://github.com/codeflash-ai/codeflash-internal/pull/1499/files#diff-53ddfb1f8a02f1231d3d15a2e694ffe1407d2cc01d3e685de5653b67fec571c7">+18/-1</a> </td> </tr> <tr> <td><strong>package.json</strong><dd><code>Integrate pre-commit hook and formatting configurations</code> </dd></td> <td><a href="https://github.com/codeflash-ai/codeflash-internal/pull/1499/files#diff-b0d32af9c2caaba1377ec3e924eb553105cdc86e244018ffc6a866c530523599">+20/-3</a> </td> </tr> <tr> <td><strong>settings.json</strong><dd><code>Enhance VSCode settings for auto-format and lint fixes</code> </dd></td> <td><a href="https://github.com/codeflash-ai/codeflash-internal/pull/1499/files#diff-a5de3e5871ffcc383a2294845bd3df25d3eeff6c29ad46e3a396577c413bf357">+13/-1</a> </td> </tr> </table></details></td></tr><tr><td><strong>Documentation</strong></td><td><details><summary>7 files</summary><table> <tr> <td><strong>.editorconfig</strong><dd><code>Add consistent editor settings for file formatting</code> </dd></td> <td><a href="https://github.com/codeflash-ai/codeflash-internal/pull/1499/files#diff-0947e2727d6bad8cd0ac4122f5314bb5b04e337393075bc4b5ef143b17fcbd5b">+32/-0</a> </td> </tr> <tr> <td><strong>.prettierrc</strong><dd><code>Update prettier config with extended formatting rules</code> </dd></td> <td><a href="https://github.com/codeflash-ai/codeflash-internal/pull/1499/files#diff-ce5b7ae243151fb6eb3db1799b95d5c50ce2fe5080e8365c7834f81e8a44aade">+10/-4</a> </td> </tr> <tr> <td><strong>.prettierrc</strong><dd><code>Update prettier settings for consistent code style</code> </dd></td> <td><a href="https://github.com/codeflash-ai/codeflash-internal/pull/1499/files#diff-e169a799a8a22863b844d1c816ebb5798c0bcf8151503b0329bf60a2b3050b03">+10/-4</a> </td> </tr> <tr> <td><strong>.prettierrc</strong><dd><code>Add new prettier configuration file</code> </dd></td> <td><a href="https://github.com/codeflash-ai/codeflash-internal/pull/1499/files#diff-7058ba9d421d7fa280582bcc9a2053e64ec0b2bb700ae46cb7073f295d154713">+10/-0</a> </td> </tr> <tr> <td><strong>.prettierignore</strong><dd><code>Extend ignore rules with node_modules and dist folders</code> </dd></td> <td><a href="https://github.com/codeflash-ai/codeflash-internal/pull/1499/files#diff-a33307d68affc99ba88b1b79308f622350c8306bdeac2368b70d99ce72a7c8fa">+3/-1</a> </td> </tr> <tr> <td><strong>.prettierignore</strong><dd><code>Add ignore patterns for node_modules and dist directories</code></dd></td> <td><a href="https://github.com/codeflash-ai/codeflash-internal/pull/1499/files#diff-8f0741d174231baef1746c1fdb003dc727bb4416e16e99166edc020670861c1d">+2/-0</a> </td> </tr> <tr> <td><strong>.prettierignore</strong><dd><code>Update ignore file to include node_modules and dist folders</code></dd></td> <td><a href="https://github.com/codeflash-ai/codeflash-internal/pull/1499/files#diff-e84a66c182e9d121fc156f4b50d606f385b591ed493f8c284628451d58907875">+2/-0</a> </td> </tr> </table></details></td></tr><tr><td><strong>Additional files</strong></td><td><details><summary>1 files</summary><table> <tr> <td><strong>package-lock.json</strong></td> <td><a href="https://github.com/codeflash-ai/codeflash-internal/pull/1499/files#diff-0214c85d1717ad8b736e0296bb8cbf50db2aed068f31316d3c39904824a14f8e">+1026/-52</a></td> </tr> </table></details></td></tr></tr></tbody></table> ___ > <details> <summary> Need help?</summary><li>Type <code>/help how to ...</code> in the comments thread for any questions about PR-Agent usage.</li><li>Check out the <a href="https://qodo-merge-docs.qodo.ai/usage-guide/">documentation</a> for more information.</li></details>
192 lines
6.8 KiB
TypeScript
192 lines
6.8 KiB
TypeScript
import fs from "fs"
|
|
import path from "path"
|
|
import { fileURLToPath } from "url"
|
|
import { dirname } from "path"
|
|
|
|
const __filename = fileURLToPath(import.meta.url)
|
|
const __dirname = dirname(__filename)
|
|
const PR_HEADER_TEMPLATE = fs.readFileSync(
|
|
path.join(__dirname, "optimization_results_header.md"),
|
|
"utf8",
|
|
)
|
|
const PR_DETAILS_TEMPLATE = fs.readFileSync(
|
|
path.join(__dirname, "optimization_results_details.md"),
|
|
"utf8",
|
|
)
|
|
const PR_TEST_REPORT_TEMPLATE = fs.readFileSync(
|
|
path.join(__dirname, "optimization_results_test_report.md"),
|
|
"utf8",
|
|
)
|
|
|
|
const summaryLinesRegex = new RegExp(
|
|
/### 📄 ([\d,]+(\.\d+)?)% \(([\d,]+(\.\d+)?)x\) speedup for \*\*\*`(.+?)` in `(.+?)`\*\*\*/g,
|
|
)
|
|
type ReportTable = Record<
|
|
string,
|
|
{
|
|
passed: number
|
|
failed: number
|
|
}
|
|
>
|
|
|
|
type PrCommentFields = Record<string, any>
|
|
|
|
export function buildPrCommentBody(
|
|
prCommentFields: PrCommentFields,
|
|
existingTests: any,
|
|
generatedTests: any,
|
|
coverage_message: any,
|
|
newBranchName: string,
|
|
): string {
|
|
return (
|
|
`## ⚡️ Codeflash found optimizations for this PR\n` +
|
|
`${buildResultHeader(prCommentFields)}\n` +
|
|
`${buildResultDetails(prCommentFields)}\n` +
|
|
`${buildResultTestReport(prCommentFields, existingTests, generatedTests, coverage_message)}\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 buildResultHeader(fields: PrCommentFields): string {
|
|
return PR_HEADER_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): string {
|
|
return (
|
|
PR_DETAILS_TEMPLATE.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,
|
|
): 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"))) {
|
|
// Add a heading for the test type details
|
|
|
|
reportTableMd += `<details>\n`
|
|
reportTableMd += `<summary>${testType} Details</summary>\n\n`
|
|
|
|
// Include the relevant test code
|
|
if (testType.includes("Existing")) {
|
|
reportTableMd += "```python\n"
|
|
reportTableMd += existingTests.trim()
|
|
reportTableMd += "\n```\n"
|
|
} else if (testType.includes("Generated")) {
|
|
reportTableMd += "```python\n"
|
|
reportTableMd += generatedTests.trim()
|
|
reportTableMd += "\n```\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 PR_TEST_REPORT_TEMPLATE.replace(/\{report_table}/g, finalMarkdown)
|
|
}
|
|
|
|
export function parseAndCreateOptimizationsDict(
|
|
prBody: string,
|
|
prComments: { body: string }[],
|
|
): Record<string, Set<string>> {
|
|
const optimizations: Record<string, Set<string>> = {}
|
|
|
|
const textsToParse = [prBody, ...prComments.map(comment => comment.body)]
|
|
for (const text of textsToParse) {
|
|
let match
|
|
|
|
while ((match = summaryLinesRegex.exec(text)) !== null) {
|
|
const functionName = match[5]
|
|
const filePath = match[6]
|
|
|
|
if (!optimizations[filePath]) {
|
|
optimizations[filePath] = new Set()
|
|
}
|
|
optimizations[filePath].add(functionName)
|
|
}
|
|
}
|
|
|
|
return optimizations
|
|
}
|
|
|
|
export function buildDependentPrTitle(
|
|
functionName: string,
|
|
speedupPct: string,
|
|
pullNumber: number,
|
|
baseBranch: string,
|
|
): string {
|
|
return buildPrTitle(functionName, speedupPct) + ` in PR #${pullNumber} (\`${baseBranch}\`)`
|
|
}
|
|
|
|
export function buildPrTitle(functionName: string, speedupPct: string): string {
|
|
const type = functionName.includes(".") ? "method" : "function"
|
|
return `⚡️ Speed up ${type} \`${functionName}\` by ${speedupPct}`
|
|
}
|