CI/CD のブランチ管理について

タブとスペースの違いと同様に、ブランチ管理もまた、オンラインとオフラインの両方で議論がヒートアップする感情的なトピックの 1 つです。

ソフトウェア開発の多くの事項と同様に、ベストアプローチに対する強い意見は多数ありますが、適切な回答は状況によって異なります。 それを踏まえて、ブランチ管理とは何か、そしてブランチ管理がどのように CI/CD と繋がっているのかについて見てみましょう。

簡単に言えば、ブランチ管理は、いつどのようにしてバージョン管理にブランチを作成してマージするのかということに関するチーム内での約束事です。 バージョン管理システムをどのようにセットアップしてブランチを使用するかによって、CI/CD パイプラインのセットアップ方法が変わってくるため、ニーズに見合うモデルを選択することが重要となります。

DVCS におけるブランチ

ブランチ管理は、分散バージョン管理システム、特に Git への人気の高まりによってブランチがより簡単になったため、開発チームの考慮事項となりました。

分散システムでは、リポジトリの複数のコピーが存在するため、ソースオブトゥルースが複数存在することになります(ただし一般的には、チーム内でセントラルコピーまたはプライマリーコピーを指定する傾向があります)。 あなたとチームメンバーは、リポジトリにあるあなたのコピーに対する変更を並行して実施することになるため、変更を同じリポジトリの別のコピーにプッシュすることで、作業を共有しています。

Git の登場により、ブランチの作成と別のブランチのコミットのマージが非常に軽量な作業になりました。 Git では、ブランチは特定の名前でラベル付けされた単なるコミット(または一連のコミット)です。 ブランチは新機能の作業やハッキング染みた実験など、一連の変更を格納するのに最適です。

その上で、別のリポジトリにブランチをプッシュしたり、マスターなどの別のブランチとマージして、残りのコードベースと合わせたりすることで、変更を共有することができます。 また、その変更を却下するのであれば、それらを破棄することもできます。 2 つのブランチをマージする場合、Git は各ブランチのコミットの整合性をとり、他のバージョン管理システムでのマージに関わるほとんどの複雑な事項を回避します。

CI/CD でのブランチの使用

継続的インテグレーションでは、開発チームの全員が頻繁に変更をコミットすることに焦点が当てられます。 つまり、すべてが期待どおりに動作することを定期的にテストできるということです。コーディングが完了した後に、異なる作業ストリームを何週間または何か月もかけて統合する必要はありません。 代わりに、より頻繁にソフトウェア更新をリリースすることが可能であるため、継続的デリバリーとデプロイのメリットを享受することができます。

変更をどこにコミットするのか、自動ビルドとテストをいつ実行するのか、そしてどこから更新をリリースするのかを決定する際に、ブランチと CI/CD の相互関係が生まれます。 最も単純なアプローチ(少なくとも概念的に言った場合)は、ブランチをまるごと避けることです。 トランクベース開発では、中央のリポジトリにあるマスターブランチに全員が定期的に変更をコミットし、常にリリース可能な状態が維持され、本番に頻繁にデプロイされます。

トランクベース開発は、特に成熟した CI/CD セットアップが存在し、ホスティングされているシステムへの継続的デプロイが実行している場合には非常に効果的ではありますが、いくつかの課題も存在します。 ブランチ管理は、コード変更をマージするための代替手法を提供するものであり、さまざまなメリットとデメリットがあります。 以降に示すのは、CI/CD を実行している開発チームが最も一般的に使用している一部の手法です。

フィーチャーブランチ

名前からわかるように、フィーチャーブランチは、個別の機能を残りのコードベースとは別に保持するために作成されるブランチです。 作業中の機能をマスターブランチに含めないようにしておくことで、マスターをデプロイ可能な状態に維持しやすくなり、リリースブランチ(以下参照)からではなく、直接マスターからデプロイしている場合には、未完成の機能が本番にデプロイされる危険を避けることができます。 この場合でも作業内容は、ブランチを中央のリポジトリ(指定している場合)かほかの任意のリポジトリにプッシュすることで、ほかのチームメンバーと共有することができます。

フィーチャーブランチの主な欠点(ほぼトランクベースの開発の支持者からの批判)は、機能が「完成」するまで変更の統合を遅らせることで、継続的インテグレーションのメリットを損なうことにあります。 このため、マージ競合のリスクが生まれ、変更が反復的にコミットされるよりも長い時間が修正にかかってしまう、より複雑なバグが導入される可能性があります。

こういった課題は、マスター(またはリリース準備に使用するブランチ)だけでなく、フィーチャーブランチでも自動ビルドとテストを実行するように CI サーバーをセットアップすることで緩和することができます。 こうすることで、構築中のものに対するフィードバックを迅速に得られるというメリットを活かしながら、変更をマージする際に発生する課題のリスクを軽減することができます。

マージ競合を最小限に抑える方法として、フィーチャーブランチの存続期間を 1 日、最大でも 2 日に維持することが挙げられます。 また、定期的にマスターの上にブランチをリベースするか、マスターの変更をマージするというオプションもあります。 この方法を使えば、フィーチャーブランチを、マスターにコミットされれるその他すべての変更で最新の状態にすることができます。 ただし、並行する大量のフィーチャーブランチがすべてマスターへのコミットを遅らせている場合には、競合が発生するリスクを拭うことはできません。

リリースブランチ

フィーチャーブランチは作業中の機能を管理する方法として使用しますが、リリースブランチは、リリース前に変更を「強化」するために使用されます。 リリースブランチは継続的デリバリーモデルに非常に適しており、更新は、準備が整った時点でではなく一定の間隔で配布されるため、本番環境にある複数のバージョンのサポートがより楽に行えるようになります。

リリースブランチのワークフローでは、特定のリリースに予定された変更の準備が整うと、関連する変更が含まれるリリースブランチが作成されます(マスターまたは別の開発ブランチから)。これ以降の機能がマージされることはありません。 一方、別のリリースに予定された機能の開発については、そのままマスターなどのブランチにマージし続けることができます。

その後、リリースブランチのビルドは一連の自動テストに掛けられます。バグ修正はリリースブランチで行われ、リリースの準備が整うまでさらにテストが繰り返されます。 これらのバグ修正はマスターブランチにも適用し直すことで、以降の製品バージョンに必ず含まれるようにする必要があります。

ソフトウェアの各バージョンをサポートする必要がある限りリリースブランチを維持しておくことで、古いバージョンへの修正のデプロイがはるかに簡単になります。

更新が必要となった場合、ホットフィックスブランチまたhマスターで更新を開発し、通常通りにテストしてからリリースブランチに適用(Cherry-Pick などによって)することが可能です。

その後、変更をデプロイする前にそのブランチの CI/CD パイプラインに通し、そのバージョンに課題が存在しないことを保証します。 または、リリースブランチで直接作業を行い、該当する場合はマスターに適用し直すこともできます。

ホットフィックスブランチ

ホットフィックスブランチはフィーチャーブランチと同じように動作しますが、完全性を得るためにも説明しておく価値があります。 ホットフィックスブランチは、バグ修正をできるだけ迅速に本番に適用することを狙いとしています。

ホットフィックスブランチは、デプロイ先に応じてマスターまたはリリースブランチから作成できます。 フィーチャーブランチと同様に、リリースブランチまたはマスターブランチにマージする前に、ホットフィックスブランチで一部の CI/CD 要素を実行することが可能です。この場合、リリース前にさらに自動テストを実施することができます。

まとめ

CI/CD ワークフローにおけるブランチの最も一般的な使用方法をいくつか見ましたが、こういったブランチには他にもたくさんの種類があります。

最も重要なのは、具体的なコンテキストで機能する戦略を見つけ出すことです。 継続的な改善の DevOps 的な考え方を採用し、さまざまなオプションを考慮することで、CI/CD 手法が成熟する過程のニーズに合わせてアプローチを調整し続けられるようになります。