Claude Media
Claude Codeでrelease-pleaseのリリースPRを整える — マージは人が押す

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: simple

tokenに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. 1

    案を読んで直す

    利用者に伝わるか、内部用語が残っていないかを人が確認します。破壊的変更には移行手順を足します。顧客向けの告知文まで広げるなら、GitHubの自動生成を元にしたリリースノートの書き方が参考になります。

  2. 2

    コミットの文面を上書きする

    直したい元のPRの本文にBEGIN_COMMIT_OVERRIDEを書きます。squash mergeしたPRに限ります。

  3. 3

    リリースPRの更新を待つ

    次のrelease-pleaseの実行でCHANGELOGが再生成されます。更新後にもう一度Claudeの案を見ます。

  4. 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段で示しています。

  1. feat、fix、depsのコミットがマージされているか。choreやbuildだけでは対象にならない
  2. 古いPRにautorelease: pendingまたはautorelease: triggeredのラベルが残っていないか。APIの失敗でラベルが外れず、前回のリリースが未完了だと判断されることがある。本当に未完了のPRがないなら、ラベルを外して再実行する
  3. 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が走らないときは、まずトークンを疑うと早く片付きます。

参照した一次ソース

この記事の記述は、次の一次ソースと照合しています。更新時に参照先が変わった場合は一覧も更新します。

  1. github.com/googleapis/release-please
  2. github.com/googleapis/release-please-action
  3. github.com/googleapis/release-please/blob/main/docs/customizing.md
  4. code.claude.com/docs/en/github-actions
この記事を共有:XはてブLinkedIn