patorashのブログ

方向性はまだない

WSL + Docker for WindowsでRailsアプリを動かしたが遅すぎた

これはノウハウとかじゃなくてただの日記。

この前久々にLenovoのPCを触れたので、Docker for Windowsの設定をして、WSLでdocker-compose upできて喜んでいたが、Railsアプリを起動するところまで時間が取れなかった。昨日ようやく少し時間が取れたのでやってみたところ、動いた。WSLでbin/rails sしてから普通にhttp://localhost:3000にアクセスして画面を表示することもできた。

できたが、めちゃくちゃ遅かった。画面遷移するのに10秒以上かかっていたんじゃないかと思う。初回のアクセスはJSとCSSのトランスパイルが実行されるからもっと遅かった。1分半くらいかかっていたように思う。さすがに開発に使うには厳しい。

WSLの起動自体はめっちゃ速いし、普通に使う分には問題ないのだけれど、どうしたもんかなぁ…という気持ち。vagrantUbuntuを入れてそこに開発環境をセットアップしたほうがいいのかな?いい方法をご存知の方がいれば教えてください。

ルーターをIPv6対応のものに交換した

我が家ではルータにTimeCupsuleを使っていたのだが、これがフレッツのIPv6に対応していないせいで、NTT西日本のClub NTT-WESTのポイント交換がうまくいかないというここ数年の悩みがあった。

話はさかのぼること数年前。

Club NTT WESTはフレッツを使っていたらポイントが貯まっていって、結構豪華なものと交換できたりする。長年使っていると、ボーナスポイントがもらえたりもする。私はいつも、このポイントをiTunes Cardに交換して、App Storeでアプリを買う時の足しにしていた。ところがある日、ポイント交換しようとしたら、ご契約の回線からのアクセスかをIPv6で認証する、ということをやり始めたのである(ただし、ポイントカード類のみ)。これで急にiTunes Cardがもらえなくなってしまい、途方に暮れていた。

そして時は今月。

気づけば、「2019年4月にポイントが失効しますよ!」という通知が来ていた。いや使いたいのに使わせないのそっちやろ!と思いつつも、失効するくらいならなんか違うものに交換するかぁ〜と思い、物色していたら、さすがNTTのポイント交換サービスだけあって、ネットワーク機器まであった。

f:id:patorash:20190321024846p:plain
ポイントで交換できるルーター

ルーターに交換できるのならば、TimeCupsuleに代わってこれにしてしまえば、またiTunes Cardとかに交換できる!と思い、今回はI-O DATAのWN-AX1167GR2と交換した。

www.iodata.jp

そして待つこと10日くらいで届いた。

早速、交換にとりかかる。その前に、速度を計測。

設定はまぁまぁ簡単だった。のだけれど、うちのプロバイダはASAHIネットなので、事前にIPv6の利用申請が必要。まぁこれはTimeCuspuleでIPv6を試す時にすでに行なっていたので問題なかった。 ただ、後でわかったのだけれど、ルーターIPv6動作確認済みプロバイダ一覧にASAHIネットがなかった…。

www.iodata.jp

IPv6設定を行うために、詳細ガイドを見ながら作業をした。

www.iodata.jp

しかし、

① [ステータス]メニューの[インターネット設定]で[接続方法]を確認する ② [v6プラス,IPv6オプションなど]または[transix]になっていれば接続完了です

と書いてあるにも関わらず、我が家はなぜかPPPoEになってしまう。手動でv6プラスやtransixにしてみたが、インターネット接続が切れるだけ…。

何度かやっていると、気づいたらPPPoEだけれど、IPv6パススルーが有効になっていた。この状態でIPv6になっているか確認する用のページにアクセスしたら、うまくいっていた!

v6.asahi-net.jp

本当にこれでいいのか、Club NTT WESTでポイント交換できるか確認したところ、成功!ようやくIPv6環境が手に入った!

そして、再び速度チェック。

150Mbpsから250Mbpsなので、まずまず速くなったと思う。さて、あとはTimeCupsuleをこれからどうしていくか、というところ。TimeMachineを使っているので、これからも活かしていきたい。

CircleCIにreviewdogを飼うことにした。

Rubocopを一応入れているのに、滅多に動かしてなくてあんまり意味を成していなかった。issueにずっとあったCIにRubocopを取り入れるというやつに着手しようと思ってようやく取り組み始めた。

reviewdogを知る

CircleCIのワークフローにRubocopのチェックを入れて、自動的にコメントをしてもらいたいなぁと思って調べていたら、reviewdogを知った。

blog.toshimaru.net

自分がやりたかったことはまさにこれだったので、これを参考にすることに。

reviewdogのインストールは本家を参考にした。

github.com

バイナリで配布もされているが、goenvでgoを入れているので、go getを使って入れた。

$ go get -u github.com/haya14busa/reviewdog/cmd/reviewdog

reviewdogが実行できない場合はパスが通ってないってことなので、パスを通しましょう。

その前にrubocopのルールを決めたい

Rubocopのルールをよく把握してなかったので、チームで以前に作ったルールを実行してみたら、かなりの量で怒られたので、たぶんプロジェクトにルールがまだ合ってないなと思ったので、一から作り直そうと思った。

とはいえ、ルールの数も途方もないだろうし、有名な指針があればいいかなと思って調べ始めたら、onkさんのRubocopの記事を見つけた。

blog.onk.ninja

スモールスタートする

スモールスタートの仕方が書いてあったので、まずはそれを検証することに。

  1. 現在の.rubocop.ymlを.rubocop.old.ymlに変更
  2. bundle exec rubocop --auto-gen-configを実行して.rubocop.ymlと.rubocop_todo.ymlを生成する
  3. bundle exec rubocop --parallelを実行して指摘がないことを確認する
  4. 一旦コミットする
  5. ローカルでreviewdogを実行してみる
  6. CircleCIでreviewdogを実行してみる

という方針を立てた。

reviewdogが動かない(俺の勘違い)

とりあえず、rubocop.old.ymlで怒られていたルールを実行してみると、たくさん指摘された。

それをreviewdogに食わせてみることに。

$ bundle exec rubocop --parallel --only Layout/SpaceAroundEqualsInParameterDefault | reviewdog -f=rubocop -diff="git diff"

何も表示されない!

しかしこれは当然の話で、reviewdogは変更のあった行でrubocopの指摘がある場合のみ通知してくる。まだコード自体は一切変えていなかったからだ。そこで、敢えてコードをルールに違反するコードに変えたところ、ちゃんと指摘された。

CircleCIでreviewdogを動かす

reviewdogを実行するワークフローを定義する

上のほうで参考にしたサイトの通りにすれば動くので、特に書くことはない…んだけど、一応書く。ちなみにcircle.ymlのフォーマットはCircleCI 2.1なのであしからず。

executorsのrubyのdocker imageの環境変数に、reviewdogのバージョンを指定する。

executors:
  default:
    docker:
      - image: patorash/circle_ci_ruby:2.5.3-node-browsers-pg11
      environment:
        RAILS_ENV: test
        REVIEWDOG_VERSION: 0.9.11 # ここ

次に、reviewdogを実行するcommandsを定義する。

commands:
  # 他のコマンドは略
  run_reviewdog:
    steps:
      - run:
          name: Install reviewdog
          command: |
            curl -fSL https://github.com/haya14busa/reviewdog/releases/download/$REVIEWDOG_VERSION/reviewdog_linux_amd64 -o reviewdog
            chmod +x ./reviewdog
      - run: bundle exec rubocop | ./reviewdog -f=rubocop -reporter=github-pr-review

次に、workflowを定義。テストが実行される前にrobocopで検査して、問題があればそこで止めるようにする。まだジョブの定義はしていないが、とりあえずワークフローを先に書く。

workflows:
  build:
    jobs:
      - prepare_test
      - reviewdog:
          requires:
            - prepare_test
      - retry_failed_test:
          requires:
            - reviewdog
      - test:
          requires:
            - retry_failed_test

しかしこれだとreviewdogが通らないとテストすら実行されないので、緊急時とかにうざいかもしれない…。そのときは、retry_failed_testのrequiresをprepare_testに変えてしまうほうがいいかも…とこの記事を書きながら思った。

さて、reviewdogジョブを定義する。もうcommandsを定義しているので、それを呼び出すだけである。一応prepare_testも載せておくが、やってることはcommand名から想像してほしい。

jobs:
  prepare_test:
    parallelism: 1
    executor: default
    steps:
      - checkout
      - restore_node_module_cache
      - restore_bootsnap_cache
      - ruby-orbs/bundle-install
      - yarn_install
      - save_node_module_cache
      - save_code_cache

  reviewdog:
    parallelism: 1
    executor: default
    steps:
      - restore_code_cache
      - run: bundle --path vendor/bundle
      - run_reviewdog
  # 他のジョブは略

これでcircle.ymlは完成。

環境変数を設定する

あとはgithubでreviewdogでコメントさせるユーザーのトークンを環境変数REVIEWDOG_GITHUB_API_TOKENに定義しなくてはならない。

githubのアクセストークンの取得ページに行く。

この時、もし自分のアカウントで取得すると、reviewdogのコメントをしてくるのが自分のアカウントになる。別に問題ない人はそれでいいが、個人アカウントで機械的にであっても個人のアイコンがある状態でコメントされると、なんか殺伐としそう…。なので、bot用の別アカウントを作るなりして、そいつにコメントしてもらうほうがいいと思う。onkさんの記事でも、カーチャンに指摘してもらうみたいに書いてた。

話を元に戻すが、repoにチェックを入れてアクセストークンを発行する。

f:id:patorash:20190312004123p:plain
githubのアクセストークンを発行する。repoにチェックを入れる。

発行したアクセストークンは、CircleCIのプロジェクト毎の環境変数に保存しておく。

f:id:patorash:20190312004858p:plain
CircleCIの設定画面から環境変数を設定する

これで完了。

あとは、先ほど設定したcircle.ymlを含むbranchをpushして、PRにしてreviewdogがコメントするのを確認すればよし。ちゃんとCIのワークフローがそこで止まることも確認する。

f:id:patorash:20190312005703p:plain
reviewdogによってworkflowが停止していることを確認

そして、指摘された点を修正し直して、ワークフローが全部通ることを確認する。

f:id:patorash:20190312010004p:plain
reviewdogの指摘を修正してワークフローが通ることを確認

オーケー、完成だ。

今後の方針

CircleCIのworkflowにreviewdogを入れられたのは一歩前進。とはいえ、rubocopはスモールスタートの設定をしただけなので、ルールを決めていく必要がある。onkさんが公開しているonkcopが参考になりそうなので、それを読みながら一部を自分のルールで上書きしていこうと思う。

github.com

Amazon Linux 1でImageMagick6系の最新版を入れる

gem rmagick 3.0.0を入れようとしたら、bundle installのときにImageMagickのバージョンが古いという理由で落ちました。というわけで、ImageMagickのアップデートやります!

qiita.com

ここに書かれてることをやれば概ね大丈夫かと思いますが、最初CentOS6系のリポジトリを入れる理由がよくわからなかったので、そこを無視して色々試していたのですが、依存性解決が全然うまくいかず…。

さらにググり続けることに。今度は依存性解決できなかったsoファイル名とかで以下の記事がヒット。

qiita.com

あ〜、soファイルがあるのがCentOS6系のリポジトリなのか…と理解し、ようやく追加。

$ sudo touch /etc/yum.repos.d/CentOS-Base.repo
$ sudo vi  /etc/yum.repos.d/CentOS-Base.repo
[base]
name=CentOS-6 - Base
mirrorlist=http://mirrorlist.centos.org/?release=6&arch=x86_64&repo=os
gpgcheck=1
enabled=0
gpgkey=http://mirror.centos.org/centos/RPM-GPG-KEY-CentOS-6

古いImageMagickを削除し、新しいImageMagickをインストールしました。

$ sudo yum remove ImageMagick ImageMagick-libs ImageMagick-devel
$ sudo yum install ImageMagick6 ImageMagick6-libs ImageMagick6-devel --enablerepo=remi,epel,base

その後、bundle installでrmagick 3.0.0のインストールが成功しました。

Amazon Linux 1にPostgreSQL 11をインストールする

まず、PostgreSQLyumリポジトリを追加します。 参照先は以下。

yum.postgresql.org

Amazon Linux 1はRedHat Enterprise Linux6互換(?)のため、そのURLをコピーして追加します。そのあと、/etc/yum.repos.d/pgdg-11-redhat.repoに記載されているURLをsedで置換します。

$ sudo yum install https://download.postgresql.org/pub/repos/yum/11/redhat/rhel-6-x86_64/pgdg-redhat11-11-2.noarch.rpm
$ sudo sed -i "s/rhel-\$releasever-\$basearch/rhel-6.10-x86_64/g" "/etc/yum.repos.d/pgdg-11-redhat.repo"

あとは、インストールするだけ。クライアントだけ欲しかったのでpostgresql11, postgresql11-develのみを指定しています。

$ sudo yum install -y postgresql11 postgresql11-devel

psqlのバージョンを確認して終わり。

$ psql --version
psql (PostgreSQL) 11.2

2019-03-08 追記

gem pgのインストールでこけた…。pg_configが見つからないと言われた。

Gem::Ext::BuildError: ERROR: Failed to build gem native extension.

    current directory: /home/heroku/.rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/pg-1.1.4/ext
/home/heroku/.rbenv/versions/2.5.3/bin/ruby -r ./siteconf20190307-22703-1t1ti1k.rb extconf.rb
checking for pg_config... no
No pg_config... trying anyway. If building fails, please try again with
 --with-pg-config=/path/to/pg_config
checking for libpq-fe.h... no
Can't find the 'libpq-fe.h header
*** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of necessary
libraries and/or headers.  Check the mkmf.log file for more details.  You may
# .bash_profile
need configuration options.

/usr/pgsql-11/binにPATHを通せばいいことがわかった。

bitarts.jp

.bash_profileを編集する。

PATH=$PATH:/usr/pgsql-11/bin
export PATH

source ~/.bash_profileしてから、bundle installしたら成功した。

database.ymlのschema_search_pathにpublicを書いたらあかん

PostgreSQL 11にアップデートしようとしていたときに起きました。

docker imageを11に変更して、CircleCIでテストを流そうとしたところ、bin/rake db:structure:loadで失敗しました。

psql:/home/circleci/workspace/db/structure.sql:15: ERROR:  schema "public" already exists

該当行はCREATE SCHEMA public;をやろうとしていたのですが、publicは最初から存在するので、そりゃエラーになるわな…と。

今まで出てなかったのに、なんでだろう?と思いつつ、Railsのコードを追ってみました。

rails/postgresql_database_tasks.rb at b366be3b5b28f01c8a55d67a5161ec36f53d555c · rails/rails · GitHub

search_pathに値があれば、--schema=値を設定するようだったので、database.ymlを確認したら、schema_search_path: publicと書いていました…。もういつ書いたのかほとんど覚えてないけれど。これをコメントアウトしてからrake db:migrateを行い、db/sctructure.sqlを再生成したところ、CREATE SCHEMA public;の表記がなくなりました。

schema_search_pathにはpublic以外のスキーマを作った時に、それらを指定したほうがよさそうです。

CircleCI ユーザーコミュニティミートアップにリモート参加した

3/5にあったCircleCIのミートアップにリモートで参加させてもらいました。

イベントのConnpassはこちら。

circleci.connpass.com

ちょうどCircleCIをPerformancePlanに移行したりしていたので、CircleCI Japanの方からZoomで参加しませんか?とtwitterのDMで連絡を頂きました。

patorash.hatenablog.com

せっかくの機会なので、参加させていただくことに。

この時に、社外の方も参加募集したのですが、悲しいことに集まらなかったので、社内のメンバー4人で参加しました。

皆同じような課題を抱えていた

弊社でもJenkinsでの並列テストを経た後にCircleCIの導入をしているので(1.0の頃から)、「あ〜、わかるわ〜」という感じでした。

うちのテスト事情の遷移

CI環境はCircleCIになるまではほぼ関与してないので、記憶で書く(間違ってるかも)

  1. ローカル環境でrspecをparallel_testsで実行する。テストが肥大化して30分くらいかかるようになって辛くなる。
  2. Jenkinsを導入。会社で空いていたMacでテストを実行するように。テストが肥大化して1時間くらいかかるようになる。
  3. Jenkinsで並列処理をするように。そのため、Mac miniを複数台購入した。テスト実行されると同時にbundle installが実行され、ネットワークが遅くなる等、問題が出始める。Mac miniの構成管理はChefとかでやってたはず。20〜40分くらいかかっていたかと思う。
  4. 並列数に限界を感じ、AWSで都度EC2を立ち上げてテストするように。スポットインスタンスが安いリージョンを探し求めていた。
  5. いろんなCIサービスを検討し始める。CircleCIのbundle installの速さがすごい!みたいなことで盛り上がっていた記憶がある。
  6. CircleCIへ移行!
  7. CircleCI 2.0に移行!(多分このあたりから自分がやった)
  8. CircleCIでparallel_testsを使う!
  9. CircleCI + parallel_tests + knapsack proで爆速化!
  10. CircleCIをPerformancePlanに移行!

高速化には色々と取り組みました。

patorash.hatenablog.com

patorash.hatenablog.com

課題を解決した後に入社した若者たち

今回の参加者は私以外は入社2年以内の若者が3名だったのだけれど、上記のような歴史を知らないので、

若者たち「Jenkinsってなに???🤔」

ってなっていたので、発表は聞きつつもCI導入の歴史を説明したりしました。まぁいい機会だったのかもしれないですねぇ。

リモート参加してみて…

現地はピザや飲み物があったりしたみたいで羨ましかったですが、実はこちらもピザを食べてました!

発表後のネットワーキングの時間とかはリモートだと参加できないので、やっはり現地がいいなぁと。まぁ岡山だとなかなか厳しいんですが。機会があったら現地参加したいと思います!