ci: add pull-request URL in commit emails #62
This file contains hidden or 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: 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: | | |
| echo "$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 | |
| 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 mentionned 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/* |