release-please でリリース自動化
今年に入ってAIによるagentic codingが出来るようになって趣味でOSSを作るようになって楽しんでいる。
- ainame/swift-slack-client - Swift製のSlack bolt相当のclient
- ainame/xcodeproj-cli - CLI版(Docker不要)の giginet/xcodeproj-mcp-server/
- ainame/tuzuru - このブログをホストするために作った静的ブログジェネレーター
- ainame/swift-displaywidth - tuzuruでターミナル上でテーブルを表示するために文字の幅を計算するのに作ったライブラリ
一方で新しいバージョンをリリースするのは結構大変で最近はCLIを作っていたので単にGitのタグをつけるだけでは足りなくて、 タグをつけたらそこからツールを配布する用の処理を実行していきたい。 そのために、今回 aianme/tuzuru に release-please を導入してみたので紹介したいと思う。
release-please を知る前
mainブランチに直接コミットしている時はリリース前の処理を scripts/release.sh
にしておいた。
GitHub Actionsのworkflowも含めると以下のようなことをやっていた。
- 手元で
scripts/release.sh
を実行- ビルド・テストを実行
- 成功したらバージョンが書かれたファイルを更新してgit tag & push
- GitHub上ではgit tagを検知してビルド
- macOS用のUniversal binaryを作成
- Linux用のstatic link binaryを作成
- GitHub Releaseを作成してビルド済みのバイナリをアップロード
- バイナリをラップしたnpmをpush
- Homebrew formulaを更新
一応これでもそれなりに回るので問題はないのだけど、ある程度ツールが安定してきたら、
出来ればPRベースで開発をしていきたい。そこで自前でPRベースのフローをClaude Codeなどを活用して、
構築してみたものの、GitHub Actionsから利用できるトークンだけだと制限があったり、
いまいちうまくいかなかったので、同じ問題を解決してる事例がすでにあるはずだと思って調べたら見つけたのが、
release-pelase
だった。
release-please とは
TypeScriptで開発されているCLIツールで、GitHub Actions上で使う場合は基本的には release-please-action
をGitHub Actionsの中で使うだけでも済む。
READMEを読むだけだと、どうやって動いているか全くわからなかったので、使ってみて理解した部分をまとめてみる。
コードリーディングまでしているわけではないので間違ったら教えて欲しい。
仕組み
READMEにある通り、GitHubで .github/workflows/release-please.yml
を以下のように設置しておいておくと、
mainブランチにマージするたびに release-please
が実行されることになる。
on:
push:
branches:
- main
permissions:
contents: write
issues: write
pull-requests: write
name: release-please
jobs:
release-please:
runs-on: ubuntu-latest
steps:
- uses: googleapis/release-please-action@v4
with:
# this assumes that you have created a personal access token
# (PAT) and configured it as a GitHub action secret named
# `MY_RELEASE_PLEASE_TOKEN` (this secret name is not important).
token: ${{ secrets.MY_RELEASE_PLEASE_TOKEN }}
# this is a built-in strategy in release-please, see "Action Inputs"
# for more options
release-type: simple
release-please
はGitHubのPRのタグを元に2種類の挙動を自動で使い分けて自動化している
- Conventional Commitsを元にリリース用のPRを作る
- 次のリリース候補となるコミットを探して
feat
やfix
などのユーザー向けの変更がリリース対象コミットが例え1つでもあればPRを作る - PR自体に
autorelease: pending
ラベルをつける release-please-config.json
と.release-please-manifest.json
を元にコードベース内のバージョン表記を書き換えた差分が含まれる- リリース用PRはmainに差分がマージされるごとに更新される(CHANGELOG.mdも更新される)
- 次のリリース候補となるコミットを探して
autorelease: pending
ラベルのPRがマージされた時にGitタグを打ち、GitHub Releaseのページを作る- この時にGitHub Actionsで release publishedの時に任意のworkflowを実行できる
- GitHub Releaseのページがすでにあるので任意のビルドをしてバイナリをアップロードしたり
- この時にGitHub Actionsで release publishedの時に任意のworkflowを実行できる
自作しようとした時はGitHubに状態を持つという発想がなかったのでうまくいかなかったけど、pendig状態のPRをラベルで管理するというのがポイントだと思った。 Renovateにやり方が近いGitHubネイティブな実装だと思った。
https://github.com/ainame/tuzuru/pull/64
こんな感じでPRにリリース内容が蓄積されていく。
癖
ここまで見ると良さそうに思うけど、release-pleaseを使うための癖はあって、
- Conventional Commits を元にリリースのバージョンを判定(fixだけならpatch releaseとか)
- Linear git commit history(squash merge)を半強制される(mainブランチをmerge commitでPRに取り込むとCHANGELOGが乱れる)
- GitHub Actionsで標準で使えるtokenの制限を突破するためにPAT(personal access token)かGitHub Appのtokenが必要
など、慣れていないと面倒くさいと思ったりすることはありそう。 Conventional Commitsは今まで使ったことなかったし、面倒くさそうではあるけど、虚無なコミットメッセージを書くよりは何倍も良いかもと思った。 というか、GitHubでPRベースの開発をしてsquash mergeのみ許可なら実質PRタイトルだけConventional Commitsに従えば良いかも?
まとめ
色々試行錯誤して release-please
は ainame/tuzuru
に導入できて、
リリースフローがすっきりして満足している。release-please
、みんなも使ってどんどんリリースしていこう!!