Notify on Workflow Failure #104
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Notify on Workflow Failure | |
on: | |
workflow_run: | |
workflows: ["Process new code merged to main"] | |
types: | |
- completed | |
permissions: | |
issues: write | |
jobs: | |
notifyFailure: | |
runs-on: ubuntu-latest | |
if: ${{ github.event.workflow_run.conclusion == 'failure' }} | |
steps: | |
- name: Fetch Workflow Run Jobs | |
id: fetch-workflow-jobs | |
uses: actions/github-script@v7 | |
with: | |
script: | | |
const runId = "${{ github.event.workflow_run.id }}"; | |
const jobsData = await github.rest.actions.listJobsForWorkflowRun({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
run_id: runId, | |
}); | |
return jobsData.data; | |
- name: Process Each Failed Job | |
uses: actions/github-script@v7 | |
with: | |
script: | | |
const jobs = ${{ steps.fetch-workflow-jobs.outputs.result }}; | |
const headCommit = "${{ github.event.workflow_run.head_commit.id }}"; | |
const prData = await github.rest.repos.listPullRequestsAssociatedWithCommit({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
commit_sha: headCommit, | |
}); | |
const pr = prData.data[0]; | |
const prLink = pr.html_url; | |
const prAuthor = pr.user.login; | |
const prMerger = "${{ github.event.workflow_run.actor.login }}"; | |
const failureLabel = 'Workflow Failure'; | |
for (let i = 0; i < jobs.total_count; i++) { | |
if (jobs.jobs[i].conclusion == 'failure') { | |
const jobName = jobs.jobs[i].name; | |
const jobLink = jobs.jobs[i].html_url; | |
const issues = await github.rest.issues.listForRepo({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
labels: failureLabel, | |
state: 'open' | |
}); | |
const existingIssue = issues.data.find(issue => issue.title.includes(jobName)); | |
if (!existingIssue) { | |
const annotations = await github.rest.checks.listAnnotations({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
check_run_id: jobs.jobs[i].id, | |
}); | |
let errorMessage = ""; | |
for(let j = 0; j < annotations.data.length; j++) { | |
errorMessage += annotations.data[j].annotation_level + ": "; | |
errorMessage += annotations.data[j].message + "\n"; | |
} | |
const issueTitle = `Investigate workflow job failing on main: ${ jobName }`; | |
const issueBody = `🚨 **Failure Summary** 🚨:\n\n` + | |
`- **📋 Job Name**: [${ jobName }](${ jobLink })\n` + | |
`- **🔧 Failure in Workflow**: Process new code merged to main\n` + | |
`- **🔗 Triggered by PR**: [PR Link](${ prLink })\n` + | |
`- **👤 PR Author**: @${ prAuthor }\n` + | |
`- **🤝 Merged by**: @${ prMerger }\n` + | |
`- **🐛 Error Message**: \n ${errorMessage}\n\n` + | |
`⚠️ **Action Required** ⚠️:\n\n` + | |
`🛠️ A recent merge appears to have caused a failure in the job named [${ jobName }](${ jobLink }).\n` + | |
`This issue has been automatically created and labeled with \`${ failureLabel }\` for investigation. \n\n` + | |
`👀 **Please look into the following**:\n` + | |
`1. **Why the PR caused the job to fail?**\n` + | |
`2. **Address any underlying issues.**\n\n` + | |
`🐛 We appreciate your help in squashing this bug!`; | |
await github.rest.issues.create({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
title: issueTitle, | |
body: issueBody, | |
labels: [failureLabel, 'Hourly'], | |
assignees: [prMerger] | |
}); | |
} | |
} | |
} |