「2週間に一度からリリースを日々の当たり前にするエンジニアリングマネジメント」というタイトルでJBUG沖縄#4で発表してきました
JBUG沖縄 #4「スタートアップがみせるプロジェクトマネジメント」というイベントが2023年4月23日に参加して、「2週間に一度からリリースを日々の当たり前にするエンジニアリングマネジメント」というタイトルで発表させていただきました。
こちらの発表内容は、私がCBcloudという会社に入社してから取り組んできたリリースの頻度と安定性を上げるための取り組みについてまとめた内容になっています。ちなみにぼくがすべてやってきたこと、というよりもチーム全体で取り組んできたことをまとめています。
はじめに
2020年8月にCBcloudに入社したのですが、当時のプロダクト開発は以下のような状況でした。
- 2週間に一度リリースするかどうか
- リリースしても影響範囲の把握やテストが不十分でバグ・障害が発生することが頻繁に起きる
- リリースが怖いので、夜間リリースが当たり前
そこから2023年4月時点では以下のような状況になりました。
- 毎日なにかしらのリリースが行われるのが当たり前。1日5回リリースされることもある
- バグ・障害発生がないわけではないが、頻度は確実に減っている
- リリースが怖くないので、大きなリリース以外は日中にリリースすることが当たり前
今回はこの状況を作るために取り組んできた活動について共有していきたいと思います
プロダクト品質への投資
開発速度を上げることはスタートアップにおいては非常に重要で、それを実現するためにはリリース頻度とそれに伴う不具合発生率を下げることが重要です。そのためにはそもそも土台となるプロダクト品質を上げる必要があるのでそのための投資を行ってきました。
テストコードを書く文化を作る
サーバーサイドはRuby on Railsで開発しているのですが、その当時はテストコードがほぼゼロの状態でした。
そのため仕様の把握、修正による影響範囲の把握、互換性が壊れていないかの保証ができず、リリース時にバグが出ないことを神に祈りながらリリースするという状況です。
ただ開発メンバーとしてはみんなテストコードを書く必要性は理解していて、とはいえ既存のコードがテストがかかれていなかったので、みんなやりたいとは思っているが、リーダーシップを発揮してGOを出す人がいないためズルズルと同じようにテストなしでコードを書いていました。
そこで「このままの状況を続けてもジリ貧なのでテストコード書きながらコードを書くことを当たり前にするぞ!」と号令をかけ、以下の方針を立てました。
- テストコードが書かれていないプルリクはマージしない(新機能開発した場合その箇所のテストを書く)
- 自分がコードを書いたとき周辺のコードのテストがかかれていなければテストを書く
- テストカバレッジを計測し、0.01%でも増えたらSlackで大喝采して褒め合う
これに加えて、重要なビジネスロジックが含まれているがテストがないAPIはみんなで時間をとってモブプロしながらテストコードを追加したり、そもそも不要になったコードを削除していく活動などを続けることで現在ではテストカバレッジが76%を超えることができました。
QAチームによるリリース前の統合テスト導入
当時のチーム状況として、一年以上このプロダクトの開発を続けているエンジニアが一人だけで、それ以外は一年以下の新人ばかりでした。エンジニアとして経験はそれなりにあるメンバーが揃ってましたが、テストコードもなく、ドキュメントもない状況で仕様と影響範囲を把握しながらバグを出さずに開発することがかなり困難だったので、外部のQA専門会社に開発プロセスへ入っていただき、リリース前の統合テストと主要機能のデグレテストを行うようになりました。
これによって、リリース前のテスト不足による不具合発生率が下がっていき、ある程度リリースへの怖さが減ってきました。
NewRelicというモニタリングツールの導入
アプリケーションのモニタリングがまともにできていないので、リリース後に想定外の問題が起きたのかどうかはユーザーからの問い合わせでしかわからない状況でした。
問題が起きたことをユーザーや社内のカスタマーサポートの声によって把握できても、そこから原因を探るためにログを漁っても実際に原因を見つけることが難しくかなり時間がかかっていました。
この状況を解決するため、NewRelicというモニタリングツールを導入しました。
NewRelicはアプリケーションモニタリング、インフラモニタリング、ログ収集、エラー検知までできるプロダクトになっていて、リリース後にパフォーマンスに影響があったのか、その後エラーが増えていないか、どのようなエラーが起きているか、エラーが起きたときのログはどれかなどがすべてわかるようになりました。
これによってリリース時に問題が起きてもユーザーの声がカスタマーサポートに届くよりも先に自分たちでキャッチすることができ、それによってバグ修正の速度も上がったり、即座に直せないものだと判断してやはり切り戻すという判断も適切に素早くできるようになりました。
NewRelicさんにも利用事例を取材していただいたので、こちらの記事もぜひ参考にのせておきます。
ドキュメントを書く文化を育てる
機能開発や修正をするときに、なぜこの仕様になっているのか、誰のための修正なのか、どういう仕様で作ったのかという情報が少なかったため、「コードを読んで作者の意図を想像せよ」という問題をずっと解いている状態だったので開発を進める上での大きなボトルネックの一つとなっていました。
この問題を改善するためにドキュメントを当たり前に書く文化を育てていきました。
そのひとつの例が機能開発・修正をするときのデザインドキュメントを書くことで、「なぜやるのか」「だれのためか」「どういう仕様で作るのか」「その仕様にした理由はなにか」をesaというドキュメントツールに書きながら仕様検討や開発を進めることで情報を残し、GitHubのプルリクに関連URLにそのドキュメントのURLを貼るようにしました。プルリクに貼るURLはドキュメントだけでなく、そのタスク管理しているAsanaというプロジェクト管理ツールのタスクのURLであったり、その開発に関連するコミュニケーションをとっているSlackのスレッドへのURLも貼ることで、Gitの履歴を探っていけばその当時のコンテキストを早く理解できるようにしました。
その他にも、既存の仕様が分からなくて調べた内容をまとめたり、オペレーションや調査を実施した際のログを残したりすることで、esaを検索すると大体わかるという状況を作っていきました。
リリースマネジメントの考え方の変更
当時はリリースが怖かったのでなかなかリリース頻度が上げれない状況だったのですが、それでも大体2週間に一度くらいはアドホックに何らかのリリースを行なっている状況でした。
そこからQAチームに参加してもらうことになり、以下のような明確なルールをもって2週間に一度のリリースを行うように変更しました。
- 2週間に一度の定期リリース曜日を定める
- その日にリリースしたい内容をリリースマネジメントMTGで事前に決めておく
- QAチームにリリース内容を共有し、テスト計画を立てていく
- リリース用のブランチを作成し、そこにリリースしたい内容がふくまれたfeatureブランチをマージしていく
- このリリースブランチで機能修正に関する結合テストと主要なユースケースがこれまで通り動いているかのデグレテストを行う
- 問題なければ定期リリース曜日に、そのリリースブランチをマージしてリリースする
QAチームの参加とこのようなリリースプロセスの整備によって以下のようなメリットがありました。
- 既存機能が想定外に壊れることが防げる
- 事前にリリース内容がきまる、リリース曜日が固定化されることで、プロダクトの変化が予想しやすい
ただ逆にこのようなデメリットもありました。
- 開発が終わってもリリースするまで2週間待たないといけない
- QAで一部の機能に不具合があったときにそこだけリリースから取り除くことが難しい
- 複数の修正をまとめているため、不具合が起きたときにどの修正が原因なのか判別が難しい
- 切り戻しを行う際、複数の修正をまとめているため切り戻しもまとめて行われてしまう
大体半年〜1年くらいは2週間に一度のリリースプロセスで運用していたのですが、ある程度こなれてきたタイミングでリリースをまとめるのではなく修正毎に個別でリリースできるようなプロセスへ変更していき、二週間に一度のリリースサイクルではなくリリースできるときにリリースするという風に変えていきました。
- 開発が終わりリリース日の目処が立ってきたらQAチームとQA日程を調整する
- テスト計画を個別のリリース毎に立てて、QA日になったら個別にQAしていく
- QAが通ったらリリース
これによってリリースの待機が減り、問題が起きたときの切り戻しの難易度も減りました。
しばらくこの運用を続けると、次はQAリソース自体がボトルネックとなってリリース待ちが発生してきました。
プロダクト品質がまだ低く、エンジニアのプロダクトに対する理解も低い状態だとそれでもすべてのリリースでQAを通した方がメリットが大きかったのですが、開発メンバーの習熟度も高くなりテストカバレッジも上がってきた頃には「このレベルはQAしなくても開発チーム内でのテストで十分」と判断して開発チームやステークホルダーの動作検証だけでリリースできることが増えてきました。
開発者リソースを増やすためのプロダクト改善
プロダクト開発していく上で、ユーザーが利用する画面や機能は作り込むのですが、その運用をするための管理機能の作り込みが足りておらず、サービス運営する上で必要なオペレーションの中で開発者に依頼しないとできないことが非常に多い状況でした。1日に2~3件そういうオペレーションがあり、SQLを作ったりAPIを叩くスクリプトを用意して実行したりしながら対応していました。
- 料金表の追加や変更
- 荷主の設定情報の変更
- パートナーへのポイント付与
- etc...
サービスを普通に運用するだけに開発者の手を使わないといけない運用負荷が高いプロダクトになっているがために、新しい機能を開発するときにもリソースが足りず管理機能の優先度が下がってしまい、「後で作る」という名目でまた運用負荷を上げてしまう。その後も結局管理機能を作るリソースが取れないという負の自己強化サイクルに陥っている状況でした。
この状況を脱却するために、管理機能を作り込むための開発リソースを確保して、そのメンバーに開発者の手を借りないとできないオペレーションを他の部署の方でも管理画面で実行できるようにしました。
開発者のリソースを確保 => 運用負荷を下げる開発をする => 運用負荷が下がるの開発者リソースに余力がでる => そのリソースで運用負荷を下げる開発をするというサイクルを回していくことでいまでは開発チームがDBのデータを直接いじってオペレーションをする機会も月に数回程度に削減されました
これによって開発チームはより本業に集中する時間が多く取れ、機能開発の質や量が増えたりそれ以外の技術負債の解消のための時間に使うことができるようになり、結果リリース頻度の向上にも繋がっていきました。
この効果は開発者の負荷を下げるだけではなく、他部署の人が自分たち自身でオペレーションを完結できるようになることで、いままで開発者の実行待ちになっていたオペレーションのボトルネックをなくせてオペレーション効率が上がったり、システム理解がより高まることであらたな使い方や顧客への提案ができるようになるなどの効果もありました。
さいごに
このような取り組みを続けることで当初はリリースをビクビクしながらしていた状況から毎日当たり前に何らかのリリースがおこなれるような開発体制まで改善していくことができました。
ただまだまだ技術的負債の解消を進めたり、システムの信頼性をよりエンタープライズレベルにまで向上させたり、よりドライバー様や荷主様に価値を感じていただけるようなプロダクトにするための開発を進めたりと、解かないといけない問題はまだまだ山積みです。
いつものやつですが、一緒に様々な課題を解くことに楽しんで取り組める仲間を募集中です。
興味があればぜひカジュアル面談からでもいいのでご連絡お待ちしております!
Discussion