セマンティックバージョニング 2.0.0

要約

バージョン番号MAJOR.MINOR.PATCHがある場合、以下のように番号を上げます。

  1. 互換性のないAPI変更を行った場合は、MAJORバージョンを、
  2. 下位互換性を保って機能を追加した場合は、MINORバージョンを、そして、
  3. 下位互換性を保ったバグ修正を行う場合は、PATCHバージョンを上げる。

プレリリースやビルドメタデータのための追加ラベルは、MAJOR.MINOR.PATCHフォーマットの拡張子として使用可能です。

はじめに

ソフトウエア管理の世界では、「依存関係地獄」という非常に恐ろしい場所が存在します。 システムが大きくなればなるほど、そしてソフトウェアにより多くのパッケージを統合すれば するほど、ある日、自分がその絶望の中にいる可能性がより高くなりなます。

多くの依存関係を持つシステムでは、新規のパッケージバージョンをリリースすることは、 すぐに悪夢になり得ます。もし、依存関係の記述が厳しすぎると、バージョンロック(各依存パッケージの 新規バージョンのリリースなしにパッケージをアップグレードできないこと)の危険があります。 もし、依存関係の記述が緩すぎると、必ずバージョンの混乱(妥当な範囲以上に、将来の バージョンへの互換性があると仮定してしまうこと)に噛みつかれることになります。 バージョンロックおよび/またはバージョンの混乱がプロジェクトを安全に先に進めるのを 妨げる時、あなたは依存関係地獄にいます。

この問題のひとつの解決法として、どのようにバージョン番号を割り当て増加させるかを 定めた単純なルールと要件を提案します。これらのルールは、クローズドソースおよび オープンソースのソフトウェアですでに存在する、広く一般に使用されている事例 (ただし必ずしもそれに限定されるものではない)に基づいています。 このシステムが正しく機能するには、まずパブリックAPIを宣言する必要があります。 これは文書により構成されるかもしれませんし、コード自体によって強制されるかもしれません。 いずれの場合も、このAPIが明確で正確であることが重要です。 一旦パブリックAPIを決めたら、特定のバージョン番号を増加することで変更点を表現します。 X.Y.Z (Major.Minor.Patch)というバージョン番号で考えてみます。 APIに影響しないバグ修正ではパッチバージョンを、下位互換性のあるAPI追加/変更では マイナーバージョンを、そして下位互換性のないAPI変更ではメジャーバージョンを増加します。

このシステムを「セマンティックバージョニング」と呼ぶことにします。 この方法では、バージョン番号およびバージョン番号の変更方法は、 そのもととなるコードの意味と、あるバージョンから次のバージョン で何が変更されたかを伝えます。

セマンティックバージョニング仕様 (SemVer)

このドキュメントにおけるキーワード、「しなければならない(MUST)」, 「してはならない(MUST NOT)」, 「要求されている(REQUIRED)」, 「することになる(SHALL)」, 「することはない(SHALL NOT)」, 「する必要がある(SHOULD)」, 「しないほうがよい(SHOULD NOT)」, 「推奨される(RECOMMENDED)」, 「してもよい(MAY)」, および 「選択できる(OPTIONAL)」 は、RFC 2119に 記述されている通りに解釈される。(訳注:RFC 2119で規定される用語の翻訳にあたっては、こちらの RFC 2119日本語訳を参照した。)

  1. セマンティックバージョニングを使用するソフトウェアは、パブリックAPIを宣言しなければならない(MUST)。 このAPIは、コード自身で宣言されるかもしれないし、ドキュメント中に厳密に存在するかもしれない。 どのように定義されるにせよ、正確で包括的でなければならない。

  2. 通常のバージョン番号は、X, Y, およびZが負でない整数であるX.Y.Zの形式をとらなければ ならず(MUST)、先行するゼロを含んではならない(MUST NOT)。 Xはメジャーバージョン、Y はマイナーバージョン、そしてZはパッチバージョンである。 各要素は数値として増加しなければならない(MUST)。例:1.9.0 -> 1.10.0 -> 1.11.0。

  3. 一旦バージョン付けされたパッケージがリリースされたら、そのバージョンの内容を 修正してはならない(MUST NOT)。いかなる修正も新規バージョンとしてリリース しなければならない(MUST)。

  4. メジャーバージョンのゼロ(0.y.z)は、初期開発のために使用される。 いかなる時にいかなるものも変わる可能性がある。 パブリックAPIを安定したものと考えるべきではない。

  5. バージョン1.0.0はパブリックAPIを定義する。このリリース後にどのようにバージョン番号が 増加されるかは、このパブリックAPIとそれがどのように変わるかに依存する。

  6. パッチバージョンZ (x.y.Z | x > 0) は、下位互換性を保ったバグ修正が導入された場合にのみ 増加されなければならない(MUST)。 バグ修正は、誤った振る舞いを修正する内部的な変更として定義される。

  7. 新規機能および下位互換性のある機能がパブリックAPIに導入された場合、 マイナーバージョンY (x.Y.z | x > 0)を増加しなければならない(MUST)。 もしパブリックAPIの機能を非推奨とした場合は、マイナーバージョンを増加しなければならない(MUST)。 プライベートなコード内に多くの新規機能または改善が導入された場合、マイナーバージョンを増加してもよい(MAY) マイナーバージョンには、パッチレベルの変更を含んでもよい(MAY)。 マイナーバージョンが増加された場合、パッチバージョンは0にリセットしなければならない(MUST)。

  8. 下位互換性のない変更がパブリックAPIに導入された場合、メジャーバージョンX (X.y.z | X > 0) を 増加しなければならない(MUST)。 メジャーバージョンには、マイナーまたはパッチレベルの変更を含んでもよい(MAY)。 メジャーバージョンが増加された場合、パッチバージョンおよびマイナーバージョンは、 0にリセットしなければならない(MUST)。

  9. パッチバージョンのすぐ後に、ハイフンとそれに続くドットで区切られた連続する識別子を付与した プレリリースバージョンを記述してもよい(MAY)。 識別子は、ASCII英数字およびハイフン[0-9A-Za-z-]のみで構成されなければならない(MUST)。 識別子は、空であってはならない(MUST NOT)。 数字の識別子は先行するゼロを含んではならない(MUST NOT)。 プレリリースバージョンは、関連する通常のバージョンより優先順位が低い。 プレリリースバージョンは、そのバージョンが不安定であり、関連する通常のバージョンにより 示される意図する互換性要求を満たさないかもしれないことを示す。 例: 1.0.0-alpha, 1.0.0-alpha.1, 1.0.0-0.3.7, 1.0.0-x.7.z.92。

  10. パッチバージョンまたはプレリリースバージョンのすぐ後に、プラス記号とそれに続く ドットで区切られた連続する識別子を付与することにより、ビルドメタデータを記述してもよい(MAY)。 識別子は、ASCII英数字およびハイフン[0-9A-Za-z-]のみで構成されなければならない(MUST)。 識別子は、空であってはならない(MUST NOT)。 バージョンの優先順位を決める際には、ビルドメタデータを無視する必要がある(SHOULD)。 したがって、ビルドメタデータのみが異なる2つのバージョン番号の優先順位は同じである。 例: 1.0.0-alpha+001, 1.0.0+20130313144700, 1.0.0-beta+exp.sha.5114f85。

  11. 優先順位は、バージョン番号を順序づける際に、お互いを比較する方法を表す。 優先順位は、バージョンをメジャー、マイナー、パッチ、およびプレリリース識別子に分割し (ビルドメタデータは優先順位に影響しない)、その順序通りに算出されなければならない(MUST)。 優先順位は、次のようにこれらの識別子を左から右に比較する際に、最初に現れる違いにより 決定される。すなわち、メジャー、マイナー、パッチバージョンは、常に数値として比較される。 例: 1.0.0 < 2.0.0 < 2.1.0 < 2.1.1。 メジャー、マイナー、パッチが等しい場合、プレリリースバージョンは通常のバージョンより 優先順位が低い。例: 1.0.0-alpha < 1.0.0。 メジャー、マイナー、パッチバージョンが同じである2つのプレリーリースバージョンの優先順位は、 次のように各ドットで分割された識別子を左から右に違いが見つかるまで比較することによって、 決定されなければならない(MUST)。すなわち、 数字だけで構成される識別子は数字として比較され、文字とハイフンを持つ識別子は ASCIIのソート順により単語として比較される。 数字の識別子は、常に数字でない識別子より優先順位が低い。 先行するすべての識別子が同じ場合、プレリリースのフィールドが多いほうが少ないほうより優先順位が高い。 例: 1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-alpha.beta < 1.0.0-beta < 1.0.0-beta.2 < 1.0.0-beta.11 < 1.0.0-rc.1 < 1.0.0。

なぜセマンティックバージョニングを使用するのか?

これは新しいアイデアでもなければ革新的なアイデアでもありません。実際、 おそらくこれに近いことをすでにしているでしょう。 問題は、「近い」は十分ではないということです。 公式な仕様のようなものへの準拠がなければ、バージョン番号は 本質的に依存関係管理の役に立ちません。 上記のアイデアに名前と明確な定義を与えることにより、 あなたの意図をソフトウェアのユーザに伝えることが容易になります。 一旦、これらの意図が明確になれば、柔軟な(だが柔軟すぎない)依存関係定義が 達成されます。

セマンティックバージョニングが、どのようにして依存関係地獄を過去のものにすることができるかを、 ある単純な例で示してみます。 “Firetruck”と呼ばれるライブラリについて考えてみます。 そのライブラリは、”Ladder”という名前のセマンティックバージョニングで管理された パッケージを要求します。 Firetruckが作られた時には、Ladderはバージョン3.1.0でした。 バージョン3.1.0で初めて導入された機能をFiretruckは使用しているので、 Ladderの依存関係を3.1.0と等しいかそれより大きい、ただし4.0.0より小さいものとして 安全に定義できます。さて、Ladderのバージョン3.1.1や3.2.0が使えるようになった時には、 それれらをパッケージ管理システムにリリースできますし、また既存の依存ソフトウェアと 互換性があることを知ることができます。

責任ある開発者として、あなたはもちろん、いかなるパッケージのアップグレードも公表されている通りに 機能することを確かめたいと思うでしょう。 現実世界は厄介なところで、そのことについて我々ができることはありませんが、用心深くなることはできます。 時間を節約し手間を省くために、あなたにできることは、セマンティックバージョニングが、 依存パッケージの新規バージョン導入を強制することなくリリースやアップグレードを行う分別ある方法を 提供できるようにすることです。

もし、そのすべてが望ましいと思うなら、セマンティックバージョニングを使いはじめるために しなければならないことは、そうすることを宣言し、そのルールに従うことだけです。 READMEからこのWebサイトにリンクすれば、ほかの人もルールを知り、その恩恵を受けることが できます。

よくある質問

0.y.zという初期開発フェーズにおいて、どのようにリビジョンを取り扱うべきでしょうか?

行うべき最も簡単なことは、初期開発リリースを0.1.0で始めて、 それに続く各リリースでマイナーバージョンを増加することです。

いつ1.0.0をリリースするか、どうしたらわかりますか?

もし、ソフトウェアが本番で使用されているなら、おそらくすでに1.0.0であるべきです。 もし、ユーザがすでに依存している安定したAPIがあるなら、1.0.0であるべきです。 もし、下位互換性についてとても心配なら、おそらくすでに1.0.0であるべきです。

高速な開発や素早いイタレーションを妨げませんか?

メジャーバージョンゼロは高速な開発に他なりません。もしAPIを毎日変更しているなら、 まだバージョン0.y.zであるべきか、次のメジャーバージョンの作業をする 別の開発ブランチにいるべきかのどちらかでしょう。

パブリックAPIに対して下位互換性を損なう些細な変更をした時も、メジャーバージョンの増加が必要ですか?すぐに42.0.0になってしまうのでは?

これは、責任ある開発・配慮の問題です。 依存するコードが多くあるソフトウェアに 対して、互換性のない変更を軽々しく導入するべきではありません。 アップグレードを招くコストは甚大です。 互換性のない変更をリリースすることによりメジャーバージョンを上げなければならないということは、 変更に対するインパクトをよく考え、そこに含まれる便益費用比を評価することになること を意味します。

すべてのパブリックAPIを文書化するのは手がかかりすぎます!

他人によって使用されることを意図したソフトウェアを正確に文書化するのはプロの開発者としての責任です。 ソフトウェアの複雑性を管理することは、プロジェクトを効率的に保つためのとても重要な部分であり、 どのようにソフトウェアを使うか、あるいはどのメソッドを安全に呼び出せるかということを誰も知らなければ、 難しいことです。 長い目で見れば、セマンティックバージョニングと、明確に定義されたパブリックAPIの強要によって、 あらゆる人があらゆることを円滑に実行し続けられるようになります。

もし後方非互換の変更を誤ってマイナーバージョンとしてリリースしてしまったら、何をすればよいでしょうか?

セマンティックバージョニング仕様に違反したと気付いたらすぐに、問題を修正の上、 その問題を修正し下位互換性を回復する新規マイナーバージョンをリリースして下さい。 このような状況下であっても、バージョン付けされたリリースを修正することは受け入れられません。 必要なら、違反したバージョンについて文書化して、その問題をユーザに知らせます。 そうすれば、ユーザはその違反したバージョンに気が付くでしょう。

パブリックAPIを変更せずに依存関係を更新するには、何をすべきでしょうか?

パブリックAPIに影響しないので、互換性はあると考えられます。 あなたのパッケージと同じ依存関係を明示的に持つソフトウェアは、 自身で依存関係を定義すべきであり、その作者がいかなる矛盾にも気づくはずです。 依存関係を、バグ修正のために更新するのか、新機能導入のために更新するのかによって、 その変更がパッチレベルなのかマイナーレベルなのかが決まります。 新機能導入の場合は、コードの追加があるのが普通でしょうから、その場合はマイナーレベルの 増加であることは明白です。

このバージョン番号変更に適合しないような方法でパブリックAPIを不注意に変更してしまった場合はどうしたらいいでしょうか(例 パッチリリースで、メジャー番号が変わるような変更が誤ってコードに導入された)

最善の判断をして下さい。振る舞いをパブリックAPIが意図する状態に戻すことにより劇的なインパクトを 受けるユーザが大勢いるなら、 その修正が厳密にはパッチリリースと考えられるものであっても、メジャーバージョンリリースを実施するのが 最善でしょう。 セマンティックバージョニングは、どのようにバージョン番号を変更するかによって意味を伝達する ことに他ならないことを思い出して下さい。 これらの変更がユーザにとって重要な場合は、そのことを知らせるバージョン番号を使用して下さい。

非推奨な機能はどのように取り扱えばよいですか?

既存の機能を非推奨にすることはソフトウェア開発では当たり前のことで、 前進するために頻繁に必要とされるものです。 パブリックAPIの一部を非推奨にする場合は、2つのことをすべきです。(1) ユーザに 変更を知らせるためにドキュメントを更新し、 (2) 非推奨化を反映する新たな マイナーリリースを実施します。 新規メジャーリリースでその機能を完全に削除する前に、 非推奨化を含むマイナーリリースを少なくとも1回はするべきで、 それによっていユーザはスムーズに新規APIに移行できます。

SemVerにはバージョン文字列のサイズ制限はありますか?

いいえ、しかし適切に判断して下さい。例えば、255字のバージョン文字列はおそらく長すぎます。 また、特定のシステムは、文字列のサイズに独自の制限を強いるでしょう。

セマンティックバージョン仕様について

セマンティックバージョン仕様は、Gravatarsの考案者でGitHubの共同創業者であるTom Preston-Wernerによって書かれました。

フィードバックを残したければ、GitHubでissueをオープン して下さい。 (訳注:この日本語訳へのフィードバックは、semver-ja.github.ioでissueをオープン して下さい。)

ライセンス

Creative Commons - CC BY 3.0