継続的ブログ

主にweb系の技術について書いています

CircleCI2.0に移行しました(Rails)

早くなるという噂を聞いたので試しにやってみたら、少しだけ早くなりました。(8min→6min)

.circleci/config.yml

version: 2
jobs:
  build:
    docker:
      - image: ruby
        environment:
          - TZ: "/usr/share/zoneinfo/Asia/Tokyo"
          - LANG: ja_JP.UTF-8
          - LC_ALL: C.UTF-8
          - LANGUAGE: ja_JP.UTF-8
      - image: circleci/mysql
        environment:
          - MYSQL_ROOT_PASSWORD:

    # parallelism: 2
    working_directory: ~/repo
    steps:
      - checkout

      # Restore cache
      - type: cache-restore
        key: phantomjs-2.1.1
      - type: cache-restore
        key: repo-{{ checksum "Gemfile.lock" }}

      - run: apt-get update

      # Install phantomjs
      - run: apt-get install -y fonts-migmix
      - run: |
          which phantomjs && exit
          curl --location --silent https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-2.1.1-linux-x86_64.tar.bz2 | tar xj -C /tmp --strip-components=1
          mv /tmp/bin/phantomjs /usr/local/bin/phantomjs

      # Bundle install dependencies
      - run: bundle install -j 4 --path vendor/bundle

      # Store cache
      - type: cache-save
        key: phantomjs-2.1.1
        paths:
          - /usr/local/bin/phantomjs
      - type: cache-save
        key: repo-{{ checksum "Gemfile.lock" }}
        paths:
          - vendor/bundle

      # DB setup
      - run: bundle exec rake db:create
      - run: bundle exec ridgepole -E test -c config/database.yml --apply -f db/Schemafile --enable-migration-comments

      # Run rspec in parallel
      - type: shell
        command: |
          bundle exec rspec --profile 10 \
                            --format RspecJunitFormatter \
                            --out /tmp/test-results/rspec.xml \
                            --format progress \
                            $(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings)

      - run: bundle exec rubocop -D -R -c .rubocop.yml

      - type: store_artifacts
        path: tmp/capybara/
        destination: capybara

      # Save artifacts
      - type: store_test_results
        path: /tmp/test-results

基本的には公式のものを参考に作りましたが、気をつけた点を少し紹介させていただきます。

Language Guide: Ruby - CircleCIcircleci.com

rubyはcircleci/rubyを使わず、docker公式のものを採用

https://hub.docker.com/r/circleci/ruby/

CircleCIが用意してくれているDockerイメージがあって、gitsshやDockerツールが最初からインストールされていてと便利なのですが、phantomjsインストールして使用する際に少し面倒だったので、公式のものを使うようにしました。

mysqlの方はcircleci/mysqlを使っています。

https://hub.docker.com/r/circleci/mysql/

phantomjsのインストール

個人 Rails アプリを CircleCI 2.0 で動くようにした - アジャイルSEの憂鬱sinsoku.hatenablog.com

こちらのブログを参考にさせていただきました。
ありがとうございました。

ArgumentError: invalid byte sequence in US-ASCIIが出る対策

ArgumentError: invalid byte sequence in US-ASCII on v2.2.0 in Docker · Issue #277 · ffaker/ffaker · GitHubgithub.com

上記URLを参考に下記設定をしています。

environment:
  - LANG: ja_JP.UTF-8
  - LC_ALL: C.UTF-8
  - LANGUAGE: ja_JP.UTF-8

featureスペックエラー時に保存しているスクリーンショットを見れるように

- type: store_artifacts
  path: tmp/capybara/
  destination: capybara

tmp/capybaraに保存したスクリーンショットをCircleCIのArtifactsから見れるようにしています。

f:id:akiza:20170702115849p:plain

まとめ

CIが少しでも早くなることは嬉しいですね。
まだβ版ですが使って見る価値はあるのではないでしょうか。

クローラー(スクレイピング)をRspecでテスト

今回初めて、個人用にクローラーを開発してみました。
JavaScript多めのサイトのため、「Capybara + Poltergeist」を使用しました。

順調に開発は進んだのですが、テストってどう書けばいいんだろうと思い、知り合いに相談したところ、下記方針に決まりました。

  • feature_specとして書く
  • 毎回アクセスするのはよろしくないので、用意したHTMLファイルを解析する

やり方

CapybaraのHTTPリクエストをstub化する

毎回アクセスしないように、CapybaraのHTTPリクエストをstub化し、用意したローカルのHTMLファイルを返却するようにします。

HTTPリクエストをスタブ化するGemとして「webmock」は有名だと思います。

github.com

しかし、これはCapybaraでは使えません。
代わりに「puffing-billy」を使います。

github.com

Gemをインストールして、設定を追加します。
README通りだと、jsのエラーが無視されずRspecが失敗してしまうため、私は以下のように設定しました。

Capybara.register_driver :pg_billy do |app|
  options = {
    js_errors: false,
    phantomjs_options: [
      '--ignore-ssl-errors=yes',
      "--proxy=#{Billy.proxy.host}:#{Billy.proxy.port}"
    ]
  }
  Capybara::Poltergeist::Driver.new(app, options)
end
Capybara.configure do |config|
  config.default_driver = :pg_billy
  config.javascript_driver = :pg_billy
end

テストを書いてみる

テストコードはこんな感じです。

require 'rails_helper'

feature 'Login' do
  background do
    Billy.config.record_stub_requests = true
  end

  given(:url) { "http://www.example.com" }
  
  scenario 'login' do
    proxy.stub(url).and_return(body: File.read("spec/features/htmls/login.html"))
    visit url

    within("#form") do
      fill_in 'id', with: 'id'
      fill_in 'password', with: 'password'
    end

    stub = proxy.stub(url, method: 'post').and_return(
      headers: { 'Access-Control-Allow-Origin' => '*' },
      code: 200,
      text: "Success"
    )
    click_button('ログイン')

    request_params = stub.requests.shift[:body].split("&")
    expect(page).to have_content("Success")
    expect(request_params).to include("id=id", "password=password")
  end
end

ポイント1

Billy.config.record_stub_requests = true

フィールドに値が入って、ちゃんとPostされているかチェックするため、リクエスト情報を記録するようにしています。

ポイント2

proxy.stub(url).and_return(body: File.read("spec/features/htmls/login.html"))

指定のURLにアクセスした際に、用意したHTMLをbodyに入れて返すようにしています。

ポイント3

stub = proxy.stub(url, method: 'post').and_return(
      headers: { 'Access-Control-Allow-Origin' => '*' },
      code: 200,
      text: "Success"
    )

ログイン処理をstub化しています。

最後に、フィールドに値がちゃんと入っていること、ログインボタンが押されたことをチェックして、テストは完了です。

なかなか情報もなく、いろいろ悩んだ末、今回このようにテストしてみました。
「うちはこうやってるよ」とかアドバイスいただけるとありがたいです!

参考

Rubyでやるならこの本はオススメです!

Rubyによるクローラー開発技法 巡回・解析機能の実装と21の運用例

Rubyによるクローラー開発技法 巡回・解析機能の実装と21の運用例

メール受信 → 解析(Postfix + Rails)

Railsアプリと連携して下記のことをしたい。

  1. メール受信でRailsアプリ内プログラム実行
  2. メールの中身を確認

今回はMacのローカル環境で検証します。

環境

手順

まずはメール受信できるように

1. Postfixの起動(元々入っている)

$ sudo postfix start

2.メール送信

$ mail <Macユーザー名>

件名入力 → 本文入力 → 最後にEnterで改行して、'.'を入力してEnter

3.メール確認

$ mail

メールを受信することができました!

メール受信→プログラム実行してみる

1.プログラム作成

  • mailin
$ vim /Users/fakiyer/rails_project/script/mailin
#! /usr/bin/env bash
cd /Users/fakiyer/rails_project
/Users/fakiyer/.rbenv/shims/rails runner -e development ‘Mailer.receive(STDIN.read)'
$ chmod 777 /Users/fakiyer/rails_project/script/mailin
  • Mailer
def self.receive(mail)
  email = Mail.new(mail)
  body = email.body.decoded
  charset = email.charset
  body = body.force_encoding(charset).encode('utf-8')

  logger.info body
end

2.Postfixのaliases設定

$ sudo vim /etc/aliases
...
  <Macユーザー名>
  fakiyer: "| /Users/fakiyer/rails_project/script/mailin”
$ sudo newaliases

3.Postfix実行ユーザー変更

  • main.cf
#default_privs = nobody
default_privs = fakiyer
$ sudo postfix start

4.メール送信

$ mail <Macユーザー名>

railsログにbodyの内容が出力されているはずです!

参考

New RelicでDockerコンテナ監視 - Elastic Beanstalk

現在Elastic BeanstalkのMulti-Container Docker環境を使っています。

New Relicを使ってコンテナを監視するようにしたので設定をメモ。
公式のドキュメントがだいぶ丁寧なので、ほとんどその通りなのですが。。。

設定ファイルを追加するだけ

  • .ebextensions/newrelic.config
packages:
  yum:
    newrelic-sysmond: []
  rpm:
    newrelic: http://yum.newrelic.com/pub/newrelic/el5/x86_64/newrelic-repo-5-3.noarch.rpm
commands:
  "01":
    command: usermod -a -G docker newrelic
  "02":
    command: nrsysmond-config --set license_key=YourNewRelicLicense 
  "03":
    command: echo hostname=NameOfYourServer >> /etc/newrelic/nrsysmond.cfg
  "04":
    command: /etc/init.d/newrelic-sysmond start

あとは.ebextensionsとDockerrun.aws.jsonをzipにしてdeployするだけです!

参考

DockerでWhenever(gem)が動かなくてハマった話

久々の更新です。
最低でも月1で書きたいなあと思ってたのですが、2ヶ月以上も空いてしまいました。
最近はRailsはもちろんのこと、React NativeやDockerもバリバリ使ってます!

さて、標題の件ですが、いやー、かなりハマりました。

現在、開発環境にDocker(Docker Compose)を使って、Railsアプリを開発しています。
そして、crontab管理にwheneverというgemを使っています。

コンテナでcronを動かしたいなと思ったのですが、なかなかうまくいかない。。。
cronをインストールして、起動して、wheneverのコマンドでcrontabの設定も完了したのですが、実行時間になるとwheneverのログにエラーが。

Could not find rake-10.5.0 in any of the sources (Bundler::GemNotFound)

crontabに設定されているコマンドをdocker-compose run等で実行すると正常に実行される。

いろいろ調べて下記サイトに辿り付きました。

support.aptible.com

qiita.com

環境変数を渡してあげなきゃいけないみたいです。

一番目のリンクの通り、config/schedule.rbにENV.each { |k, v| env(k, v) }を追記したらうまくいきました。

ghq + peco!じゃなくて fzf連携

対象

ghq + fzf

よく ghq + peco でやってる記事が挙がってますが、それのfzf 版です。
ghq で管理しているリポジトリのパスをインクリメンタルサーチして、選択すると、cdするスクリプトです。

frepo() {
  local dir
  dir=$(ghq list > /dev/null | fzf-tmux --reverse +m) &&
    cd $(ghq root)/$dir
}

f:id:akiza:20160129142308g:plain

私も最近 fzf 使い始めたばかりなので、fzf 使いの方、良い情報あったら教えてください!

最後に

おい、peco もいいけど fzf 使えよ - Qiita

この記事を見てから、fzfを使うようになりました。
素晴らしい記事をありがとうございました!