トランクベース開発をしてみたときの理想と現実
🧑🏻‍💻

トランクベース開発をしてみたときの理想と現実

Category
Author
Description
最近チーム内で「小さくリリース」をするブランチ戦略としてトランクベース開発を取り入れ始めたので、ブランチ戦略と理想と現実をお伝えしていこうかと思います!
Published
December 8, 2022
Last Updated
Last Updated December 8, 2022
Writings
この記事は約11分で読めます
この記事は Rakuten Rakuma Advent Calendar 2022 の9日目の記事です。

はじめに

こんにちはApplication EngineerのYoshikiです。
最近チーム内で「小さくリリース」をするブランチ戦略としてトランクベース開発を取り入れ始めたので、ブランチ戦略と理想と現実をお伝えしていこうかと思います!

そもそもGitHub FlowとかGit Flowについて

よくGit FlowとGitHub Flowが混在して語られるので違いを説明していきます!

Git Flowとは

  • 5種類のブランチが存在
    • main
    • develop
    • feature
    • release
    • hotfix
  • 開発者はdevelopから切る
  • QAの際はdevelopから切り、releaseブランチを作成して検証して main マージを行う
  • hotfixがあれば main から切りそのまま mainにマージをする
見て分かる通りGitFlowはmainとdevelopの乖離が発生しやすく、開発頻度の高い開発であればあるほど、最新ブランチを全て維持することが難しくなります。
もちろん忘れずにhotfixが起きた場合にmainとdevelopを更新出来ればよいですが、その頃にもmainとdevelopに乖離が生じている可能性が高くコンフリクトしやすいです。

GitHub Flowとは

上記のGit Flowをよりシンプルにしたものが、GitHub Flowです。
こちらではmainとfeatureブランチしか使用しません。developという中間のブランチが存在しなく、リリースバージョンを管理するブランチもないのでライブラリ管理するようなアプリケーションには向いていません。
ですが、現代のWebアプリケーション・サービスにおいてv1.0.0などのバージョン管理は必要でしょうか?恐らくリリース時に障害が起きたときに切り戻す以外に不要でしょう。
💡
ラクマではmainにマージするたびに自動的にタグを切るようにしています。リリースする際はそのタグを使用してリリースします

トランクベース開発とは

最近話題?のトランクベース開発ですが、フロー自体はGitHub Flowと同じですが、featureブランチのマージを1-2日で行うことを求められます。
GitHub Flowとの大きな違いは「ブランチを放置しておくことが許されない」であることですが、大きな流れとしてはあまり変わりません。
詳しくはこちらに詳しく記載されているので興味のある人は読んでみてください。

なるべく早くマージするために取り組んでいること

  • Staleを使用して放置されたIssue, PRを自動クローズする
RepositoryのIssueの数がとんでもないことになっていませんか?2年前のPRが残っていませんか?ソフトウェアはナマモノなので覚えているうちに早く対応して早く綺麗にしましょう。
  • ペアプロやモブプロでレビューコストを下げる
ペアプロの利点はコードのレビューが同期的にできる点です。PRに対してコメントを受けて修正して、それに返して… だとどうしても時間がかかってしまうので、修正しながらレビューを受けれてマージまでの速度が上がりやすくなります。
  • 承認フローをなるべく減らす(意味のあるフローだけ残す)
ラクマにも承認フローがチームによって数個あります。例えばお金関係のリリースを行う場合は内部監査用に承認履歴を取っておかないと行けないので他の開発承認フローと異なります。
他にも〇〇承認っているんだっけ?という議論をプロセス改善をチーム化して組織として取り組んでいます。
  • (小さくリリースするために)FeatureFlagを利用する
みんな大好きFeature Flagを使って特定機能のABテストや試験的な機能を出すのに有効的です。

今までどうだったか

notion image
mermaid
%%{init: { 'gitGraph': {'showCommitLabel':false}} }%% gitGraph commit branch reviewed/AA commit branch BB commit checkout reviewed/AA branch CC commit checkout reviewed/AA branch DD commit checkout main merge reviewed/AA
形式的にはGitHub Flowでしたが、今までは集約ブランチを作成して集約ブランチに対して細かくレビュー&マージをし、最終的にリリース時は集約ブランチをmain に対してリリースを行うという方法を取っていました。
そうです。分かる通りこれは、GitHub Flowと言いながらやってることはGit Flowのようなものです。develop的な役割のブランチがないのでマシですが、半年もマージされないブランチは想像するだけでも大変ですよね。担当しているエンジニアが途中で退職したらより大変です。

理想と現実

ここからは「小さくリリースする」を目標に考えていた理想と現実を書いていきます。

🦁理想

📉コンフリクトの減少

正直ここが一番大変なイメージでした。変更行数が多いと別プロジェクトの集約PRとコンフリクトがよく発生していました。集約Aと集約Bでコンフリクトが発生すると直せる人はもはやプロジェクトの根幹を担っている人同士(+発生する場所によってはそのエンジニア)なので工数もそれなりに高いです。加えて直しても治っているのかどうかわからないことがあることです。直し方を間違えるとそれなりの障害になりかねないので、これが減ることが一番大きなメリットに感じていました。

📉レビュー工数の削減

大規模な組織で開発をしているとレビューの工数って意外と取られますよね?ファイル変更数 100とかきたらげんなりしますよね??従来の集約リリースだと一番最後のマージまでのPRのレビューは正直何を見たらよいかわからないです。(一応全部見る必要はなく、レビューされていないPR、Commitはないかを確認していました。)
これが物理的に少なくなるので小さくなります。レビューはよりスムーズになります。

➡️リリース期間

ここはもともとFeature Flagを使用していたのでmainにマージすること=リリースまでの期間ではなかったので、Feature Flagをオンにし始めること=リリース期間なのでそこまで変わらないだろうと考えてました。

🐱現実

上記3つの内容がどう変わったかをお伝えする前に(ある程度は想像していたけど)大変だったことをお伝えします

承認フローが大変

想像すると分かる通り小さくリリースするということはその分承認も増えるということです。プロジェクトで10個リリースするということは10個承認を通さなければいけず、本当に大変でした。。。
その期間も短くなっているので「開発 ⇒ 承認 ⇒ リリース」が10回繰り返すことになります。これは導入前もわかってましたが、承認をなるべく減らす、もしくは簡素化する等の対策をして乗り切っています。(今でもまあまあ大変です)
例えば、○○承認の依頼時期は1日営業日前となっていてレビュー&修正に2日かかるとします。なので1PRにつき、3日はかかります。
何が言いたいかというとある程度のスケジュール調整をエンジニアがしなければいけず、調整が嫌いなエンジニアにはあまり嬉しくないかもしれません。
なのでなるべく承認をなくすため、簡易化するための努力をしています。

作業分担が大変

notion image
mermaid
%%{init: { 'gitGraph': {'showCommitLabel':false}} }%% gitGraph commit branch AA commit branch BB commit
集約ブランチではそのブランチを各エンジニアがPullして開発すればよかったですが、トランクベースでは常にmainを見なければいけません。上記の承認フローが加わると正直トランクベース開発はあまり機能しません。なぜなら1〜2日でマージしなければいけないのにマージまでに3日もかかっていると次の作業者は AA を見なければいけません。そしてマージされるまでをちゃんとWatchしておかないと行けないので自分の作業以外のことに注意を注がなければいけないです。
これに対しては解決策はあります。
それは作業を依存させるような状態で割り振らないことです。例えば hogeAPIhogehogeAPI があるとします。当たり前ですが、1つのAPI開発に2人のエンジニアをアサインすれば依存度は上がります。例が簡単なのでわかりやすいですが、実際の開発になると意外と何に依存しているかどうかは設計を行わないとわからない事が多いので、これに関しては設計力をあげるしかないです笑

1つのPR粒度が難しい

上記のなるべく依存度を下げるために別機能の開発を行うとありますが、どうしても〇〇APIがないと次の開発が進まないなどどうしても待たなければいけないタスクがあると思います。そうしたときに小さくしすぎると待つ人が増えるため、トランクベースのメリットが失われてしまい、ブランチ戦略がごちゃごちゃしてしまいます。
さすがに下記は大げさな例ですが、〇〇ブランチはどこに紐付いているのかわからなくなってしまいます。
notion image
mermaid
%%{init: { 'gitGraph': {'showCommitLabel':false}} }%% gitGraph commit branch AA commit branch BB commit branch CC commit branch DD commit branch EE commit
なので粒度を大きくしてなるべく依存しないために努力をすると今度は「小さくリリース」のメリットが失われてしまうのでここだけは、段々慣れていって最適なPR粒度を掴んで行くしかありません。
 
長々とそれ以外のことについて語ってきましたが、もちろんメリットは大きいです。

📉 コンフリクトについて

もちろん集約でのリリースをしていないのでそういうレベルのコンフリクトは起きません。ただし、個人間のタスク同士のコンフリクトはあり、そういうときは作業者同士で解決できることのほうが多いです。むしろコンフリクトのレベルが知らないチームの人からチームメイトになってコンフリクトミスがしににくなったのでその点は最高です。

📉 レビュー工数について

レビュー工数としては確実に下がっています。ファイル変更数が多くても15ファイルとかなのでだいぶ負荷は少なく、その機能についてのレビューが出来ます。100ファイルもあると正直神頼み的なLGTMしかできず、リリースも神頼みになってしまいます。
またビジネスロジック的な変更を含む修正はペアプロでやることによってだいぶ負荷が少なくなりレビューまでの道のりが短くなり、良い体験でした。

➡️リリース期間

期間的な変化はありませんが、心理的なハードルは下がりました。なぜなら、先にリリースが済んでいる&コンフリクト発生していないので、ビックバンリリースでのびっくり障害の可能性がないからです。また、QAなどの連携もスムーズです。mainにマージが済んでいるということはStagingブランチなどの更新もmainの取り込みさえしていれば良いからです。QAにはFeature Flagを使ってテストをしてねとお願いすればよいのです。

まとめ

大規模な開発組織では承認のような煩雑な手順があるとあまり機能しないことが多いのですが、組織の承認フローが改善されれば、よりスムーズな開発が出来るかと思います。現状はまだ承認があり、トランクベース開発の文化がチーム全員に馴染んでいなく、理解がされていないこともあります。
なのでより一層「小さくリリースすること」「デプロイ頻度をあげること」をチームに対して意識させていくことが必要になります。Googleの提唱する有名な4Keysでもそうですが、組織全体に数値の見える化をすることも重要だと考えています。
トランクベース開発でなくてもマージするために取り組んでいることも参考になるかと思いますのでぜひ取り入れてみてください!長々とした文章にお付き合いいただきありがとうございました。
 
気になることがあればTwitterのDMにてお受けしますのでぜひお気軽に🙏