Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

自己紹介 ● 自称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

Slide 6

Slide 6 text

自己紹介 ● 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 ○ しかし中止(◞‸◟)

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

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/

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

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に比べたら記述が冗長

Slide 46

Slide 46 text

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

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

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

Slide 49

Slide 49 text

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分なので仮に漏れても被害は最小限

Slide 50

Slide 50 text

余談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

Slide 51

Slide 51 text

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

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

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

Slide 54

Slide 54 text

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

Slide 55

Slide 55 text

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はある)

Slide 56

Slide 56 text

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

Slide 57

Slide 57 text

余談: 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/

Slide 58

Slide 58 text

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

Slide 59

Slide 59 text

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

Slide 60

Slide 60 text

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

Slide 61

Slide 61 text

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

Slide 62

Slide 62 text

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

Slide 63

Slide 63 text

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

Slide 64

Slide 64 text

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

Slide 65

Slide 65 text

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

Slide 66

Slide 66 text

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

Slide 67

Slide 67 text

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

Slide 68

Slide 68 text

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

Slide 69

Slide 69 text

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

Slide 70

Slide 70 text

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

Slide 71

Slide 71 text

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

Slide 72

Slide 72 text

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

Slide 73

Slide 73 text

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

Slide 74

Slide 74 text

参考: 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利用

Slide 75

Slide 75 text

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

Slide 76

Slide 76 text

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

Slide 77

Slide 77 text

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

Slide 78

Slide 78 text

one more thing

Slide 79

Slide 79 text

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

Slide 80

Slide 80 text

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

Slide 81

Slide 81 text

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

Slide 82

Slide 82 text

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

Slide 83

Slide 83 text

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

Slide 84

Slide 84 text

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

Slide 85

Slide 85 text

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

Slide 86

Slide 86 text

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