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
880
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
400
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
Amazon Neptuneで始めてみるグラフDB-OpenSearchによるグラフの全文検索-
satoshi256kbyte
4
330
CSC305 Lecture 13
javiergs
PRO
0
130
Server Driven Compose With Firebase
skydoves
0
400
【Kaigi on Rails 2024】YOUTRUST スポンサーLT
krpk1900
1
250
VR HMDとしてのVision Pro+ゲーム開発について
yasei_no_otoko
0
100
Jakarta Concurrencyによる並行処理プログラミングの始め方 (JJUG CCC 2024 Fall)
tnagao7
1
230
Vaporモードを大規模サービスに最速導入して学びを共有する
kazukishimamoto
4
4.3k
Modern Angular: Renovation for Your Applications
manfredsteyer
PRO
0
210
Nuxtベースの「WXT」でChrome拡張を作成する | Vue Fes 2024 ランチセッション
moshi1121
1
510
EventSourcingの理想と現実
wenas
6
2.1k
[PyCon Korea 2024 Keynote] 커뮤니티와 파이썬, 그리고 우리
beomi
0
110
Googleのテストサイズを活用したテスト環境の構築
toms74209200
0
270
Featured
See All Featured
Build your cross-platform service in a week with App Engine
jlugia
229
18k
Making the Leap to Tech Lead
cromwellryan
132
8.9k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
27
4.2k
A better future with KSS
kneath
238
17k
Being A Developer After 40
akosma
86
590k
Practical Orchestrator
shlominoach
186
10k
4 Signs Your Business is Dying
shpigford
180
21k
Documentation Writing (for coders)
carmenintech
65
4.4k
How To Stay Up To Date on Web Technology
chriscoyier
788
250k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
25
1.8k
Building Adaptive Systems
keathley
38
2.2k
The Straight Up "How To Draw Better" Workshop
denniskardys
232
140k
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