はじめに
こんにちは、エンジニアの id:kiryuanzu です!今回はチームで管理するRailsリポジトリ9個の CI/CD を CircleCI から GitHub Actions に移行した際の話を共有します。
概要
Classi では全社的な方針により、メインで使う CI/CDプラットフォームを CircleCI から GitHub Actions に移行することにしました。
主な理由としては、複数の CI/CD サービスを並行して利用し続けるのは運用管理・コスト管理で負担があったこと、社内の知見交換で片方に寄せた方が良いと判断したためです。
筆者が所属するチームでは当時9個のリポジトリの運用を行っていました。それらのリポジトリの CI/CD を全て置き換えることになったため、期日までに全て移行できるように中期的な計画を立てて進めました。
今回の記事では、移行の際にまず取り組んだこと、取り組みを通して得た知見について紹介したいと思います。
取り組んだこと
複数のリポジトリの CI/CD の移行を進める上で、まずは1つのリポジトリを選定し叩き台にし、チーム共通となるデプロイフローを作りました。
最初に着手するリポジトリの選定基準は、チーム内でもっともデプロイ頻度が高かったものにしました。デプロイの試行回数が多ければ、考案したデプロイフローの改善点を見つけやすいと判断したためです。
そのようにして、作成したデプロイフローについてチームからフィードバックをもらい、より効率的なデプロイフローに作り替えた上で他リポジトリの移行作業に着手するようにしました。
チーム共通で使うデプロイフローを考案する
CircleCI から GitHub Actions に移行する上で、まずはどのようなデプロイフローに作り替えるとより良い運用方法になるかを考えました。
各リポジトリの環境に多少の差異があっても先にチームで共通で使うデプロイフローを決めておけば、用意するワークフローの大部分は同様の設計で作ればよいため、より効率的に移行できます。
GitHub Actions は GitHub 関連のイベントをトリガーとして使えるため、CIrcleCI時代に比べてより柔軟にデプロイフローの設計を考えることができました。
最初はチームメンバーと相談して以下のように CI(lint, テストの実行)とステージング環境のデプロイはPR作成後にコミットがプッシュされる度に、プロダクション環境のデプロイは PR がレビュアーから approve された時に実行するようにしました。
しかし、チームで運用する中で、以下の問題点が見えてきました。
- stg デプロイを行うために CI の完了を毎回待たないといけない
- 最新のmain に追従していない古いブランチのワークフローからデプロイを行うと、デグレが発生して障害に繋がるおそれがある
- PR approve 後に最新の main へリベースを行った際、再度チームメンバーに approve を依頼し、もう一度最新の状態のデプロイ用ワークフローを作成する必要がある
その問題点を踏まえて、以下のデプロイフローに作り替えました。
主な変更点
- CI と staging デプロイのワークフローは分離し、CI を待たずに staging デプロイを実行できるようにする
- production デプロイは PR のマージ後に main ブランチから実行することで常に最新の状態からデプロイできるようにする
- コンカレンシーグループを設定し、デプロイ用のワークフローは常に1つだけとし、デグレを起こさない運用にした
デプロイフローの変更により不便だった点が解消され、チームメンバーからはデプロイがスムーズになって楽になったというフィードバックをもらいました。
このように、一度デプロイフローを決めた後も、不便な部分が分かってきたら柔軟に変えていくようにしました。
チームの人数やリポジトリの運用の仕方によって適したデプロイフローは変わるため、柔軟に別の種類のワークフローのトリガーやアクションを試していくのが良いでしょう。
例えば、Classi 内の他チームでも Release Please という GitHub Actions のアクションライブラリを使ってリリース自動化した例が開発者ブログの記事で紹介されています。
タスクのチェックリスト作成・見積もりを立てる
チーム共通のデプロイフローを決定後、実際に対象リポジトリの移行作業を1つずつ対応する作業に移りました。
やり方としては、タスクのチェックリストを作成し1PRごとにどの順番でワークフロー・ジョブを追加する計画を立てて実際にPRを作るようにしました。
最初のリポジトリの作業では完了まで2週間前後かかりましたが、最終的に1リポジトリごとで3〜5日で移行できるようになりました。
早く終えられるようになった理由としては、各リポジトリの環境の差異もありデプロイに必要なビルドの手順が違う部分がありつつも、大部分のワークフローの実装を共通で利用することで見積もりが立てやすくなったためだと捉えています。
CI/CD の構築が未経験のチームメンバーにも1つのリポジトリの作業にチャレンジしてもらい、前述したワークフローを通して作業を進めてもらいました。CI/CD の作り方を学ぶ良い機会になりました。
これは筆者の個人的な感覚かもしれませんが、CI/CD の移行作業は追加するワークフローやジョブごとでタスクを分割できるため、見積もりに関しては他のアプリケーション開発のタスクよりもイメージしやすい作業だと感じました。
また、CI/CD を考える上では対象のリポジトリのインフラ・アプリケーション構成を再確認してデプロイフローを組み立てていくことになるため、リポジトリに対する最低限の技術理解も求められます。
上記の点により、チームのオンボーディング向けのタスクとして CI/CD に触れてもらうのはとても良いと考えています。
筆者自身、この CI/CD 移行作業は半年間の休職から明けて初めて取り組んだ開発でした。
復帰後にまずこのタスクから取り組めたことは良いリハビリになったと感じています。
まとめ
このような流れで進めていき、9個あったリポジトリの CI/CD をCircleCI からGitHub Actions の移行作業を予定していた期間までに完了できました。
また、本記事の中では紹介しませんでしたが、GitHub Actions を触る中で細かい詰まり所がいくつかありそれらの知見を社内の esa で共有する活動もしました。
これらの経験を通して GitHub Actions や CI/CD周辺の技術に対して少し自信を持てるようになりました。チーム内で CI/CD周りの困り事があれば率先して動くようにし、チームに貢献する範囲を広げることができました。
移行自体は完了しましたが、より効率的なデプロイフロー・自動化の設計やCIのコスト削減などまだまだ改良できるポイントが多い領域です。効率化を進めることが顧客へ届けるリードタイムの短縮・有事の際のMTTR短縮にも繋がります。
今後も CI/CD 周辺の知見を増やし実践することで、社内の開発サイクルの効率化に繋げていきたいです。