🦔

GitHub Actionsでリリースタグを切ってリリースノートを自動作成する

2023/03/30に公開

前書き

聞こえよくいうとスタートアップらしくスピード重視だったため、リリースをきちんとversion管理しておりませんでした。
しかし人数も多くなってきたしということできちんとタグを切ってリリースノートを作り、遅ればせながらいつ誰が何をリリースしたのかをきちんと管理することにしました。

初めは手作業で行っていたのですが、もちろん面倒なので手軽にgithub actionsで自動作成することにしました。

先に完成系

公式ドキュメントはこの辺を参照しました。

.github/workflows/release_note.yml を作成した後、以下の内容を書く。
これをmainブランチにマージすると、次回以降はmainブランチに何かしらmerge(PR merge含む)されるとactionsのworkflowが動きます。処理時間は30秒ほどでした。

name: Create release tag and release note.

on:
  push:
    branches:
      - main

jobs:
  create-release-tag:
    runs-on: ubuntu-latest

    env:
      GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      TZ: 'Asia/Tokyo'

    steps:
      - uses: actions/checkout@v3

      # Step1. 前回のリリースタグを取得する
      - name: Get previous tag
        id: pre_tag
        run: |
          echo "pre_tag=$(curl -H 'Accept: application/vnd.github+json' -H 'Authorization: token ${{ secrets.GITHUB_TOKEN }}' -H "X-GitHub-Api-Version: 2022-11-28" https://api.github.com/repos/${{ github.repository }}/releases/latest | jq -r .tag_name)" >> $GITHUB_OUTPUT

      # Step2. patch verをインクリメントする
      # ex.) v4.0.45
      - name: Generate release tag
        id: release_tag
        run: |
          major=$(echo ${{ steps.pre_tag.outputs.pre_tag }} | awk -F'.' '{print $1}')
          minor=$(echo ${{ steps.pre_tag.outputs.pre_tag }} | awk -F'.' '{print $2}')
          patch=$(echo ${{ steps.pre_tag.outputs.pre_tag }} | awk -F'.' '{print $3}')
          echo "release_tag=$major.$minor.$(($patch + 1))" >> $GITHUB_OUTPUT

      # Step3. タグを切り、前回のリリースからの差分をもとにリリースノートの本文を生成する
      - name: Generate release note
        id: release_note
        run: |
          echo "release_note=$(curl -X POST -H 'Accept: application/vnd.github+json' -H 'Authorization: token ${{ secrets.GITHUB_TOKEN }}' -H "X-GitHub-Api-Version: 2022-11-28" https://api.github.com/repos/${{ github.repository }}/releases/generate-notes -d '{"tag_name":"${{ steps.release_tag.outputs.release_tag }}", "target_commitish": "main", "previous_tag_name":"${{ steps.pre_tag.outputs.pre_tag }}"}' | jq .body | sed -e 's/"//g' -e "s/'/''/g")" >> $GITHUB_OUTPUT

      # Step4. リリースノートを作成する
      - name: Create Release
        run: |
          curl -X POST \
            -H "Accept: application/vnd.github+json" \
            -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
            -H "X-GitHub-Api-Version: 2022-11-28" \
            -d '{ "tag_name": "${{ steps.release_tag.outputs.release_tag }}", "target_commitish": "main",  "name": "${{ steps.release_tag.outputs.release_tag }}", "body": "${{ steps.release_note.outputs.release_note }}"}' \
            https://api.github.com/repos/${{ github.repository }}/releases

作成されるリリースノートはこんな感じです

ハマりポイント

Step3でリリースノート作成のためにAPIを叩くのですが、bodyに入っている返り値をそのまま使うと表示が崩れるので"と'をいい感じに置換する必要がありました。

やってることちょっと解説

Step1. APIを叩いて、現行最新のtag名を取得して変数に保存

Step2. v4.0.45のように管理していたので、一番右のpatch verを+1して変数に保存

Step3. Step1で取得した現行最新tag名とStep2で計算した次のtag名を指定して、この2つの差分でリリースノートの内容を作成するAPIを叩き、変数に保存。ちなみに次のtag名が存在しない場合、指定したブランチの最新commitでtagを新規作成してくれるようです。

Step4. Step3で作成した内容で、リリースノートを作成するAPIを叩く。

Discussion