Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Ruby on CI #ginzarails

sue445
PRO
August 28, 2020

Ruby on CI #ginzarails

銀座Rails#24の発表資料です
https://ginza-rails.connpass.com/event/181807/

sue445
PRO

August 28, 2020
Tweet

More Decks by sue445

Other Decks in Technology

Transcript

  1. Ruby on CI
    2020/08/28 銀座rails#24 @sue445

    View Slide

  2. 自己紹介
    ● Go Sueyoshi (a.k.a. sue445)
    ● ピクシブ インフラ部所属
    ○ AWS, GCP, CI
    ○ アプリケーションコードを一切触らずにパフォーマンスチューニングす
    るリアルISUCON
    ○ その他色々

    View Slide

  3. 自己紹介
    ● 社内GitLabメンテナ
    ○ 運用知見はSoftware Design 2020年1月
    号に書いた(ダイマ)
    ○ https://gihyo.jp/magazine/SD/archive/
    2020/202001

    View Slide

  4. 自己紹介
    ● 女児アニメチョットワカル
    ○ プリキュアシリーズ全話視聴
    ○ プリティーシリーズ(プリティーリズム・プリパラ・King of Prism・キ
    ラッとプリ☆チャン)全話視聴
    ○ アイカツ(無印〜オンパレード)全話視聴

    View Slide

  5. 自己紹介
    ● 自称YAMLエンジニア
    ○ Ansible, docker-compose, CircleCI, GitLab CI, Travis CI
    Wercker, GitHub Actions, Serverless Framework, AWS
    SAM, Kubernetes
    ● 自称CIマニア
    ○ Jenkins(昔), Travis CI, CircleCI, Wercker, GitLab CI, GitHub
    Actions

    View Slide

  6. 自己紹介
    ● RubyKaigi 2019 Speaker
    ○ Best practices in web API client development
    ○ https://rubykaigi.org/2019/presentations/sue445.html
    ● RubyKaigi 2020 Speaker
    ○ Ruby on CI
    ○ https://rubykaigi.org/2020/presentations/sue445.html
    ○ しかし中止(◞‸◟)

    View Slide

  7. 9/4(金)が僕の登壇日だった...

    View Slide

  8. 今日話すこと
    ● RubyKaigi2020で話すつもりだった内容
    ○ CFP: https://sue445.fanbox.cc/posts/771529
    ● CIマニアがCIの話をする
    ○ Railsはおろか、Ruby固有の話もそんなにありません
    ○ 逆に言うと他言語でも使い回せるベストプラクティスです

    View Slide

  9. アジェンダ
    ● なぜCIをするのか
    ● CIの歴史
    ● 何をCI/CDするのか
    ● いつCIを導入すべきか
    ● いつ(どのタイミングで、どの周期で)CIすべきか
    ● 何を使うべきか
    ● スロービルド改善
    ● CIのキャッシュ戦略
    ● これからのCI

    View Slide

  10. まとめ
    ● 何をしたいかや規模によって使うもの(SaaS、セルフホスティング含めて)
    が変わる
    ○ 銀の弾丸はない
    ● CIの仕組みやエコシステムにのっかることによっていくらでもリファクタリン
    グできる
    ● 手作業を自動化することによって生産性を何倍にもできる
    ● 技術革新によってその時点の最適解がすぐに陳腐化する
    ○ 作った当時の最適解が今の最適解とは限らない
    ○ 必要に応じて式年遷宮も必要

    View Slide

  11. アジェンダ
    ● なぜCIをするのか
    ● CIの歴史
    ● 何をCI/CDするのか
    ● いつCIを導入すべきか
    ● いつ(どのタイミングで、どの周期で)CIすべきか
    ● 何を使うべきか
    ● スロービルド改善
    ● CIのキャッシュ戦略
    ● これからのCI

    View Slide

  12. (sue445は)なぜCIするか?
    ● 教科書的な模範解答はググればいくらでも出てくるのであくまで僕がどう
    してCIするかの話です
    ● 異論は認める

    View Slide

  13. (sue445は)なぜCIするか?
    ● 働きたくないから
    ○ 日本人は勤勉で真面目で働き者
    ○ 僕は真逆

    View Slide

  14. 働かずに5000兆円欲しい!!!

    View Slide

  15. (sue445は)なぜCIするか?
    ● 人は間違えるが機械は間違えない
    ○ 自分自身も信用しない
    ○ Q. 機械も間違えるのでは?
    ■ A. 機械が間違えてるのではなく、機械を作った人間や機械に支
    持を出した(コードを書いた)人間が間違えてる

    View Slide

  16. アジェンダ
    ● なぜCIをするのか
    ● CIの歴史
    ● 何をCI/CDするのか
    ● いつCIを導入すべきか
    ● いつ(どのタイミングで、どの周期で)CIすべきか
    ● 何を使うべきか
    ● スロービルド改善
    ● CIのキャッシュ戦略
    ● これからのCI

    View Slide

  17. CIの歴史
    ● 2005年: 自前で頑張る期
    ● 2011年: SaaS登場
    ● 2014年: Dockerの台頭
    ● 2019年: MSの本気

    View Slide

  18. 自前で頑張る期
    ● 2005年: Hudson
    ● 2011年: Jenkins
    ● この時代は自分でCIサーバを立てるのが主流
    ● 自分でCIサーバの面倒を見る必要があって大変
    ○ 仕事を減らすために導入したはずなのに仕事が増えるジレンマ
    ○ メンテナが属人化する問題(Jenkinsおじさん)

    View Slide

  19. SaaS登場
    ● 2011年: Travis CI
    ● 2011年: CircleCI 1.0
    ● 2011年: Wercker (box (non Docker))
    ● 2016年: CloudBees (SasS版Jenkins)
    ● CIサービスが用意した環境を利用
    ○ 自分でサーバを管理しなくてよくなった反面、CIサービス毎のハック
    がつらい
    ○ ローカルだと問題ないのにCIがなぜかコケる
    ○ CI毎に互換性がないのでポータビリティが微妙

    View Slide

  20. Dockerの台頭
    ● 2014: Docker Hub
    ● 2014: Wercker (Docker support)
    ● 2017: CircleCI 2.0 (Docker support)
    ● CIの実行環境がポータビリティになった
    ○ ベースのDockerイメージが一緒ならどこで動かしても同じ環境なの
    が保証される

    View Slide

  21. MSの本気
    ● 2019: GitHub Actions
    ○ ヘビーなマトリクスビルドも並列数で殴れるようになった(後述)

    View Slide

  22. アジェンダ
    ● なぜCIをするのか
    ● CIの歴史
    ● 何をCI/CDするのか
    ● いつCIを導入すべきか
    ● いつ(どのタイミングで、どの周期で)CIすべきか
    ● 何を使うべきか
    ● スロービルド改善
    ● CIのキャッシュ戦略
    ● これからのCI

    View Slide

  23. 何をCI(CD)するか
    ● 普通のRuby製アプリ
    ● gem

    View Slide

  24. 普通のRuby製アプリのCI
    ● test:rspecなど
    ● lint : rubocop, slimlintなどのような静的解析
    ● deploy
    ○ アプリ:capisrtanoなど
    ■ デプロイを自動にするか手動にするかはアプリによって変わる
    (本番環境のみCI上から手動デプロイとか)
    ○ ドキュメント:YARD, Storybookなど

    View Slide

  25. gemのCI
    ● deployがない以外はアプリと構成は一緒
    ● RubyのバージョンやRailsのバージョン毎に分けたgemfileによってマトリ
    クスビルド
    ○ マトリクステストのジョブ数を増やしすぎるとジョブの実行時間が長く
    なるのでほどほどに
    ○ 今までの経験上、Rubyのバージョンはサポートしてる下限(最古)と
    上限(最新)でいいことが多い
    ○ Railsはマイナーバージョン毎に細かい挙動が変わるので全部テスト
    しないときつい

    View Slide

  26. 余談1: CIのジョブをどこまで細分化すべきか?
    ● testやlintなどのように依存しないジョブを複数ジョブで並列実行するか
    単一ジョブで直列実行するかはケースバイケース

    View Slide

  27. ジョブを細分化した方がいい場合
    ● 基本的には並列実行の方が効率的だしジョブ毎の依存関係がなくなる
    ● 時間のかかるジョブを分割して並列実行することで実行時間を減らせる
    ● 実行環境(dockerイメージ)が変わる場合はジョブ分けないと無理
    ○ 例)通常はRubyのDockerイメージを使いつつnpm系だけnode系
    のイメージを使う。デプロイ時にaws-cliやgcloudコマンドだけが
    入ったDockerイメージを使う

    View Slide

  28. ジョブを細分化しない方がいい場合
    ● 一瞬系のジョブの場合、ジョブの中で実行してるコマンドの実行時間より
    も、docker pullやリポジトリのcheckoutなどのジョブ初期化の方が時間
    がかかることが多いので細分化しすぎると逆効果
    ● CIサービスのプランによって並列数が制限されている場合は敢えて並列
    数を増やさないこともある

    View Slide

  29. 余談2: Ruby以外の活用事例
    ● 例)packageやバイナリやDockerイメージのビルド、Terraformの実行
    ● Terraform運用事例書きました
    ○ https://inside.pixiv.blog/2020/07/30/172828

    View Slide

  30. 余談3: CIのスケジューラを利用したbotの定期実行
    について
    ● GitHub Actionsでは禁止されているので注意
    ○ 「GitHubアクションが使用されるリポジトリに関連するソフトウェアプ
    ロジェクトの製造、テスト、デプロイ、公開に関連しないその他の行
    為。」にあたる
    ○ https://help.github.com/ja/github/site-policy/github-additi
    onal-product-terms#a-actions-usage

    View Slide

  31. アジェンダ
    ● なぜCIをするのか
    ● CIの歴史
    ● 何をCI/CDするのか
    ● いつCIを導入すべきか
    ● いつ(どのタイミングで、どの周期で)CIすべきか
    ● 何を使うべきか
    ● スロービルド改善
    ● CIのキャッシュ戦略
    ● これからのCI

    View Slide

  32. いつCIを導入すべきか?
    ● 継続的にメンテする必要が出てきた時
    ○ 基本的にはリポジトリ作成時にCIを導入する
    ○ 逆にいうと使い捨てのコードにはテストもCIも不要
    ● 2〜3回手作業をやってルーチン化し始めたら自動化
    ○ 早ければ早い方がいい

    View Slide

  33. アジェンダ
    ● なぜCIをするのか
    ● CIの歴史
    ● 何をCI/CDするのか
    ● いつCIを導入すべきか
    ● いつ(どのタイミングで、どの周期で)CIすべきか
    ● 何を使うべきか
    ● スロービルド改善
    ● CIのキャッシュ戦略
    ● これからのCI

    View Slide

  34. いつ(どのタイミングで、どの周期で)CIすべきか?
    ● アプリの場合
    ● gemの場合

    View Slide

  35. アプリの場合のCI実行周期
    ● pushやPRの単位
    ● 定期ビルド(Nightly Build)
    ○ 毎コミット実行したくない重めのインテグレーションテスト
    ○ 継続的な負荷テスト
    ○ 開発用のDockerイメージをビルド

    View Slide

  36. gemの場合のCI実行周期
    ● 基本的にはアプリと同様(push, PRの単位)
    ● 定期ビルドが重要
    ○ 自分のコードに変更がなくても依存してるgemの破壊的変更により
    masterブランチのビルドはすぐにぶっ壊れる
    ■ 例)古いRubyのサポート切れ (required_ruby_version)
    ○ 最低週1回は定期ビルドすべき
    ■ 他の人のリポジトリにPR投げた時に自分の変更以外でビルドが
    コケるのがすごい嫌なので、自分のgemは全部weekly buildを
    してる

    View Slide

  37. FAQ. Gemfile.lockをコミットしてればmasterの
    ビルドは壊れないのでは?
    ● A. そうね
    ○ Gemfile.lockをコミットすることで使うgemのバージョンが固定化さ
    れるので、何もしないのにビルドが壊れることはなくなるというメリット
    はある
    ● デメリットの方が多いと思ってる
    ○ 個人の感想です

    View Slide

  38. Gemfile.lockをコミットするデメリット
    ● gemに対してbundle updateするコスト
    ○ CIで複数のgemfileをつかっているとそれらもbundle updateする
    必要が出てくる
    ○ dependabotがサブディレクトリには対応しているがGemfile以外の
    名前に非対応
    ■ https://dependabot.com/docs/config-file/
    ■ https://help.github.com/en/github/administering-a-re
    pository/configuration-options-for-dependency-updat
    es

    View Slide

  39. Gemfile.lockをコミットするデメリット
    ● gemは色んな状況(依存gemのバージョン)で使われるので、
    Gemfile.lockをコミットするとそういったケースをCIで検知できなくなる
    ○ 本当に依存gemのバージョンを管理したければgemspecを使うべき
    ● version.rb変えた時にGemfile.lockで差分が出るのでrake release直
    前にGemfile.lockもコミットする必要がある
    ○ gitの差分がある状態でrake releaseしようとすると失敗するのだ
    が、もしかしたらRubyMineが裏でbundle installしてるせいかもし
    れない

    View Slide

  40. アジェンダ
    ● なぜCIをするのか
    ● CIの歴史
    ● 何をCI/CDするのか
    ● いつCIを導入すべきか
    ● いつ(どのタイミングで、どの周期で)CIすべきか
    ● 何を使うべきか
    ● スロービルド改善
    ● CIのキャッシュ戦略
    ● これからのCI

    View Slide

  41. CIは何を使うべきか
    ● 何を使うべきか x 3
    ○ CIサービス
    ○ Dockerイメージ
    ○ 実行環境
    ● だいたいみんなGitHub使っていると思うのでGitHub前提
    ● 自分が使ったことあるやつ中心

    View Slide

  42. gemで使うべきCI
    ● たくさんgem(5個以上くらい)をメンテしてるならGitHub Actions、それ以
    外ならTravis CIかCircleCI

    View Slide

  43. gemでTravis CIやGitHub ActionsやCircleCI
    を選択する理由
    ● 「各Rubyのバージョン x 各Railsのバージョン」のようなマトリクスビルドが
    書きやすい
    ○ https://docs.travis-ci.com/user/build-matrix/
    ● 最近CircleCIもマトリクスビルドを正式にサポートした
    ○ https://circleci.com/blog/circleci-matrix-jobs/

    View Slide

  44. Travis CIのマトリクスビルド
    ● メリット
    ○ GitHub Actionsに比べると少ない記述量で書ける
    ■ シンプルなgemのCIであればTravis CIで十分なことも多い
    ● デメリット
    ○ 5並列/ownerなので大量にgemをメンテして一気にPRマージすると
    ビルドが詰まる
    ○ 30個のgemのweekly build 1.5時間

    View Slide

  45. GitHub Actionsのマトリクスビルド
    ● メリット
    ○ 20並列/repo
    ○ ownerごとの上限はプランによって変わる
    ■ https://help.github.com/en/actions/getting-started-wi
    th-github-actions/about-github-actions#usage-limits
    ○ 30個のgemのweekly build 15分
    ● デメリット
    ○ Travis CIに比べたら記述が冗長

    View Slide

  46. アプリで使うべきCI
    ● 基本的にはCircleCIかGitHub Actionsでいい
    ○ 複雑なworkflowを書けるのでやりたいことはだいたい実現できる
    ● 個人的にはCircleCI推し
    ○ GitHub ActionsはYAMLのアンカー(&〜)とエイリアス(*〜)が使え
    なくてリファクタリング時にたまに困る

    View Slide

  47. アプリとかgemとか関係無しにGitHub Actionsを
    使った方がいいケース
    ● CI上でGitHub APIを使う場合
    ○ メインでCircleCI使ってても一部分だけGitHub Actionsは選択肢と
    してアリ

    View Slide

  48. 【注意】CI 上でパーソナルアクセストークンは使って
    はいけない
    ● 会社orgの場合、個人のパーソナルアクセストークンを使うとその人が退
    職してorgからいなくなった時にCIが止まる
    ○ ボットユーザの管理が必要
    ● パーソナルアクセストークンはリポジトリ単位の権限管理ができない
    ○ (ボットユーザ含めて)orgの誰か1人のトークンが漏れたらその人がア
    クセス可能なリポジトリ全部漏洩したと一緒
    ○ 漏れたらインシデント

    View Slide

  49. GitHub APIを使う場合なぜGitHub Actionsを
    使った方がいいのか?
    ● CI用のパーソナルアクセストークンの発行が不要なため
    ○ https://help.github.com/ja/actions/configuring-and-manag
    ing-workflows/authenticating-with-the-github_token
    ○ secrets.GITHUB_TOKEN で使える
    ● インストールアクセストークン
    ○ hubコマンドで試したけど自分自身のプライベートリポジトリとパブリッ
    クリポジトリは見れるけど、他のプライベートリポジトリは見えなかった
    ● 有効期限60分なので仮に漏れても被害は最小限

    View Slide

  50. 余談1: GitLabの場合
    ● GitLabではGitLab CIを使うのがデファクト
    ○ 機能的にもCircleCIと同等なので遜色ない
    ○ リポジトリとCIが統合しているのでメリットも多い
    ■ 例)セットアップ不要、ビルドが終わったらMergeRequestを自動
    マージ
    ● ピクシブでのGitLab CI事例
    ○ https://speakerdeck.com/sue445/pixiv-tech-salon-numbe
    r-pixivtechsalon
    ○ https://sue445.hatenablog.com/entry/2019/12/18/000108

    View Slide

  51. 余談2: クラウドのCIツール
    ● CodeBuild(AWS)やCloud Build(GCP)など
    ● クラウドにデプロイする前提ならクラウドのCIツールを使うのもあり
    ○ VPN内にアクセス可能なアクセスキーなどを外に出さなくてよかった
    り、踏み台サーバが不要なのでセキュアというメリット

    View Slide

  52. RubyのDockerイメージについて
    ● 最近のCIはDockerイメージを使うのが主流
    ● Dockerイメージソムリエ(自称)として色んなイメージを使った結果、最終
    的にこの3つに落ち着いた
    ○ https://hub.docker.com/_/ruby
    ○ https://hub.docker.com/r/circleci/ruby
    ○ https://hub.docker.com/r/rubylang/ruby

    View Slide

  53. 余談: Dockerイメージソムリエが気をつけてること
    ● Docker Hubではたくさんのイメージが公開されているが、頻繁に更新さ
    れていることが一番大事
    ○ Rubyの場合最低でも最新版が出たらすぐにパッチバージョン単位
    (x.y.z)でtagがうたれてリリースされていないと厳しい
    ○ gemのCIを考えるとマイナーバージョン単位(2.7とか)でtagが打たれ
    ていると嬉しい
    ● 個人が手動でリリースしてるようなDockerイメージを使うのはメンテされ
    なくなるリスクがあるので使いづらい

    View Slide

  54. https://hub.docker.com/_/ruby
    ● slimやalpineもあるのでイメージサイズを抑えたい時はこっち
    ● 一番利用されている
    ● Docker Official ImagesだがRubyコアチームの公式ではない

    View Slide

  55. https://hub.docker.com/r/circleci/ruby
    ● _/ruby ベース
    ● テストに必要なものが全部入りで便利(そこそこ重い)
    ● nodeタグやbrowserタグもあるので必要に応じて使う
    ○ https://circleci.com/docs/2.0/circleci-images/
    ○ headless chromeのインストールに困ったらコレ
    ● circleciと言いつつ他のCIでも普通に使える
    ● 普通のdockerイメージと違って実行時のユーザがrootユーザじゃなく
    circleciユーザなのが注意(sudoはある)

    View Slide

  56. https://hub.docker.com/r/rubylang/ruby
    ● Rubyコアチームの公式
    ● GitHub ActionsでTravis CIのruby-headみたいな開発版のrubyでビ
    ルドをしたい時にmaster-nightly-bionicタグが便利

    View Slide

  57. 余談: cimg/ruby
    ● 最近CircleCIが新しいDockerイメージを出したらしい
    ○ https://hub.docker.com/r/cimg/ruby
    ○ circleci/rubyよりイメージが軽量化
    ■ circleci/ruby:2.7.1 => 476.71 MB
    ■ cimg/ruby:2.7.1 => 332.04 MB
    ● 日本語の詳しいブログ
    ○ https://budougumi0617.github.io/2020/06/08/circleci_cim
    g_go_2020/

    View Slide

  58. CIの実行環境は何を使うか
    ● CircleCI
    ○ 前述のDockerイメージのどれか
    ● GitHub Actions
    ○ GitHub ActionsのVM上でビルドを実行
    ○ GitHub ActionsのVM上でコンテナを起動しその中でビルドを実行

    View Slide

  59. GitHub ActionsのVM上でビルドを実行
    ● 基本的には ruby/setup-ruby でいい
    ○ https://github.com/ruby/setup-ruby
    ○ ruby orgなので安心感がある(eregonさんがメンテナ)
    ● GitHub公式の actions/setup-ruby は最新版への追従が遅いので実
    アプリで使うのは厳しい
    ○ https://github.com/actions/setup-ruby
    ● 詳しいこと
    ○ https://mstshiwasaki.hatenablog.com/entry/2020/02/08/1
    30844

    View Slide

  60. GitHub ActionsのVM上でコンテナを起動しその
    中でビルドを実行
    ● 基本的にはVMとコンテナどっちでもいい
    ● 下記のような場合はDockerイメージを使うしかない
    ○ Docker Hubにしかない古いRubyのバージョンでCIしたい時
    ○ gemのマトリクステストなどで開発版のRubyでCIする必要がある場

    ■ rubylang/ruby:master-nightly-bionic

    View Slide

  61. アジェンダ
    ● なぜCIをするのか
    ● CIの歴史
    ● 何をCI/CDするのか
    ● いつCIを導入すべきか
    ● いつ(どのタイミングで、どの周期で)CIすべきか
    ● 何を使うべきか
    ● スロービルド改善
    ● CIのキャッシュ戦略
    ● これからのCI

    View Slide

  62. スロービルド改善
    ● 「CIの スロービルドに 立ち向かう」 #一句
    ● 実際にCIのビルドを1回20分から10分にした事例をベースに、どうCIを
    チューニングすればいいかを紹介

    View Slide

  63. どこが遅いかを調べる
    ● 「推測するな、計測せよ」って言葉もあるのでまずはどこで時間がかかって
    るか調べる
    ● CIサービスによってはstep毎の時間が出るので楽

    View Slide

  64. どこが遅いかを調べる
    ● time コマンドを仕込めばコマンド単位で計測はできる
    ● rspec --profile で各example単位でのワーストワンキングを出せる

    View Slide

  65. スロービルド対策の方針
    ● ジョブ起動時のdockerイメージのpullが重いパターン
    ○ 700MB超えるイメージを使うとこの問題に引っかかる
    ○ たいていの場合Docker Hubで配布されてるイメージを使ってる場合
    が多いので、alpine版やslim版があればそれを使う
    ■ パッケージが足りずに大量のパッケージをapt-get
    install(yum install)するコストも出てくるのでケースバイケース
    ○ CIサービスによっては1ジョブで複数コンテナを起動できることが多い
    が減らすのも大事。(例:rubocop実行時はDBやredisのコンテナを
    起動しないなど)

    View Slide

  66. スロービルド対策の方針
    ● gemなどのライブラリインストール
    ○ CI側で適切にキャッシュしてやる(後述)
    ● パッケージインストールやmake
    ○ makeしたバイナリをCIのキャッシュに乗せるのも有り
    ○ インストールそのものが遅い場合はCI専用のDockerイメージを作っ
    た方が速いのだが、オレオレDockerイメージというメンテすべきもの
    が増えるので一長一短

    View Slide

  67. スロービルド対策の方針
    ● テスト
    ○ CIマシンで複数コア積んでいることが多いので、全CPU使うような設
    定にする
    ■ CPUのコア数に応じて自動で並列bundle installするコマンド
    ■ bundle install --job=$(nproc)
    ○ 1つのジョブを複数のジョブに分割&並列化する

    View Slide

  68. スロービルド対策の方針
    ● テスト
    ○ DBアクセスが多すぎて遅いのであれば
    https://hub.docker.com/r/circleci/mysql のramがついてるtag
    を使ってみるのも一興
    ■ ストレージの代わりにRAMを使うので速い分、メモリを喰ってジョ
    ブによってはOOMになる可能性があるので注意
    ■ ramつけるだけで使えるので試しやすいし戻しやすい

    View Slide

  69. 設定ファイルをシンプルにする
    ● ボトルネックが分かってチューニングしようにもスパゲッティymlが足を
    引っ張ることが多いのでリファクタリングもセットで行う
    ● 複数箇所で使うものはymlにインラインで書かずにシェルスクリプトに抽出
    する
    ● CircleCIのorbsのように再利用できる仕組みがあれば乗っかる

    View Slide

  70. オチ
    ● ここまでやっても多少は速くなったが劇的に改善しなかったのでCircleCI
    の並列数を増やしたら速くなった(それはそう)

    View Slide

  71. CIのキャッシュ戦略
    ● 長いのでブログ参照
    ● GitLab CIとCircleCIのキャッシュ戦略の違い - くりにっき
    ○ https://sue445.hatenablog.com/entry/2019/10/30/084626

    View Slide

  72. アジェンダ
    ● なぜCIをするのか
    ● CIの歴史
    ● 何をCI/CDするのか
    ● いつCIを導入すべきか
    ● いつ(どのタイミングで、どの周期で)CIすべきか
    ● 何を使うべきか
    ● スロービルド改善
    ● CIのキャッシュ戦略
    ● これからのCI

    View Slide

  73. これからのCI
    ● 分からん
    ● 今後もどんどん便利なツールが出てくるはずなので定期的に式年遷宮し
    た方がよさそう
    ● 基本的にはDockerイメージとシェルを実行する場所が変わるだけなので
    容易に乗り換えできるはず

    View Slide

  74. 参考: index_shotgunの式年遷宮
    ● https://github.com/sue445/index_shotgun
    ● Travis CI期
    ○ sqlite3, MySQL, PostgreSQLだけ
    ● Travis CI + Wercker併用期
    ○ Travis CIでOracleインストールするだけで30分くらいかかってつら

    ○ この当時Dockerに対応してたのがWerckerのみだったのでOracle
    のCIするためにWercker利用

    View Slide

  75. 参考: index_shotgunの式年遷宮
    ● Travis CI + CircleCI 2.0併用期
    ○ Werckerも悪くはなかったが設定がymlで完結しないつらみ
    ■ ワークフローの設定は画面で設定する必要がある
    ○ CiecleCI 2.0が出たあたりで移行

    View Slide

  76. 参考: index_shotgunの式年遷宮
    ● GitHub Actions
    ○ .circleci/config.yml 修正しただけでTravis CIのクソデカビルドが
    走るのがつらい
    ○ Travis CI並列数が全然足りない
    ■ Travis CIだと5並列で50ビルド計1時間。ピーク期は70ビルド計
    2時間
    ○ GitHub Actions発表直後に移行
    ■ 20並列で70ビルド20分

    View Slide

  77. まとめ
    ● 何をしたいかや規模によって使うもの(SaaS、セルフホスティング含めて)
    が変わる
    ○ 銀の弾丸はない
    ● CIの仕組みやエコシステムにのっかることによっていくらでもリファクタリン
    グできる
    ● 手作業を自動化することによって生産性を何倍にもできる
    ● 技術革新によってその時点の最適解がすぐに陳腐化する
    ○ 作った当時の最適解が今の最適解とは限らない
    ○ 必要に応じて式年遷宮も必要

    View Slide

  78. one more thing

    View Slide

  79. one more thing
    CI as a CI
    「CIをCIする」

    View Slide

  80. 複数リポジトリのCI設定の共通化(CI as a CI)
    ● アプリケーションコードと同様CIの設定も継続的にメンテしていく
    ○ みんなリファクタリング大好きだよね?
    ● 複数リポジトリメンテしてるとリポジトリによって設定が違うと大変なので極
    力統一したい
    ● 同一yamlを複数リポジトリでコピペして使い回すのが理想だがgemに
    よってサポートしてるrubyのバージョンが変わったりするので厳しい
    ○ とはいえ8割方一緒なので共通化できる

    View Slide

  81. というわけでCI as a CIした
    ● https://github.com/sue445/ci-config-itamae
    ● RailsのmigrationとAnsibleのplaybookがあわさった感じ
    ● Itamaeを活用したマイグレーションシステム
    ● 自分の作業を効率化することに特化してるので汎用化はあまり考えられ
    ていない

    View Slide

  82. Usage (Generate a migration file)
    $ ./bin/generate --template=github_actions some_migration
    Write to
    /path/to/ci-config-itamae/cookbooks/migrate/github_actions/202
    00311232827_some_migration.rb

    View Slide

  83. Usage (Edit a migration)
    file "#{node[:repo]}/.github/workflows/test.yml" do
    action :edit
    block do |content|
    next if content.include?("centos:8")
    content.gsub!(<<-YAML, <<-YAML)
    - centos:7
    YAML
    - centos:7
    - centos:8
    YAML
    end
    only_if "ls #{node[:repo]}/.github/workflows/test.yml"
    end

    View Slide

  84. Usage (Apply to a repo)
    # dry run結果が問題なければ--dry-runを外して実行
    $ ./bin/migrate
    --recipe=cookbooks/migrate/github_actions/20200311232827_som
    e_migration.rb -m "This is commit message"
    --repo=github.com/sue445/rubicure --dry-run

    View Slide

  85. Usage (Apply to multiple repos)
    # dry run結果が問題なければ--dry-runを外して実行
    $ ./bin/migrate
    --recipe=cookbooks/migrate/github_actions/20200311232827_som
    e_migration.rb -m "This is commit message" --include=gem
    --dry-run

    View Slide

  86. 挙動
    ● ローカルの複数リポジトリに対して下記を実行
    ○ ghq get
    ○ git pull
    ○ git checkout -b 【適当なブランチ名】
    ○ Itamaeでmigrationを適用
    ○ 差分があったらコミットしてPR投げる
    ● 30個のリポジトリにPR投げるまで10分
    ○ これ作る前は手作業で半日がかり
    ● PR投げられたらあとはビルドが終わるまで待つだけ

    View Slide