Skip to content

Commit

Permalink
Enhance GitHub Action failure analysis script with improved logging a…
Browse files Browse the repository at this point in the history
…nd parameter handling
  • Loading branch information
pelikhan committed Sep 27, 2024
1 parent 2e2e7ed commit 7306524
Showing 1 changed file with 34 additions and 11 deletions.
45 changes: 34 additions & 11 deletions packages/sample/genaisrc/gai.genai.mts
Original file line number Diff line number Diff line change
@@ -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(
Expand All @@ -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`
)
Expand All @@ -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)
Expand All @@ -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" : ""}
Expand All @@ -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})
Expand Down

0 comments on commit 7306524

Please sign in to comment.