こんにちは、技術推進部の本田です。S+BIMチームを担当しています。
今年1月から新たな期が始まり、組織も変わり、チーム内としての開発フローを見直す機会がありました。
今回はその一環としてブランチ戦略の整備をしたのでその時に考えたこと、やったことを記事にまとめたいと思います。
チームのブランチ戦略を考えている方にとって少しでも参考になれば幸いです。
※公開用に一部情報を省略、編集しております。
- 📝 この記事で説明しないこと
- ✔️ ブランチ戦略を整備する際にやったこと
- 🏁 ブランチ戦略によって達成したいこと
- 💼 開発体制、開発フローを整理する
- 📐 ブランチ戦略を設計する
- 🛠️ おまけ
- 🦺 今後の課題
- 最後に
- 参考
📝 この記事で説明しないこと
- ブランチ戦略とは何か
- 既存のブランチ戦略の詳細
- GitHub Actionsとは何か
✔️ ブランチ戦略を整備する際にやったこと
- ブランチ戦略によって達成したいことの言語化
- 開発体制、開発フローの整理
- ブランチ戦略の設計
- ベースとなるブランチ戦略とスコープの検討
- 環境とブランチの対応表の作成
- ブランチ表の作成
- 開発の流れの言語化
- ブランチフロー図の作成
- GitHub Actionsの作成
🏁 ブランチ戦略によって達成したいこと
大きな目的は顧客に価値を素早く届けるサイクルを作りたいというものです。
今までは月1の定期リリースを前提としてリリース毎にブランチを生やす戦略だったのですが、チームの方針としてリリースサイクルを短くしていくためにブランチ戦略の変更が必要になったという背景があります。
とっかかりとしてまずは下記のような方針のメモを作りました。
- リリース頻度は毎月→隔週→毎週と徐々に頻度を上げていきたい
- 開発体制と開発フローを整理して、管理対象とする状態とそれに対応するブランチを明確にしたい
- メンバーがコア作業(開発)に集中して開発できるようにしたい
- 今まではリリース日を決め切ってからでないと着手できないという課題があったが、リリース日を決めるという工程の優先度は着手よりも落としてもよい
- GitHub Actionsで解決可能
- タスクが決まったら開発にすぐ着手できるようにすることを優先したい
- 開発時のブランチ運用はシンプルにわかりやすくしたい
- ブランチのマージミスなどがなるべく起きないような設計にしたい
- 人間がやる必要のない定型的なマージ作業は自動化する
- 既存の開発フローに大きく手を入れることはスコープ外とする
- 体制変更直後でバタついている中進める必要があったため、移行コストを考慮して現実的な範囲に限定した
💼 開発体制、開発フローを整理する
多くの組織では開発体制(チーム編成)は簡単には変えられないイメージがあります。組織体制変更は開発フローを見直す良い機会かもしれません。開発フローは開発体制よりも融通は効くものの、やはり開発体制に依存する部分もあるため、組織体制変更のタイミングがあれば体制とフローをセットで考えるのが良いと考えています。
開発体制
体制変更により、フロー効率を重視するために機能横断的チーム(CFT)の開発体制に移行しており、開発チームは主に下記のメンバー(7人)で構成されています。
対応案件を決めるところからリリースまでのスピードを高めることを目的とする変更だったため、チームの中で開発をほぼ完結できるようになりました。
- PO
- PdM
- Webエンジニア
- UI/UXデザイナー
- テスター
開発フロー
開発フローとブランチ戦略は完全に分けて考えることはできないので、それぞれのフェーズに必要な環境やブランチを決定するためにもブランチ戦略策定時には開発フローの整理も必須だと考えております。
また、必要性や裁量があれば関係者と調整して整備、共通認識の形成を同時に進めます。
- 設計・実装→社内確認→(ベータ版確認)→テスト→リリース
- ブランチ戦略を決める上で問題ないとする粒度で記載しています
- 社内確認=POや非エンジニアのメンバーが、実装が完了した機能をテスト未完了の状態でも使用感を確認できるプロセスとして必要でした
- ベータ版確認=必須のプロセスではないですが、未リリースの機能を展示会で披露したり、開発中の機能を先にお客様にお見せする機会があるときの利用を想定しています
- 実際はここから外れた作業もあったりしますがリリースまでのリードタイムに影響しない範囲で作業優先度の調整を行うものとしました
📐 ブランチ戦略を設計する
ベースにするブランチ戦略と対応スコープの検討
組織体制やプロダクトのフェーズによって最適なブランチ戦略は異なるため、既存のブランチ戦略をベースにした方法の検討と今やらないことも決めていきました。
- ベースにするブランチ戦略の検討
- Git Flow →見送り
- 柔軟なリリース対応ができるが、今の体制には不要だった
- 結局ベータ版用にブランチを用意する必要があり、ブランチが多くなり複雑でわかりにくい
- 考えないといけないことが増えてマージのミスなどのリスクは避けたい
- GItHub Flow →見送り
- シンプルなのが良いが、派生元ブランチとマージ先ブランチが異なるのでマージミスを避けたい
- gitworkflows →見送り
- マージ作業が多く、作業の起点となるブランチが複数あるのがわかりにくさが合わない
- 安定trunkパターン →見送り
- マイルストーンごとにブランチを作成するのがリリースサイクルを速くする目的と合わないい
- メインラインモデル →見送り
- 案件毎に作業ブランチを分けたいので合わない
- GitLab Flow →採用
- シンプルかつチームの規模、目標のリリース頻度にフィットしそう
- エンジニアにとってはmainから切って作業してmainにPRを投げるだけなのであまり余計なことを考えなくて良くなる想定
- 本番環境にはテスト済みであることが保証されたコードと同一のコードをデプロイしたいという理由により現状のチームやフローとの親和性が最も高そう
- 今後テスト完了とテスト未完了の案件が混在するかもしれないという課題はある
- シンプルかつチームの規模、目標のリリース頻度にフィットしそう
- Git Flow →見送り
- テスト完了の対応とテスト未完了の対応が混在するのを避けるために、案件毎にテスト用ブランチを作成することも検討
- マージタイミングの調整でカバーできそうではある
- 厳密にやるならこれを採用したい
- ただし現状の体制から見るとやりすぎ感がある
- 必要なブランチ、環境、リソースが見合わないとしてnot for usであると判断しスコープ外と判断した
- 今後の状況が変わった時の課題でもある
- 緊急対応についてはどうする?
- mainからhotfixブランチを切って作業し本番などのブランチにはcherry-pickで取り込む想定
- 基本的にhotfixは緊急度合いが様々だったりするので例外的な対応として都度フローを調整する前提とした
- 以上を踏まえて管理したい状態を整理
- 開発中の状態 (feature or hotfix)
- 実装が完了して社内確認Readyな状態。開発起点 (main)
- テスト待ちの状態 (pre-production)
- テストが完了しておりリリースOKの状態。本番と同じ状態 (production)
- リリース前だが展示会などで公開したい状態 (beta)
環境とブランチの対応表を作る
チーム内で、どの環境にどのブランチがデプロイされているの?のような質問は必ず出てくるため下記のような表を作り、共通認識を合わせられるようにしておきます。
- 担当プロダクト環境=我々のチームがデプロイする環境
- 対応メインプロダクト環境=担当プロダクト環境と連携する弊社のメインプロダクト環境
ブランチ表を作る
ブランチの流れを整理するため、出来上がったブランチは下記の表のような形にまとめました。
ベータ版環境にあるものは必ずしも本番リリースされるとは限らないため、mainに合流しない前提としています。
feature開発の流れ
まずはブランチにフォーカスしつつ整理した流れを言語化しておきます。
- mainからfeatureブランチを切って作業
- featureブランチ→mainのプルリクを作成
- コンフリクトがあれば必ずレビュー依頼前に開発者が解消する
- featureブランチをmainにマージ
- コンフリクトがあれば必ずテスト前に解消する
- マージしてBeta環境に反映し、PO確認する
- マージ時に自動でmainからpre-productionブランチにマージする
- 同時にpre-production→productionのプルリクを自動で作成する
- 同時にfeatureブランチからbeta向きにも自動でプルリクが作成される
- テストが完了したらpre-production→productionをマージしてリリース
ブランチフロー図
開発の流れを元にブランチフロー図を作ります。今回はMermaidを使用して作成しました。
出来上がったブランチフロー図の一例を紹介します。
🛠️ おまけ
ブランチ運用を言語化したら自動化の部分に関して、あとはやるだけ、です 💪
作ったGitHub Actionsの例として、featureブランチからmainブランチにプルリクエストをマージした時をトリガーとする設定を紹介します。
# .github/workflows/merged-feature-to-main-branch.yaml name: "Merged Feature To Main Branch" on: # Pull Requestのマージをトリガーにしたいため、push イベントではなく pull_request イベントにする。 # pull_request イベントにしたいのは、プルリクの情報を使いたいのと head_ref を取得したいから。 pull_request: branches: - main types: - closed paths-ignore: - "docs/**" - "*.md" - ".github/**" jobs: create_pr: # on.pull_request.types ではマージイベントとしては取れないのでマージされたかどうかはここで判別する # feature/ から始まるブランチのみを対象とする if: github.event.pull_request.merged == true && startsWith(github.head_ref, 'feature/') runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 # main → pre-production のプルリクを作成 - name: Create PR to pre-production Branch id : create-pr-to-pre-production env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | PR_URL=$(gh pr create --base pre-production --head main --title "[Pre-Production] ${{ github.event.pull_request.title }}" --body "- #${{ github.event.pull_request.number }}" --label "auto") echo "PULL_REQUEST_URL=$PR_URL" >> $GITHUB_ENV # main → pre-production のプルリクをマージ - name: Merge PR to pre-production Branch env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | gh pr merge ${{ steps.create-pr-to-pre-production.outputs.PULL_REQUEST_URL }} --merge # pre-production → production のプルリクを作成 - name: Create PR to production env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | gh pr create --base production --head pre-production --title "[Production] ${{ github.event.pull_request.title }}" --body "- #${{ github.event.pull_request.number }}" # main → beta のプルリクを作成 - name: Create PR to beta id: create-pr-to-beta env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | gh pr create --base beta --head ${{ github.head_ref }} --title "[Beta] ${{ github.event.pull_request.title }}" --body "- #${{ github.event.pull_request.number }}"
🦺 今後の課題
前述しましたが、今後の体制変更などにより状況が変化した時にテスト完了の対応とテスト未完了の対応が混在するのを避けたいというモチベーションが高まる可能性は否定できません。その時には案件毎にテスト用ブランチを作成するというところも再検討するなど、変化に柔軟に対応していけたらと思います。
最後に
スパイダープラスでは仲間を募集中です。
もっといい方法を知っている、変化とともにありたい、などなど、スパイダープラスにちょっと興味が出てきたなという方がいらっしゃったらお気軽にご連絡ください。
https://spiderplus.co.jp/contact/