トリガーを引く:SVN から Git への移行

Matt Shelton
Matt Shelton
リストに戻る

私たちは Git への移行を進めており、効率的な開発ワークフローの中でgit-flow と Maven を併用する方法を考案 しました。私たちの今のワークフローがどのようなものかをお話しする前に、以前はどんな状況であったかを知っておくことが重要です。

以前のやり方

SVN から Git に移行する前の私たちの環境では、バージョン管理はすべて手動で行っていました。チームが作業に取り組んでいるあらゆるフィーチャーの開発は trunk 上で同時に行われていました。開発者が SVN に変更をコミットすると、Bamboo がスナップショット ビルド (1.0.0-SNAPSHOT)を始めます。作業が統合テストに合格すると、他の誰も次のスナップショットを実行していないのを手動で確認した後、リリース プランを実行します[1]。そのリリース ビルド (1.0.0-1)[2] にすばやくスモーク テストを施した後、QA に回して機能検証を行うという具合でした。

私たちはのべつ幕なしに "リリース" していました。QA に回されるビルドは、すべて Maven リリース ゴールからのもので、マイナー番号またはパッチ番号のインクリメントはしていませんでした。それぞれのリリースには Bamboo によって例の -buildnumber を付けていたため、QA に回す特定のリリースを追跡することが可能でした。

その後、QA がそのリリースに"最終版" というお墨付きを与えると、mvn version:set を使用して、私たちがマイナー バージョンをインクリメントしていました。これは、もし仕事の調子が必ずしも絶好調でない場合は、そのバージョン番号の数を増やすのを忘れるリスクがあり、既に本番にリリースしたものの後続に当たる "リリース" 1.0.0-x をビルドするリスクがあるということでした。そうなれば、大失敗です。大変な手間が発生します。しかし、開発から出てくるビルドはすべて明快で、追跡可能な、永続的な番号が付いているということを意味していました。

それは "結構" なのですが、追跡の大変さは悪夢のようでした。

そのようなことは二度としたくありませんでした。顧客に届ける準備ができ、送り出せる段階になった時にリリースしたいと考えているだけでした。それに、本番環境でビルド番号はもう使わない、つまり、メジャー番号 . マイナー番号 . パッチ番号のみ。

しかし、私たちは QA が特定のデリバリーを特定のリリースまで追跡する手段を確保していてほしいとも考えました。QA が SNAPSHOT リリースを常にテストすることは不可能でした。ありがたいことに、Jira ソフトウェアを使用して Jira 課題と Bitbucket リポジトリ、そして課題のビルドが含まれるビルドプランの間のリンクを表示させることによって、この作業の一部が簡単になります。

結局、私たちはいくつかのルールに従うことにしました。

  1. 開発者は自分の feature ブランチから統合テストを行い、そのブランチには常に develop ブランチの最新の状態を反映させておく。
  2. 統合テストが完了し、合格した後は、開発者はプル リクエストを発行し、develop ブランチに自分のコードがプルされるようにする。
  3. 開発者は共通プロジェクトの QA 候補バージョンをプロモートし、次に本番プロジェクト用の develop の QA 候補バージョンをトリガーする。ビルド時に特定の共通プロジェクト リリースを使用する必要があるため [3]、開発者に前述の共通 QA 候補リリース バージョンを要求する。
  4. QA テストの QA 候補ビルドのみ。スナップショットは決して作成しない。

すべてのフィーチャー、QA で発見されたバグなどに、1 - 5 の手順を繰り返します。その後、バージョンの作業をすべて終えると、Bamboo 内の特定の QA 候補ビルドをプロモートし、git-flow とブランチの行程を経て、リリース ブランチに至ります。これによって最初のリリース候補セットが作成され、QA が最終テスト、回帰テストなどを行います。

正しく構築する

ビルドを適切に作成するのは難しい場合があります。全員が SVN と元の Bamboo ビルド プランから離れる前に、POC プロジェクトをセット アップし、それを使用してすべての Bamboo プランを練り上げました。最終的には、以下の計画が我々のニーズを満たしていることがわかりました。

  1. develop: Bitbucket Server からトリガーされ、プル リクエストからプルされるすべての変更とともに SNAPSHOT ビルドが作成される。ビルド プランには 3 つの段階がある。
    1. スナップショット - スナップショットがビルドされ、バージョンには影響しない。
    2. QA ビルド - X.Y.Z-QA {buildnumber} という番号の "QA 候補" リリースが、そのスナップショットの作成に使用したのと同じ git コミットからビルドされる。
    3. リリースへのプロモート-リリース ブランチを作成し、開発マイナーバージョン番号をインクリメントします。すべて QA ビルドを作成するのに使用したのと同じ git コミットから行います。
  2. フィーチャー: 既定のビルド プランが設定されるが、ほとんどは Bamboo のプラン ブランチ機能を使用して作成され、名前に feature/* が含まれる新しいブランチを監視し、ブランチが作成されるたびに、そのブランチ用のブランチ プランを作成する。フィーチャーには、SNAPSHOT をビルドするステージが 1 つあるだけである。[4] また、フィーチャーが自動的にビルドしないようにするため、リポジトリが "偽のブランチ" という名前のブランチをポイントし、決してトリガーしないようにしている。
  3. リリースとホットフィックス: ビルドとリリースの手順は同じなので、プランを共有できる。また、このプランは「偽のブランチ」を指しており、次の 2 つのステージでブランチ プランベースのリリースのみを削除する。
    1. 候補リリースのビルド - これによって X.Y.Z-rc{buildnumber} というバージョン番号が付いたリリースが作成される。
    2. リリースのファイナライズ- これにより最終リリース番号のセット、マスターへのマージ、タグの作成が行われます。その後、リリース ブランチが削除され、プランが無効となります。
  4. サポート: これはリリースやホットフィックスとほぼ同じですが、main にマージされることはありません。代わりに、リリースのファイナライズ ステージの最後にマイナー バージョンをインクリメントします。

フィーチャー、リリース、ホットフィックス、サポートの各プランはすべて実行中のブランチ プランであるため、Bamboo でそれらを表示すると、各プランに “未ビルド” と表示されます。これを初めて見たときは、誰もがぽかんとした顔つきになりました。私のビルドはどこにいってしまったのでしょうか? しかし、私たちはこれが理にかなっていることに気付きました。

私たちには非常に多くのビルド プラン [5] があるので、Bamboo でブランチ プランを含むすべてのプランをインラインで表示すると、永久にスクロールすることになります。情報が多すぎても、実際にはあまり役に立ちません。そこで、もう一度クリックしてブランチ プランのステータスを確認してみます。大したことではありませんが、これらをすべて表示できる方法があれば便利です [6]。

移行のプロセス

POC プロジェクトが期待したように機能し、開発者のワークフローに整合性があり、信頼できることを確信した段階で、私たちは SVN のコードベースを Git にインポートして、想定されるワークフローごとにさらにいくつかテストを繰り返し、ビルド問題やワークフローの異常などを解決していきました。

Bamboo でフィーチャー ブランチ ビルドを実行するたびに Maven ワークスペースをクリーン アップすることについて、上記のような事実にいくつか気付きました。また、特定の Maven ライフサイクルに関するさまざまなフラグが必要な場合もあります。一般的に、これらについては簡単に理解できましたが、ときには、腹が立ったり悔しさで歯ぎしりしたりすることもありました。[8]

こういったことすべてを経験した後で、やるなら今しかないと決意し、移行日を発表したのです。移行の一環として、Git リポジトリがすばらしいスタート地点となるように、一連のクリーン アップを実行することにしました。私たちは次のようなことをしました。

  • ビルド プロセスの一環として、より厳密なスタイル チェックを可能にするために、コードを一括で再フォーマットした
  • すべての行末を UNIX に変換する
  • 3 つの最上位の依存関係プロジェクトを 1 つにまとめ、結果としてすべての依存コードをリファクタリングした

これらの作業とは別に、私たちはすべてを SVN から取り出し、これらを読み取り専用にして、最後に Git にプルしました。すべての開発者とトレーニング セッションを実施し、ワークフローをもう一度確認し、実際のコードベースで動作することを示しました。

これは、私が今まで経験した中で最もスムーズな移行でした。私たちは月曜日の午後 5 時頃に SVN を凍結し、午後 10 時までに最初のビルドの問題はすべて解決されました。大きな問題はありませんでしたが、いくつかの問題では長時間の待機が必要でした。トレーニングは翌朝行い、昼食まではフィーチャー作業をしていました。

新しい開発者向けフロー

移行が完了すると、このワークフローが現実世界でどのように機能するかを確認できました。開発者がフィーチャー (ABC-4321) に関する作業し始める場合、開始するにはいくつかのことを行う必要があります。

  1. Jira Software の課題の [開発] エリアで、[ブランチを作成] をクリックします。
  2. これによって Bitbucket Server 内の画面が開かれ、ここで開発者はブランチ タイプ(通常は feature)、リポジトリ、ブランチ名を選択できます。前回の投稿でお話しした Maven のエクステンションのために、ブランチ名は常に Jira 課題キーであり、説明は付属しません。
  3. そのフィーチャーに関連する各プロジェクトについて、常に単一の同じ課題キーを使用しながら、手順 1 - 2 を繰り返します。
  4. git pull && git checkout origin/feature/ABC-4321 feature/ABC-4321[7]

このワークフローは、わかりやすく、繰り返し可能で、信頼性があります。開発者は孤立して作業し、貢献した変更を開発から引き出すことができます。たとえば、4 つの垂直製品すべてと共通のプロジェクトでの作業がユーザー ストーリーに含まれる場合、分岐アクションは少し反復的に感じられます。私たちは、Bitbucket Server REST API を呼び出すためにある種の Jira ワークフローの事後操作でこれを自動化することを考えてきましたが、開発時間がそれほどかかっていないものについては、これはやり過ぎかもしれません。

教訓

SVN から最新のワークフローを備えた Git への移行は長いプロセスでした。取りかかりから移行まで、ほぼ 7 か月を要しました。その時間の大部分は maven との格闘に費やされました。

途中で要員に関する懸念があったのは私も認めます。移行に取り組んでいる同じエンジニアのグループは、この移行作業と並行して、800 名の事業部に対するアトラシアン ツールセットのサポートを行い、プラットホーム アプリケーションに対する製品サポートを提供し、他の事業研究開発プロジェクトに取り組んでいました。最終的に 3 名にほぼフルタイムで移行を担当させたあとは、約 1 か月でやり終えることができました。

これらすべてにもかかわらず、私たちは多くのことを学びました:

  1. どれほど準備しても、本当に現実に対応した準備はできないものです。たとえば、私たちが実行しようとしたリリース ビルド タイプは、どういうわけか最初の試行でことごとく失敗しました。そのタイプのプロジェクトのビルドを 1 つを修正した後、config を他のビルドにコピーしたところ、同じことは 1 回も起こりませんでした。
  2. このワークフローでは大量のビルドが生成されます。本当に多くのビルドです。これに追いつくために Bamboo エンジンを 2 倍にする必要がありました。
  3. このワークフローでは、多くのビルド アーティファクトが生成されます。最初の 1 週間で、Artifactory インスタンスのディスク容量がなくなり、古いリリース候補を手動で削除することに丸 1 日を費やさなければならず、QA ビルドも不要になりました。次に、フィーチャー ブランチが削除されたときに、そのブランチ固有のスナップショット アーティファクトもすべて確実に削除できるようにする方法を考える必要がありました。
  4. ホットフィックスかサポート ブランチのどちらかを選択しなければならないことを、チームは望んでいませんでした。ホットフィックスをリリースできることは理にかなっていますが、ほとんどの場合、チームはサポート ブランチを必要としています。ホットフィックスは、マージが本当に簡単である特別な機会にのみ使用することを決定する場合があります。
  5. Jira Software、Bitbucket Server、Bambooの組み合わせは、本当に優れています。誰かが Jira Software で作業を開始し、ブランチを作成し、すぐにブランチ プランを作成し、その作業を検証する準備が整うのを目の当たりにすることは、すばらしいことです。
  6. Bitbucket Server でのプル リクエストは、新しくて非常に役に立つ機能です。プッシュに満足したエンジニアを寄せ付けないことと、国外のチームの貢献の準備を確実に整えることの狭間で、私たちはプル リクエスト プロセスを使用できてとても幸せでした。プル リクエストにおいてではなく Crucible でコードの検査を実行する場合、迅速な健全性チェックにも使用できます。
  7. 以前の SVN ベースのタグは、ビルドを実行していたサービス アカウントによってタグ付けされていました。そのユーザーは本物ではなかったので、タグからブランチを作成しようとすると、特定のコミットに対してユーザーが有効であることを検証するための git-hook が失敗しました。私の個人ブログでは、Git で単一コミットの作成者を変更する方法について記事を書きました。これは、古い SVN ベースのタグからサポート ブランチを初めて作成する必要があったときに役に立ちましたが、それはまさに移行の翌日でした!

全体として、私たちの移行は大成功でした。私のチームが抱えていた問題がすべて解決できたわけではありませんが、確かに多くの問題を解決でき、前進するためのより安定した基盤を提供してくれました。

[1]: 開発者ルームでの HipChat に関する居心地の悪い会話の 1 つは、リリース ビルドが行われる前に誰が変更をコミットする必要があるかどうかを尋ねる質問でした。HipChat 前は、Lync を利用するか、電子メールを送信するか、防音壁に向かって叫んでいました。

[2]: -1 は、決して 1 にリセットされないプランの増分ビルド番号です。リリース ビルドが 200 に近い数字になるのにそれほど時間はかかりませんでした。

[3]: POM はここでも共通の -SNAPSHOT リリースを参照しており、ビルドが誤ったスナップショットをプルするリスクはありません。

[4]: また、ビルドのたびに強制的にワークスペースをクリーン アップします。状況に応じて異なりますが、しかしこれが必要であることがわかりました。

[5]: 組織全体で、この特定の Bamboo インスタンスには 120 のプランがあり、常に増え続けています。私のチームのプランだけに絞り込んでも、私たちがそのリストの約半分を占めています。すべてのブランチで 200 を超えています。

[6]: 私のエンジニアの 1 人が、すべてのブランチ プランを表示できる greasemonkey スクリプトを作成しました。これは、表示可能なプランの数が多いため、Bamboo 管理者でない場合にのみ機能します。私は、自分専用の AtlasBoard を作成することに取り組んでいます。

[7]: ここでの正確な手順は、開発者がブランチを切り替えるためにコマンドラインを使用しているか Eclipse を使用しているかによって異なります。

[8]: 私たちが Maven を槍玉にあげたのは一度か二度だけです。

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

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

今すぐ始める