name: Failure Notifications
on:
workflow_run:
workflows: ["CI/CD Pipeline", "Security Scanning", "Docker Build"]
types: [completed]
jobs:
notify-failures:
if: ${{ github.event.workflow_run.conclusion == 'failure' }}
runs-on: ubuntu-latest
permissions:
issues: write
actions: read
steps:
- name: Get workflow details
id: workflow-info
uses: actions/github-script@v7
with:
script: |
const workflowRun = context.payload.workflow_run;
const workflowName = workflowRun.name;
const runId = workflowRun.id;
const headBranch = workflowRun.head_branch;
const headSha = workflowRun.head_sha;
const htmlUrl = workflowRun.html_url;
// Get associated PRs
const { data: pulls } = await github.rest.pulls.list({
owner: context.repo.owner,
repo: context.repo.repo,
head: `${context.repo.owner}:${headBranch}`,
state: 'open'
});
const prNumbers = pulls.map(pr => pr.number);
core.setOutput('workflow_name', workflowName);
core.setOutput('run_id', runId);
core.setOutput('head_branch', headBranch);
core.setOutput('head_sha', headSha);
core.setOutput('html_url', htmlUrl);
core.setOutput('pr_numbers', JSON.stringify(prNumbers));
return {
workflowName,
runId,
headBranch,
headSha,
htmlUrl,
prNumbers
};
- name: Comment on associated PRs
if: fromJson(steps.workflow-info.outputs.pr_numbers)[0]
uses: actions/github-script@v7
with:
script: |
const prNumbers = JSON.parse('${{ steps.workflow-info.outputs.pr_numbers }}');
const workflowName = '${{ steps.workflow-info.outputs.workflow_name }}';
const htmlUrl = '${{ steps.workflow-info.outputs.html_url }}';
const headSha = '${{ steps.workflow-info.outputs.head_sha }}';
const comment = `## ❌ CI/CD Failure Alert
**Workflow Failed:** \`${workflowName}\`
**Commit:** \`${headSha.substring(0, 7)}\`
The \`${workflowName}\` workflow has failed. Please check the logs and fix the issues before merging.
📋 **[View Failed Run](${htmlUrl})**
### Common fixes:
- Check for linting errors: \`ruff check .\`
- Verify tests pass locally: \`pytest\`
- Check for import issues: \`python -c "import simplenote_mcp"\`
This comment will be automatically updated when the workflow passes.`;
for (const prNumber of prNumbers) {
await github.rest.issues.createComment({
issue_number: prNumber,
owner: context.repo.owner,
repo: context.repo.repo,
body: comment
});
}
- name: Create issue for main branch failures
if: steps.workflow-info.outputs.head_branch == 'main' && !fromJson(steps.workflow-info.outputs.pr_numbers)[0]
uses: actions/github-script@v7
with:
script: |
const workflowName = '${{ steps.workflow-info.outputs.workflow_name }}';
const htmlUrl = '${{ steps.workflow-info.outputs.html_url }}';
const headSha = '${{ steps.workflow-info.outputs.head_sha }}';
const title = `🚨 ${workflowName} failing on main branch`;
const body = `## Critical CI/CD Failure on Main Branch
**Workflow:** \`${workflowName}\`
**Commit:** \`${headSha}\`
**Failed Run:** ${htmlUrl}
### Impact
This failure affects the main branch and may impact:
- New PRs and merges
- Docker image builds
- Security scanning
- Release processes
### Action Required
This needs immediate attention to restore CI/CD pipeline health.
**Auto-generated by failure notification workflow**`;
await github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: title,
body: body,
labels: ['ci-failure', 'priority-high', 'main-branch']
});
notify-recovery:
if: ${{ github.event.workflow_run.conclusion == 'success' }}
runs-on: ubuntu-latest
permissions:
issues: write
actions: read
steps:
- name: Check for recovery from previous failures
uses: actions/github-script@v7
with:
script: |
const workflowName = context.payload.workflow_run.name;
const headBranch = context.payload.workflow_run.head_branch;
// Check if there were recent failures for this workflow
const { data: runs } = await github.rest.actions.listWorkflowRuns({
owner: context.repo.owner,
repo: context.repo.repo,
workflow_id: context.payload.workflow_run.workflow_id,
branch: headBranch,
per_page: 5
});
const recentFailures = runs.workflow_runs.slice(1, 3).some(run => run.conclusion === 'failure');
if (recentFailures) {
console.log(`🎉 ${workflowName} has recovered from recent failures on ${headBranch}`);
// Close related failure issues if this is main branch
if (headBranch === 'main') {
const { data: issues } = await github.rest.issues.listForRepo({
owner: context.repo.owner,
repo: context.repo.repo,
labels: 'ci-failure,main-branch',
state: 'open'
});
for (const issue of issues) {
if (issue.title.includes(workflowName)) {
await github.rest.issues.createComment({
issue_number: issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `✅ **Workflow Recovery Confirmed**\n\nThe \`${workflowName}\` workflow is now passing on the main branch. Closing this issue.\n\n**Auto-resolved by failure notification workflow**`
});
await github.rest.issues.update({
issue_number: issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
state: 'closed',
labels: ['ci-failure', 'main-branch', 'resolved']
});
}
}
}
}