Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
How to use CircleCI and Sider in CrowdWorks
Search
Hideki Igarashi
September 13, 2018
Programming
1
890
How to use CircleCI and Sider in CrowdWorks
CircleCI/Sider合同ミートアップ@プレイド 新GINZA SIXオフィス
https://connpass.com/event/98494/
Hideki Igarashi
September 13, 2018
Tweet
Share
More Decks by Hideki Igarashi
See All by Hideki Igarashi
AWSマルチアカウント管理 / ODC2021 Online
hideki
0
4k
な…何を言っているのかわからねーと思うが、コードを書いていたと思ったらレビューが終わっていた / Code Review Meetup 3
hideki
1
290
CrowdWorks Engineering Culture
hideki
0
410
CrowdWorksのChatOpsの歴史 / ChatOps History of CrowdWorks
hideki
1
990
Bring out the ability of CircleCI 2.0
hideki
1
650
Grails with Spock
hideki
0
1.3k
JavaOne Report for G* 2012 San Francisco
hideki
2
1.2k
Other Decks in Programming
See All in Programming
『ドメイン駆動設計をはじめよう』のモデリングアプローチ
masuda220
PRO
8
540
見せてあげますよ、「本物のLaravel批判」ってやつを。
77web
7
7.7k
シールドクラスをはじめよう / Getting Started with Sealed Classes
mackey0225
4
640
Laravel や Symfony で手っ取り早く OpenAPI のドキュメントを作成する
azuki
2
110
Ethereum_.pdf
nekomatu
0
460
3 Effective Rules for Using Signals in Angular
manfredsteyer
PRO
0
100
AI時代におけるSRE、 あるいはエンジニアの生存戦略
pyama86
6
1.1k
.NET のための通信フレームワーク MagicOnion 入門 / Introduction to MagicOnion
mayuki
1
1.5k
WebフロントエンドにおけるGraphQL(あるいはバックエンドのAPI)との向き合い方 / #241106_plk_frontend
izumin5210
4
1.4k
Less waste, more joy, and a lot more green: How Quarkus makes Java better
hollycummins
0
100
Enabling DevOps and Team Topologies Through Architecture: Architecting for Fast Flow
cer
PRO
0
320
よくできたテンプレート言語として TypeScript + JSX を利用する試み / Using TypeScript + JSX outside of Web Frontend #TSKaigiKansai
izumin5210
6
1.7k
Featured
See All Featured
A better future with KSS
kneath
238
17k
The Cult of Friendly URLs
andyhume
78
6k
Docker and Python
trallard
40
3.1k
StorybookのUI Testing Handbookを読んだ
zakiyama
27
5.3k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
169
50k
Navigating Team Friction
lara
183
14k
Fashionably flexible responsive web design (full day workshop)
malarkey
405
65k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
229
52k
For a Future-Friendly Web
brad_frost
175
9.4k
A Philosophy of Restraint
colly
203
16k
The Pragmatic Product Professional
lauravandoore
31
6.3k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
93
16k
Transcript
How to use in CrowdWorks CircleCI and Sider $JSDMF$*4JEFS߹ಉϛʔτΞοϓ!ϓϨΠυ৽(*/;"4*9ΦϑΟε
About me twitter.com/ganta0087 github.com/ganta Hideki Igarashi Engineer
クラウドソーシングサービス クラウドソーシング = Crowd (群衆) + Sourcing (外注) 2012年3⽉サービス開始〜 会員数215万⼈
インターネットを活⽤することで、世界中の企業と個⼈が 直接つながり、仕事の受発注を⾏うことができる
CrowdWorksのリポジトリ ▶ ⾔語・フレームワーク ▶ Ruby (Rails / Gem) ▶ Go
▶ JavaScript (Node.js / Hubot) ▶ Swift (iOS) / Java (Android) ▶ Elixir
本⽇はRails成分多め Rails
CrowdWorksにおける CircleCI Sider の活⽤⽅法
CrowdWorksにおける CircleCIの活⽤⽅法
▶ .circleci/config.ymlがあるリポジトリ数: 56 ▶ ⽤途 ▶ テスト / ビルド ▶
Dockerイメージ作成 ▶ ドキュメント⽣成 CircleCI
すべてCircleCI 2.0に移⾏完了
▶ リポジトリのサイズ: 約1.3GB ▶ ⼤きすぎてキャッシュからリストアするのも遅い ▶ 過去の遺物は削除したのでShallow Cloneならばだいぶ速 くなる GitリポジトリのShallow
Clone % git count-objects -vH count: 2802 size: 13.28 MiB in-pack: 547956 packs: 1 size-pack: 1.34 GiB prune-packable: 0 garbage: 0
GitリポジトリのShallow Clone - checkout - run: name: GitリポジトリのCheckout command: |
git clone --depth=1 --branch $CIRCLE_BRANCH --single-branch $CIRCLE_REPOSITORY_URL . # ビルド対象のリビジョンにリセットして⽬的のコミットが取得できたかを確認 git reset --hard $CIRCLE_SHA1
▶ 2.0からBuild SettingsのClear Cachesは効かなくなった ▶ 設定ミスなどで稀にキャッシュを全部⾶ばしたくなる ▶ 全部のキャッシュキーを書き換えるのは⾯倒 ▶ 初めからキャッシュキーに共通の環境変数を埋めておく
▶ Build SettingsのEnvironment VariablesにYYYYMMDDhhmm形式で値を 格納しておく キャッシュを⼀⻫にクリアできるようにする - restore_cache: name: Restoring Cache - Bundler keys: - gems-{{ .Environment.COMMON_CACHE_KEY }}-{{ checksum "Gemfile.lock" }} - gems-{{ .Environment.COMMON_CACHE_KEY }}-
▶ キャッシュにGemfile.lockの ハッシュ値をテキストで残し ておき、⼀致したら完全ス キップするようにした ▶ Gemがたくさんあると完全 ⼀致状態でbundle install しても少し時間が掛かる
▶ うっかりGemfile.lockのコ ミット忘れたものをスルーし てしまったのでGemfileも チェックするように変更 キャッシュ戦略 - run: name: bundle installの実⾏ command: | checksum_file=vendor/bundle/checksum.sha256 bundle config --local disable_shared_gems 1 bundle config --local path vendor/bundle if [ -e $checksum_file ] && shasum --check $checksum_file then echo "Skipped." else # Gemのインストール bundle install --deployment # 使われなくなったGemの削除 (キャッシュを圧迫するため) bundle clean # チェックサムを保存 shasum --algorithm 256 Gemfile > $checksum_file shasum --algorithm 256 Gemfile.lock >> $checksum_file fi
▶ また、OSにインストールされてい るライブラリのバージョン等に依 存する場合があるため、Rubyや Node.jsの場合はそれらもキーに 含めてチェックしたほうが安全 ▶ {{ arch }}でアーキテクチャも取れ
るのでこれも⼊れておく キャッシュ戦略 - run: name: Generate OS version file command: | cat /etc/os-release > tmp/os_version - run: name: Generate Ruby version file command: | ruby --version > tmp/ruby_version - run: name: Generate Node version file command: | node --version > tmp/node_version key: gems-{{ arch }}-{{ .Environment.COMMON_CACHE_KEY }}-{{ checksum "tmp/os_version" }}- {{ checksum "tmp/ruby_version" }}-{{ checksum "Gemfile"}}-{{ checksum "Gemfile.lock" }}
▶ イメージのRegistryはQuay or Amazon ECR ▶ Quayの⾃動ビルドは柔軟性がない ▶ ⾃前でCircleCIを使ってビルド&プッシュ Dockerイメージのビルド
Dockerイメージのビルド build_and_push: docker: - image: docker:18.05.0-ce-git steps: - setup_remote_docker: version:
18.05.0-ce - checkout - run: name: Build command: | docker build -t --build-arg xxx=$XXX quay.io/crowdworks/xxxxxx . - run: name: Login to Quay command: | echo $QUAY_TOKEN | \ docker login --username $QUAY_USER --password-stdin quay.io - deploy: command: docker push quay.io/crowdworks/xxxxxx Docker Hubに公式イメージがあるので ビルドイメージに利⽤。 checkoutで必要になるため、Git⼊りの イメージを使う。 バージョンを揃えておく。
▶ ジョブが⾛るビルドイメージ側の話 ▶ ⾃前イメージはlatestタグが付いているその時点のイメージの SHA256を使っていたが、タグが差し替わったり消えたりする とSHA256の参照も消えてしまってCIが回せなくなった ▶ <image name>@sha256:XXXXXXXXXX ▶
何よりも中⾝がいつのものかわかりづらい ▶ 元のミドルウェアのバージョン+Dockerfileのコミットハッ シュにするとわかりやすい ▶ 例: quay.io/crowdworks/elasticsearch:5.6.10-11ead2b ⾃前Dockerイメージのバージョン固定⽅法
▶ 同時実⾏可能なノード数の制約がなくなるため、ビルド待ちが なくなる ▶ pushしたら常に即ビルド開始 ▶ 以前は定期的にAPIを叩いて ビルド待ち時間をDatadogに ⾶ばし、⻑くなってきたら Slackに通知してコンテナを
買い⾜したり戻したりしていた (温かみのある⼿作業) Performance Pricing plan
▶ コンテナのリソース設定ができるようになる ▶ https://circleci.com/docs/2.0/configuration-reference/ #resource_class ▶ モノリシックなRailsアプリケーションはメモリを⾷う… Performance Pricing plan
▶ まだ単純に切り替えただけ ▶ 元々ジョブの先頭でキックしていた別のジョブを分離 Workflow workflows: version: 2 build: jobs:
- build - validate_factory - staging_build: filters: branches: only: - /staging-.*/ 元のジョブ 元のジョブからキックされていたジョブを 並べて、stepsからジョブをキックしてい るrun定義を削除するだけ この状態から、分けると効率が上がりそうな ステップの塊を少しずつ分離していくとよさそう
▶ ジョブを増やしていくと定 義内容の重複が増えてくる ▶ デフォルト値として定義し ておいて使い回す YAMLのアンカーとエイリアスの利⽤ generate_yard_documents: docker: -
<<: *rails_docker_container working_directory: *working_directory_default steps: # Git - run: *configure_github_authentication - run: *checkout_repository - run: *configure_git # Bundler - run: *generate_os_version_file - run: *generate_ruby_version_file - restore_cache: *restore_bundler_cache - run: *bundle_install ... defaults: # Dockerコンテナ docker_containers: # Rails - &rails_docker_container image: quay.io/crowdworks/xxxxxx auth: ...
あれ…どこかで⾒たような
▶ commands ▶ runステップをパラメーター差し替え可能な状態で定義できる ▶ https://github.com/CircleCI-Public/config-preview-sdk/blob/master/ docs/commands.md CircleCI 2.1: Orb
structure commands: sayhello: description: "A very simple command for demonstration purposes" parameters: to: type: string default: "Hello World" steps: - run: echo << parameters.to >> jobs: myjob: docker: - image: "circleci/node:9.6.1" steps: - sayhello: to: "Lev"
▶ jobs ▶ jobをパラメーター差し替え可能な状態で定義できる ▶ https://github.com/CircleCI-Public/config-preview-sdk/blob/master/ docs/jobs.md CircleCI 2.1: Orb
structure jobs: sayhello: parameters: saywhat: description: "To whom shall we say hello?" default: "World" type: string machine: true steps: - run: echo "Hello << parameters.saywhat >>" workflows: build: jobs: - sayhello: saywhat: Everyone
▶ executors ▶ Dockerイメージや環境変数などを埋め込み済みのexecutorを定義できる ▶ https://github.com/CircleCI-Public/config-preview-sdk/blob/master/ docs/executors.md CircleCI 2.1: Orb
structure executors: lein_exec: docker: - image: clojure:lein-2.8.1 working_directory: ~/project environment: MYSPECIALVAR: "my-special-value" MYOTHERVAR: "my-other-value" jobs: build: executor: lein_exec steps: - checkout - run: echo "hello world" test: executor: lein_exec environment: TESTS: unit steps: - checkout - run: echo "how are ya?"
CircleCI 2.1: Orb structure generate_yard_documents: docker: - <<: *rails_docker_container working_directory:
*working_directory_default steps: # Git - run: *configure_github_authentication - run: *checkout_repository - run: *configure_git # Bundler - run: *generate_os_version_file - run: *generate_ruby_version_file - restore_cache: *restore_bundler_cache - run: *bundle_install ... executor化できる 意味のある単位の塊でjob化 command化できる
▶ 現在preview版 ▶ https://github.com/CircleCI-Public/config-preview-sdk ▶ プロジェクトごとにAdvanced SettingsのEnable build processingから有効化 CircleCI
2.1: Orb structure
CrowdWorksにおける Siderの活⽤⽅法
Sider ▶ Siderが有効になっているリポジトリ数: 18 ▶ 基本的に各リポジトリの⾔語の主要Linterを有効にしてい る
有効にしているルール ▶ Ruby ▶ RuboCop ▶ Brakeman ▶ Reek ▶
Querly ▶ JavaScript ▶ ESLint ▶ Other ▶ Misspell
RuboCop ▶ MeowCop + Gryでいい感じにしてからカスタマイズ ▶ MeowCop ▶ https://github.com/sideci/meowcop ▶
スタイル以外のバグやパフォーマンスに関する指摘のみのルールセット ▶ 使い⽅ ▶ Gemfileにrubocopに加えてmeowcopを追加 ▶ mewocop initで.rubocop.ymlを⽣成 or 既存.rubocop.ymlの先頭に inherit_gemの定義を追加 # To use the MeowCop gem. inherit_gem: meowcop: - config/rubocop.yml gem 'rubocop', require: false gem 'meowcop', require: false
RuboCop ▶ Gry ▶ https://github.com/pocke/gry ▶ 現⾏コードからスタイルのルールを⾃動⽣成 ▶ 使い⽅ ▶
gem install gryでインストール ▶ gryコマンドの出⼒を .rubocop.ymlに追記 ▶ gry >> .rubocop.yml #==== Gry Generated ==== # EnforcedStyle: empty => 7 offenses # EnforcedStyle: nil => 31 offenses # EnforcedStyle: both => 38 offenses Style/EmptyElse: EnforcedStyle: empty Enabled: true
Querly ▶ https://github.com/soutaro/querly ▶ ルールで指定したRubyのメソッド呼び出しを警告 ▶ ローカルルールを定義したいときにRuboCopプラグインを がんばって作らなくて済む
Querly - id: jp.crowdworks.oj pattern: - JSON.load - JSON.dump message:
| `Oj` を使ってください。 (`JSON.load` -> `Oj.load` / `JSON.dump` -> `Oj.dump`) Specの場合は `json_spec` を使ってください。 ローカルルール(抜粋) - id: jp.crowdworks.active_record.update_attributes pattern: "update_attributes(...)" message: | `update_attributes` はバリデーションをスキップする `update_attribute` と紛らわしいた め `update` に統⼀しましょう。 `update_attributes` は `update` のエイリアスです。
Querly - id: jp.crowdworks.redirect_to.and.return pattern: "redirect_to(_) [conditional]" message: | `redirect_to()`
に続けて `and return` するのはやめましょう。 `redirect_to` が真で評価される値を返す実装に依存しているためです。 また、⾏が⻑いときに、右端の `and return` を⾒落とす可能性もあります。 ローカルルール(抜粋)
Querly - id: jp.crowdworks.metaprogramming_abuse pattern: - classify - constantize -
eval - instance_values - safe_constantize message: | フレームワーク等ではないアプリケーションコードでメタプログラミングが必要になることはありません。 本当に、本当に、メタプログラミングが必要か、3回考えてから使うのをやめましょう。 ローカルルール(抜粋)
Querly - id: jp.crowdworks.controllers.before_filter pattern: "before_filter(...)" message: | `before_filter` はRails5.1で廃⽌されます。
`before_action` を使ってください。 Deprecatedな機能 - id: jp.crowdworks.active_record.attr_accessible pattern: - "attr_accessible(...)" - "attr_protected(...)" message: | protected_attributes gemはRails5.0で廃⽌されます。 StrongParametersで対応してください。 http://morizyun.github.io/ruby/rails-controller-strong-parameters.html
Goodcheck ▶ Ruby以外でもRubyコード内でもカジュアルに正規表現で チェックしたいときはGoodcheck ▶ 要求されるGemの依存・Rubyバージョンが合わなかったため 導⼊⾒送っていたが… ▶ ルールファイルさえあればSiderがチェック実⾏してくれる ▶
ローカルでの確認はDockerイメージにすれば…! ▶ ⽤意されている…! ▶ https://github.com/sider/goodcheck#docker-image
Misspell ▶ https://github.com/client9/misspell ▶ Go製のスペルチェックツール ▶ かなり⾼速 ▶ おもむろにリポジトリ丸ごとチェックに掛けてみたとこ ろ、明らかなスペルミスしか出てこなかったので、有効に
しておいて損はない
まとめ ▶ Shallow Cloneによるリポジト リのチェックアウト ▶ キャッシュ戦略 ▶ Dockerイメージのビルド⽅法 ▶
Performance Pricing Plan ▶ Workflow ▶ YAMLのアンカー&エイリアス ▶ RuboCop • MeowCop + Gry ▶ Querly • ローカルルール • Deprecatedな機能 ▶ Goodcheck ▶ Misspell
Thanks