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
1k
1
Share
How to use CircleCI and Sider in CrowdWorks
CircleCI/Sider合同ミートアップ@プレイド 新GINZA SIXオフィス
https://connpass.com/event/98494/
Hideki Igarashi
September 13, 2018
More Decks by Hideki Igarashi
See All by Hideki Igarashi
AWSマルチアカウント管理 / ODC2021 Online
hideki
0
4.3k
な…何を言っているのかわからねーと思うが、コードを書いていたと思ったらレビューが終わっていた / Code Review Meetup 3
hideki
1
310
CrowdWorks Engineering Culture
hideki
0
430
CrowdWorksのChatOpsの歴史 / ChatOps History of CrowdWorks
hideki
1
1.1k
Bring out the ability of CircleCI 2.0
hideki
1
710
Grails with Spock
hideki
0
1.4k
JavaOne Report for G* 2012 San Francisco
hideki
2
1.3k
Other Decks in Programming
See All in Programming
Strategy for Finding a Problem for OSS: With Real Examples
kibitan
0
130
「効かない!」依存性注入(DI)を活用したAPI Platformのエラーハンドリング奮闘記
mkmk884
0
300
メッセージングを利用して時間的結合を分離しよう #phperkaigi
kajitack
3
550
Geminiをパートナーに神社DXシステムを個人開発した話(いなめぐDX 開発振り返り)
fujiba
0
130
PHPのバージョンアップ時にも役立ったAST(2026年版)
matsuo_atsushi
0
280
仕様漏れ実装漏れをなくすトレーサビリティAI基盤のご紹介
orgachem
PRO
8
4.4k
VueエンジニアがReactを触って感じた_設計の違い
koukimiura
0
150
最初からAWS CDKで技術検証してもいいんじゃない?
akihisaikeda
4
180
Going Multiplatform with Your Android App (Android Makers 2026)
zsmb
1
270
それはエンジニアリングの糧である:AI開発のためにAIのOSSを開発する現場より / It serves as fuel for engineering: insights from the field of developing open-source AI for AI development.
nrslib
1
820
PHP でエミュレータを自作して Ubuntu を動かそう
m3m0r7
PRO
2
170
PHPで TLSのプロトコルを実装してみるをもう一度しゃべりたい
higaki_program
0
170
Featured
See All Featured
The Art of Programming - Codeland 2020
erikaheidi
57
14k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
12
1.6k
Public Speaking Without Barfing On Your Shoes - THAT 2023
reverentgeek
1
350
JAMstack: Web Apps at Ludicrous Speed - All Things Open 2022
reverentgeek
1
410
GraphQLとの向き合い方2022年版
quramy
50
14k
The B2B funnel & how to create a winning content strategy
katarinadahlin
PRO
1
320
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
25
1.8k
Intergalactic Javascript Robots from Outer Space
tanoku
273
27k
BBQ
matthewcrist
89
10k
Done Done
chrislema
186
16k
Evolving SEO for Evolving Search Engines
ryanjones
0
170
Future Trends and Review - Lecture 12 - Web Technologies (1019888BNR)
signer
PRO
0
3.4k
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