【定時外に手動で回す?深夜に自動実行する?】高負荷試験をGitHub Actionsで自動化したときにハマった3つの壁

「高負荷試験の環境が日中は空いていないから、また定時後に残って手動でデプロイと負荷試験を回さないと、、、」

大規模な開発現場にいると、こうした「環境の空き待ちによる時間外作業」に悩まされることがありますよね。

人間が夜遅くに手動で作業すると、ブランチの指定ミスみたいなしょうもないミスも起きやすいです。

そこで今回は、僕が参画していた大規模サービスの現場で「定時外に手動で回していた高負荷試験を、GitHub Actionsで深夜に自動実行できるようにした話」と、そのワークフロー構築で「実際にハマった3つの罠」について書いていきます。

日中は試験環境が空いていない!定時外の手動実行がつらすぎた

僕が参画していた大規模サービスのバックエンド開発では、リリース前などにGatlingを使ったAPI単位の高負荷試験を実施していました。

計画通りのスケジュールであれば問題ないのですが、開発を進めていると「やっぱりこの修正分でもう一度、計画外の高負荷試験を回したい」という場面がちょくちょく発生します。

ところが、日中は他のチームや別の試験で高負荷試験環境が埋まっていて、空いていないことがほとんどでした。

その結果どうなるかというと、環境が空く定時外(夜)にエンジニアが残って、手動で環境へデプロイし、Gatlingを実行する羽目になっていたんです。

「これ、昼間のうちに対象ブランチだけ指定しておいて、深夜に自動で流れるようにしたらみんな楽になるよな」と思い、深夜実行可能なGitHub Actionsワークフローを作ることにしました。

具体的には、試験対象のブランチ名などを書いた設定ファイルを読み込み、検証対象資材のビルドとデプロイ、そしてGatlingの実行までを深夜に自動で一気通貫で回す仕組みです。

ただ、普段はJavaやSpring Bootでバックエンドのコードを書いている僕にとって、このワークフロー作りは技術的にかなり苦戦したタスクでした。

GitHub Actionsのワークフロー構築でハマった3つの壁

実際にワークフローを作ってみて、特に頭を悩ませたポイントは以下の3つです。

  • ① 別ワークフローの呼び出し方と「完了検知」の仕組み
  • ② 前段のジョブが失敗しているのに、後続のジョブが動いてしまう罠
  • ③ ローカルでサクッと動作確認できないYAMLファイルとの格闘

① 別ワークフローの呼び出し方と「完了検知」の仕組み

今回の仕組みは、ゼロからすべての処理を1つのYAMLファイルに書くのではなく、すでに現場にあった「資材デプロイ用」「Gatling実行用」といった別々のワークフローを順番に呼び出す構成にする必要がありました。

最初は「既存のワークフローを順番に呼ぶだけならすぐ終わるだろう」と軽く考えていたんです。

でも、いざ書き始めると「あれ、YAMLファイルから別のワークフローを呼び出すときってどう書くんだっけ?」「しかも、呼び出した先のワークフローがちゃんと終わったことをどうやって検知するんだ?」と手が止まりました。

単に別ワークフローをキックするだけだと、「デプロイのワークフローを開始させた直後に、デプロイ完了を待たずにGatlingが走り出してしまう」という状態になってしまいます。
(デプロイ途中の環境に高負荷試験を流しても、当然まともな結果は取れません、、、)

そのため、設定ファイルから読み込んだブランチ名を渡して別ワークフローを呼び出しつつ、「呼び出し先のジョブが完了するまでしっかり待ってから次へ進む」という完了検知の制御を組み込むのにかなり試行錯誤しました。

② 前段のジョブが失敗しているのに、後続のジョブが動いてしまう罠

完了検知と並んで一番焦ったのが、「前段のジョブがコケているのに、後続のジョブがそのまま動いてしまう」という事象でした。

深夜自動実行で一番やってはいけないのが、以下のようなパターンです。

【深夜自動実行で防ぎたいNGパターン】
・前段の「ビルド・デプロイ」がエラーで失敗している
・それなのに後続の「Gatling負荷試験」がそのまま実行されてしまう
・翌朝見たら、古いコードのまま負荷試験が回っていてやり直しになる

検証中にわざと前段のジョブを失敗させてみたところ、後続のジョブが何食わぬ顔で動いてました。

原因は、ジョブ間の依存関係やステータス判定の条件指定が甘かったこと。

そこで、前段のビルド・デプロイが正常終了(成功)したときだけ後続のGatling実行ジョブが動くように条件を厳密に制御し、失敗時はそこでワークフロー全体を止めるように修正しました。

③ ローカルでサクッと動作確認できないYAMLファイルとの格闘

3つ目は、ワークフロー開発ならではの「動作確認のやりづらさ」です。

JavaやSpring Bootの実装なら、手元のIDEで単体テスト(UT)を回してすぐに挙動を確かめられます。

でもGitHub ActionsのYAMLファイルは、実際にリポジトリへプッシュして動かしてみないと細かな挙動や連携が分からない場面が多く、1つ修正しては動かして確認する……という地道な検証の繰り返しでした。
(インデントのズレや変数の渡し方1つで動かなくなるので、何度やり直したか分かりません)

それでも、粘り強く検証を重ねてワークフローを完成させた結果、定時外に人が張り付かなくても、設定ファイルを書き換えておくだけで深夜に自動でビルド・デプロイ・高負荷試験まで完了するようになりました。

チームメンバーからも「夜に残らなくてよくなって本当に助かる!」と喜んでもらえて、その現場で自分が貢献できたなと思える仕事になりました。

さいごに

今回は、定時外に手動で回していた高負荷試験を、GitHub Actionsのワークフローで深夜自動実行できるようにした実体験を書きました。

普段バックエンドのコードを書いていると、CI/CDのYAMLファイルやジョブ連携は少しとっつきにくく感じることもあります。

ただ、「毎回人間が時間をかけて手でやっている定型作業」を仕組み化してなくすことは、機能追加と同じくらいチームへの貢献度が大きいなと実感しました。

もし現場で「環境が空くのを待って夜に手動でジョブを回している」といった悩みがあれば、前段ジョブの失敗検知に気をつけつつ、ワークフローによる自動化を試してみてください。

それでは!