エンジニアリング

Conventional commitsからチェンジログへとつなげる方法

1分で読めます 更新

Conventional commitsはチェンジログに三つのことを無料で与えてくれる。各変更のタイプ、それが触れたシステムの部分、そして何かを壊すかどうか。それ以外は何も与えない。言い回し、グループ化、選定、つまりチェンジログそのものは、完全に未解決のままであり、そうではないふりをするパイプラインは、フォーマットされたgit logを出荷することになる。

feat(exports): add CSV column selection
fix(auth): reject expired refresh tokens
chore(deps): bump node-pg to 8.11

Conventional Commits形式の三つのコミット。これらから、機械は一つが機能であり、一つが修正であり、一つが整理であり、それぞれがシステムのどの部分に触れたかを教えてくれる。それは本当に有用であり、この慣習の約束のすべてでもある。人間以外の何かが読めるコミット履歴。誤りは、それがチェンジログを与えてくれると考えることだ。それは原材料を与えてくれるにすぎない。

この慣習は何を規定しているか

タイプ、任意のスコープ、そして説明。type(scope): description。タイプは慣習的にfeat、fix、chore、docs、refactor、test、perf、build、ci。二つのものが破壊的変更を示す。コロンの前の!、またはBREAKING CHANGE:フッターだ。ツールはminorとpatchのバージョン更新のためにfeatとfixに依拠し、majorのために破壊的変更のマーカーに依拠する。

コミットが与えてくれるものチェンジログが必要とするもの誰が隙間を埋めるか
feat / fix / choreAdded / Fixed / 内部向けマッピング、自動
(scope)読者が認識できるグループ化人間、スコープごとに一度
! または BREAKING CHANGE:誰が壊れるか、いつまでか、何をすべきか人間、毎回
レビュアー向けに書かれた説明顧客向けに書かれた結果人間、項目ごと
一つのコミット複数のコミットになりうる一つの変更squashのルール、または人間

このマーカーはツールに伝えるだけであり、呼び出し元には伝えない。それはAPIの非推奨化と破壊的変更とは何かのテーマだ。これは小さな仕様であり、そこから何も生成しなくても従う価値がある。なぜならそれが、変更ごとに一つの決定を強制するからだ。それはユーザーが目にする変更かどうか、という決定だ。

Conventional commitsはどこで力尽きるか

文章のところで力尽きる。この慣習が捉えるすべては変更についてのメタデータであり、変更そのものはまだレビュアーの語彙で記述されている。

コミットメッセージはレビュアーのために書かれている。 fix(auth): reject expired refresh tokensは正しいが、顧客には何も伝えない。チェンジログの読者は「セッションが実際に期限切れになったときにログアウトされるようになりました。断続的な401を見ることはなくなります」を求めている。

スコープは内部向けだ。 exports、auth、ingestはモジュール名であり、安定しているのでグループ化には適しているが、コードベースの外にいる誰にとっても無意味だ。

一つの変更はしばしば複数のコミットになる。 十一のコミットにわたってマージされた機能は十一の項目を生み出し、そのうち十はノイズであり、それを隠すために圧縮すると、レビュー履歴が失われる。

choreはカテゴリではなくゴミ箱だ。 依存関係の更新、CIの変更、リネームはすべてそこに落ち、そのうちいくつかはユーザーに関係あるが、大半はそうではない。

つまり、この慣習はタイプ、スコープ、破壊的かどうかの状態を無料で与えてくれ、言い回し、グループ化、選定を完全に未解決のままにする。この三つがチェンジログそのものだ。 チェンジログの項目は実際には誰が所有すべきかは、その 言い回し、グループ化、選定を誰が担うべきかを扱っている。慣習そのものはそれについて何の意見も 持っていないからだ。

Conventional commitsからどのようにチェンジログを生成するか

二つの層で行い、二つ目は必須でなければならない。

層一、自動。 マージ時に、コミットから下書きの項目を導出する。タイプをチェンジログのタイプにマッピングし(featをAddedに、fixをFixedに、破壊的変更のマーカーをフラグ付きのChangedに)、スコープはテキストではなくメタデータとして保持し、PRへのリンクを持たせる。それをKeep a Changelogが求めるUnreleasedセクションに置く。

層二、人間、そして必須。 リリースが出る前に、それぞれの下書きの項目は、ユーザーの語彙での一行の書き直しを受けるか、内部向けとしてマークされて公開ビューから外される。これは人々が飛ばそうとするステップであり、それを飛ばすことがdiffのように読めるチェンジログを生み出す。

重要な設計上の詳細は、層二がパイプライン内でオプションではないということだ。編集されていない下書きでリリースが切られてしまうなら、全員が忙しい週にそれが起こる。どのステップが機械のもので、どれが人間のものかが、チェンジログの自動化のすべての内容だ。

リリースを切ることは、Gitタグ、リリース、このチェンジログのエントリが噛み合うか、それとも同期しなくなり始めるかの瞬間でもある。Gitタグ、リリース、そしてあなたのチェンジログが三つを同期させ続ける方法を扱っている。

三つの落とし穴

squash mergeはフッターを食べてしまう。 プラットフォームがPRのタイトルをメッセージとして圧縮する場合、そのブランチ内のコミットのBREAKING CHANGE:フッターは消え、あなたのツールは静かに破壊的変更を見なくなる。squashテンプレートが実際に何を保持しているか確認しよう。

revertコミットは幻の項目を生み出す。 翌日にrevertされるfixは、導出がrevertを調整しない限り、出荷されなかったものについての項目を生成する。多くのツールはそれをしない。

バージョンの更新とチェンジログが同期しなくなる。 バージョンがコミットから計算され、チェンジログが後から手動で書かれる場合、それらは約二回のリリースで乖離する。両方を同じパスで計算するか、どちらか一方が間違っていることを受け入れよう。

パイプラインなしで機械的な部分だけが欲しい場合

私たちのチェンジログジェネレーターは導出のステップをブラウザで行う。コミットを貼り付けると、グループ化されタイプ付けされた項目が得られる。意図的に決定論的で完全にクライアントサイドであり、貼り付けたコミットがあなたのマシンから外に出ることはない。これはメッセージが非公開のリポジトリからのものであるときに重要だ。収集の半分を正直に行い、層二を試みない。層二は判断であり、それを装うツールは、この記事が反論しているまさにそのチェンジログを生み出すことになるからだ。

パイプライン版については、チェンジログツールが何が存在するかをカバーしている。

まとめ

Conventional commitsは「これはどんな種類の変更か」という問いに、信頼できて安価に答える。「人々に何を伝えるべきか」には答えず、コミットメッセージの上にどれだけツールを重ねてもそれは変わらない。なぜなら、その情報はコミットメッセージの中に一度も存在しなかったからだ。書き直しのための予算を確保しよう。

FAQ

Conventional commitsは自動的にチェンジログを生成するか? 自動的に下書きを生成する。タイプ付けされ、スコープを持ち、リンクされた項目だ。顧客向けの言い回し、グループ化、そして何を省くかの判断は、依然として人間を必要とし、そのステップを飛ばすパイプラインはコミットメッセージを公開することになる。

どのConventional commitのタイプがチェンジログに現れるか? featとfixは常にAddedとFixedとして現れる。perfは通常Changedとして現れる。chore、docs、refactor、test、build、ciはデフォルトで内部向けであり、人間がそのうちの一つを昇格させたときだけ現れる。

Conventional commitsは破壊的変更をどうマークするか? タイプまたはスコープの後の!(feat(api)!: ...)、あるいはコミット本文のBREAKING CHANGE:フッター。squash mergeがPRのタイトルだけを保持する場合、両方とも失われる。

チェンジログを自動化するのにConventional commitsは必要か? 必要ない。PRのラベル、PRのテンプレート、issueへのリンクは、pull requestでマージするチームにとって同じメタデータを運ぶ。Conventional commitsは、変更の単位がコミットであるときに最も安価な選択肢だ。


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

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

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