GitHubリリース周りの自動化
2024-02-29

仕事でGitHubのリリース周りを触る機会があり、せっかくならと思い、個人で開発しているリポジトリたちにも導入しました🚀

結論から

完成形のフローは以下のとおりです。

  1. featureブランチをmainブランチにマージ
  2. タグを作成
  3. タグからリリースを作成

1をトリガーにGitHubActionsを動かして、2・3を実施します。
GitHubActionsの完成形は以下のとおりです。

.github/workflows/generate-release.yml
name: Generate Release

on:
  pull_request:
    branches:
      - main
    types:
      - closed

jobs:
  build:
    if: github.event.pull_request.merged == true
    runs-on: ubuntu-22.04
    permissions:
      contents: write
    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ github.event.pull_request.merge_commit_sha }}
          fetch-depth: '0'

      - name: Generate Tag
        uses: anothrNick/github-tag-action@1.67.0
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          WITH_V: true
          DEFAULT_BUMP: patch
          INITIAL_VERSION: 1.0.0
      - name: Set Tag Name
        run: |
          latest_tag=$(git describe --tags)
          echo "TAG_NAME=${latest_tag}" >> $GITHUB_ENV
      - name: Generate Release Note
        uses: softprops/action-gh-release@v1
        with:
          name: ${{ env.TAG_NAME }}
          tag_name: ${{ env.TAG_NAME }}
          generate_release_notes: true

やったこと

タグの自動作成

https://github.com/anothrNick/github-tag-action を使いました。
調べるといろいろな選択肢がありますが、とりあえず以下のことができれば不自由はしなさそうだったので、これに決めました。

  • 基本動作として、patchがインクリメントされる
  • コミットメッセージでmajor, minorのインクリメントを制御できる

オプションで制御するようになっていて、↑のコードだと以下の部分が該当します。

WITH_V: true
DEFAULT_BUMP: patch
INITIAL_VERSION: 1.0.0

この設定をしておくと、リリースタグは以下のようになります。 screen.png

タグの取得

リリースを作成するステップで使えるように、タグを取得する必要があります。

latest_tag=$(git describe --tags)
echo "TAG_NAME=${latest_tag}" >> $GITHUB_ENV

describeでタグを取得して、ENVに書き込んでいます。

リリースの自動作成

READMEにあるように設定を書けば特にハマることもなく動きます。

リリースノートのテンプレ

自動生成リリースノート」というのを設定しておくと、よくライブラリなどで見るキラキラした感じのやつを作れます。

基本的にGitHubの公式どおりですが、一応自分が書いた設定を置いておきます。

.github/release.yml

changelog:
  categories:
    - title: 🚀 Features
      labels:
        - '*'
      exclude:
        labels:
          - dependencies
          - bug
    - title: 🐉 Bug Fixes
      labels:
        - bug
    - title: 👒 Dependencies
      labels:
        - dependencies

dependenciesbug以外のラベル(ラベルなしも含む)はfeature扱いにしています。

以前gitmojiをコミットメッセージに含める運用をしているチームで開発をしたことがあり、そこではバグを🐛ではなく🐉にしていて、虫嫌いな自分にとってとても快適だったので今回は🐉を採用しました

ちなみに、そのチームで🐉を使っていた由来は以下の記事だったそうです。

動かしてみる

こんな感じでリリースが作成されます screen.png

Flutterで開発しているリポジトリでは・・

Flutterで個人開発をしているのですが、それらのリポジトリでは少しだけ設定を変えています。

.github/workflows/generate-release.yml
...
jobs:
  generate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Generate tag
        run: |
          export TAG_NAME=$(sed -n 4P pubspec.yaml | sed 's/version: //')
          git tag $TAG_NAME
          git push origin $TAG_NAME
          echo "TAG_NAME=$TAG_NAME" >> $GITHUB_ENV
      - name: Generate release note
        uses: softprops/action-gh-release@v1
        with:
          name: ${{ env.TAG_NAME }}
          tag_name: ${{ env.TAG_NAME }}
          generate_release_notes: true

Flutterの場合、pubspec.ymlでバージョンを管理しているので、そのバージョンでタグを生成するようにしています。

(個人開発のリポジトリだといずれもpubspec.yamlの4行目にバージョンを書いているので、その行を取得し、不要なversion:文字列を削除しています。行数に依存するの脆いので微妙ですね。。)

おわりに

インクリメントの様子が可視化されるので、個人開発のモチベーションアップにも繋がっています!

今回はコミットメッセージをちゃんとするところまで手が回らなさそうだったので諦めましたが、semantic-releaseを使うのもよさそうだなーと思いました。

© 2023 yutasb