Skip to content

Commit 1eb73c7

Browse files
committed
Refactor Dependabot alert workflow to create issues for pull requests and automate merging. Enhanced issue creation with detailed metadata and improved duplicate detection.
1 parent 9818cf5 commit 1eb73c7

File tree

1 file changed

+97
-30
lines changed

1 file changed

+97
-30
lines changed
Lines changed: 97 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,138 @@
11
name: Dependabot high/critical alert issues
22

33
on:
4-
dependabot_alert:
5-
types: [created]
4+
pull_request:
5+
types: [opened, reopened, synchronize]
66

77
permissions:
88
issues: write
9-
security-events: read
10-
contents: read
9+
contents: write # was: read -> needed for merging
10+
pull-requests: write # was: read -> needed for merging
11+
checks: read
12+
statuses: read
1113

1214
jobs:
1315
create_issue_for_high_critical:
1416
runs-on: ubuntu-latest
15-
if: |
16-
github.event.alert.severity == 'high' ||
17-
github.event.alert.severity == 'critical'
17+
18+
if: github.event.pull_request.user.login == 'dependabot[bot]'
1819

1920
steps:
20-
- name: Create tracking issue for alert
21+
- name: Fetch Dependabot metadata
22+
id: metadata
23+
uses: dependabot/fetch-metadata@v2
24+
with:
25+
github-token: ${{ secrets.GITHUB_TOKEN }}
26+
27+
- name: Create tracking issue for advisory
2128
uses: actions/github-script@v7
29+
env:
30+
GHSA: ${{ steps.metadata.outputs.ghsa-id }}
31+
PACKAGE: ${{ steps.metadata.outputs.dependency-names }}
32+
PREVIOUS_VERSION: ${{ steps.metadata.outputs.previous-version }}
33+
NEW_VERSION: ${{ steps.metadata.outputs.new-version }}
34+
UPDATE_TYPE: ${{ steps.metadata.outputs.update-type }}
35+
DEPENDENCY_TYPE: ${{ steps.metadata.outputs.dependency-type }}
2236
with:
2337
github-token: ${{ secrets.GITHUB_TOKEN }}
2438
script: |
2539
const { owner, repo } = context.repo;
26-
const alert = context.payload.alert;
27-
28-
const severity = (alert.severity || 'unknown').toUpperCase();
29-
const pkg = alert.affected_package_name ||
30-
(alert.package && alert.package.name) ||
31-
'unknown-package';
32-
const ghsa = alert.ghsa_id ||
33-
alert.external_identifier ||
34-
'unknown-GHSA';
35-
const alertUrl = alert.html_url ||
36-
alert.url ||
37-
'(no URL provided)';
40+
const pr = context.payload.pull_request;
41+
42+
const pkg = process.env.PACKAGE || 'unknown-package';
43+
const ghsa = process.env.GHSA || '';
44+
const previousVersion = process.env.PREVIOUS_VERSION || 'unknown';
45+
const newVersion = process.env.NEW_VERSION || 'unknown';
46+
const updateType = process.env.UPDATE_TYPE || 'unknown';
47+
const dependencyType = process.env.DEPENDENCY_TYPE || 'unknown';
48+
const alertUrl = pr.html_url; // link to PR as the "alert" surface
3849
3950
const teamMention = '@Dopeamin';
4051
41-
const title = `[Dependabot] ${severity} vulnerability in ${pkg} (${ghsa})`;
52+
const title = ghsa
53+
? `[Dependabot] Advisory for ${pkg} (${ghsa})`
54+
: `[Dependabot] Update for ${pkg} (${previousVersion} → ${newVersion})`;
4255
43-
// Avoid duplicates: search by GHSA id in title
56+
// Avoid duplicates: search by GHSA id or package/version in title
57+
const duplicateQuery = ghsa
58+
? `repo:${owner}/${repo} "${ghsa}" in:title is:issue`
59+
: `repo:${owner}/${repo} "${pkg}" "${newVersion}" in:title is:issue`;
4460
const search = await github.rest.search.issuesAndPullRequests({
45-
q: `repo:${owner}/${repo} "${ghsa}" in:title is:issue`,
61+
q: duplicateQuery,
4662
});
4763
4864
if (search.data.total_count > 0) {
49-
console.log('Issue already exists for this alert, skipping.');
65+
console.log('Issue already exists for this advisory, skipping.');
5066
return;
5167
}
5268
69+
const details = [
70+
`- **Package**: \`${pkg}\``,
71+
`- **Update**: \`${previousVersion}\` → \`${newVersion}\``,
72+
`- **Update type**: ${updateType}`,
73+
`- **Dependency type**: ${dependencyType}`,
74+
`- **PR**: #${pr.number}`,
75+
];
76+
77+
if (ghsa) {
78+
details.splice(2, 0, `- **Advisory (GHSA)**: \`${ghsa}\``);
79+
}
80+
5381
const body = `${teamMention}
5482
55-
A new **${severity}** Dependabot alert was detected.
83+
A new Dependabot pull request requires attention.
5684
57-
- **Package**: \`${pkg}\`
58-
- **Advisory (GHSA)**: \`${ghsa}\`
59-
- **Alert URL**: ${alertUrl}
85+
${details.join('\n')}
6086
6187
This issue was created automatically by a GitHub Actions workflow.`;
6288
89+
const labels = ['dependabot'];
90+
if (ghsa) {
91+
labels.push('security');
92+
}
6393
await github.rest.issues.create({
6494
owner,
6595
repo,
6696
title,
6797
body,
68-
labels: ['security', 'dependabot', severity.toLowerCase()],
69-
98+
labels,
7099
assignees: ['Dopeamin'],
71100
});
101+
102+
auto_merge_dependabot:
103+
runs-on: ubuntu-latest
104+
if: github.event.pull_request.user.login == 'dependabot[bot]' || contains(github.event.pull_request.labels.*.name, 'auto-merge-test')
105+
106+
permissions:
107+
contents: write
108+
pull-requests: write
109+
checks: read
110+
statuses: read
111+
112+
steps:
113+
- name: Wait for all checks to complete
114+
uses: lewagon/wait-on-check-action@v1.3.3
115+
with:
116+
ref: ${{ github.event.pull_request.head.sha }}
117+
repo-token: ${{ secrets.GITHUB_TOKEN }}
118+
wait-interval: 10 # seconds between polls
119+
# optional: avoid waiting on THIS workflow itself
120+
running-workflow-name: "Dependabot high/critical alert issues"
121+
check-regexp: "^(?!.*(create_issue_for_high_critical|auto_merge_dependabot)).*$"
122+
123+
- name: Merge Dependabot PR
124+
uses: actions/github-script@v7
125+
with:
126+
github-token: ${{ secrets.GITHUB_TOKEN }}
127+
script: |
128+
const { owner, repo } = context.repo;
129+
const pr = context.payload.pull_request;
130+
131+
await github.rest.pulls.merge({
132+
owner,
133+
repo,
134+
pull_number: pr.number,
135+
merge_method: 'merge',
136+
});
137+
138+
core.info(`Merged Dependabot PR #${pr.number}`);

0 commit comments

Comments
 (0)