Claude Codeでrelease-pleaseのリリースPRを整える — マージは人が押す
release-pleaseが作るリリースPRのCHANGELOGをClaude Codeに利用者向けへ言い換えさせ、マージ(タグ付け)は人に残す構成を、CLAUDE.mdとworkflowの設定例でまとめます。
release-pleaseは、mainに積まれたConventional Commitsを読み、CHANGELOGとバージョン更新を載せた「リリースPR」を作り続けるツールです。このPRをマージした瞬間にタグとGitHub Releaseができます。つまりマージボタンが、そのままリリースの発射ボタンです。
Claude Codeに任せやすいのは、マージの前にあるCHANGELOGの文面づくりです。コミットの1行目をそのまま並べた変更履歴を、利用者が読んで意味の分かる文に直す作業にあたります。逆にマージは人が押します。
この記事では、コミット規約をCLAUDE.mdに書く、リリースPRを読ませて言い換え案を出させる、マージ権限は渡さない、の3点を設定例つきで扱います。コミットメッセージが即座にリリースへ流れる方式ならClaude Codeでsemantic-releaseを回す手順が、changesetファイルを積む方式ならClaude CodeでChangesetsを回す手順が対応します。
リリースPR型は「マージ」が境界になる
release-pleaseは、前回のタグ以降のgit履歴からConventional Commitsを探し、リリースPRを作ります。mainに新しい作業が入るたびに、このPRは更新され続けます。リリースの準備ができたらPRをマージするだけで、通常のマージコミットでもsquashでも動きます。
マージされると、次の3つが走ります。
- CHANGELOGファイルを更新する(言語ごとのバージョンファイル、たとえば
package.jsonも同時に更新) - コミットにバージョン番号のタグを付ける
- そのタグを元にGitHub Releaseを作る
リリースPRの状態は、付いているラベルで分かります。
| ラベル | 意味 |
|---|---|
autorelease: pending | 意味マージ前の初期状態 |
autorelease: tagged | 意味マージ済みで、GitHubにタグが付いた |
autorelease: snapshot | 意味スナップショットのバージョン上げ用の特別な状態 |
autorelease: published | 意味GitHub Releaseが公開された(release-pleaseは自動では付けず、公開用ツール側の慣習として推奨されている) |
semantic-releaseはコミットが入るたびに公開まで進みます。changesetsは変更を1枚ずつのファイルで積みます。release-pleaseは、その間に「人が読めるPR」を1枚挟みます。Claude Codeが入る余地は、この1枚の文面にあります。
落とし穴
release-pleaseのマージは、取り消しにくい操作になる
リリースPRのマージはタグ付けとGitHub Releaseの作成を伴います。Claudeにgh pr mergeを使わせると、文面を整えるだけのつもりがリリースまで進みます。後述のとおり、権限で明示的に止めます。
利用者向けの文面は、コミットの書き方で半分決まる
release-pleaseの変更履歴は、コミットメッセージがそのまま材料です。Claudeに後から言い換えさせる前に、コミットを書くClaude自身に規約を守らせるほうが手戻りが減ります。release-pleaseが前提にしている型は次の3つです。
fix:は修正で、SemVerのpatchに対応するfeat:は新機能で、minorに対応するfeat!:やfix!:のように!を付けると破壊的変更で、majorになる
リリース対象になるのはfeat、fix、depsのコミットです。choreやbuildのコミットだけでは、リリースPR自体が作られません。言語によってはdocsもリリース対象になります。
CLAUDE.mdには、この規約を短く書きます。
## コミット規約(release-please)
- コミットは Conventional Commits で書く(feat: / fix: / deps: / chore: / docs:)
- 利用者に見える変更だけ feat: か fix: にする。内部整理は chore: / refactor:
- 破壊的変更は feat!: のように ! を付け、本文に移行手順を書く
- 1つのPRは squash merge で1コミットにする。subject は利用者向けの文にする
- バージョン番号の指定やタグ付けは自分で行わないsquash mergeを勧める理由は、release-please側が説明しています。PR内でfeat:の直後にfix:が入っても、mainには存在しなかった不具合の修正が履歴に載るだけで、利用者には意味がないためです。1PR1コミットなら、PRタイトルがそのまま変更履歴の1行になります。
1つのコミットに複数の変更を載せたいときは、コミット本文の末尾に追加のConventional Commitsを書けます。
feat: adds v4 UUID to crypto
This adds support for v4 UUIDs to the library.
fix(utils): unicode no longer throws exception
BREAKING-CHANGE: encode method no longer throws.
feat(utils): update encode to support unicode上の例では、3つの変更がそれぞれ別の項目としてCHANGELOGに入ります。追加のメッセージはコミットの末尾に置く必要があります。
マージ済みの文面を直す: BEGIN_COMMIT_OVERRIDE
すでにマージしたコミットの文面を変えたいときの手段も用意されています。マージ済みPRの本文に、次のブロックを書き足します。
BEGIN_COMMIT_OVERRIDE
feat: add ability to override merged commit message
fix: another message
chore: a third message
END_COMMIT_OVERRIDE次にrelease-pleaseが走ると、元のコミットメッセージではなくこの内容が使われます。ただし通常のマージコミットでは、どのコミットに上書きを当てるかが分からないため機能しません。squash mergeが前提です。
この仕組みは、Claudeに言い換えさせた結果をリリースPRへ反映する正規の経路になります。
言い換え案をどこに出させるか
リリースPRのCHANGELOGを手で書き換えたとき、次の実行で残るか上書きされるかは、READMEに書かれていません。書き換え案はブランチの外に出させ、反映はBEGIN_COMMIT_OVERRIDEで行う構成にすると、この不確かさを避けられます。
| 出力先 | 向く場面 | 注意 |
|---|---|---|
| ローカルで読ませて貼る | 向く場面1人運用・頻度が低い | 注意手元でgh pr viewの出力を渡す |
| PRコメント | 向く場面チームで案をレビューしたい | 注意コメント投稿の権限が要る |
| ワークフローのログ | 向く場面まず試す | 注意既定では結果がログに出る |
GitHub Actionsでは、promptを渡すと自動実行モードになり、結果は既定でワークフローのログに出ます。PRへ投稿させたい場合は、プロンプトで指示したうえで、投稿できるツールを許可します。なお、下のpromptを渡すworkflowは自動実行モードで、@claudeの呼びかけを待たずに動きます。
workflowを組む: release-pleaseとClaudeを別々に動かす
まずrelease-please本体です。リリースPRを作るworkflowで、READMEの基本構成は次の形です。
name: release-please
on:
push:
branches:
- main
permissions:
contents: write
issues: write
pull-requests: write
jobs:
release-please:
runs-on: ubuntu-latest
steps:
- uses: googleapis/release-please-action@v4
with:
token: ${{ secrets.MY_RELEASE_PLEASE_TOKEN }}
release-type: simpletokenにPersonal Access Tokenを指定している点が重要です。既定のGITHUB_TOKENで作られたPRやタグは、後続のworkflowを起動しません。つまりClaudeのworkflowも、CIも走らなくなります。リリースPRで他のActionsを動かしたいなら、PATが必要です。
次にClaude側です。リリースPRが開かれたとき、または更新されたときに、変更履歴を読んで言い換え案を出します。
name: Release notes draft
on:
pull_request:
types: [opened, synchronize, labeled]
jobs:
draft:
if: contains(github.event.pull_request.labels.*.name, 'autorelease: pending')
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
id-token: write
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
prompt: |
このPRはrelease-pleaseのリリースPRです。CHANGELOGの追加分を読み、
利用者向けの短い文に言い換えた案を出してください。
ファイルは変更せず、コミットもしないでください。
claude_args: |
--max-turns 5
--allowedTools "Read,Bash(git diff:*),Bash(git log:*)"
settings: |
{"permissions": {"deny": ["Bash(gh pr merge:*)", "Bash(git push:*)", "Bash(git tag:*)"]}}ポイントは3つあります。
ifの条件は、release-pleaseが付けるautorelease: pendingラベルを使う。PRが開かれた時点でラベルがまだ無い場合に備え、labeledも入れているclaude_argsの--allowedToolsは許可ツールの絞り込み、--max-turnsは暴走を止める上限settings入力にpermissionsを渡すと、マージ・push・タグ付けを拒否できる。許可リストを絞るだけでなく、拒否も書いておくと意図が読み取りやすい
workflowが動かないときに見る場所
Claude Code GitHub Actionは、実行前に2つの検査をします。1つは書き込み権限の確認で、もう1つはbotの拒否です。
- リリースPRをbotアカウントが作る構成では、
allowed_botsにそのアカウントを入れないと実行が失敗する GITHUB_TOKENで作られたPRではそもそもworkflowが起動しない。release-please側のトークンをPATにする
Claudeの言い換え案を、どうリリースPRに反映するか
出てきた案をそのまま使うか、手で調整して反映します。反映の経路は2つあります。
文面を反映する手順
- 1
案を読んで直す
利用者に伝わるか、内部用語が残っていないかを人が確認します。破壊的変更には移行手順を足します。顧客向けの告知文まで広げるなら、GitHubの自動生成を元にしたリリースノートの書き方が参考になります。
- 2
コミットの文面を上書きする
直したい元のPRの本文に
BEGIN_COMMIT_OVERRIDEを書きます。squash mergeしたPRに限ります。 - 3
リリースPRの更新を待つ
次のrelease-pleaseの実行でCHANGELOGが再生成されます。更新後にもう一度Claudeの案を見ます。
- 4
人がマージする
内容に納得してから、リリースPRをマージします。これでタグとGitHub Releaseが作られます。
バージョン番号を変えたいときも、Claudeではなくコミットで指定します。mainのコミット本文にRelease-As: 2.0.0を書くと、そのバージョンのリリースPRが開かれます。
git commit --allow-empty -m "chore: release 2.0.0" -m "Release-As: 2.0.0"リリースPRが出ないとき
mainにマージしても、リリースPRが作られないことがあります。release-pleaseのREADMEは、確認順を3段で示しています。
feat、fix、depsのコミットがマージされているか。choreやbuildだけでは対象にならない- 古いPRに
autorelease: pendingまたはautorelease: triggeredのラベルが残っていないか。APIの失敗でラベルが外れず、前回のリリースが未完了だと判断されることがある。本当に未完了のPRがないなら、ラベルを外して再実行する - release-pleaseを再実行する。GitHubアプリを使っているなら、マージ済みPRに
release-please:force-runラベルを付ける。Actionなら失敗した実行をリトライする
この切り分けはClaudeに頼ってもかまいません。gh pr list --label "autorelease: pending"の結果を読ませて、取り残されたPRを探させる使い方が向きます。ラベルを外す操作だけは、人が内容を見て決めるほうが安全です。
まとめ
release-pleaseにClaude Codeを組み合わせるときの線引きは、マージです。CLAUDE.mdで規約を揃え、リリースPRの文面はワークフローかローカルで案を出させ、反映はBEGIN_COMMIT_OVERRIDEのような正規の経路を通し、マージは人が押します。
最初の1回は、GITHUB_TOKENとPATの違いでつまずきやすい点だけ注意してください。他のworkflowが走らないときは、まずトークンを疑うと早く片付きます。
参照した一次ソース
この記事の記述は、次の一次ソースと照合しています。更新時に参照先が変わった場合は一覧も更新します。