Skip to content

Commit e466b3d

Browse files
committed
ci: automatically add Reviewed-by trailer when Accepted label is set
This introduce new workflow that is run when Accepted label is set. It appends Reviewed-by trailers to all commits in the pull request for all reviewers that ack-ed it. * It is skipped if Accepted label is missing/removed * It is no-op success if PR was synchronized after label was set (this is required to make it green as it is automatically re-run when the job finishes as a side effect to pushing to this repository) * It adds the trailers when Accepted label is added It uses secrets.BOT_TOKEN and SSSD_AUTHORS variable that contains mapping from github account to name and email. Since PR CI is restarted when commits with Reviewed-by are pushed, the job also submits comment with current PR CI status, so it is not lost and we do not have to necessarily wait for new PR CI run to finish. Reviewed-by: Alexey Tikhonov <atikhono@redhat.com> Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com> (cherry picked from commit 2e5ad5b)
1 parent fc1ae0b commit e466b3d

File tree

1 file changed

+158
-0
lines changed

1 file changed

+158
-0
lines changed

.github/workflows/accepted.yml

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
name: Accepted
2+
on:
3+
pull_request_target:
4+
types:
5+
- synchronize
6+
- labeled
7+
- unlabeled
8+
env:
9+
PR_ID: ${{ github.event.pull_request.number }}
10+
GH_TOKEN: ${{ secrets.BOT_TOKEN }}
11+
AUTHORS: ${{ vars.SSSD_AUTHORS }}
12+
ACTOR: ${{ github.actor }}
13+
jobs:
14+
15+
accepted-label-set:
16+
# Make the job appear as skipped if Accepted label is missing
17+
if: >
18+
(
19+
github.event.action == 'labeled'
20+
&& github.event.label.name == 'Accepted'
21+
) || (
22+
github.event.action == 'synchronize'
23+
&& contains(github.event.pull_request.labels.*.name, 'Accepted')
24+
)
25+
runs-on: ubuntu-latest
26+
permissions:
27+
contents: write
28+
pull-requests: write
29+
30+
steps:
31+
- name: Checkout Repository
32+
uses: actions/checkout@v4
33+
with:
34+
# Fetch the entire history of the repository
35+
# This is necessary for a successful git push
36+
fetch-depth: 0
37+
# The pull request head branch is checked out
38+
ref: ${{ github.event.pull_request.head.ref }}
39+
repository: ${{ github.event.pull_request.head.repo.full_name }}
40+
token: ${{ secrets.BOT_TOKEN }}
41+
42+
- name: Reviewed-by trailer was already added and pull request is accepted
43+
if: github.event.action == 'synchronize'
44+
run: |
45+
# Just succeed, as the pull request was updated by this job
46+
exit 0
47+
48+
- name: Set git user identity
49+
if: github.event.action == 'labeled'
50+
run: |
51+
git config --global user.name "sssd-bot"
52+
git config --global user.email "sssd-maintainers@lists.fedoraproject.org"
53+
54+
- name: Add 'Reviewed-by' trailer
55+
if: github.event.action == 'labeled'
56+
run: |
57+
set -e -o pipefail
58+
59+
gh repo set-default ${{ github.repository }}
60+
61+
PR_REVIEWERS=`gh pr view "$PR_ID" --json reviews --jq '.reviews.[] | select(.state == "APPROVED") | .author.login' | sort | uniq`
62+
PR_COMMITS_SHA=`gh pr view "$PR_ID" --json commits --jq .commits.[].oid`
63+
PR_COMMITS_FIRST=`echo "$PR_COMMITS_SHA" | head -1`
64+
65+
git config trailer.where end
66+
git config trailer.ifexists addIfDifferent
67+
68+
trailers=""
69+
for name in $PR_REVIEWERS; do
70+
value=$(echo "$AUTHORS" | jq -r \
71+
--arg user "$name" \
72+
'
73+
# Iterate over the array and select the object with a matching github_username.
74+
.[] | select(.github_username == $user) |
75+
76+
# If a match is found, format the output as "Name <email>".
77+
# The `//` operator provides a fallback.
78+
"\(.name) <\(.email)>" //
79+
80+
# If no match is found, use the default fallback string.
81+
"\($user) <https://github.com/\($user)>"
82+
'
83+
)
84+
85+
trailers+="--trailer 'Reviewed-by: $value' "
86+
done
87+
88+
if [ ! -z "$trailers" ]; then
89+
git rebase "$PR_COMMITS_FIRST~1" -x "git commit --allow-empty --amend --no-edit $trailers"
90+
fi
91+
92+
- name: Add comment to print current CI status
93+
if: github.event.action == 'labeled'
94+
run: |
95+
set -e -o pipefail
96+
97+
gh repo set-default ${{ github.repository }}
98+
99+
COMMENT_FILE=.accepted-add-reviewed-by.comment
100+
101+
echo "**The pull request was accepted by @$ACTOR with the following PR CI status:**" > $COMMENT_FILE
102+
echo "" >> $COMMENT_FILE
103+
echo "---" >> $COMMENT_FILE
104+
echo "" >> $COMMENT_FILE
105+
106+
CHECKS=`gh pr checks "$PR_ID" --json state,workflow,name,link`
107+
108+
echo $CHECKS | jq -r '
109+
# Filter the array to exclude accepted and backport workflows
110+
# these will be always in_progress or skipped at this point
111+
map(select(
112+
.workflow != "Accepted" and .workflow != "Backport"
113+
)) |
114+
115+
# First, sort the entire array by the "workflow" and "name" keys.
116+
sort_by(.workflow, .name | ascii_downcase) |
117+
118+
# Then, iterate over each element in the sorted array.
119+
.[] |
120+
121+
# A conditional check to determine the icon based on the state.
122+
(if .state == "FAILURE" then "🔴"
123+
elif .state == "SUCCESS" then "🟢"
124+
elif .state == "CANCELLED" then "⚪"
125+
elif .state == "IN_PROGRESS" then "🟡"
126+
elif .state == "PENDING" then "⏳"
127+
elif .state == "SKIPPED" then "➖"
128+
else .state
129+
end
130+
) as $icon |
131+
132+
# Another conditional check to format the output.
133+
# If the workflow is an empty string, print a simplified format.
134+
# Otherwise, print the full format including the workflow.
135+
if .workflow == "" then
136+
"\($icon)&ensp;[\(.name)](\(.link)) (\(.state | ascii_downcase))"
137+
else
138+
"\($icon)&ensp;[\(.workflow) / \(.name)](\(.link)) (\(.state | ascii_downcase))"
139+
end
140+
' >> "$COMMENT_FILE"
141+
142+
echo "" >> $COMMENT_FILE
143+
echo "---" >> $COMMENT_FILE
144+
echo "" >> $COMMENT_FILE
145+
146+
unfinished=`echo $CHECKS | jq '.[] | select(.state != "SUCCESS")'`
147+
if [ -z "$unfinished" ]; then
148+
echo "All checks passed. It is safe to merge this pull request." >> $COMMENT_FILE
149+
else
150+
echo "**There are unsuccessful or unfinished checks.** Make sure that the failures are not related to this pull request before merging." >> $COMMENT_FILE
151+
fi
152+
153+
gh pr comment "$PR_ID" --body-file "$COMMENT_FILE"
154+
155+
- name: Push changes
156+
if: github.event.action == 'labeled'
157+
run: |
158+
git push origin HEAD --force

0 commit comments

Comments
 (0)