はじめに
STORES レジ アプリのエンジニアをしている @nekowenです。今年の6月に STORES へ入社して4ヶ月が経ちました。
この記事では、私が行なったレジアプリのリリースフローの見直しについて内容や背景と共に紹介します。
以前のリリースフローについて
見直しを行う以前のリリースフローは以下のようになっていました。
またレジチームはブランチワークフローとしてgit-flowを採用していました。
git-flowは開発機能を含むdevelopブランチ、機能の追加を含むfeatureブランチ、リリース準備で用いられるreleaseブランチ、プロダクトの最終リリースで用いられるmaster(main)ブランチ、リリース後のクリティカルな不具合の修正に用いられるhotfixブランチの5つの種類のブランチを用いて開発を進めます。
レジも基本的にはgit-flowに沿って以下の流れで開発を進めていました。
- 機能開発完了後、developブランチへ取り込む
- QAで問題がないことを確認したらGitHub Actionsを使用し、releaseブランチの作成〜AppStoreConnectへアプリをアップロードを行う
アプリチェックを実施
- アプリチェックとはエンジニアとPdM、デザイナーが集まり、3でビルドしたアプリを実機にインストールしてもらい、機能の動作チェックおよびデザイン崩れや周辺機器に問題がないかを確認する会です
- GitHub Actionsを使用し、リリースノートなどメタデータをFastlane経由でAppStoreConnectへアップロード
- エンジニアが審査に提出
- 審査完了後、エンジニアがプロモーションコードを発行して動作確認を実施
- PdMがリリース作業を実施
- エンジニアが3で作られたPRのマージ、GitHub ReleasesのPublishを実施
ブランチの動きとして図で表すとこのような形です。
出てきた課題
レジチームではアプリのバージョン毎にリリース担当が決められています。これは持ち回り制でモバイルエンジニアが行います。
チームメンバーがそれぞれリリースサイクルを回していく中で、以下のような課題がちらほら見えてくるようになりました。
- releaseブランチとmainブランチのコンフリクトが時々発生している
- リリース後作業がGitHub Actionsで自動化できていない
- アプリチェックと最終確認の手順が重複している
特に最初のコンフリクトが発生してしまう点を深掘りすると、リリース後作業で実施するreleaseブランチからmainブランチへのマージ漏れが起きており、それが認識されないまま次バージョンのリリース作業で発覚するということがありました。
これらの課題を解決する上で全体的にリリースフローを見直すことも含め、自分の方で叩き案を作成しチーム内と相談した上でリリースフローを変えていくことにしました。
見直した後のリリースフロー図
見直した後はこのようなリリースフロー図となりました。
大まかには以下のような変更点が挙げられます。
- 機能開発完了後、mainブランチへ取り込む
- QAで問題がないことを確認したらGitHub Actionsを使用し、releaseブランチの作成〜AppStoreConnectへアプリをアップロードを行う
- アプリチェックを実施
- releaseブランチからmainブランチへマージ
- エンジニアが審査に提出
- PdMがリリース作業を実施
ブランチの流れもこのようにシンプルになりました。
ブランチワークフローを思い切って変更した
今までブランチワークフローとしてgit-flowを採用していましたが、今回からGitHub Flowをベースとしたワークフローへ変更しました。
理由としてはワークフローとして最もシンプルで関係するブランチが少ないこともあり、今のレジチームの開発サイクルにより向いていると考えたためです。
GitHub Flowはメインの機能が入っているmainブランチと機能開発のfeatureブランチの2つから構成されます。
mainブランチは常にデプロイ可能と定義されており、安定したコードが入っている前提です。 しかし、モバイルアプリの場合は審査の概念があるため、mainブランチをデプロイ可能とするのではなく、releaseブランチを作りそちらにデプロイの役割を持たせることでうまく適合させています。
そのためmainブランチには開発中の機能が入ることや、機能規模によってはfeatureブランチで開発を進めることもあります。どのブランチで作業するかどうかはチーム内で適宜相談の上進めるようにしています。
またGitHub Flowベースのワークフローを採用することで、単純に依存関係となるブランチ数が減るためコンフリクトのリスクも抑えることができます。
mainブランチのフリーズについて
またこの提案をチーム内でしたときに releaseブランチを作った後、リリース作業が完了するまでmainブランチをフリーズさせる必要があるか といった検討事項も出てきました。
リリース作業が進んでいる間も開発作業は進むため、releaseブランチとmainブランチで同じ箇所に修正を入れてしまった場合、mainブランチにreleaseブランチを含めようとするとコンフリクトが発生してしまいます。
この点においては以下の選択肢があがりました。
- フリーズする
- フリーズした場合その間mainに含めたい機能はどうするか
- フリーズが明けるのを待つ
- マージ用のブランチを用意する
- フリーズした場合その間mainに含めたい機能はどうするか
- フリーズしない
それぞれの選択肢のメリットデメリットを比較した上で、チーム内での結論としてはフリーズしない方向で進めることにしました。
もちろんコンフリクトが発生する可能性はそのまま残ってしまうのですが、まずはリリースフローの変更を取り入れてしばらく様子を見てからで良いという判断にしています。
リリース後作業を自動化、かつ審査準備前に移動させた
審査提出の準備ができた段階でブランチをマージするようにして、その後のGitHub ReleasesのPublishなどは自動で行うようにしました。 これによりアプリ公開後の作業を一切なくし、自動化によって作業漏れのリスクを減らしました。
一方で審査提出後のリジェクトされたときやクリティカルな不具合が見つかった場合はこのケースではカバーしきれなくなってしまいます。
この場合はリリースブランチを復活させて再マージさせるといった特別対応を取る方針で進めることにしました。
動作確認のタイミングをアプリチェックにまとめた
PdMにも確認し、事前にアプリチェックでTestFlightを使い本番アプリに近い環境で確認することでアプリチェックが何らかの要因で実施できなかった場合を除いてリリース後の最終確認はスキップするようにしました。
見直してみて
実際に見直しを行ってみて、感覚としてリリース担当のやるべき作業量が減ったためエンジニアの負担も減ったように感じます。
今後もリリース作業は定期的に行われていくので、継続的に改善に取り組んでいければと考えています。
最後に
STORES ではモバイルアプリエンジニアを募集しています。少しでも興味がありましたらぜひカジュアル面談やBeer Bashに来ていただけると嬉しいです。