くりにっき

フルスタックキュアエンジニアです

Packer with mitamaeこぼれ話 #技術書典

Packer with mitamae のおまけというか付録みたいなやつ

sue445.hatenablog.com

副産物

sue445/vagrant-aws

vagrantvagrant-awsvagrant-serverspecがインストールされてるDockerイメージです

https://hub.docker.com/r/sue445/vagrant-aws/

github.com

CircleCI上でVagrantvagrant-awsを使おうとするとvagrant-awsのインストールにそこそこ時間がかかって*1つらかったので、Dockerイメージを自分で作りました。

https://github.com/sue445/dockerfile-vagrant-aws/blob/master/.circleci/config.yml を見てもらえれば分かると思いますが、Vagrantの最新版が出ると自動でDockerfileを更新してtag push&Dockerイメージの自動アップデートをするようにしています。

特定のミドルウェアのDockerイメージを自動更新したい場合に参考になるかと思います。

この辺の最新のバージョンを取得する部分だけ変えてやれば他のDockerfileリポジトリでも流用できるはず。*2

https://github.com/sue445/dockerfile-vagrant-aws/blob/1c73ea65415a649635d36d727519f8441445676e/.circleci/config.yml#L63-L66

packer-provisioner-serverspec

packerでserverspecを使うためのprovisionerです

github.com

https://github.com/unifio/packer-provisioner-serverspec をforkしてるだけなんですが、本家でバイナリを提供してなくて不便だったので自分でビルドしたバイナリをReleasesに置いています。

https://github.com/sue445/packer-provisioner-serverspec/releases

fork元とfork先でコードレベルでの差分はありません。

執筆中に気づいたのですが、Packerはgolang製のバイナリで実行環境に依存しないのがウリなのに、packer-provisioner-serverspecはserverspecを実行するために実行元にRubyがインストールされている必要があるのがイケてないんですよね。。。

provisioner内でDockerのコンテナを起動してその中でserverspecを実行すればまだマシになるとは思ってるのでそのうちなんとかしたいという思いはあります。(思いだけ)

Packer以外の事例だと https://www.npmjs.com/package/serverless-python-requirementsdockerizePip がDockerコンテナ内で pip install しているので同じようなことをやればいいはず。

書名がPacker with mitamaeなのにどうしてリポジトリ名がtechbookfest5-itamaeなのか?

github.com

最初はmitamaeじゃなくてItamaeでやろうとしてたのですが、やりたいこと的にmitamaeの方が筋が良さそうということに気づいて方向転換しています。

途中で方向転換したのがこのコミットです。

https://github.com/sue445/techbookfest5-itamae/commit/5307461804342b1e0af2fac7151da7aa95e06506

途中でリポジトリ名を変えるという手もあったのですが、リポジトリ名を変えた時にCircleCIの挙動がどうなる(再設定すれば勝手に同期してくれるのか、作り直しになるのか)か自信がなかったのでそのままにしてます。

書こうと思ってやめたこと

最初にサンプルプロジェクト( https://github.com/sue445/techbookfest5-itamae )を一通り作ってから執筆したのですが、サンプルプロジェクトにあって紙面にない要素があります

rubocop-itamae

github.com

せっかく自分が作ったものだし一応rubocopの静的チェックを入れてはいるのですが、実際に執筆しようとするとPackerでmitamaeを使うという本質から外れてしまうのでオミットしました。

執筆期間

  • サンプルプロジェクト作成:2週間
  • 執筆:4週間
  • レビュー:1ヶ月間

執筆自体は9月頭に終わっていて、技術書典までの残り1ヶ月間をレビューや当日の準備などにあてています

執筆用のリポジトリのコミット頻度はこんな感じです。

f:id:sue445:20181014170513p:plain

被チェック数

f:id:sue445:20181014170855p:plain

マイページの被チェック数を定期的に取得してスプレッドシートに送りつけてグラフ化してたのですが、技術書典の開催中も被チェック数が増えていて面白かったです。

f:id:sue445:20181014170915p:plain

*1:10分くらい

*2: 実際このリポジトリの設定も https://github.com/sue445/dockerfile-heroku-cli/blob/master/.circleci/config.yml をほぼ流用しています

syobocaliteを作った

しょぼいカレンダー のLite(軽量)版APIクライアントを作りました

github.com

モチベーション

元々は https://github.com/sue445/cure-mastodon-botshttps://github.com/xmisao/syobocal を使っていたのですが、以下のような難点がありました

  • 番組の時間をTime.parse でpaeseしてるので *1、HerokuのようにJST以外の環境で動かすと時間がずれる
  • レスポンスが HashArray なので、レスポンスを利用側で拡張したい時にオープンクラスしてモンキーパッチをあてづらい

1年くらいはアプリ側でモンキーパッチをあてて使っていたのですが *2、別のボットを作る時にcure-mastodon-botsと同じことをやるのが嫌だったのでgem化しました

使い方

Ruby本体の TimeactivesupportActiveSupport::TimeWithZone に対応してます。

require "syobocalite"
require "time"

start_at = Time.parse("2018-10-07 08:30:00")
end_at   = Time.parse("2018-10-07 09:00:00")

# or

Time.zone = "Tokyo"
start_at = Time.zone.parse("2018-10-07 08:30:00")
end_at   = Time.zone.parse("2018-10-07 09:00:00")

# Get programs that start between 8:30 and 9:00
Syobocalite.search(start_at: start_at, end_at: end_at)

http://cal.syoboi.jp/cal_chk.php は日付単位でしか取得できないですが、自分の用途だと時間で絞りたいことが多いので時間を引数に渡せるようにしています。*3

*1:https://github.com/xmisao/syobocal/blob/v0.9.1/lib/syobocal/calchk.rb#L27-L28

*2: https://github.com/sue445/cure-mastodon-bots/blob/cd4940a07e2bd38d2671838e44fe6eac9cf799f7/lib/syobocal_ext.rb

*3: https://sites.google.com/site/syobocal/spec/db-php だと時間単位で取得できるのは知ってるのだけど、そっちは番組名とサブタイトルが同時に取得できないので不便

Itamaeのコミッタになった

いきさつ

blog.unasuke.com

Itamae のCIってここ2年くらいずっと落ちたままになっていて、RubyKaigi2018で仙台にいる時にCIを直しました。

github.com

ずっと放置されつつも id:yu_suke1994id:ryotarai を突っついてくれてPRをマージしてもらい、Itamae *1のコミット権をもらいました

コミッタになってやったこと

Admin権限をもらったのでTravisCIの設定をして、約2年ぶりにmasterブランチのビルドをグリーンに戻しました

f:id:sue445:20181011002905p:plain

ちなみにPRを送りまくってたらいつの間にかコミッタになってたやつはこれで4つ目になります

コミット権をもらったリポジトリ一覧

github.com

github.com

github.com

ポエム:僕とItamae

僕が初めてItamaeと出会ったのが2014年の Infrastructure as Code 現状確認会 でした。*2

その時はItamaeはおろかプロビジョニング全くやったことがない状態でした。

その後なんやかんやでItamaeを使い始めて2015年の Itamae Meetup #1 ではLTをするくらいにはなりました。

qiita.com

その後さらにItamaeプラグインをたくさん作ったり 前職でItamaeを使ったインフラCI を構築したりして、つい先日はmitamae *3 の本を執筆して技術書典5で頒布しました。

sue445.hatenablog.com

プロビジョニングツールはChef, Ansibleと色々ありますが僕はItamaeが一番筋がいいと思っているし好きなので、今後も使い続けていくと思います。ちなみに最近のマイブームはMacの環境構築をmitamaeで行うことです

https://github.com/sue445/dotfiles/tree/master/mac

技術書典が終わって一段落したので、たまったIssueとかPRを読んでマージできるやつはどんどんマージしていきたいと思ってます。(アドベントカレンダーのことは思い出さないようにしつつ)

*1:厳密には https://github.com/itamae-kitchen 全体

*2:イベントページはZusaarなのでもう見れない。。。

*3:Itamaeのmruby実装

Packer with mitamaeのDL販売を始めました #技術書典

技術書典5 お疲れ様でした。

ウインドテイストとしては14年ぶりのサークル参加 *1 でした。

Go*2なので技術書典5にサークル参加できてよかったです。(様式美)

DL版について

BOOTHでのDL版販売を始めました。会場頒布と同様の500円です

sue445.booth.pm

技術書典5のハイライト

他に色々書きたいことはあるんですが疲れすぎてるのでそれはまた後日

CircleCI 2.1 previewのcommandsが便利だった

https://github.com/CircleCI-Public/config-preview-sdk を見てたら commands が便利そうだったのでためしに個人プロダクトに入れてみた。

github.com

準備

Advanced Settingsの「Enable build processing (preview)」で有効にしないと使えないので注意

f:id:sue445:20180930092753p:plain

Before (CircleCI 2.0)

Ruby製のアプリのCIを構築してると

  • restore_cache でbundle installのキャッシュをリストア
  • bundle install
  • save_cache でキャッシュを保存

というのが頻出すぎてリファクタリングしたかった。

実際に使ってた設定を抜粋したのが下記です。

version: 2

save_bundle_cache_option: &save_bundle_cache_option
  key: v2-bundle-{{ checksum "Gemfile.lock" }}
  paths:
    - ~/app/vendor/bundle

restore_bundle_cache_option: &restore_bundle_cache_option
  keys:
    - v2-bundle-{{ checksum "Gemfile.lock" }}
    - v2-bundle

jobs:
  rspec:
    <<: *default

    steps:
      - checkout
      - restore_cache:
          <<: *restore_bundle_cache_option
      - run: ./.circleci/setup_bundle.sh
      - save_cache:
          <<: *save_bundle_cache_option
      - run: ./.circleci/setup_database.sh

      - run: bundle exec rspec
      - run: bundle exec codeclimate-test-reporter

https://github.com/sue445/chatwork_mention_task/blob/bd6d7ec65d4bc0a8e38d55e082e740539737e538/.circleci/config.yml

rspec以外にrubocopとかの実行でもbundle installが必要なのでDRYにするためにrestore_cachesave_cache のオプションを抽出したり、bundle installの処理をsetup_bundle.sh に抽出しています。

#!/bin/bash -xe

bundle install --jobs=4 --retry=3 --path vendor/bundle
bundle clean

# Resolve bundler version difference between Gemfile.lock and pre-installed in CI
gem install restore_bundled_with --no-document
restore-bundled-with

https://github.com/sue445/chatwork_mention_task/blob/bd6d7ec65d4bc0a8e38d55e082e740539737e538/.circleci/setup_bundle.sh

After (CircleCI 2.1 preview)

restore_cache , bundle install, save_cache の組み合わせを setup_bundle というcommandとして抽出できたので再利用しやすくなりました。

version: 2.1

commands:
  setup_bundle:
    description: "Setup bundle with cache"
    steps:
      - restore_cache:
          keys:
          - v2-bundle-{{ checksum "Gemfile.lock" }}
          - v2-bundle
      - run:
          name: Setup bundle
          command: |
            set -xe
            bundle install --jobs=4 --retry=3 --path vendor/bundle
            bundle clean

            # Resolve bundler version difference between Gemfile.lock and pre-installed in CI
            gem install restore_bundled_with --no-document
            restore-bundled-with

      - save_cache:
          key: v2-bundle-{{ checksum "Gemfile.lock" }}
          paths:
          - ~/app/vendor/bundle

jobs:
  rspec:
    <<: *default

    steps:
      - checkout
      - setup_bundle
      - run: ./.circleci/setup_database.sh

      - run: bundle exec rspec
      - run: bundle exec codeclimate-test-reporter

https://github.com/sue445/chatwork_mention_task/blob/654e5137002bd611f44674d2e69b8ae1b4d31102/.circleci/config.yml

bundle install系の処理が1つになったことでBeforeにあったsave_bundle_cache_optionsetup_bundle.sh にような工夫が不要になったのが嬉しい

所感

今回はcommandsしか使ってないですが他の機能を利用することでリファクタリングの余地が増えそう。

まだpreviewで色々変更ありそうなので個人プロダクト全部には投入しづらいけど、正式版になったら上のような修正を全部に入れたい。

作業PR

https://github.com/sue445/chatwork_mention_task/pull/184/files

apple_system_status v1.0.0を出した

自分以外使ってなさそうだけど一応アナウンス

github.com

このgemについては過去のエントリを参照

sue445.hatenablog.com

大きな変更点

https://github.com/sue445/apple_system_status/blob/master/CHANGELOG.md#v100-2018-09-22 からピックアップ

phantomjsに依存してたのでHeadless Chromeを使うようにした

今更ですがHeadless Chromeに移行。

実は結構前に実装自体は終わっててローカルだとサクッと動いたのですが、CI周りで苦戦してました

簡単に書くと

  • 最初TravisCIでやろうかと思ったらうまく動かない
  • Docker Hubの circleci/ruby のbrowsersタグがついてるイメージならHeadless Chromeがインストール済だから大丈夫だろうと思ったらうまく動かない
    • ChromeにはつながるんだけどDOM取得がうまくいかない
  • 3ヶ月くらい経ってふとnode-browsersタグを使ったらCI通った

って感じ

https://github.com/sue445/apple_system_status/pull/25

activesupport への依存を外した

若気の至りで blank?present? のためだけにactivesupport を使ってたので依存を外した

https://github.com/sue445/apple_system_status/pull/27

Ruby 2.1以下をサポート外にした

最近のcapybara v3.0.0以降だとxpath v3系に依存してるけど *1 xpath v3系はruby 2.2以降でしかインストールできないので*2、メジャーバージョン上げるついでにサポートを明示的に切った

https://github.com/sue445/apple_system_status/pull/28

プリッカソン#5に参加した #prickathon

プリパラを見ていた時期に面白そうなハッカソンがあったので参加しました。*1

prickathon.connpass.com

第一印象

成果物

プリティーオールフレンズ誕生日カレンダー

f:id:sue445:20180924131200p:plain

github.com

下記のプリティーシリーズ版です。

sue445.hatenablog.com

発表資料

esa-pages.io

雑にスライド作るのにesa便利。*2

*1:現時点ではプリティーリズム、キンプリ、プリパラ全て視聴済

*2:Qiitaでもいいんだけど技術以外のことは書きづらい