エンジニアリング

GitHubリリースノートを生成し、読める形に仕上げる方法

1分で読めます

GitHubのリリースノートとは、リポジトリのReleasesページでリリースに添えられる説明文のことで、前のタグ以降にマージされたプルリクエストから、GitHubがその最初の下書きを書いてくれる。下書きは、ラベルごとにまとめたプルリクエストのタイトルの一覧に、コントリビューターの行と比較リンクが付いたものだ。正確で漏れがなく、そしてプルリクエストをマージした人たちに向けて書かれている。これをプロジェクトのユーザーが読めるものにするには、.github/release.ymlファイルと短い編集作業が要る。その両方を以下で説明する。

ノートの作り方動く場所得られるもの
「Generate release notes」ボタンWeb UIのリリースフォーム前のタグ以降のPRタイトルをrelease.ymlのカテゴリで分類したもの
gh release create v1.4.0 --generate-notesGitHub CLI、ローカルまたはCI同じ下書きを、リリース作成と一つのコマンドで
POST /repos/{owner}/{repo}/releases/generate-notesREST APIリリースを作らずに下書きをテキストとして取得。自前のパイプライン向け
release-please、semantic-release、conventional-changelogGitHub ActionsまたはリリースジョブPRタイトルではなくコミットメッセージからのノート。バージョン更新とCHANGELOG.md付き
手書きリリースフォーム入力したとおりの文章。プルリクエストへのリンクは付かない

GitHubでリリースノートを自動生成するにはどうするか

リリースフォームを開き、タグを選ぶか作成して、「Generate release notes」をクリックする。GitHubは前のリリースタグを見つけ、その二つの間でターゲットブランチにマージされたすべてのプルリクエストを列挙し、プルリクエストごとにタイトル、作者、番号を一行ずつ書き出す。コマンドラインではgh release create <tag> --generate-notesが同じことをして、リリースの公開まで一度に済ませる。--notes-start-tagで、範囲の起点になる過去のタグを変えられる。

この機能はプルリクエストを元に動くので、プルリクエストなしでmainに直接マージしているリポジトリでは、下書きは空になる。スカッシュマージは問題ない。プルリクエスト自体は残るからだ。長命ブランチからmainへのマージコミットは、マージしたプルリクエストの一行だけになり、それ以前にそのブランチへマージされたプルリクエストは一つも出てこない。範囲がおかしく見えるなら、たいていの原因は前のタグがないか順序が狂っていることだ。生成器はターゲットブランチの最新リリースを使い、リリースが紐づいていないタグは無視する。

ボタンについては自動生成されるリリースノートに関するGitHub Docsのページが、CLIのフラグについてはgh release createのマニュアルが扱っている。

release.ymlは何を変えるのか

.github/release.ymlは、どのプルリクエストを除外し、残りをどう分類するかを生成器に伝える。これがないと、Dependabotも含めてすべてのプルリクエストが一つのリストに並ぶ。あれば、プルリクエストはラベルによってカテゴリに振り分けられ、ラベル付きやボット作者のノイズは消える。

# .github/release.yml
changelog:
  exclude:
    labels:
      - skip-changelog
    authors:
      - dependabot
      - renovate
  categories:
    - title: Breaking changes
      labels:
        - breaking-change
    - title: New
      labels:
        - enhancement
    - title: Fixed
      labels:
        - bug
    - title: Other changes
      labels:
        - "*"

知っておく価値のあるルールが三つある。カテゴリは順番に照合されるので、breaking-changeとbugの両方が付いたプルリクエストは、最初に一致した見出しの下に入る。"*"のキャッチオールは、ラベルのないプルリクエストを表示したいなら必須で、ないと黙って落とされる。そしてこのファイルは生成器が書くものにしか影響しないので、変更しても既存のノートには何も起きない。CIのチェンジログチェックのためにすでにプルリクエストへラベルを付けているチームは、同じラベルをここで使い回せる。

生成されたGitHubリリースノートはなぜ読みにくいのか

プルリクエストのタイトルは、変更が完成する前にレビュアーに向けて書かれ、コードを説明しているからだ。「エクスポートワーカーをストリーミングにリファクタ」は良いプルリクエストのタイトルだが、リリースノートとしては役に立たない。リリースを読む人が知りたいのは、100 MBを超えるエクスポートがタイムアウトしなくなったことだ。

二つ目の理由は、マージされたすべてのプルリクエストが同じ重みで並ぶことだ。一行の誤字修正が新しい認証フローの隣に、マージされた順で座っている。読者は、自分に関係する三行を見つけるためにリスト全体を眺めなければならない。

三つ目は、下書きに冒頭の文がないことだ。上に一文もない40行のリストは、このリリースを安心して取り込めるのか、移行が必要なのか、依存関係を固定するためだけに存在するのかを、誰にも教えてくれない。

編集作業では何を変えるべきか

生成されたリストは残して、そこに書き足す。ゼロから書き直すのではない。リストは監査証跡であり、プルリクエスト番号は、ある行から差分へたどる手がかりだ。編集作業では、生成器には知りようのない部分を足す。

  1. 冒頭に二、三文書く。 このリリースは何のためか、アップグレードに何か作業が要るか、まず何を読むべきか。破壊的変更があるなら、最初の行でそう言う。
  2. 読者が気にする行を読者の側から書き直す。 消えた症状、新しくできるようになったこと、場所が変わった設定。行末のプルリクエスト番号は残す。リリースノートの書き方に全体の形があり、バグ修正のリリースノートは修正の行を特に扱っている。
  3. 読者がしなければならないことは、正確なコマンドや設定とともに独立したセクションへ移す。 「Other changes」のリストに埋もれた破壊的変更は、一週間後のサポートチケットだ。
  4. 生成されたリストからは何も削らない。 長ければ「Full list of changes」の見出しの下に畳んでよいが、残しておく。プロジェクトのコントリビューター自身がそれを使うからだ。

こうすれば、典型的なリリースでGitHubリリースノートの編集は10分ほどで済み、ノートは両方の読者に役立つ。上の要約はユーザーに、下のリストはコントリビューターに。

GitHubのリリースをチェンジログにしてよいか

変更を知る必要がある全員がすでにReleasesページを読んでいる場合に限る。パッケージマネージャー経由で開発者が使うライブラリなら、それはよくあることで、ReleasesページとリポジトリのCHANGELOG.mdで十分だ。GitHubを開くことのないユーザーを持つ製品では、そうはいかない。リリースページは読者に合わない粒度で書かれ、開発者向けのURLの裏にあり、GitHubアカウントのない人は購読できない。

長持ちするパターンは、GitHubのリリースを開発者向けの記録、製品のチェンジログを読者向けの記録として扱い、リリースからチェンジログのエントリへリンクすることだ。Gitタグ、リリース、チェンジログは、この三つの記録をどう揃えるかを扱っている。製品のチェンジログを同じコミットから生成するなら、チェンジログジェネレーターでそちら側の下書きも得られ、チェンジログとリリースノートの違いの分け方が、どの詳細をどちらに置くかを説明している。

リリースノート自体はどうバージョン管理するか

GitHubで公開済みのリリースはいつでも編集でき、その編集はページ上に目に見える履歴を残さない。ほとんどのプロジェクトではそれで構わない。ノートがコンプライアンスや顧客の拠り所になる記録であるプロジェクトでは、二つの習慣が役に立つ。正式な文章はリポジトリの中(CHANGELOG.mdかdocs/releases/フォルダ)に置いてリリース本文からそこを指すこと、そしてプランが対応していればリポジトリでimmutable releasesを有効にし、公開後にタグとアセットをロックすることだ。リリース管理に関するGitHub Docsは、下書き、プレリリース、そして手で設定しない限りセマンティックバージョンの順で付く「latest」ラベルを説明している。

FAQ

GitHubのリリースノートは自動生成できるか? できる。リリースフォームの「Generate release notes」ボタン、gh release createの--generate-notesフラグ、generate-notesのRESTエンドポイントのどれも、前のリリースタグ以降にマージされたプルリクエストから下書きを作る。分類と除外は.github/release.ymlファイルで制御する。

生成したリリースノートが空なのはなぜか? 生成器はプルリクエストを列挙するので、ブランチへの直接コミットは出てこない。また範囲は最新のタグではなく、ターゲットブランチの最新リリースから始まる。前のリリースが存在すること、変更がプルリクエスト経由で入ったことを確認しよう。

release.ymlはすでにあるリリースにも効くか? 効かない。ファイルを置いた後に生成されるノートの形だけを決める。既存のリリース本文は、誰かが編集するまでそのままだ。

GitHubリリースノートとCHANGELOG.mdのどちらを使うべきか? プロジェクトにコントリビューターとユーザーの両方がいるなら両方だ。リリースページは開発者が見る場所でアセットの置き場でもあり、リポジトリ内のファイルはGitHubからの移転にも耐え、オフラインで読める。リリースノートを生成し、ファイルを最新に保ち、互いにリンクする。


この記事の技術的な記述は第三者による確認を受けていません。誤りがあればお知らせください。修正します。

changeloopの関連ページ: changelogジェネレーター, 開発者向けドキュメント

changeloop
ループを閉じるchangelogを作っているチームです。ユーザーが何かを求め、あなたのチームがそれを届け、求めた人がそれを知る。