見出し画像

高いデプロイ頻度を保つ技術 ~徹底的な自動化でデプロイフローを簡略化~

こんにちは、すべての開発組織の生産性を上げたいhamです。

近年、デプロイ頻度を上げることで開発パフォーマンスが上がるという調査結果が多数発表されています。
例えば、DORAのFour KeysLeanとDevOpsの科学などです。

デプロイ頻度が高いことによるメリットは前述した記事や書籍、ChatGPTなどに聞いていただくと良いと思いますが、私自身も去年、デプロイ頻度が週1回の環境から1日4回の環境に変わったことで、一開発者として下記のメリットを感じています。

  • 微修正は即日リリースできる

  • 開発したものがすぐに本番デプロイされ手離れするので認知負荷が低い

  • 本番障害時に差分コードが少ないので原因特定が容易

  • コンフリクトが少ない

言葉で聞くだけでは想像しづらいかもしれませんが、テンポよくデプロイされていく環境は開発者としても心地よく、自動テストに慣れた人が自動テストがない環境に戻れないのと同じくらい、デプロイ頻度が高い環境に慣れたらデプロイ頻度が低い環境には戻れないと感じています。

この記事では高いデプロイ頻度を保つために私の所属している開発チームで行なっているデプロイフローの自動化を紹介します。

ちなみに私が所属する開発チームの2023年2月のFour Keysは下記の通りです。Four Keysの測定にはFindy Team+を使っています。

2月のFour Keys

デプロイ頻度は平均4.5回/日(フロントエンド2回、バックエンド2回)です。
変更のリードタイムは23.5hなので、コミットした修正は翌日にはデプロイされていることになります。
また、エンジニアの人数は13名なのでd/d/d(deploys / a day / a developer)は0.35です。d/d/dは0.1以上であれば健全とのことなのでかなり良い数値です。

デプロイフローの自動化

1日複数回デプロイするためにはデプロイフローを簡略化する必要があります。
デプロイ時に手作業がたくさん必要でデプロイ担当者の負担が大きかったり、1回のデプロイに30分以上かかるようでは1日複数回のデプロイは難しいでしょう。
LeanとDevOpsの科学にも下記のように書かれています。

継続的デリバリを実践すれば、チームにとってデプロイが負荷の高い大事ではなくなり、勤務時間中にこなす日常業務の1つとなる

LeanとDevOpsの科学

デプロイフローは下記の通りです。

デプロイフロー

①〜⑩の順にリリースプルリクを作成して、CIやQAで品質を担保しつつ、本番環境へリリースしています。
このフローを1日4回行うため、自動化できるところは徹底的に自動化しています。
ここからは各ステップについて説明します。

① 定時にリリースプルリクを生成

リリースプルリクはGitHub Actionsをスケジュール実行を使って定時に自動的に作成しています。
プルリクは手動でもGitHubでサクッと作れると思いますが、1日4回リリースするので自動化できるものは徹底的に自動化します。

② CIで自動テストやLintを実行

リリースプルリクに限りませんが、プルリク作成時やプルリクに変更をプッシュしたときにはCIが実行されます。
CIでは自動テストやLintなどを行っています。

自動テストのカバレッジはバックエンドの98%、フロントエンドは70%ほどあるので、既存動作の保証はほぼほぼ自動テストでカバーできています。
デプロイのたびにリグレッションテストを手動で行っていては1日複数回のデプロイは不可能なので、デプロイ頻度を上げるためには自動テストで既存動作が保証されていることは必須です。

③ 検証環境へデプロイ

リリース前にQAを行うため、リリースプルリクを作成すると同時に検証環境へ自動的にデプロイされます。
検証環境にデプロイ後、e2eテストを自動実行しています。
e2eでは自動テストでカバーできていない外部システムとの連携や、各画面を表示する正常系のテストなどを行っています。
検証環境へのデプロイが終わるとリリース担当者へSlackでメンションが飛びます。

④ QA有無の自動抽出

QAの有無はリリースプルリクに含まれるフィーチャープルリクによって判断しています。
フィーチャープルリクのテンプレートにQA有無のチェックボックスを設置しており、QAが必要な修正を行った場合はONにします。
リファクタリングなど自動テストでカバーできる修正しか含まれない場合はOFFにします。

上記でチェックしたQA有無をリリースプルリクに紐づくフィーチャープルリクから抽出してQA有無の一覧を自動生成しています。
リリース担当者はこの一覧を見て、必要に応じてQA担当者をアサインします。

⑤ リリース時作業の自動抽出

リリース時にワンショットタスクの実行など手動作業が必要になることがあります。
フィーチャープルリクのテンプレートにリリース時作業を記載する項目があるのでリリース時作業が必要な場合はこちらに記載しておきます。

QA有無と同様に、フィーチャープルリクからリリース時作業を抽出してリリース時作業の一覧を自動生成しています。
リリース担当者はこの一覧を見て、リリース時作業を実施します。

⑥ QA

QA担当者は検証環境でQAします。
QAを行った結果、修正が必要になることがあります。
リリースプルリクに対して修正を行う場合は、リリースブランチに向けてプルリクを作成します。
修正後、リリースブランチにマージすると検証環境に自動的に再デプロイされるので再度QAを依頼します。

⑦ デプロイ🚀

QAやリリース時作業が完了したらデプロイします。
リリースプルリクをマージしたら、その先は全自動で本番環境にデプロイされます。
バックエンドは5分、フロントエンドは3分ほどでデプロイが完了します。
リリースが完了するとリリース担当者にSlackでメンションが飛ぶので必要に応じてリリース連絡等を行います。

⑧ タグ作成

リリース後、リリースタグを自動生成します。
タグの本文にはリリースに含まれるプルリクの一覧が含まれます。
また、バックエンドのバージョンはセマンティックバージョンに準拠していますが、commitコメントからmajor / minor / patchを判定できるようにしているので、リリースプルリクに含まれるcommitにmajorの変更が含まれていたらmajorを+1、majorはないがminorの変更が含まれていたらminorを+1、patchの変更のみであればpatchを+1してバージョンを自動的に決めています。

⑨ リリース後のe2eテスト

リリース後に本番環境に対してe2eテストを自動実行しています。
実行している内容は検証環境に対して実行している内容と同様です。

⑩リリースブランチへの修正を開発ブランチへ反映

QAで指摘があった場合などリリースブランチに対して修正した場合、その修正を開発ブランチへ反映する必要があります。
リリース後に開発ブランチへ差分を反映するプルリクが自動生成され、レビュアーがアサインされます。
レビュアーは内容を確認して、approve & mergeします。

hotfixの自動化

デプロイ頻度を上げるとき、デプロイフローを簡略化するのと同時に、障害が発生した場合に素早く切り戻せるようにする必要があります。
どれだけ事前にテストをしたとしても障害が発生することを完全に防ぐことはできないので、障害時にいかに素早く切り戻せるかが重要になります。
Four Keysの指標の1つにも平均修復時間(MTTR)が含まれていることからも、平均修復時間が開発パフォーマンスを保つために重要な指標の1つということがわかります。

Fix or Revert

障害を検知したらmasterブランチをベースにhotfix-というプレフィックスをつけたブランチを作成して、修正したり、該当のリリースマージをrevertしたりします。
通常開発と同様にCIで自動テストやLintを実行して修正の妥当性を確認します。

QA

修正後、プルリクを作成すると検証環境へ自動的にデプロイされます。
(hotfix-というプレフィックスのブランチ名をトリガーに自動実行しています)

検証環境で動作確認を行い、問題なければマージします。

デプロイ🚀

マージ後は通常デプロイと同様のフローで本番環境へデプロイされます。
タグの作成や開発ブランチへの反映プルリク作成なども自動的に行われます。
デプロイにかかる時間は通常デプロイと同様なので、例えば任意のコミットをリバートするだけであれば、数分で切り戻しが完了します。

まとめ

デプロイ頻度を上げるには徹底的な自動化が必須です。
「手動でやってもすぐできるし〜」や「ここは念のため手動で確認しておこう」が積もり積もってデプロイ作業の負担になります。
また、手動作業が多いとオペレーションミスが混入する可能性も増えてしまいます。

この記事で紹介した手順でもまだまだ手動作業が含まれているので、自動化できるものはどんどん自動化してデプロイ頻度をさらに上げていきたいと思っています!

この記事が気に入ったらサポートをしてみませんか?