Skip to content

Merge Dependabot PRs #55

Merge Dependabot PRs

Merge Dependabot PRs #55

name: Merge Dependabot PRs
on:
schedule:
- cron: "0 9 * * 1" # Run this workflow every Monday at 9:00
workflow_dispatch:
jobs:
merge:
runs-on: ubuntu-latest
steps:
- name: Get current on-call
id: on-call
run: |
now=$(date -u +%Y-%m-%dT%H:%M:%SZ)
end_time=$(date -u -d '+24 hour' +%Y-%m-%dT%H:%M:%SZ)
oncall=$(curl --request GET \
--url "https://api.pagerduty.com/oncalls?since=$now&until=$end_time&schedule_ids[]=PQLHTOP" \
--header 'Accept: application/vnd.pagerduty+json;version=2' \
--header "Authorization: Token token=${{ secrets.PAGERDUTY_TOKEN }}" \
--header 'Content-Type: application/json' )
engineer_name=$(echo "$oncall" | jq -r '.oncalls[0].user.summary')
declare -A engineer_to_slackid
engineer_to_slackid=(
["Nipun Singh"]="U02AMC70R6E"
["Jagadeesh Karicherla"]="U038BDE0XUZ"
["Gabe De Luna"]="U02MDA0PHK5"
["Ernest Cho"]="UCV77QDSL"
["Nidhi Dixit"]="U02GDFBP88N"
)
slack_id=${engineer_to_slackid["$engineer_name"]}
echo "oncall_slack_id=$slack_id" >> $GITHUB_OUTPUT
- name: Create PR
uses: actions/github-script@v6
id: create-pr
with:
script: |
const uniqueBranchName = 'dependabot-combined-prs-' + Date.now().toString();
const pulls = await github.paginate('GET /repos/:owner/:repo/pulls', {
owner: context.repo.owner,
repo: context.repo.repo
});
let branchesAndPRStrings = [];
let baseBranch = null;
let baseBranchSHA = null;
for (const pull of pulls) {
const branch = pull['head']['ref'];
if (branch.startsWith('dependabot/')) {
console.log('Branch matched prefix. Adding to array: ' + branch);
const prString = '#' + pull['number'] + ' ' + pull['title'];
branchesAndPRStrings.push({ branch, prString });
baseBranch = pull['base']['ref'];
baseBranchSHA = pull['base']['sha'];
}
}
if (branchesAndPRStrings.length == 0) {
core.setFailed('There are no open dependabot PRs.');
return;
}
try {
await github.rest.git.createRef({
owner: context.repo.owner,
repo: context.repo.repo,
ref: 'refs/heads/' + uniqueBranchName,
sha: baseBranchSHA
});
} catch (error) {
console.log(error);
core.setFailed('Failed to create combined branch');
return;
}
let combinedPRs = [];
let mergeFailedPRs = [];
for(const { branch, prString } of branchesAndPRStrings) {
try {
await github.rest.repos.merge({
owner: context.repo.owner,
repo: context.repo.repo,
base: uniqueBranchName,
head: branch,
});
console.log('Merged branch ' + branch);
combinedPRs.push(prString);
} catch (error) {
console.log('Failed to merge branch ' + branch);
mergeFailedPRs.push(prString);
}
}
console.log('Creating combined PR');
const combinedPRsString = combinedPRs.join('\n');
let body = '✅ This PR was created by the Merge Dependabot PRs action by combining the following dependabot PRs:\n' + combinedPRsString;
if(mergeFailedPRs.length > 0) {
const mergeFailedPRsString = mergeFailedPRs.join('\n');
body += '\n\n⚠️ The following dependabot PRs were left out due to merge conflicts:\n' + mergeFailedPRsString
}
let response = await github.rest.pulls.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: 'Combined Dependabot PR',
head: uniqueBranchName,
base: baseBranch,
body: body
});
console.log('Created combined PR: ' + response.data.html_url);
core.setOutput('pr_url', response.data.html_url);
core.setOutput('pr_list', combinedPRsString);
- name: Post to a Slack channel
uses: slackapi/[email protected]
id: slack
with:
channel-id: "C03RTLRKJQP"
payload: |
{
"text": "React Native: New Dependabot PR Awaiting Review",
"blocks": [
{
"type": "header",
"text": {
"type": "plain_text",
"text":"📱🔧 React Native: New Dependabot PR Awaiting Review",
"emoji": true
}
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*Included PRs:*\n${{ toJSON(steps.create-pr.outputs.pr_list) }}\n\n\nCurrent On-Call: *<${{ steps.on-call.outputs.oncall_slack_id }}>*"
}
},
{
"type": "actions",
"elements": [
{
"type": "button",
"text": {
"type": "plain_text",
"text": ":github-pull-request-open: View Combined PR",
"emoji": true
},
"value": "pr-button",
"url": "${{ steps.create-pr.outputs.pr_url }}",
"action_id": "link-action",
"style": "primary"
}
]
}
]
}
env:
SLACK_BOT_TOKEN: ${{ secrets.SLACK_SDK_BOT_TOKEN }}