PR Review Reminder #222
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: PR Review Reminder | |
on: | |
schedule: | |
# 한국 시간 12시에 실행 (UTC 기준 03시) | |
- cron: '0 3 * * *' | |
# 한국 시간 18시에 실행 (UTC 기준 09시) | |
- cron: '0 9 * * *' | |
workflow_dispatch: | |
jobs: | |
review-reminder: | |
runs-on: ubuntu-latest | |
env: | |
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
OWNER: ${{ github.repository_owner }} | |
REPO: ${{ github.event.repository.name }} | |
steps: | |
- name: Check out the code | |
uses: actions/checkout@v3 | |
- name: Get open PRs and requested reviewers | |
id: get-prs | |
run: | | |
prs=$(gh api graphql -F owner=$OWNER -F repo=$REPO -f query=' | |
query($owner: String!, $repo: String!) { | |
repository(owner: $owner, name: $repo) { | |
pullRequests(states: OPEN, first: 100) { | |
edges { | |
node { | |
number | |
title | |
url | |
} | |
} | |
} | |
} | |
} | |
' --jq '.data.repository.pullRequests.edges | map({number: .node.number, title: .node.title, url: .node.url})') | |
prs_without_completed_reviews="[]" | |
while read -r pr; do | |
pr_number=$(echo "$pr" | jq -r '.number') | |
pr_url=$(echo "$pr" | jq -r '.url') | |
pr_title=$(echo "$pr" | jq -r '.title') | |
reviewers=$(gh api repos/$OWNER/$REPO/pulls/$pr_number/requested_reviewers \ | |
-H "Authorization: Bearer $GH_TOKEN" \ | |
-H "Accept: application/vnd.github+json" \ | |
--jq '.users | map(.login)') | |
if [ -n "$reviewers" ] && [ "$reviewers" != "[]" ]; then | |
pr=$(echo "$pr" | jq --argjson reviewers "$reviewers" '. + {incompleteReviewers: $reviewers}') | |
prs_without_completed_reviews=$(echo "$prs_without_completed_reviews" | jq --argjson pr "$pr" '. += [$pr]') | |
fi | |
done < <(echo "$prs" | jq -c '.[]') | |
echo "$prs_without_completed_reviews" > prs.json | |
- name: Map GitHub users to Discord users and notify | |
id: map-github-users | |
run: | | |
reviewer_map='[ | |
{"github": "junest66", "discord": "<@444811214623735839>"}, | |
{"github": "YeaChan05", "discord": "<@391487793995579403>"} | |
]' | |
prs=$(cat prs.json) | |
embed_fields="[]" | |
reviewers_processed=() | |
while read -r pr; do | |
pr_number=$(echo "$pr" | jq -r '.number') | |
pr_title=$(echo "$pr" | jq -r '.title') | |
pr_url=$(echo "$pr" | jq -r '.url') | |
incomplete_reviewers=$(echo "$pr" | jq -r '.incompleteReviewers[]') | |
for reviewer in $incomplete_reviewers; do | |
if [[ ! " ${reviewers_processed[@]} " =~ " ${reviewer} " ]]; then | |
reviewers_processed+=("$reviewer") | |
discord_user=$(echo "$reviewer_map" | jq --arg user "$reviewer" -r '.[] | select(.github == $user) | .discord') | |
if [ -n "$discord_user" ]; then | |
github_user=$(echo "$reviewer_map" | jq --arg user "$reviewer" -r '.[] | select(.github == $user) | .github') | |
pr_list="" | |
while read -r pr_item; do | |
pr_num=$(echo "$pr_item" | jq -r '.number') | |
pr_title=$(echo "$pr_item" | jq -r '.title') | |
pr_url=$(echo "$pr_item" | jq -r '.url') | |
pr_list+="- [PR #$pr_num: \"$pr_title\"]($pr_url)\n" | |
done < <(echo "$prs" | jq -c --arg user "$reviewer" '.[] | select(.incompleteReviewers[] == $user)') | |
pr_count=$(echo "$prs" | jq --arg user "$reviewer" '[.[] | select(.incompleteReviewers[] == $user)] | length') | |
fire_count=$(printf ' 🔥%.0s' $(seq 1 $pr_count)) | |
embed_fields=$(echo "$embed_fields" | jq --arg name "$github_user $fire_count ($pr_count건)" --arg value "$discord_user\n$pr_list" '. += [{"name": $name, "value": ($value | gsub("\\\\n"; "\n")), "inline": false}]') | |
fi | |
fi | |
done | |
done < <(echo "$prs" | jq -c '.[]') | |
if [ "$(echo "$embed_fields" | jq length)" -eq 0 ]; then | |
echo "No reviewers to notify." | |
echo "has_notifications=false" >> $GITHUB_OUTPUT | |
else | |
current_time=$(date --utc +%Y-%m-%dT%H:%M:%SZ) | |
embed=$(jq -n \ | |
--arg title "리뷰를 기다리고 있어요!!" \ | |
--arg description "[리뷰하러 가기](https://github.com/$OWNER/$REPO/pulls)" \ | |
--argjson fields "$embed_fields" \ | |
--arg thumbnail "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRidSZL4BdECVb3sL0ZQ2jZSYIWNDQTiTcJJQ&usqp=CAU" \ | |
--arg author_name "PR BOT" \ | |
--arg author_icon "https://avatars.githubusercontent.com/u/9919?s=200&v=4" \ | |
--arg footer_text "Chzz-Market" \ | |
--arg footer_icon "https://github.com/user-attachments/assets/234444a3-bcd3-4ab3-bd2e-18ee8ed7cb22" \ | |
--arg timestamp "$current_time" \ | |
'{ | |
"embeds": [{ | |
"title": $title, | |
"description": $description, | |
"color": 15258703, | |
"fields": $fields, | |
"thumbnail": {"url": $thumbnail}, | |
"author": { | |
"name": $author_name, | |
"icon_url": $author_icon | |
}, | |
"footer": { | |
"text": $footer_text, | |
"icon_url": $footer_icon | |
}, | |
"timestamp": $timestamp | |
}] | |
}') | |
echo "$embed" > embed.json | |
echo "has_notifications=true" >> $GITHUB_OUTPUT | |
fi | |
- name: Send Discord Notification | |
if: steps.map-github-users.outputs.has_notifications == 'true' | |
run: | | |
curl -H "Content-Type: application/json" \ | |
-d @embed.json \ | |
${{ secrets.DISCORD_WEBHOOK_URL }} |