diff --git a/.github/scripts/credit-authors.sh b/.github/scripts/credit-authors.sh new file mode 100755 index 00000000..a52598a4 --- /dev/null +++ b/.github/scripts/credit-authors.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash +# Append " by " to every changelog entry for a commit in .... +# Credited entries no longer end in a commit link, so re-running is a no-op. +# Usage: credit-authors.sh ... (needs GH_TOKEN, GH_REPO) +set -euo pipefail + +base=$1 +head=$2 +shift 2 + +# Raw " " lines, not @tsv: a name is taken verbatim, escapes and +# all, and a Git author name can hold no newline to break the format. +authors=$(mktemp) +gh api --paginate "repos/$GH_REPO/compare/$base...$head" \ + --jq '.commits[] + | .sha + " " + (if .author.login then "@" + .author.login else .commit.author.name end)' \ + > "$authors" + +for file in "$@"; do + awk ' + NR == FNR { author[$1] = substr($0, index($0, " ") + 1); next } + { + if (match($0, /\/commit\/[0-9a-f]+\)\)$/)) { + sha = substr($0, RSTART + 8, RLENGTH - 10) + if (sha in author) $0 = $0 " by " author[sha] + } + print + }' "$authors" "$file" > "$file.credited" + mv "$file.credited" "$file" +done diff --git a/.github/workflows/release-please.yaml b/.github/workflows/release-please.yaml index 75a7794a..dfba1afc 100644 --- a/.github/workflows/release-please.yaml +++ b/.github/workflows/release-please.yaml @@ -11,36 +11,58 @@ jobs: name: Release Please runs-on: ubuntu-latest steps: + - uses: actions/checkout@v7 + with: + token: ${{ secrets.RELEASE_TOKEN }} - uses: googleapis/release-please-action@v5 id: release with: token: ${{ secrets.RELEASE_TOKEN }} + # The release notes come from the pull request body, so they need the + # same credits applied separately from the changelog. - name: Credit commit authors in the release notes if: ${{ steps.release.outputs.release_created == 'true' }} shell: bash env: GH_TOKEN: ${{ secrets.RELEASE_TOKEN }} - REPO: ${{ github.repository }} + GH_REPO: ${{ github.repository }} TAG: ${{ steps.release.outputs.tag_name }} run: | - previous=$(gh api "repos/$REPO/releases?per_page=10" \ + previous=$(gh api "repos/$GH_REPO/releases?per_page=10" \ --jq 'map(select(.draft | not)) | map(select(.tag_name != env.TAG)) | .[0].tag_name // empty') if [ -z "$previous" ]; then echo "No previous release to compare against, skipping." exit 0 fi - gh api --paginate "repos/$REPO/compare/$previous...$TAG" \ - --jq '.commits[] - | [.sha, (if .author.login then "@" + .author.login else .commit.author.name end)] - | @tsv' > authors.tsv - gh release view "$TAG" --repo "$REPO" --json body --jq .body > notes.md - awk -F'\t' ' - NR == FNR { author[$1] = $2; next } - { - if (match($0, /\/commit\/[0-9a-f]+\)\)$/)) { - sha = substr($0, RSTART + 8, RLENGTH - 10) - if (sha in author) $0 = $0 " by " author[sha] - } - print - }' authors.tsv notes.md > credited.md - gh release edit "$TAG" --repo "$REPO" --notes-file credited.md + gh release view "$TAG" --json body --jq .body > notes.md + bash .github/scripts/credit-authors.sh "$previous" "$TAG" notes.md + gh release edit "$TAG" --notes-file notes.md + # Credit on the release branch, not on main: the changelog is then + # already credited at the tag. release-please force-pushes the branch on + # every run, so this reapplies the credits each time. + - name: Credit commit authors in the changelog + if: ${{ steps.release.outputs.pr }} + shell: bash + env: + GH_TOKEN: ${{ secrets.RELEASE_TOKEN }} + GH_REPO: ${{ github.repository }} + BRANCH: ${{ fromJSON(steps.release.outputs.pr).headBranchName }} + HEAD_SHA: ${{ github.sha }} + run: | + previous=$(gh api "repos/$GH_REPO/releases?per_page=10" \ + --jq 'map(select(.draft | not)) | .[0].tag_name // empty') + if [ -z "$previous" ]; then + echo "No previous release to compare against, skipping." + exit 0 + fi + git fetch origin "+refs/heads/$BRANCH:refs/remotes/origin/$BRANCH" + git checkout -B "$BRANCH" "refs/remotes/origin/$BRANCH" + bash .github/scripts/credit-authors.sh "$previous" "$HEAD_SHA" CHANGELOG.md + if git diff --quiet; then + echo "Authors already credited." + exit 0 + fi + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git commit -am "chore(release): credit commit authors in the changelog" + git push origin "$BRANCH"