エンジニアリング

GitHub Actionsのためのチェンジログチェック

1分で読めます

チェンジログを手作業で維持しているすべてのチームは、同じインシデントの後に同じ会話を経験している。項目なしでリリースが出て、誰かが理由を尋ね、正直な答えは、それを書くはずだった人が急いでいて、チェンジログの手順が記憶の中にしか存在していなかったというものだ。チェンジログの自動化は、パイプラインが安全に自動化できるものと、まだ人間を必要とするものを扱っている。CIでのチェンジログチェックはこの問題のもう半分だ。書くことを自動化しても、そもそも誰もそれを起動する義務を負っていなければ役に立たないからだ。GitHub Actionsは、ほとんどのチームがすでにプルリクエストのチェックを実行している場所であり、だからこそこのチェックもそこに置く。

なぜ「人々に項目を追加するよう頼む」は予測可能なパターンで失敗するのか

プルリクエスト内の他のすべてと注意を奪い合い、飛ばしても即座の結果がない唯一の部分だからだ。テストは大きな音を立てて失敗しマージをブロックする。欠けているチェンジログ項目は何もブロックしないので、誰かが急いでいる瞬間、実際にはほとんどの時間、負けてしまう。記憶によって強制されるポリシーは、まさに予想される速度で劣化する。全員が合意した最初の数週間はうまくいき、気にかけていた人が休暇に入るかチームを変わった瞬間、静かに放棄される。

チェンジログ項目のためのCIチェックは実際に何を検証するのか

文章の質ではなく、項目が存在し、かつ正しい形式であることだけであり、それは人の頭の中ではなくCIで動くチェンジログチェックにとって正しい範囲だ。よくある形は、チェックがPRのdiffを見て、changesetディレクトリの新しいファイル(Changesetsや類似のツールが使うパターン)か、チェンジログファイルの変更された行のどちらかを要求し、どちらも存在しなければビルドを失敗させる。項目が実際に何を語っているかのレビューは、常にそうであった場所、つまりコードレビューで引き続き行われる。その判断はスクリプトの領分ではないからだ。

CIチェックが検証すること検証しないこと
diffにchangesetかチェンジログの行が存在する文章が明確かどうか
項目がモノレポ内で正しいパッケージを参照しているか変更がそもそも項目に値するかどうか
ファイルが構文的に有効か(フロントマター、JSON形式)項目が影響について正直かどうか

すべてのPRにこれが必要か、それとも一部の変更は免除されるのか

一部は免除され、その免除リストこそが、こうしたシステムが実際に構築されるか放棄されるかの分かれ目だ。目に見える影響のない依存関係の更新、テストだけの変更、振る舞いの変わらない内部リファクタリング。これらのどれも、チェンジログを読む誰も気にしないことのためにチェンジログ項目をでっち上げるよう貢献者に強制すべきではない。うまく機能するパターンは、貢献者が適用できる(no-changelog-needed)ラベルかフラグで、ファイルなしでCIチェックを満たし、PRを承認する人によってレビューされる。そうすれば免除自体が、項目が通るのと同じ精査を通ることになる。

緊急のホットフィックスのような正当な例外はどうなるのか

ゲートはデプロイではなくマージに属する。本当の時間的プレッシャーの下にあるホットフィックスは、CIチェックが完成した段落ではなく意図によって満たされる限り、プレースホルダーの項目やフォローアップチケットでマージできる。一部のチームは、次のリリースカットの前にメンテナーが磨き上げる一行のスタブを受け入れる。ゲートが決して許すべきではないのは、その手順を静かに飛ばすことだ。忘れられたスタブは一度も存在しなかった項目より小さな失敗であり、スタブは少なくとも誰かが後で見つけられる痕跡を残すからだ。

# .github/workflows/changelog-check.yml
on:
  pull_request:
    types: [opened, synchronize, reopened, labeled, unlabeled]
jobs:
  changelog:
    if: >-
      !contains(github.event.pull_request.labels.*.name,
      'no-changelog-needed')
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0 # the diff needs the base branch
      - name: Require changelog entry
        run: |
          base="origin/${{ github.base_ref }}"
          if ! git diff --name-only "$base"...HEAD \
              | grep -q '^\.changeset/'; then
            echo "No changeset. Add one, or have a maintainer"
            echo "apply the no-changelog-needed label."
            exit 1
          fi

チェック自体が正しいことは、実際のPRをブロックし始める前にどう確認するのか

まず使い捨てのブランチに対してスクラッチのプルリクエストを開く。changesetがあるもの一つ、ないもの一つ、免除ラベルを付けたもの一つを作り、他の誰かの作業にチェックが適用される前に、三つとも期待どおりの結果になることを確認する。条件が逆向きに書かれていたために、あらゆるPRを通してしまうフェイルオープンなチェンジログチェックは、チェックが存在しないよりも悪い。存在しないはずのカバレッジがあるように見えてしまうからだ。同じファイルに対してworkflow_dispatchを使い、最近マージされたいくつかのPRに対して手動で実行すれば、生きたプルリクエストを一切必要とせずに、こうした間違いのほとんどを捕まえられる。

同じ考え方はGitHub Actions以外でも通用するのか

形は引き継がれ、構文だけが変わる。GitLab CIは同じルールを、GitHub Actionsのifの代わりに$CI_MERGE_REQUEST_LABELSをチェックするジョブのrulesブロックとして表現でき、必須のマージリクエスト承認が免除レビューのステップの代わりになれる。この記事が説明しているチェックがGitHub Actionsなのは、読んでいるほとんどのチームがすでにそのプラットフォームにいるからにすぎず、根底にある要件、つまり頼み込む慣習ではなく機械がチェックするゲートという要件は、マージの前にCIが動くあらゆる場所で同じだ。

これはモノレポでも同じように機能するのか

もう一つの要素が必要だ。項目がどのパッケージ用のものかということだ。モノレポのチェンジログは、パッケージが独立してリリースされるようになった瞬間、リポジトリ全体で一つのファイルという方式が機能しなくなる理由を扱っている。CIチェックは同じ要件を引き継ぐ。パッケージを名指ししないchangesetは、正しいチェンジログが更新されることの有用な証拠ではなく、diffのどこかでファイルが変わったことを示すだけだ。これ専用に構築されたツール(JavaScriptエコシステムではChangesetsが一般的だ)は、changesetが作成されるまさにその瞬間に、貢献者に影響を受けるパッケージとsemverの引き上げを選ばせるので、CIチェックは後から推測するのではなく両方の情報を無料で得られる。

FAQ

CIチェックはマージをブロックすべきか、それとも警告だけにすべきか? ブロックすべきだ。警告は機能的には丁寧に頼むことと同じであり、それはすでに失敗している。免除ラベルは、正真正銘の警告だけのケースでも同じ厳格なゲートを通る正当な経路を持てるように、まさにそのために存在する。

免除ラベルが正しく適用されたかを誰がレビューするのか? プルリクエストを承認する人が、いずれにせよすでに行っているレビューの一部として行う。ラベルは決して自己適用されレビューされないままであるべきではない。さもなければ、ゲートが閉じるはずだった同じ静かな抜け道になってしまう。

CIでこれを必須化することは、チェンジログ自動化パイプラインの必要性を置き換えるのか? いいや、それに餌を与えるものだ。チェンジログの自動化は、構造化された項目をページ、フィード、メールに変えることを扱っている。CIチェックは、そもそも自動化する対象としてそれらの構造化された項目が存在することを保証するものだ。

最初に構築する価値がある、これの最小バージョンは何か? 指定されたチェンジログディレクトリの下でファイルが一つも変更されていなければ失敗する単一のチェックと、一つの免除ラベルだ。パッケージ単位のルーティングとモノレポ向けのsemver推論は後で来ればいい。核となる習慣、項目が存在するか誰かが明示的に不要だと言ったか、こそが初日から持つ価値のあるものだ。


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

changeloopの関連ページ: changelogツール比較, changelogジェネレーター

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