Skip to content

Commit

Permalink
#28718: Adding GH workflow to fetch open PRs and notify about them t…
Browse files Browse the repository at this point in the history
…o assigned dev (#29931)
  • Loading branch information
victoralfaro-dotcms authored Sep 9, 2024
1 parent 6f66f1b commit 9dea667
Show file tree
Hide file tree
Showing 4 changed files with 209 additions and 8 deletions.
196 changes: 196 additions & 0 deletions .github/workflows/cicd_scheduled_notify-seated-prs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
name: 'Notify about seated PRs'
on:
schedule:
- cron: '0 10 * * *'
workflow_dispatch:
env:
PR_DAY_THRESHOLD: 3
DRAFT_PR_DAY_THRESHOLD: 5
REPO: core

jobs:
resolve-seated-prs:
runs-on: ubuntu-22.04
outputs:
seated_prs: ${{ steps.fetch-seated-prs.outputs.seated_prs }}
members: ${{ steps.fetch-seated-prs.outputs.members }}
members_json: ${{ steps.fetch-seated-prs.outputs.members_json }}
steps:
- run: echo 'GitHub context'
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
- name: Filter execution
uses: actions/github-script@v7
with:
result-encoding: string
script: |
const day = new Date().getDay();
console.log(new Date());
if (day === 0 || day === 6) {
console.log('It\'s (happy) weekend, not sending any notifications');
process.exit(1);
}
- id: fetch-seated-prs
name: Fetch Seated PRs
if: success()
uses: actions/github-script@v7
with:
result-encoding: string
retries: 3
retry-exempt-status-codes: 400,401
script: |
const prDayThreshold = ${{ env.PR_DAY_THRESHOLD }};
const draftPrDayThreshold = ${{ env.DRAFT_PR_DAY_THRESHOLD }};
const now = new Date();
const seatedPrs = [];
const excludedUsers = ['dependabot[bot]']
const fetchOpenPrs = async () => {
const opts = github.rest.pulls.list.endpoint.merge({
...{
owner: '${{ github.repository_owner }}',
repo: '${{ env.REPO }}',
per_page: 100
}
});
return await github.paginate(opts);
};
const isPrSeated = (pr) => {
const createdAt = new Date(Date.parse(pr.created_at));
console.log(`Now: ${now} / CreatedAt: ${createdAt}`);
let weekdaysCount = 0;
for (let date = new Date(createdAt); date <= now; date.setDate(date.getDate() + 1)) {
const dayOfWeek = date.getDay();
if (dayOfWeek !== 0 && dayOfWeek !== 6) {
weekdaysCount++;
}
}
const threshold = pr.draft ? draftPrDayThreshold : prDayThreshold;
return weekdaysCount >= threshold;
};
const addPr = (pr, login) => {
if (!isPrSeated(pr)) {
return;
}
let userPrs = seatedPrs.find(pr => pr.login === login);
if (!userPrs) {
userPrs = {
login,
prs: []
};
seatedPrs.push(userPrs);
}
userPrs.prs.push({
pr_number: pr.number,
url: pr.html_url,
draft: pr.draft,
created_at: pr.created_at,
updated_at: pr.updated_at
});
};
const handlePr = (pr) => {
const login = pr.user.login;
if (excludedUsers.includes(login)) {
return;
}
addPr(pr, login);
};
const prs = await fetchOpenPrs();
console.log(`PRs size: [${prs.length}]`);
prs.forEach(handlePr);
const members = seatedPrs.map(pr => pr.login);
console.log(`Seated PRs size: [${seatedPrs.length}]`);
console.log(JSON.stringify(seatedPrs, null, 2));
console.log(`Users: ${JSON.stringify(members)}`);
core.setOutput('seated_prs', JSON.stringify(seatedPrs));
core.setOutput('members', members.join(' '));
core.setOutput('members_json', JSON.stringify(members));
slack-channel-resolver:
name: Resolve Slack Channel
needs: resolve-seated-prs
if: success() && needs.resolve-seated-prs.outputs.members
uses: ./.github/workflows/utility_slack-channel-resolver.yml
with:
github_users: ${{ needs.resolve-seated-prs.outputs.members }}
secrets:
CI_MACHINE_USER: ${{ secrets.CI_MACHINE_USER }}
CI_MACHINE_TOKEN: ${{ secrets.CI_MACHINE_TOKEN }}
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}

notify-seated-prs:
runs-on: ubuntu-22.04
needs: [resolve-seated-prs, slack-channel-resolver]
if: success()
name: Notifying team member ${{ matrix.member }}
strategy:
fail-fast: false
matrix:
member: ${{ fromJSON(needs.slack-channel-resolver.outputs.channel_ids) }}
steps:
- name: Build Message
id: build-message
uses: actions/github-script@v7
with:
result-encoding: string
script: |
const urlMapper = (pr) => `- ${pr.url}`;
const prDayThreshold = ${{ env.PR_DAY_THRESHOLD }};
const draftPrDayThreshold = ${{ env.DRAFT_PR_DAY_THRESHOLD }};
const seatedPrs = ${{ needs.resolve-seated-prs.outputs.seated_prs }}
const members = ${{ needs.resolve-seated-prs.outputs.members_json }}
const channels = ${{ needs.slack-channel-resolver.outputs.channel_ids }}
console.log(JSON.stringify(members, null, 2));
console.log(JSON.stringify(channels, null, 2));
const idx = channels.findIndex(channel => channel === '${{ matrix.member }}');
if (idx === -1) {
console.log('Could not find channel [${{ matrix.member }}], skipping this');
process.exit(2);
}
const login = members[idx];
const userPrs = seatedPrs.find(pr => pr.login === login);
const prs = userPrs.prs.filter(pr => !pr.draft).map(urlMapper);
const draftPrs = userPrs.prs.filter(pr => pr.draft).map(urlMapper);
const prStatement = `The following PRs have at least *${prDayThreshold}* days since created:
${prs.join('\n')}`;
const draftPrStatement = `The following *draft* PRs have at least *${draftPrDayThreshold}* days since created:
${draftPrs.join('\n')}`;
let message = `:hurtrealbad: Attention dev *${login}*! You have PRs seated for a while.`;
if (prs.length > 0) {
message += `\n${prStatement}`
}
if (draftPrs.length > 0) {
message += `\n${draftPrStatement}`
}
message += `\n\nYou can always check your PRs at: https://github.com/${{ github.repository_owner }}/${{ env.REPO }}/pulls/${login}`
core.setOutput('message', message);
- name: Notify member
if: success()
shell: bash
run: |
channel=${{ matrix.member }}
curl -X POST \
-H "Content-type: application/json" \
-H "Authorization: Bearer ${{ secrets.SLACK_BOT_TOKEN }}" \
-d "{ \"channel\":\"${channel}\",\"text\":\"${{ steps.build-message.outputs.message }}\"}" \
-s \
https://slack.com/api/chat.postMessage
2 changes: 1 addition & 1 deletion .github/workflows/issue_comp_frontend-notify.yml
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ jobs:
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}

frontend-notify:
name: Notify team member ${{ matrix.members }}
name: Notify team member ${{ matrix.member }}
needs: [resolve-data, slack-channel-resolver]
runs-on: ubuntu-20.04
if: success() && needs.resolve-data.outputs.issue_number && needs.slack-channel-resolver.outputs.channel_ids
Expand Down
14 changes: 8 additions & 6 deletions .github/workflows/issue_comp_next-release-label.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# action.yml
name: 'QA not needed update'
name: 'Label to Next Release'
on:
workflow_call:
secrets:
Expand All @@ -22,6 +22,7 @@ jobs:
runs-on: ubuntu-20.04
env:
QA_NOT_NEEDED_LABEL: 'QA : Not Needed'
REPO: core
steps:
- run: echo 'GitHub context'
env:
Expand Down Expand Up @@ -51,11 +52,12 @@ jobs:
github-token: ${{ secrets.CI_MACHINE_TOKEN }}
script: |
async function getIssue(issueNumber) {
return github.rest.issues.get({
const response = await github.rest.issues.get({
issue_number: issueNumber,
owner: '${{ github.repository_owner }}',
repo: 'core'
repo: '${{ env.REPO }}'
});
return response.data;
}
let issue = context.payload.issue;
Expand All @@ -71,7 +73,7 @@ jobs:
}
console.log(`Issue: ${JSON.stringify(issue, null, 2)}`);
const issueNumber = issue.data.number;
const issueNumber = issue.number;
const dropAndLearnText = 'Drop Everything & Learn';
if (issue.data.title.includes(dropAndLearnText)) {
Expand All @@ -89,9 +91,9 @@ jobs:
await github.rest.issues.addLabels({
issue_number: issueNumber,
owner: '${{ github.repository_owner }}',
repo: 'core',
repo: '${{ env.REPO }}',
labels: ['Next Release']
});
const updated = await getIssue(issueNumber);
console.log(`Labels: ${JSON.stringify(updated.data.labels, null, 2)}`);
console.log(`Labels: ${JSON.stringify(updated.labels, null, 2)}`);
5 changes: 4 additions & 1 deletion .github/workflows/utility_slack-channel-resolver.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ jobs:
slack_mapping_url=${githack_core_repo_url}/${{ inputs.branch }}/.github/data/${slack_mappings_file}
json=$(curl -s ${slack_mapping_url})
echo "Looking for [${github_user}]"
channel_ids=
for github_user in "${github_users_array[@]}"; do
channel_id=$( \
Expand All @@ -94,7 +95,7 @@ jobs:
)
echo "Resolved user email: [${user_email}]"
if [[ -n "${user_email}" ]]; then
if [[ -n "${user_email}" && "${user_email}" != 'null' ]]; then
channel_id=$( \
curl \
--request GET \
Expand All @@ -109,6 +110,8 @@ jobs:
)
echo "Resolved channel id [${channel_id}] from email [${user_email}]"
else
echo "Could not resolve email for [${github_user}], skipping it"
fi
fi
Expand Down

0 comments on commit 9dea667

Please sign in to comment.