-
Notifications
You must be signed in to change notification settings - Fork 225
300 lines (244 loc) · 11.4 KB
/
send-emails.yml
File metadata and controls
300 lines (244 loc) · 11.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
name: Send emails for merged PR
on:
push:
branches:
- "master"
jobs:
send_patches:
runs-on: ubuntu-latest
steps:
- name: Checkout repo with full history
uses: actions/checkout@v5
with:
fetch-depth: 100
- name: Install deps (git send-email and jq)
run: |
sudo apt-get update
sudo apt-get install -y jq
## GHA images have a special git package that conflicts with
## git-send-email So this is a workaround to force the installation of
## the conflicting package.
sudo apt-get install -y libauthen-sasl-perl \
libemail-valid-perl \
libio-socket-ssl-perl \
libmailtools-perl perl \
libnet-smtp-ssl-perl
apt-get download git-email
sudo dpkg -i --force-all git-email*deb
- name: Configure git identity
run: |
git config user.name "gccrs gerris bot"
git config user.email "${{ vars.SMTP_FROM }}"
- name: Export env
env:
GH_EVENT: ${{ toJson(github.event) }}
run: |
# GH_EVENT can be very big as it contains the full commit log and
# overflow the shell's maximum length.
echo '$GH_EVENT' | envsubst '$GH_EVENT' > /tmp/gh_event.json
BEFORE_REF=$(jq -r '.before' /tmp/gh_event.json)
echo "BEFORE_REF=$BEFORE_REF" >> $GITHUB_ENV
AFTER_REF=$(jq -r '.after' /tmp/gh_event.json)
echo "AFTER_REF=$AFTER_REF" >> $GITHUB_ENV
# PR_NUMBER=$(jq -r '.pull_request.number' /tmp/gh_event.json)
# echo "PR_NUMBER=$PR_NUMBER" >> $GITHUB_ENV
# PR_TITLE=$(jq -r '.pull_request.title' /tmp/gh_event.json)
# echo "PR_TITLE=$PR_TITLE" >> $GITHUB_ENV
# PR_URL=$(jq -r '.pull_request.html_url' /tmp/gh_event.json)
# echo "PR_URL=$PR_URL" >> $GITHUB_ENV
# PR_MERGE_COMMIT=$(jq -r '.pull_request.merge_commit_sha' /tmp/gh_event.json)
# echo "PR_MERGE_COMMIT=$PR_MERGE_COMMIT" >> $GITHUB_ENV
# PR_TARGET_BRANCH=$(jq -r '.pull_request.base.ref' /tmp/gh_event.json)
# echo "PR_TARGET_BRANCH=$PR_TARGET_BRANCH" >> $GITHUB_ENV
# PR_LABELS=$(jq -r '[.pull_request.labels[].name] | join(",")' /tmp/gh_event.json)
# echo "PR_LABELS=$PR_LABELS" >> $GITHUB_ENV
# REPO_SSH=$(jq -r '.repository.ssh_url' /tmp/gh_event.json)
# echo "REPO_SSH=$REPO_SSH" >> $GITHUB_ENV
echo "GH_TOKEN=${{ github.token }}" >> $GITHUB_ENV
# echo "SERIES_DIR=/tmp/series" >> $GITHUB_ENV
- name: Get commit list and skip the internal ones
id: commits
env:
MAX_NUM_COMMITS: 30
BEFORE_REF: ${{ github.event.before }}
AFTER_REF: ${{ github.event.after }}
run: |
# Skip commits that touches any of these
patterns=(".github/"
"CODE_OF_CONDUCT.md"
"CONTRIBUTING.md"
"Dockerfile"
"README.md"
"logo.png"
"gcc/rust/gource-gccrs.sh"
"gcc/rust/monthly-diff.py"
)
regex=$(printf '%s\n' "${patterns[@]}" | sed -e 's/[.[\*^$+?(){|\/\\]/\\&/g' | paste -sd'|' -)
rm -f /tmp/commits.txt
if [ "$BEFORE_REF" = "0000000000000000000000000000000000000000" ] ; then
echo "New branch created, not sending anything" | tee $GITHUB_STEP_SUMMARY
echo "has_commits=false" >> $GITHUB_OUTPUT
exit 0
fi
if [ "$AFTER_REF" = "0000000000000000000000000000000000000000" ] ; then
echo "Branch is being deleted, not sending anything" | tee $GITHUB_STEP_SUMMARY
echo "has_commits=false" >> $GITHUB_OUTPUT
exit 0
fi
if git merge-base --is-ancestor "$BEFORE_REF" "$AFTER_REF"; then
echo "fast-forward push (not forced)"
else
echo "non-fast-forward push (force push or history rewrite), not sending anything" | tee $GITHUB_STEP_SUMMARY
echo "has_commits=false" >> $GITHUB_OUTPUT
exit 0
fi
IS_MERGE=$(git show --pretty=%P -s HEAD | wc -w)
if [ "$IS_MERGE" -gt 1 ] ; then
echo "Last commit is a merge, don't send anything" | tee $GITHUB_STEP_SUMMARY
echo "has_commits=false" >> $GITHUB_OUTPUT
exit 0
fi
# Fetch commits from the pull request (maybe they're from another repository)
#git fetch origin "pull/$PR_NUMBER/head"
TOTAL=$(git log --oneline "$BEFORE_REF..$AFTER_REF" | wc -l)
if [ "${TOTAL}" -gt "$MAX_NUM_COMMITS" ]; then
echo "Push has too many commits" | tee $GITHUB_STEP_SUMMARY
echo "has_commits=false" >> $GITHUB_OUTPUT
exit 0
fi
git log --reverse --format=%H "$BEFORE_REF..$AFTER_REF" | while read SHA1; do
echo "Looking at $SHA1"
if grep -q -E "$regex" <(git diff-tree --no-commit-id --name-only -r "$SHA1"); then
echo "Touching something not to be upstreamed, skipping commit $SHA1"
else
echo "Adding one commit to the send list"
echo "$SHA1" >> /tmp/commits.txt
fi
done
if [ ! -f /tmp/commits.txt ]; then
echo "No commits to send email for" | tee $GITHUB_STEP_SUMMARY
echo "has_commits=false" >> $GITHUB_OUTPUT
exit 0
fi
COUNT=$(wc -l < /tmp/commits.txt)
echo "Has $COUNT commits in the series"
echo "has_commits=true" >> $GITHUB_OUTPUT
- name: Check for label 'no-ml' to skip sending emails
id: checklabel
run: |
# not sure how to do that with "push".
echo "skip=false" >> $GITHUB_OUTPUT
exit 0
# Skip if PR has label "no-ml"
# if echo "$PR_LABELS" | grep -qiE "(^|,)no-ml(,|$)"; then
# echo "Opt-out label present: skipping mailing list." | tee $GITHUB_STEP_SUMMARY
# echo "skip=true" >> $GITHUB_OUTPUT
# else
# echo "No opt-out label found"
# echo "skip=false" >> $GITHUB_OUTPUT
# fi
- name: Decide if we're sending something or not
id: send_emails
if: ( steps.commits.outputs.has_commits == 'true' &&
steps.checklabel.outputs.skip == 'false' )
run: |
echo "enabled=true" >> $GITHUB_OUTPUT
- name: Prepare patch series
if: steps.send_emails.outputs.enabled == 'true'
run: |
set -euo pipefail
# Create a temporary branch that linearizes the PR commits
git checkout -B ci-mail-patches "$BEFORE_REF"
# Cherry-pick commits in the exact PR order (no-commit to batch, then commit)
while read sha; do
git cherry-pick "$sha"
done < /tmp/commits.txt
echo "This change was merged into the gccrs repository and is posted here for" >> /tmp/description.txt
echo "upstream visibility and potential drive-by review, as requested by GCC" >> /tmp/description.txt
echo "release managers." >> /tmp/description.txt
echo "Each commit email contains a link to its details on github from where you can" >> /tmp/description.txt
echo "find the Pull-Request and associated discussions." >> /tmp/description.txt
echo "" >> /tmp/description.txt
mkdir /tmp/series
# Generate series + cover letter
git format-patch \
--subject-prefix="gccrs COMMIT" \
--no-cover-letter \
--base="$BEFORE_REF" \
--output-directory /tmp/series \
"$BEFORE_REF"..HEAD
echo "" >> /tmp/description.txt
cp /tmp/commits.txt /tmp/commits_stack.txt
while IFS= read -r -d '' f;do
# Read next SHA1...
SHA1=$(head -n1 /tmp/commits_stack.txt)
# ... and pop it from the stack
sed -i '1d' /tmp/commits_stack.txt
echo "SHA1: $SHA1"
echo "patch file: $f"
echo ""
cp /tmp/description.txt "/tmp/tmp_descr.txt"
echo "Commit on github: https://github.com/${{ github.repository }}/commit/$SHA1" >> /tmp/tmp_descr.txt
LINKED_ISSUES_LIST_FILE=/tmp/commit_linked_issues.txt
## find issue(s) referenced in commit message
gccrs_ref_regex='Rust-GCC/gccrs#[0-9]+'
git show -s --format=%B "$SHA1" | \
grep -Eo "$gccrs_ref_regex" | \
sort -u > "$LINKED_ISSUES_LIST_FILE"
echo "Issues list: >>>"
cat "$LINKED_ISSUES_LIST_FILE"
echo "<<<"
echo
if [ -s "$LINKED_ISSUES_LIST_FILE" ]; then
echo -e "\nThe commit has been mentioned in the following issue(s):" >> /tmp/tmp_descr.txt
while read -r i; do
ISSUE_NUM=${i##*#} # 1234
echo " - $i: https://github.com/Rust-GCC/gccrs/issues/${ISSUE_NUM}" >> /tmp/tmp_descr.txt
done < "$LINKED_ISSUES_LIST_FILE"
fi
## find corresponding pull-request(s)
if gh api "repos/${{ github.repository }}/commits/$SHA1/pulls" | \
jq '.[].html_url' > /tmp/tmp_pr_links.txt;
then
if [ -s /tmp/tmp_pr_links.txt ]; then
echo -e "\nThe commit has been mentioned in the following pull-request(s):" >> /tmp/tmp_descr.txt
tr -d '"' < /tmp/tmp_pr_links.txt | \
sed 's/^/ - /' >> /tmp/tmp_descr.txt
else
echo "The commit is not linked to any pull-request" >> /tmp/tmp_descr.txt
fi
else
echo "There was an error fetching data from github API for getting PR for commit" | tee -a "$GITHUB_STEP_SUMMARY"
fi
echo >> /tmp/tmp_descr.txt
# insert the github header right after the '---'.
sed '/^---$/ r /tmp/tmp_descr.txt' -i "$f"
# loop over the patches and make sure to do that in numerical order
# 0001-..., 0002-...., ...
done < <(find /tmp/series/ -maxdepth 1 -type f -print0|sort -z -n)
- name: Send series via git send-email
if: steps.send_emails.outputs.enabled == 'true'
env:
GIT_SMTP_SERVER: ${{ vars.SMTP_SERVER }}
GIT_SMTP_ENCRYPTION: tls
GIT_SMTP_SERVER_PORT: ${{ vars.SMTP_PORT }}
GIT_SMTP_AUTH: "true"
GIT_SMTP_USER: ${{ vars.SMTP_USERNAME }}
GIT_SMTP_PASSWORD: ${{ secrets.SMTP_PASSWORD }}
FROM: ${{ vars.SMTP_FROM }}
TO: ${{ vars.PATCH_TO }}
CC: ${{ vars.PATCH_CC }}
run: |
set -euo pipefail
git config sendemail.smtpserver "$GIT_SMTP_SERVER"
git config sendemail.smtpserverport "$GIT_SMTP_SERVER_PORT"
git config sendemail.smtpencryption "$GIT_SMTP_ENCRYPTION"
git config sendemail.smtpuser "$GIT_SMTP_USER"
git config sendemail.smtppass "$GIT_SMTP_PASSWORD"
git config sendemail.from "$FROM"
git config sendemail.to "$TO"
if [ -n "${CC:-}" ]; then git config sendemail.cc "$CC"; fi
git config sendemail.thread "true"
git config sendemail.confirm "never"
git config sendemail.annotate "false"
git send-email /tmp/series/*