diff --git a/packages/sample/genaisrc/gai.genai.mts b/packages/sample/genaisrc/gai.genai.mts index 998f9ccd02..a41acaa488 100644 --- a/packages/sample/genaisrc/gai.genai.mts +++ b/packages/sample/genaisrc/gai.genai.mts @@ -1,19 +1,22 @@ /* spellchecker: disable */ +// Script for analyzing GitHub Action runs to determine the cause of a failure. script({ title: "GitHub Action Investigator", - description: - "Analyze GitHub Action runs to find the root cause of a failure", + description: "Analyze GitHub Action runs to find the root cause of a failure", parameters: { - workflow: { type: "string" }, - failure_run_id: { type: "number" }, - success_run_id: { type: "number" }, - branch: { type: "string" }, + workflow: { type: "string" }, // Workflow name + failure_run_id: { type: "number" }, // ID of the failed run + success_run_id: { type: "number" }, // ID of the successful run + branch: { type: "string" }, // Branch name }, system: ["system", "system.files"], }) +// Assign the 'workflow' parameter from environment variables let workflow = env.vars.workflow + +// If no workflow provided, select from available workflows if (!workflow) { const workflows = await github.listWorkflows() workflow = await host.select( @@ -23,39 +26,54 @@ if (!workflow) { if (!workflow) cancel("No workflow selected") } +// Assign failure and success run IDs from environment variables const ffid = env.vars.failure_run_id const lsid = env.vars.success_run_id + +// Retrieve repository information const { owner, repo, refName } = await github.info() +// Assign branch name, defaulting to current reference name if not provided let branch = env.vars.branch || refName + +// If no branch provided, select from available branches if (!branch) { const branches = await github.listBranches() branch = await host.select("Select a branch", branches) if (!branch) cancel("No branch selected") } +// List workflow runs for the specified workflow and branch const runs = await github.listWorkflowRuns(workflow, { branch }) if (!runs.length) cancel("No runs found") -// find build +// Find the index of the failed run using the provided or default criteria let ffi = ffid ? runs.findIndex(({ id }) => id === ffid) : runs.findIndex(({ conclusion }) => conclusion === "failure") + +// Default to the first run if no failed run is found if (ffi < 0) ffi = 0 const ff = runs[ffi] + +// Log details of the failed run console.log( ` run: ${ff.id}, ${ff.conclusion}, ${ff.created_at}, ${ff.head_sha}, ${ff.html_url}` ) +// Find the index of the last successful run before the failure const lsi = lsid ? runs.findIndex(({ id }) => id === lsid) - : // last success preceding the build - runs.slice(ffi).findIndex(({ conclusion }) => conclusion === "success") + : runs.slice(ffi).findIndex(({ conclusion }) => conclusion === "success") + const ls = runs[lsi] if (ls) { + // Log details of the last successful run console.log( ` last success: ${ls.id}, ${ls.conclusion}, ${ls.created_at}, ${ls.head_sha}, ${ls.html_url}` ) + + // Execute git diff between the last success and failed run commits const gitDiff = await host.exec( `git diff ${ls.head_sha} ${ff.head_sha} -- . :!**/genaiscript.d.ts` ) @@ -67,14 +85,16 @@ if (ls) { }) } -// download logs +// Download logs of the failed job const ffjobs = await github.listWorkflowJobs(ff.id) const ffjob = ffjobs.find(({ conclusion }) => conclusion === "failure") ?? ffjobs[0] const fflog = ffjob.content if (!fflog) cancel("No logs found") console.log(`> run log: ${(fflog.length / 1000) | 0}kb ${ffjob.logs_url}`) + if (!ls) { + // Define log content if no last successful run is available def("LOG", fflog, { maxTokens: 20000, lineNumbers: false }) } else { const lsjobs = await github.listWorkflowJobs(ls.id) @@ -87,13 +107,15 @@ if (!ls) { `> last success log: ${(lslog.length / 1000) | 0}kb ${lsjob.logs_url}` ) - // include difss + // Generate a diff of logs between the last success and failed runs defDiff("LOG_DIFF", lslog, fflog, { maxTokens: 20000, lineNumbers: false, }) } } + +// Instruction for generating a report based on the analysis $`Your are an expert software engineer and you are able to analyze the logs and find the root cause of the failure. ${ls ? "- GIT_DIFF contains a diff of 2 run commits" : ""} @@ -109,6 +131,7 @@ If you cannot find the root cause, stop. Generate a diff with suggested fixes. Use a diff format. - If you cannot locate the error, do not generate a diff.` +// Write the investigator report writeText( `## Investigator report - [run failure](${ff.html_url})