くりにっき

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

本を売った

近々引っ越しをする予定があって、引越し前に荷物の整理をしたくて物理本をほぼ全部売ったのでその時のメモ。*1

漫画・ラノベ

まんだらけの宅配買取を利用

ekizo.mandarake.co.jp

詳しい冊数は数えてないけどダンボール2箱でたぶん100冊前後。買取金額は4720円也

ただし発払いで送料(3000円ちょい)をこっちが負担したので、実質的な利益は1000円ちょい。いやまぁ、荷物を減らすことが目的だったんで金額はそんなに気にしてないんですが。

技術書

電脳書房 の宅配買取を利用。

www.bookcyber.net

ここをチョイスしたのは以前知り合いのブログで読んで名前を覚えていたため。

yoonchulkoh.hatenablog.com

目録作るのが手間だったけど10冊ごとに買取金額500円アップはデカイ。

最終的に80冊で12000円(前述の事前見積りボーナス込みで16000円)で買い取ってもらえましたが特筆すべき点は着払いで先方が送料負担してくれたこと。こっちもダンボール2箱だったけどもし発払いだったら3000円くらい減ってたところだった。ありがたい

目録をメールで送って何回かやり取りしていく中でゆうパックの着払いで送ってくれって言われたのですが、発送元の場所やダンボールの数によっては発払いになるのかもしれない。

目録をメールで送った段階で「買取金額は最大このくらいだけど本の状態によっては金額が下がります」って言われてたのでちょっと心配してたんだけど、表紙の日焼けくらいは特に問題なく12000円で買い取りしてもらえた。(タバコの臭いがついていると買い取り金額が大きく下がるとのこと)

*1:「ほぼ」と書いているのはサイン本やプリキュア関係の書籍だけ手元に残しているため

padrinoにPRを送った

padrino アプリでactiverecordを5.1系から5.2.0に上げようとしたら rake ar:migrate でエラーになったので直した

エラー内容

activerecord 5.2系からは ActiveRecord::Migrator.migrate がなくなったとのこと。めちょっく!

$ bundle exec rake ar:migrate:reset --trace
** Invoke ar:migrate:reset (first_time)
** Invoke ar:drop (first_time)
** Invoke skeleton (first_time)
** Execute skeleton
** Execute ar:drop
** Invoke ar:create (first_time)
** Invoke skeleton
** Execute ar:create
** Invoke ar:migrate (first_time)
** Invoke skeleton
** Execute ar:migrate
rake aborted!
NoMethodError: undefined method `migrate' for ActiveRecord::Migrator:Class
/app/vendor/bundle/ruby/2.5.0/gems/padrino-gen-0.14.3/lib/padrino-gen/padrino-tasks/activerecord.rb:127:in `block (2 levels) in <top (required)>'
/app/vendor/bundle/ruby/2.5.0/gems/rake-12.3.1/lib/rake/task.rb:271:in `block in execute'
/app/vendor/bundle/ruby/2.5.0/gems/rake-12.3.1/lib/rake/task.rb:271:in `each'
/app/vendor/bundle/ruby/2.5.0/gems/rake-12.3.1/lib/rake/task.rb:271:in `execute'
/app/vendor/bundle/ruby/2.5.0/gems/rake-12.3.1/lib/rake/task.rb:213:in `block in invoke_with_call_chain'
/Users/sue445/.rbenv/versions/2.5.1/lib/ruby/2.5.0/monitor.rb:226:in `mon_synchronize'
/app/vendor/bundle/ruby/2.5.0/gems/rake-12.3.1/lib/rake/task.rb:193:in `invoke_with_call_chain'
/app/vendor/bundle/ruby/2.5.0/gems/rake-12.3.1/lib/rake/task.rb:237:in `block in invoke_prerequisites'
/app/vendor/bundle/ruby/2.5.0/gems/rake-12.3.1/lib/rake/task.rb:235:in `each'
/app/vendor/bundle/ruby/2.5.0/gems/rake-12.3.1/lib/rake/task.rb:235:in `invoke_prerequisites'
/app/vendor/bundle/ruby/2.5.0/gems/rake-12.3.1/lib/rake/task.rb:212:in `block in invoke_with_call_chain'
/Users/sue445/.rbenv/versions/2.5.1/lib/ruby/2.5.0/monitor.rb:226:in `mon_synchronize'
/app/vendor/bundle/ruby/2.5.0/gems/rake-12.3.1/lib/rake/task.rb:193:in `invoke_with_call_chain'
/app/vendor/bundle/ruby/2.5.0/gems/rake-12.3.1/lib/rake/task.rb:182:in `invoke'
/app/vendor/bundle/ruby/2.5.0/gems/rake-12.3.1/lib/rake/application.rb:160:in `invoke_task'
/app/vendor/bundle/ruby/2.5.0/gems/rake-12.3.1/lib/rake/application.rb:116:in `block (2 levels) in top_level'
/app/vendor/bundle/ruby/2.5.0/gems/rake-12.3.1/lib/rake/application.rb:116:in `each'
/app/vendor/bundle/ruby/2.5.0/gems/rake-12.3.1/lib/rake/application.rb:116:in `block in top_level'
/app/vendor/bundle/ruby/2.5.0/gems/rake-12.3.1/lib/rake/application.rb:125:in `run_with_threads'
/app/vendor/bundle/ruby/2.5.0/gems/rake-12.3.1/lib/rake/application.rb:110:in `top_level'
/app/vendor/bundle/ruby/2.5.0/gems/rake-12.3.1/lib/rake/application.rb:83:in `block in run'
/app/vendor/bundle/ruby/2.5.0/gems/rake-12.3.1/lib/rake/application.rb:186:in `standard_exception_handling'
/app/vendor/bundle/ruby/2.5.0/gems/rake-12.3.1/lib/rake/application.rb:80:in `run'
/app/vendor/bundle/ruby/2.5.0/gems/rake-12.3.1/exe/rake:27:in `<top (required)>'
/app/vendor/bundle/ruby/2.5.0/bin/rake:23:in `load'
/app/vendor/bundle/ruby/2.5.0/bin/rake:23:in `<top (required)>'
/Users/sue445/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.16.1/lib/bundler/cli/exec.rb:75:in `load'
/Users/sue445/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.16.1/lib/bundler/cli/exec.rb:75:in `kernel_load'
/Users/sue445/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.16.1/lib/bundler/cli/exec.rb:28:in `run'
/Users/sue445/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.16.1/lib/bundler/cli.rb:424:in `exec'
/Users/sue445/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.16.1/lib/bundler/vendor/thor/lib/thor/command.rb:27:in `run'
/Users/sue445/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.16.1/lib/bundler/vendor/thor/lib/thor/invocation.rb:126:in `invoke_command'
/Users/sue445/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.16.1/lib/bundler/vendor/thor/lib/thor.rb:387:in `dispatch'
/Users/sue445/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.16.1/lib/bundler/cli.rb:27:in `dispatch'
/Users/sue445/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.16.1/lib/bundler/vendor/thor/lib/thor/base.rb:466:in `start'
/Users/sue445/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.16.1/lib/bundler/cli.rb:18:in `start'
/Users/sue445/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.16.1/exe/bundle:30:in `block in <top (required)>'
/Users/sue445/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.16.1/lib/bundler/friendly_errors.rb:122:in `with_friendly_errors'
/Users/sue445/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.16.1/exe/bundle:22:in `<top (required)>'
/Users/sue445/.rbenv/versions/2.5.1/bin/bundle:23:in `load'
/Users/sue445/.rbenv/versions/2.5.1/bin/bundle:23:in `<main>'
Tasks: TOP => ar:migrate:reset => ar:migrate

修正内容

github.com

現時点でまだgemはリリースされてないのでpadrinoでactiverecord 5.2系使いたい場合はmasterブランチを要参照。

activerecordのメソッドを直接読んでRailsdb:migrate 相当のことを実現してるgemはたまにあるので、そういう場合はこれを参考に直せばいいと思います。

itamaeプラグインのCIを作り直した

個人開発してるitamaeプラグインのCI環境を作り直したのでその知見

tl;dr;

itamaeプラグインのCIにDockerを活用してモダンになった

今までのCI

下記のブログに詳しく書いています

sue445.hatenablog.com

問題点

元々この構成は オライリーのServerspec本 を参考に構築してたのですが、長年使ってきて下記のような問題点がありました

DigitalOcean依存による問題

  • 同一OSでもローカル(VirtualBox)とCI(DigitalOcean)とでイメージが違うので、ローカルだとOKでもCIだとビルドがコケることがある
  • WerckerからDigitalOceanでVMを立ち上げる時に、VMの起動に失敗することが稀によくある
  • ssh越しにitamaeを実行するので遅い
  • DigitalOceanに利用にもお金がかかるのでビルドを回す度にお金が減る
    • itamaeプラグイン6個でweeklyビルドを実行して月1ドル前後

Vagrant依存による問題

  • 古いVagrantに依存しているため最新のbundlerと相性が悪い *1
  • CI実行時に毎回Vagrantをダウンロードしてインストールしてるのでその分ビルドが遅い

新しいCIの構成

  • TravisCI
  • Docker

やったこと

https://github.com/sue445/itamae-plugin-recipe-tig/pull/13 をかいつまんで説明

gemの依存にdocker-apiを追加

spec.add_development_dependency "docker-api"

spec/spec_helper.rbを修正

require 'serverspec'
require 'docker'

set :backend, :docker

set :docker_image, ENV['DOCKER_IMAGE']
set :docker_container, ENV['DOCKER_CONTAINER']

# Disable sudo
# set :disable_sudo, true


# Set environment variables
# set :env, :LANG => 'C', :LC_MESSAGES => 'C'

# Set PATH
# set :path, '/sbin:/usr/local/sbin:$PATH'

# via. http://qiita.com/sue445/items/b67b0e7209a7fae1a52a
require "yaml"
require "itamae/node"

def node
  return @node if @node

  hash = YAML.load_file("#{__dir__}/../recipes/node.yml")

  @node = Itamae::Node.new(hash, Specinfra.backend)
end

自分の場合spec内でnodeの値を使うことが多いので上記のような構成にしてるので不要な場合は node メソッドを削除してください。あとnode.ymlのパスは必要に応じて要微調整。

spec_helper.rbは下記が参考しています

joe-noh.hatenablog.com

.travis.ymlを修正

serviceを使わない場合

envIMAGEでDockerイメージの名前を渡してマトリクステストできるようにしています

language: ruby
sudo: required
services:
- docker
rvm:
- 2.3
env:
- IMAGE=centos:7
- IMAGE=debian:jessie
bundler_args: "--jobs=4"
cache: bundler
before_install:
- gem update --system --no-document
- gem install bundler --no-document
script:
- bundle exec itamae docker --node-yaml=recipes/node.yml recipes/install.rb --image=$IMAGE --tag itamae-plugin:latest
- DOCKER_IMAGE=itamae-plugin:latest bundle exec rspec

serviceを使う場合

CentOS 7だけかもしれないんですが普通に docker run した状態でserviceを起動しようと「Failed to get D-Bus connection: No connection to service manager.」というエラーになるので itamae-plugin-recipe-consul では下記のように書いていました。

before_script:
- docker run --privileged -d --name container-with-service $IMAGE /sbin/init
script:
- bundle exec itamae docker --node-yaml=recipes/node.yml recipes/install.rb --container=container-with-service --tag itamae-plugin:latest
- DOCKER_CONTAINER=container-with-service bundle exec rspec

このエラーの解決には下記が参考になりました

qiita.com

メリット

一番大きなところでは、ビルドの時間が速くなってます。

外部クラウドに対してVM起動することがなくなったり、ssh越しにコマンドを実行せずにローカルのDockerコンテナに対してコマンドを実行するようになったことから全体的にビルド時間が速くなりました

修正前後での1回辺りのビルド時間を集計しましたが、軒並み速くなっているのが確認できます。(修正前後ともに3~5回くらいビルドを実行した時の平均時間を記載)

修正前のビルド時間 (秒) 修正後のビルド時間 (秒)
itamae-plugin-recipe-consul 288.3 197.5
itamae-plugin-recipe-git_now 328.3 248
itamae-plugin-recipe-omori_gohan 300.6 205
itamae-plugin-recipe-tig 374.2 322
itamae-plugin-resource-encrypted_remote_file 441.4 315
itamae-plugin-resource-tmux 612.6 255.75

その他メリット

  • 不安定なビルドがだいぶなくなった
    • 修正前はDigitalOceanのVM起動が不安定だったのですが、TravisCIでDockerを起動することによりビルドがだいぶ安定するようになりました。*2
  • ローカルとCIで完全に同じ環境が使えるようになった
    • ローカルでも --provider=digital_ocean つければいいわけなのですが、自分以外の人がローカルで確認するためだけにDigitalOceanに登録してもらう必要があるので強制しづらい
  • DigitalOceanを使わなくなったのでその分のコストが浮いた

デメリット

  • Docker依存の問題によりレシピが実行できないことがある
    • 前述のsystemd問題など
  • 他にもDocker由来の問題でハマりどころはあるかもしれない

おまけ:同じ構成をCircleCIで書いた場合

最初全く同じ構成をCircleCIで書いていたのですがymlが膨大になりすぎて途中でTravisCIに移行しました。

最初に書いていたCircleCIの設定ファイル

https://github.com/sue445/itamae-plugin-recipe-tmux/blob/fb1ee0273d5445e48c572fa8ac1528907e38b05c/.circleci/config.yml

CircleCIも悪くはないんですが、マトリクステストしたい場合にはTravisCIの方が簡潔に書けていいですね。

*1: https://github.com/hashicorp/vagrant/blob/v1.8.4/vagrant.gemspec#L23

*2:TravisでのDocker起動時にもたまにエラーは出るんだけどDigitalOceanよりはだいぶ頻度は少ない

rubicure v1.1.2リリース

はぐプリでは公式HP*1のキャラ紹介に誕生日が載っていなくててっきり誕生日設定がないのかと思っていたのですが、プリティストアのTwitterアカウントからキュアエトワールの誕生日情報が流れてきたので対応しました。

株式会社はてなに入社しました

株式会社はてなに入社しました

黒服つながりです

株式会社はてなに入社しました - hitode909の日記

キュアラインを作った

注)タイトルは半分釣りです

LINE TIMELINEスクレイピングするためのgemを作りました。

github.com

使い方

READMEからの抜粋ですがこんな感じ

# read https://timeline.line.me/user/_dYbbV3vmaJrvqBoV5ZlpCbPN2CWUZdDQayBvjBE
user = CureLine.user("_dYbbV3vmaJrvqBoV5ZlpCbPN2CWUZdDQayBvjBE")

user.info
#=> {"mid"=>"_dYbbV3vmaJrvqBoV5ZlpCbPN2CWUZdDQayBvjBE",
# "nickname"=>"プリキュア",
# "pictureUrl"=>"https://profile.line-scdn.net/0hU_sA3K0gCnBOOCZuQUx1J3J9BB05Fgw4Nl9BQmxsUEZjCU0jewlCFWo-UEk3CRhxdQtCQ20_VRBk",
# "userValid"=>true,
# "writerMid"=>"_dYbbV3vmaJrvqBoV5ZlpCbPN2CWUZdDQayBvjBE"}

user.header_url
#=> "https://obs.line-scdn.net/htzWKFLgwN1RRXiRaCAgwLR0sfTZOB28EU1VjYxs0IWYTAjkDUFViZhhgJjJHUmRR"

post = user.posts.first 

post.nickname
#=> "プリキュア"

post.picture_url
#=> "https://profile.line-scdn.net/0hU_sA3K0gCnBOOCZuQUx1J3J9BB05Fgw4Nl9BQmxsUEZjCU0jewlCFWo-UEk3CRhxdQtCQ20_VRBk"

post.post_url
#=> "https://timeline.line.me/post/_dYbbV3vmaJrvqBoV5ZlpCbPN2CWUZdDQayBvjBE/1152127900305060448"

post.text
#=> "プリキュアになってから、さあやとほまれとますます仲良くなれて、\n超うれしー!!\(^o^)/\n今日はビューティーハリーで、お互いに洋服をコーディネイトし合ったんだ~。\n\nさあやは、大人っぽいデザインのスカートがめっちゃ似合ってた!\nう~ん、絵のモデルさんになれそうなくらい素敵!( *´艸`)\n\nほまれはオシャレ上級者しか着こなせないような、最先端のオールインワンがぴったり!\n背が高くて、足が長い人はいいな~、うぅ……(T_T)\n\nはぐたんはくまさんの耳がついたフードをかぶって……。\nきゃ、きゃ、きゃわたん~~~~(・´з`・)\n拝みたくなる可愛さでした♡\n\nで……私は!?私は何が似合うかな!?\nえっ……ハリーおすすめのどデカイ虎の絵が描いてあるトレーナー!!?\nみんな、似合ってるって言ってくれるけど……お腹抱えて笑ってるじゃん!!ヽ(`Д´)ノプンプン\n\nう~ん、でも言われてみれば、たしかに似合ってるような……。\nこれを着こなせるって、逆にすごいかも☆(^ε^)\nはぁ~、今日もいい一日でした!"

post.created_time
#=> 2018-03-17 18:30:03 +0900

post.updated_time
#=> 2018-03-17 18:30:03 +0900

post.photo_urls
#=> ["https://obs.line-scdn.net/h5XG4_2KndnZXIWV4GHdxDwZTY0ZUe34iR3snQghNNkNUfSx0Qy4lRF9PPERUeS8iQy9gFwtOYENTfg"]

動いてる様子

個人Slackでプリキュアのタイムラインを通知するのに使ってます

f:id:sue445:20180321161742p:plain

元々はcure_line自体も個人Slackのボットの一機能だったのですが、今回gem化してロジックを外部に切り出しています

関連商品

ハピネスチャージプリキュア! キュアライン

ハピネスチャージプリキュア! キュアライン

自分のスライドのリンク集を作った

「リンク集」って響きに懐かしさを感じるオッサンです(挨拶)

自分の勉強会のスライドの公開先はSlideshareやSpeakerDeckやGitHub Pagesなどその時の気分で変わるんですが*1、後から探す時に不便だったのでまとめました。ご査収ください

github.com

関連リンク集

qiita.com

sue445's CI Badges

これ系のリンク集があると人に見せやすいのでおすすめ。特に前者の1人AdventCalendarは自分のプロダクト紹介でよく使ってます

*1:最近だとmaekdownで書きたい派なのでreveal.jsで書いてGitHub Pagesにupすることが多いです