ジモティーでサーバサイドとインフラを担当している吉田です。
前回は ISUCON10 に参加した話を投稿しました。今年もちょうど ISUCON11 を終えたばかりですが、残念ながら予選敗退となりました。ISUCON への参加はウェブエンジニアとしてのキャリアを見つめ直すとてもよい機会で、来年こそは決勝に進みたいと思っています。
さて、今回はジモティーのサーバサイドで1年ほど運用している、リリース作業の一部自動化の取り組みについて、背景から実施までをご紹介します。
従来のリリースフローとその課題
まず、弊社サーバサイドのリリースフローについて、当時の概要は次の様になっていました*1。
- コードレビューを経て、トピックブランチを master ブランチにマージ(作業者: 各機能担当者)
- リリース PR を作成(作業者: リリース担当者)
- 機能担当者にリリース前テスト環境での動作確認依頼(作業者: リリース担当者)
- 動作確認(作業者: 各機能担当者)
- Jenkins のジョブを実行してリリース(作業者: リリース担当者)
リリース担当者はリリースしたいメンバーによる立候補制で、サーバサイドのメンバーであれば誰でもこの役割になる可能性があります*2。
この作業の1番の課題は、マージされた PR の「タイトル」「作成者」を目視で抜き出す事が大変な点です(図の2. および 3. に該当)。
詳細な流れは次の内容になります。
- master ブランチへのコミットログの中からマージコミット (メッセージが
Merge pull request #xxxx from jmty/xxxx
) を確認 - マージコミットの PR から「タイトル」「作成者」を確認
- 確認した「タイトル」をリリース PR の本文に入力
- 確認した「作成者」にリリース前テスト環境での動作確認を Slack のメンションで依頼
また、PR の「作成者」は GitHub のアカウント名なので、Slack のアカウント名に変換して Slack で本人にメンションする必要があります。そのため、たまに誤って違うメンバーにメンションをしてしまう問題も発生していました。
これをマージ済み PR の数だけ繰り返す必要があり、リリースタイミングによっては1度に10件を超える事もあります。
改善
事前準備
まず、課題を明確にします。こちらは前述の通りです。
- リリース PR 作成時に、マージされた PR の「タイトル」「作成者」を目視で抜き出す事が大変
- 誤って違うメンバーに動作確認依頼を行ってしまう
次に、その解決方法を調べます。
基本的に手作業で行っていた、マージされた PR の「タイトル」「作成者」を目視で抜き出して作業担当者に依頼する作業を自動化する方針で、かんたんな実装を行いました。これは、次で行う提案のための準備になります。フィードバックの結果、内容を大きく変更する可能性も十分あるため、あまり作り込まず、かつ GO サインをもらえるレベルにします。
KPT での提案
準備した内容をもとに、週1で実施しているウェブチームの KPT で下記の提案をしました。
- 課題の共有
- リリース作業がツラい
- 解決案の提示
- FAQ
- リリースフローはどう変わるのか
- 導入・運用コスト
- メリットだけではなくデメリットも
- なぜ CI は既存で利用している CircleCI ではなく GitHub Actions で動作させるのか、など
想定していた実装工数は比較的小さいため、一気に導入する手もありますが、次の観点から提案のステップを挟むことにしました。
- 共通の課題である事の確認および、ニーズの確認
- 異動や退職などで技術的な負債となる可能性がある
- リリースフローの変更により、障害に繋がりやすくなる可能性がある
結果はおおむね期待していた良い反応だったため、具体的な実装に移りました。
変更後
最終的に次の流れになっています。
- コードレビューを経て、トピックブランチを master ブランチにマージ(作業者: 各機能担当者)
- リリース PR を作成(作業者: リリース担当者)
- 機能担当者にリリース前テスト環境での動作確認依頼
- 本文を自動更新 (git-pr-relase gem)
- GitHub と Slack ID のマッピングを取得 (Apps Script)
- 動作確認依頼 (Ruby スクリプト)
- 動作確認(作業者: 各機能担当者)
- Jenkins のジョブを実行してリリース(作業者: リリース担当者)
「機能担当者にリリース前テスト環境での動作確認依頼」の作業を自動化しています。
それぞれの技術トピックについてご説明します。
git-pr-release
git-pr-release はリリース PR を作成・更新する gem です。マージされた PR からタイトルや担当者を取得して、PR を作成・更新してくれます。
当初自作をしようと考えていたところ、希望の機能を満たすこちらの gem が見つかり、OSS かつ定期的にメンテナンスされていたため採用しました。
最近 GitHub の仕様変更があり、期待する動作をしなくなる事がありましたが、すぐに対応されたものがリリースされました。
- Exclude titles from checklist items by nhosoya · Pull Request #66 · x-motemen/git-pr-release
- タイトルが重複して表示される問題の対応
- PR の本文に
#番号
を入力すると自動リンクの仕組みで PR のタイトルも表示されるようになったため
- Add nil check for release_pr.body by w1mvy · Pull Request #68 · x-motemen/git-pr-release
- PR 本文を空で作成すると実行が失敗する問題の対応
- 迂回方法として、PR 本文に適当な文字を入力する謎ルールで一時的にしのいでいた
もし自作していた場合、同様の対応を行う可能性が高かったはずです。
Google Apps Script
GitHub アカウント名と Slack ID のマッピングを JOSN として返すウェブアプリケーションサービスです。
次はサービスのURLに対して curl からの擬似的なアクセス例になります。
$ curl -H "Authorization: token xxxx" -L \ --dump-header - \ "https://script.google.com/xxxxxx" (省略) HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8 (省略) [ { "slack_member_id"=>"XXXX", "slack_display_name"=>"kyoshida", "github_login_name"=>"kyoshidajp" }, { "slack_member_id"=>"YYYY", "slack_display_name"=>"yyyy", "github_login_name"=>"zzzz" }, ... ]
マージされた PR からその作成者(機能担当者)のアカウント名を取得した後、Slack ID に変換する際にこのマッピング情報を参照します。
事前に Google スプレッドシートにそれぞれの対応を記載しておきます。新しいメンバーが加入したら都度こちらに追加します。このシートのメンテナンスが手動になってしまいますが、他の利用用途でも使えるようになります。
Ruby スクリプト
リリース PR の本文から、マージされたPRの「タイトル」「担当者」を取得して Slack に通知します。
Ruby は弊社サーバサイドにてメインで利用しているプログラミング言語です。ユニットテストや JSON の変換など、豊富なライブラリが付属している事に加えて、Slack や GitHub 連携など16万を超える*3サードパーティのライブラリによる素晴らしいエコシステムがあります。
同様の目的には、後述する GitHub Actions のワークフローコマンドから gh や jq を駆使して行うことも可能だと思いますが、上記観点から Ruby スクリプトとしました。
GitHub Actions
git-pr-release および、Slack に通知する Ruby スクリプトの実行環境です。
master から release ブランチへマージするリリース PR が作成されたタイミング、もしくはmaster ブランチにコミットが行われたタイミングで実行されます。後者については、リリース PR が作成された後に、追加でリリース機能を含めるケースに対応するためです。
CI 環境としてすでに利用している CicleCI ではなく、GitHub Actions を採用したのは次の理由によるものです。
- 世の中の流れとして GitHub Actions がかなり普及してきており、キャッチアップをしておきたい
- 想定の利用ケースでは無料枠に十分収まる
- 面白そう
結果
改善により、当初の課題であった、リリース担当者による目視かつ手作業での依頼が不要になりました。
また、誤って別のメンバーに確認依頼してしまう問題も発生していません。
さらに、工夫したポイントとして、デプロイ時に Slack で通知されるリリースノートの内容が分かりづらかったため、同様の仕組みで整理しました。
この結果、エンジニアだけでなく、CS を含む社内メンバーは機能概要、機能担当者、リリース担当者が明確になりました。
まとめ
日常で感じた課題の解消をモチベーションに、その改善の提案、そして実施までをご紹介しました。
自動化した作業は、以前は1回あたりおよそ5〜15分程度だったので、リターンを時間で換算するとどうしても投資効果を低く感じてしまいがちです。しかし、日々課題に感じていて改善の目処が立っているのであれば、積極的に取り組むべきだと思います。
そもそも、対象の作業は手作業で日々繰り返され、自動化が可能なものでした。こういった、いわゆるトイルの撲滅は(インフラ)エンジニアが価値を発揮しやすい領域ではないでしょうか?
少なくとも、以前の状態には戻りたくないのが率直な気持ちです。
宣伝
ジモティーではエンジニアを募集中です。
日々の不満や課題を一緒に解決していきましょう!
弊社では一緒にプロダクトを改善していただける仲間を探しています!
こちらでお気軽にお声がけください!
*1:master ブランチへのマージ後にリリース前テスト環境への自動反映など、細かい内容は省略
*2:これは執筆時点も同じ
*3:執筆時点の https://rubygems.org/stats より