こんにちは、シンクロ・フードの大前です。
シンクロ・フードではCIにDroneを使用していましたが、2022年の11月ごろにGitHub Actionsへの移行を完了しました。
今回はその経緯やDroneとの比較についてお話します。
なぜ移行したのか
シンクロ・フードでは2018年ごろからDroneを使用していました。
導入時の記事があるので良かったらご覧ください。
その後、2020年9月ごろにGitHub Enterprise Server(以下GHES)でもGitHub Actionsが使えるようになりました。
(シンクロ・フードではGHESというオンプレ版を使っています。GitHub Enterprise Cloudと比べて機能追加が少し遅い特徴があります。)
Droneは課題を感じている部分もあり、GitHub Actionsの方が以下のような点で優れていたため移行しました。
GitHub Actionsのワークフロー構文の方が表現力が高い
CIを主に実行しているリポジトリはMonorepoで運用1しているので、各アプリケーションごとに自動テストを実行する必要がありました。
DroneではMatrix Buildsという記法でディレクトリごとに実行するワークフローを制御していましたが、GitHub Actionsではディレクトリごとにトリガーを設定することで読みやすい構造にできる点が魅力でした。
以下にDroneとGitHub Actionsのサンプルコードを記載します。(簡略化のため実際は必要な記述を省略していますがご了承ください)
Droneの場合
この後詳しく解説しますが、まずは全体のコードをご覧ください。
# 1. matrix(並列実行)を定義する matrix: include: - SUB_REPOSITORY: '' RUBY_VERSION: 2.4.1 APPLY_SEED: false - SUB_REPOSITORY: apps/rails-application1 RUBY_VERSION: 2.6.0 APPLY_SEED: true - SUB_REPOSITORY: apps/rails-application2 RUBY_VERSION: 2.7.1 APPLY_SEED: false - SUB_REPOSITORY: apps/rails-application3 RUBY_VERSION: 2.7.1 APPLY_SEED: false # 2. あとでYAMLのエイリアスとして使えるようにアンカーを定義する references: if-root-matrix: &if-root-matrix matrix: SUB_REPOSITORY: '' if-app-matrix: &if-app-matrix matrix: exclude: SUB_REPOSITORY: '' # 3. CIで実行するジョブを定義する pipeline: run-tests: commands: - bundle exec rspec when: <<: *if-rails-app-matrix lint: commands: - yarn run lint when: << *if-root-matrix apply-seed-each-app: commands: - bundle exec rails db:seed when: matrix: APPLY_SEED: true
1. matrix(並列実行)を定義する
以下の部分ではMonorepo内のアプリケーションのディレクトリをSUB_REPOSITORY
として定義しています。
SUB_REPOSITORY: ''
はMonorepoのルート階層を意味していて、全アプリケーションに適用する処理はこのときに実行するようにしています。
RUBY_VERSION
やAPPLY_SEED
は各アプリケーションごとのCI実行に必要な情報を定義しています。
この場合だと、ルート階層での実行+アプリケーション3つそれぞれで実行ということになります。
matrix: include: - SUB_REPOSITORY: '' RUBY_VERSION: 2.4.1 APPLY_SEED: false - SUB_REPOSITORY: apps/rails-application1 RUBY_VERSION: 2.6.0 APPLY_SEED: true - SUB_REPOSITORY: apps/rails-application2 RUBY_VERSION: 2.7.1 APPLY_SEED: false - SUB_REPOSITORY: apps/rails-application3 RUBY_VERSION: 2.7.1 APPLY_SEED: false
2. あとでYAMLのエイリアスとして使えるようにアンカーを定義する
以下の部分はGitHub Actionsでいうところのon.*.paths
の設定にあたるもので、Monorepoのルート階層で実行するかアプリケーションごとの階層で実行するかを判別する設定です。これをyamlのアンカーとして定義してテストやlintの処理でエイリアスとして参照します。
references: if-root-matrix: &if-root-matrix matrix: SUB_REPOSITORY: '' if-app-matrix: &if-app-matrix matrix: exclude: SUB_REPOSITORY: ''
3. CIで実行するジョブを定義する
以下は実際にCIで実行するテストやlintの設定です。
lintはMonorepo内の全アプリケーション一律で同じものを適用しているのでルート階層で実行しています。
apply-seed-each-app
というのは、特定のアプリケーションのみで実行したい処理の設定で、APPLY_SEED
をtrueにしているアプリケーションでのみ実行されます。
pipeline: run-tests: commands: - bundle exec rspec when: <<: *if-rails-app-matrix lint: commands: - yarn run lint when: << *if-root-matrix apply-seed-each-app: commands: - bundle exec rails db:seed when: matrix: APPLY_SEED: true
Matrix Buildsは各アプリケーションごとに何を実行するのかが一見しただけではわからないですし、アプリケーションごとに独自の処理が増えるとより複雑になってしまうという点がつらかったです。
GitHub Actionsの場合
今度はGitHub Actionsのサンプルコードです。
Monorepoのルート階層で実行する処理はroot.yml
に、各アプリケーションごとに実行する処理は個別にymlファイルを用意します。今回はrails-application1の設定ファイルを例としてrails-application1.yml
に記載します。
GitHub Actionsのコードについては詳しい説明は割愛しますが、ひと目見ただけでも各アプリケーションで実行する内容がなんとなく読み取れるのではないでしょうか。
name: CI on: push jobs: lint: steps: - name: Run Lint run: yarn run lint
name: rails-application1 on: push: paths: - 'apps/rails-application1' jobs: run-tests: steps: - name: RSpec run: bundle exec rspec apply-seed: steps: - name: Apply seed run: bundle exec rails db:seed
コミュニティが大きくドキュメントや知見が豊富
他にもGitHub Actionsの方が公式のドキュメントが豊富で、知見がインターネット上に多いという点が魅力でした。
また自作のワークフローが多く公開されているという点も良いです。
GitHubとの連携機能が充実している
GitHubが提供しているだけあり、GitHubとの連携機能が豊富です。
- GitHub上のPull RequestからCIの実行結果やログをスムーズに確認できる。
- ワークフローのトリガーが豊富。
- GitHubのトークンを発行する手間なく参照できる。
移行方法
GHESではCIが実行されるインスタンスを自前でホスティングする必要があることからはじめにインフラ構築をしました。
インフラ周りのお話についてはまた別途記事を公開する予定のためここでは割愛させていただきます。
その後、Droneで実行しているRuboCopやRSpecなどをGitHub Actionsに移行しました。
DroneからGitHub Actionsへの書き換えは技術的に難しいところはありませんが、GitHub Actionsの構文に慣れていなかったので勉強しながら書き換えていきました。
2020年10月ごろにActionsを導入し、Droneからの移行が完全に完了したのは2022年の11月ごろでした。2
所感
GitHub Actionsに移行してしばらく経ちましたが、やはりDroneよりも資料が豊富で開発しやすいと感じています。
また、GitHub Actionsでは複数のリポジトリでワークフローを再利用3しやすい点も便利だと思いました。
Droneでは共通化したい処理をDockerイメージにすることで共通化していたため、より手軽になったと思います。
一方でGitHub Actionsそのものというわけではないですが、GHESによる課題も少しありました。
というのもGHESはGitHub Enterprise Cloudと比べて機能追加が少し遅いです。当時はbundle install
やyarn install
の結果をキャッシュするactions/cacheがGHESでは使えなかったため自作する必要がありました。(現在はGHESでも使えるようになっています)
まとめ
DroneからGitHub Actionsへの移行について紹介しました。
GitHub Actionsへの移行によって、よりCIの開発がしやすい環境になったと言えます。
シンクロ・フードではCIチームというCIに関する開発をするチームを設置していて、各開発者が所属するメインのチームと兼任する形で所属しています。
CIチームのメンバーも徐々に増えてきているため、今後はよりCI環境の改善を加速させていきたいと思います。
最後に、エンジニア募集のお知らせです! シンクロ・フードでは、まだまだ技術的な課題やチャレンジが残っています。 ぜひ、一緒に改善していきましょう!
また、飲食店ドットコム、求人飲食店ドットコムを始めとしたサービスの開発・改善も、どんどん進めております。 ご興味のある方は、以下の採用サイトからご連絡ください!
- Monorepoへの移行についてエンジニアブログのこちらの記事にまとめています。こちらも良ければぜひご覧ください。↩
- 2年ほどかかっていますがCIの開発に割り当てられる時間があまり多くないというところによるものです。また、その期間は移行だけでなく並行してCIの速度改善などの取り組みをしていました。↩
- Composite Action↩