Skip to content

Commit 9c6e2e4

Browse files
Merge pull request #121 from BranchMetrics/SDK-2032
[SDK-2032] Create Github Action to merge dependabot PRs
2 parents 98454c7 + a3e269f commit 9c6e2e4

File tree

1 file changed

+161
-0
lines changed

1 file changed

+161
-0
lines changed
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
name: Merge Dependabot PRs
2+
3+
on:
4+
schedule:
5+
- cron: "0 9 * * 1" # Run this workflow every Monday at 9:00
6+
workflow_dispatch:
7+
8+
jobs:
9+
merge:
10+
runs-on: ubuntu-latest
11+
12+
steps:
13+
- name: Get current on-call
14+
id: on-call
15+
run: |
16+
now=$(date -u +%Y-%m-%dT%H:%M:%SZ)
17+
end_time=$(date -u -d '+24 hour' +%Y-%m-%dT%H:%M:%SZ)
18+
19+
oncall=$(curl --request GET \
20+
--url "https://api.pagerduty.com/oncalls?since=$now&until=$end_time&schedule_ids[]=PQLHTOP" \
21+
--header 'Accept: application/vnd.pagerduty+json;version=2' \
22+
--header "Authorization: Token token=${{ secrets.PAGERDUTY_TOKEN }}" \
23+
--header 'Content-Type: application/json' )
24+
25+
engineer_name=$(echo "$oncall" | jq -r '.oncalls[0].user.summary')
26+
27+
declare -A engineer_to_slackid
28+
engineer_to_slackid=(
29+
["Nipun Singh"]="U02AMC70R6E"
30+
["Jagadeesh Karicherla"]="U038BDE0XUZ"
31+
["Gabe De Luna"]="U02MDA0PHK5"
32+
["Ernest Cho"]="UCV77QDSL"
33+
["Nidhi Dixit"]="U02GDFBP88N"
34+
)
35+
36+
slack_id=${engineer_to_slackid["$engineer_name"]}
37+
echo "oncall_slack_id=$slack_id" >> $GITHUB_OUTPUT
38+
39+
- name: Create PR
40+
uses: actions/github-script@v6
41+
id: create-pr
42+
with:
43+
script: |
44+
const uniqueBranchName = 'dependabot-combined-prs-' + Date.now().toString();
45+
const pulls = await github.paginate('GET /repos/:owner/:repo/pulls', {
46+
owner: context.repo.owner,
47+
repo: context.repo.repo
48+
});
49+
let branchesAndPRStrings = [];
50+
let baseBranch = null;
51+
let baseBranchSHA = null;
52+
for (const pull of pulls) {
53+
const branch = pull['head']['ref'];
54+
if (branch.startsWith('dependabot/')) {
55+
console.log('Branch matched prefix. Adding to array: ' + branch);
56+
const prString = '#' + pull['number'] + ' ' + pull['title'];
57+
branchesAndPRStrings.push({ branch, prString });
58+
baseBranch = pull['base']['ref'];
59+
baseBranchSHA = pull['base']['sha'];
60+
}
61+
}
62+
if (branchesAndPRStrings.length == 0) {
63+
core.setFailed('There are no open dependabot PRs.');
64+
return;
65+
}
66+
try {
67+
await github.rest.git.createRef({
68+
owner: context.repo.owner,
69+
repo: context.repo.repo,
70+
ref: 'refs/heads/' + uniqueBranchName,
71+
sha: baseBranchSHA
72+
});
73+
} catch (error) {
74+
console.log(error);
75+
core.setFailed('Failed to create combined branch');
76+
return;
77+
}
78+
79+
let combinedPRs = [];
80+
let mergeFailedPRs = [];
81+
for(const { branch, prString } of branchesAndPRStrings) {
82+
try {
83+
await github.rest.repos.merge({
84+
owner: context.repo.owner,
85+
repo: context.repo.repo,
86+
base: uniqueBranchName,
87+
head: branch,
88+
});
89+
console.log('Merged branch ' + branch);
90+
combinedPRs.push(prString);
91+
} catch (error) {
92+
console.log('Failed to merge branch ' + branch);
93+
mergeFailedPRs.push(prString);
94+
}
95+
}
96+
97+
console.log('Creating combined PR');
98+
const combinedPRsString = combinedPRs.join('\n');
99+
let body = '✅ This PR was created by the Merge Dependabot PRs action by combining the following dependabot PRs:\n' + combinedPRsString;
100+
if(mergeFailedPRs.length > 0) {
101+
const mergeFailedPRsString = mergeFailedPRs.join('\n');
102+
body += '\n\n⚠️ The following dependabot PRs were left out due to merge conflicts:\n' + mergeFailedPRsString
103+
}
104+
let response = await github.rest.pulls.create({
105+
owner: context.repo.owner,
106+
repo: context.repo.repo,
107+
title: 'Combined Dependabot PR',
108+
head: uniqueBranchName,
109+
base: baseBranch,
110+
body: body
111+
});
112+
console.log('Created combined PR: ' + response.data.html_url);
113+
core.setOutput('pr_url', response.data.html_url);
114+
core.setOutput('pr_list', combinedPRsString);
115+
116+
- name: Post to a Slack channel
117+
uses: slackapi/slack-github-action@v1.24.0
118+
id: slack
119+
with:
120+
channel-id: "C03RTLRKJQP"
121+
payload: |
122+
{
123+
"text": "Capacitor: New Dependabot PR Awaiting Review",
124+
"blocks": [
125+
{
126+
"type": "header",
127+
"text": {
128+
"type": "plain_text",
129+
"text":"📞🔧 Capacitor: New Dependabot PR Awaiting Review",
130+
"emoji": true
131+
}
132+
},
133+
{
134+
"type": "section",
135+
"text": {
136+
"type": "mrkdwn",
137+
"text": "*Included PRs:*\n${{ steps.create-pr.outputs.pr_list }}\n\n\nCurrent On-Call: *<${{ steps.on-call.outputs.oncall_slack_id }}>*"
138+
}
139+
},
140+
{
141+
"type": "actions",
142+
"elements": [
143+
{
144+
"type": "button",
145+
"text": {
146+
"type": "plain_text",
147+
148+
"text": ":github-pull-request-open: View Combined PR",
149+
"emoji": true
150+
},
151+
"value": "pr-button",
152+
"url": "${{ steps.create-pr.outputs.pr_url }}",
153+
"action_id": "link-action",
154+
"style": "primary"
155+
}
156+
]
157+
}
158+
]
159+
}
160+
env:
161+
SLACK_BOT_TOKEN: ${{ secrets.SLACK_SDK_BOT_TOKEN }}

0 commit comments

Comments
 (0)