CI フレンドリーな Git リポジトリに役立つ 5 つのヒント

Sarah Goff-Dupont
Sarah Goff-Dupont
リストに戻る

アトラシアンをフォローしていれば、アトラシアンが継続的インテグレーション (CI) と Git の向上に取り組んでいることにお気付きいただけるでしょう。もちろん、これらへの取り組みは個別に行われていますが、この 2 つの組み合わせによってもたらされるパワーはさらに大きくなっています。今日は、CI システムがリポジトリと最適にやり取りできるようにするためのヒントをいくつか紹介します。ここからすべてが始まります。

1: リポジトリ内の大きなファイルの追跡を避ける

Git についてよく耳にする話の 1 つですが、バイナリファイルやメディアファイル、アーカイブされたアーティファクトなど、大規模なファイルをリポジトリに置くのは避けるべきだと言われています。いったんファイルを追加すると、そのファイルは常にリポジトリの履歴に含まれ、レポジトリが複製されるたびに、巨大な重いファイルが一緒にクローンされることになります。リポジトリの履歴からファイルを取り出すのは非常に注意が必要な作業で、いわばコードベース上でロボトミー手術をするようなものです。こうした外科手術的なファイル抽出によって、リポジトリの履歴すべてが変更され、どんな変更がいつ行われたか明確に把握することができなくなります。原則として容量の大きいファイルを避けるのはこうした理由からです。

しかし、CI を行っている場合は、容量の大きいファイルを避けることが特に重要になります。

ビルドするたびに、CI サーバーはリポジトリのクローンを作業ビルド ディレクトリに作成しなければなりません。リポジトリが山とある巨大なアーティファクトで膨れあがっている場合、その処理が遅くなり、開発者がビルド結果を待っていなければならない時間が長くなります。

それはいいとしましょう。しかし、もしビルドが他のプロジェクトや大規模なアーティファクトのバイナリに依存している場合はどうでしょうか? これは非常によくある状況であり、おそらくこれからも変わることはないと思われます。では質問です。どのようにすればこれを効果的に処理できるでしょうか。

Artifactory(Bamboo 用のアドオンを作成) や Nexus、 Archiva のようなストレージ システムには、自分のチームや周囲のチームが生成するアーティファクトに対する支援機能があります。こうしたシステムでは、ビルド開始時に必要なファイルをビルド ディレクトリにプルできます。Maven や Gradle を通してサード-パーティのライブラリーをプルするようなものです。

今、あなたは「そうだ、毎晩大きなファイルをビルド サーバーに同期させれば、これらのファイルをビルド時にディスク経由で転送するだけですむはずだ」と考えているかもしれません。

ディスク転送はネットワーク転送よりもはるかに高速ですが、特にアーティファクトが頻繁に変更される場合は、これを行わないことをお勧めします。夜間同期の合間は、結局、古いバージョンのアーティファクトでビルドすることになりますし、開発者はビルド時にこれらのファイルがローカル ワークステーションに必要です。したがって、総合的に考えて、ビルド時にアーティファクトをダウンロードするのが最もクリーンな方法です。

2: CI の shallow clone を使用する

ビルドを実行するたびに、サーバーはリポジトリのクローンを作業用のカレント ディレクトリに作成します。前にも話しましたが、リポジトリをクローンする際に、Git は既定でリポジトリ全体の履歴をクローンします。そのため、この操作は長い間にますます時間がかかるようになります。ただし、CI システムがシャロー クローンを使用する場合は別です。

シャロー クローンを使えば、リポジトリの現在のスナップショットだけがプルされます。そのため、特に大規模な古いリポジトリで作業をする場合、この方法はビルドの時間を削減する非常に有効な手段となります。

ただし、ビルドに完全なリポジトリ履歴が必要であるとします。たとえば、POM でタグを追加したりバージョンを更新したりするリリース ビルドがある場合や、ビルドごとに 2 つのブランチをマージする場合などです。

Git の以前のバージョンでは、変更をプッシュするために、リポジトリの履歴全体を必要としていました。1.9 では、ファイルの簡単な変更は、履歴全体がなくてもプッシュが可能です。しかし、マージについては、Git が 2 つのブランチをさかのぼって、共通の祖先を見つける必要があるため、依然として履歴全体が必要です。ビルドでシャロー クローンを利用している場合、このことが問題になります。そこで 3 つめのヒントが登場します。

3: ビルドエージェントでリポジトリをキャッシュする

これによって、クローン作成操作が大幅に高速化します。一部の CI サーバーでは初期設定でこれが実行されます。

リポジトリのキャッシングが役に立つのは、複数のビルドを通じてエージェントを使用している場合のみです。EC2 や他のクラウド プロバイダーでビルドを実行するたびに、ビルドエージェントを作成しては削除している場合は、リポジトリのキャッシングに意味がなくなります。なぜなら、空のビルド ディレクトリで作業していることになり、どのみち毎回リポジトリのフルコピーをプルする必要があるためです。

Shallow clone とリポジトリ キャッシングを足して常住エージェントまたはエラスティック エージェントで割ると興味深い事実がわかります。以下の表は戦略を立てる際に役立ちます。

マトリックス表

4: トリガーを上手に選ぶ

アクティブなブランチのすべてで CI を実行することがよいのは(ほぼ)言うまでもないことです。しかし、あらゆるコミットに対してすべてのブランチでビルドを実行するのはよい考えと言えるでしょうか。おそらくそうではないでしょう。その理由はこうです。

たとえば、アトラシアンの場合を考えてみましょう。アトラシアンには 500 人を超える開発者がいて、それぞれ毎日数回リポジトリに変更をプッシュしています。そのほとんどはフィーチャー ブランチへのプッシュです。ビルドの回数は大量です。ビルド エージェントの数を直ちに、そして大きく引き下げない限り、キューに大量の待ちが並ぶことになります。

当社の内部 Bamboo サーバーの1 つには、種類の異なるビルドプランが 935 本収納されています。このサーバーに 141 のビルド エージェントを接続し、アーティファクト パッシングやテストの並行実施といったベストプラクティスを使用して、各ビルドを可能な限り効率的に行いました。しかし、それでも各コミットのビルドは作業を停滞させ続けていました。

Bamboo インスタンスごとに 100 以上のエージェントを毎回ひたすら設定するかわりに、一歩下がってこの作業は本当に必要か考えてみました。答えはノーでした。

厳密なテストとリソースの保全のバランスを取るよい方法は、開発ブランチのプッシュ ボタン上でビルドすることだとわかりました。ここが、ほとんどの変更アクティビティが発生している場所であるため、コスト削減の最大のチャンスとなります。開発者は、それが自分のワークフローに自然に適合していることに気付き、これにより追加の制御と柔軟性が得られることを気に入っています。

main や安定版リリース ブランチのような重要なブランチの場合、リポジトリに変更がないかポーリングすることでビルドが自動的にトリガーされます。すべての進行中の作業で開発ブランチを使用しているため、main に入るコミットは (理論的には) マージされる開発ブランチのみのはずです。さらに、これらのコード行はリリースや開発ブランチ作成の元になります。したがって、すべてのコミットに対してタイムリーなテスト結果を得ることが非常に重要です。

5: ポーリングを止めて、フックを始める

もう一つのオプションは、完全にポーリングをやめて、変更がプッシュされてビルドが必要になった時に、リポジトリが CI サーバーに合図するように設定する方法です。一般的には、これはリポジトリでフックすることによって実行できます。

これはどんなツールを使っても可能ですが、たまたま、当社では最近 Bitbucket Server と Bamboo の統合を追加し、こうした追加の設定が不要になりました。 Bamboo と Bitbucket Server がバックエンドでリンクされた後は、リポジトリ主導のビルドトリガーが細かい設定なしで即時に機能します。フックも特別な設定も必要ありません。

ツールに関係なく、リポジトリ主導のトリガーには、ターゲット ブランチがアクティブでなくなったときに自動で終了するというメリットがあります。つまり、何百もの放棄されたブランチをポーリングして CI システムの CPU サイクルを無駄にすることはありません。または、ブランチのビルドを手動でオフにする作業でユーザーが時間を無駄にすることもありません(ただし、やはりポーリングが必要であれば、アクティブでない期間が X 日間続いた後にブランチを無視するように Bamboo を簡単に設定できることは注目に値します)。

本格的に始動する

ここで説明したすべてのヒントは、市販されているどの CI サーバーでも実装可能です。しかし、私たちは常にベスト プラクティスを実践しやすくすることを目指しているので、それらすべてを Bamboo に組み込むことで、セット アップが非常に簡単になるようにしました。ツアーに参加して、すべてのメリットを確認してください。

Git を学習する準備はできていますか?

この対話式チュートリアルを利用しましょう。

今すぐ始める