Thanks Driven Life

日々是感謝

2015年を振り返って

f:id:gongoZ:20151231190704p:plain

gongo.hatenablog.com

ふりかえり〜

OSS活動

2014年に Turnip のオーナー権を貰って から、ちょくちょく活動しています。 今年の作業としては、RSpec のバージョンを結構新しめ限定にするという Turnip 2.0.0 をリリースできたのが良かったです。

[Proposal] RSpec support policy · Issue #158 · jnicklas/turnip

社外でこのような提案する機会は今までなかったので、良い経験でした。

発表

今年は珍しく発表する機会がありました。

最初で最後だった YAPC Asia はやはり印象深いです。よく、あの規模の会場の壇上にあがって Perl にまったくカスらない内容を発表できたなーと。 発表のネタに繋がる作業は割とマジメに取り組んでいたんですが、結果的に笑い取れたので今年勝利したことにしておきます。

その他

久々に Advent Calendar に参加したり、ちょくちょく Vue.js 触ったり、ぐらいでしょうか。 2014年のふりかえり と見比べると、だいたい同じことしてるなという感想です。

まとめ

2016年もよろしくお願い致します。

Turnip 2.0.1 リリースしました

Release Version 2.0.1 · jnicklas/turnip

修正内容

たとえばこういう feature があったとして

Feature: Feature with background
  Background:
    Given there is a monster
  Scenario: simple scenario
    When I attack it
    Then it should die

RSpec の documentation format でテスト結果を表示した場合、Turnip 2.0.0 までは

Feature with background
  simple scenario
    When I attack it -> Then it should die

こういう形で Background のステップ名が表示されていなかった のですが、2.0.1 より

Feature with background
  simple scenario
    Given there is a monster -> When I attack it -> Then it should die

こんな感じで Background のステップ名も表示されるようになりました。

まとめ

メリークリスマス!!

Turnip 2.0.0 リリースされました

Release Version 2.0.0 · jnicklas/turnip

メジャーバージョンアップとなる 2.0.0 ですが、機能追加されたとか機能削除されたとかではなく

RSpec のサポートバージョンポリシー策定

の一環です。

経緯

github.com

以前は RSpec 2.14.x 系から RSpec 3.x の最新まで全てをサポートする体制でした。 定義されていなかった というのが正確なところですが。

ともかく近年の RSpec の躍進ぶりを追い続けるため、全てのバージョンをサポートしていくのは現状メンテナ一人の状態では無理と判断し、上記のような提案をさせていただきました。

提案の結果

反応としては「まあいいんじゃないのー」といった肯定的なものだったので、安心してばっさりいきました。つまり

  • 最新のバージョン、およびその一つ前のバージョンだけをサポートする
  • それ以前のバージョンはサポート対象外(動くかもしれない)

という形にしました。

最近の RSpec 3.x のリリースは 2,3 ヶ月に1回となっており、まあ約半年ぐらいあれば Turnip ユーザも手元の RSpec のバージョン上げられるだろ、ぐらいの気持ちで進めています。

そんなわけで

Turnip をこれからもよろしくお願い致します。

heroku-docker を使って Emacs & Cask がインストールされた Heroku 環境 (Slug) を作成する Docker イメージ作った

成果物

経緯

Emacs を使っている人は、日頃から

「あー Emacs でも HTTP サーバ立てられるんだし Heroku で起動してーなー」

と考えていると思います。

しかし Emacs ぐらいになると Heroku が標準サポートしている環境には含まれておらず、
いわゆるサードパーティ製 buildpack の導入が必要となります。

Emacs の buildpack もあった*1 のですが

  1. 試しに使ってみたら、なんかエラー出た*2
  2. まあ直せばいいかーと思う
  3. buildpack の修正検証ってものすごいめんどくさいイメージ(ちゃんと調べてない)
  4. モチベーション消えた

みたいな人生を送っていました。

Heroku + Docker

そんなある日、もう一つの可能性である Docker を思い出しました。

Build and Deploy with Docker | Heroku Dev Center

リリースされた当時は

「好きな Docker イメージを Heroku で動かせるのかよすごい!!」

みたいな反応が多数(私も)だったのですが、実際には

  1. 「Heroku と同等の環境を Docker イメージとして配布する」
  2. 「その中で動作確認しろよ」
  3. 「(制限はあるが)そのままデプロイできるフローも作ったぜ」

的なものでした。

デプロイ方法もあるし、ドカドカデバックできるので、これで行こうと決めました。

そんなわけで作りました。

https://github.com/gongo/emacs-heroku-docker

概要は README を読んでもらうとして、つまり必要なことは

  1. 普段通り Emacs Lisp で Web アプリケーションを書く
  2. Cask ファイルを作成し、依存パッケージを書く
  3. Heroku ではお馴染の Procfile に、起動コマンドを書く
  4. コンテナビルドしたり Heroku へリリースするためのファイルを作成
    • docker build したあとのファイルを転送するため、リリースにも使われる
  5. heroku docker:release

みたいな感じです。

試しに作ったのがこちら

https://emacs-heroku-docker-sample.herokuapp.com/

いつか消します

補足

heroku-docker でデプロイする時に注意するところ、備忘録も兼ねて

1. /app 以下のファイルしか転送されない

heroku docker:release で Heroku にデプロイされるファイルは、awesome氏のポストにもある通り

/app以下をtgzで固めてcpコマンドでそれを取り出している.なのでDockerfileに独自の変更を加えるときは注意が必要で/app以下に依存をちゃんと含めるように書く必要がある.

Herokuの'docker:release'の動き | SOTA

という制限(仕様)となっています。

つまり、Dockerfile で素直に apt-get install emacs とかやっても、Heroku 側には Emacs が入っていない slug が転送されてしまう、ということです。 なので今回はソースコードからコンパイルし、 /app/emacs 以下にインストールすることで依存を /app 以下に閉じ込めました。Cask についても同様。

2. 環境変数 export は /app/.profile.d/* 以下に書いておこう

上記のとおり heroku docker:release で転送されるのは、コンテナ内の /app 以下だけ。つまり

ENV PATH /app/emacs/bin:$PATH

みたいなのを書いていても、docker run した環境では使えますが Heroku 上には反映されません

ではどうするか。/app/.profile.d/ 以下に、環境変数設定するファイルを書いておきます。

.profile.d Scripts | Heroku Dev Center

$HOME/.profile.d/ 以下に置いたやつは Dyno 起動時に読まれるので、必要な処理はここに書いておきましょう。

ちなみに heroku-ruby では Dockerfile の ENTRYPOINT として init.sh というものを仕込んでいます。

#!/bin/bash

for SCRIPT in /app/.profile.d/*;
  do source $SCRIPT;
done

exec "$@"

こうすることで

Procfile:

web: cask exec emacs -Q --batch -l app.el

docker run 時:

$ docker run `コンテナ名` cask exec emacs -Q --batch -l app.el

つまり

  • Procfile に書くコマンドと docker run のコマンドを揃えることができる
  • どちらもコンテナ起動時に /app/.profile.d/* 以下を読んでくれる

という感じで、より Heroku の環境に近づけることができる、というわけです。

まとめ

heroku-docker を使うことで、buildpack よりも破壊再構築のサイクルを早く回せると思います。 どんどん作って最高のオレオレ cedar:14 にしよう!!

参考

*1:https://github.com/technomancy/heroku-buildpack-emacs

*2:libgpmが無いとかなんとか

json-reformat.el v0.0.4 リリースしました

Release 0.0.4 · gongo/json-reformat · GitHub

修正内容

v0.0.3 までは、空のハッシュに対して json-reformat-region とかを仕掛けると、
下記のように null になってしまう という 仕様 でした。

{"foo": {}}

// ↓↓↓

{
  "foo": null
}

v0.0.4 からは、ちゃんと空のハッシュのまま整形できるようになりました。

{"foo": {}}

// ↓↓↓

{
    "foo": {
    }
}

空のハッシュであれば "foo": { } という感じで改行入らない方がいいかもしれませんね。
いつか考えます。

今回の内容を仕様としていた理由

json-reformat.el では、JSON テキストのパースを (json-read) で行っています。

;; $ cat foo.json
;; {
;;     "foo": 3,
;;     "bar": "pizza"
;; }

(dolist (type '(plist alist hash-table))
  (let ((json-object-type type))
    (with-temp-buffer
      (insert-file-contents "foo.json")
      (json-read))))

;; => (:bar "pizza" :foo 3)
;; => ((bar . "pizza") (foo . 3))
;; => #s(hash-table size 65 test equal rehash-size 1.5 rehash-threshold 0.8 data ("foo" 3 "bar" "pizza" ...))

このように alist plist hash-table の中の好きな形でパースした結果を受け取れます。

v0.0.3 までは plist で実装していたのですが、この時問題となるのが、前述の 空のハッシュ です。

;; $ cat foo.json
;; {
;;     "foo": {},
;;     "bar": null
;; }

(let ((json-object-type 'plist))
  (with-temp-buffer
    (insert-file-contents "foo.json")
    (json-read)))

;; => (:bar nil :foo nil)

このように 空のハッシュも null もパースすると nil になってしまう ということで、
受け取った側としては「どっちかわからんから {} に直すこともできねーなー」となって
最終的に「これは仕様ですわー」みたいな感じにしていました。

光明

そんなことを Tweet してみたところ、 @ さんから以下の reply をいただきました。

なるほど hash-table と思って実際に試してみたところ

;; $ cat foo.json
;; {
;;     "foo": {}
;; }

;; $ cat bar.json
;; {
;;     "bar": null
;; }

(let ((json-object-type 'hash-table))
  (dolist (filename '("foo.json" "bar.json"))
    (with-temp-buffer
      (insert-file-contents filename)
      (json-read))))

;; => #s(hash-table size 65 test equal rehash-size 1.5 rehash-threshold 0.8 data ("foo" #s(hash-table size 65 test equal rehash-size 1.5 rehash-threshold 0.8 data ( ...)) ...))
;; => #s(hash-table size 65 test equal rehash-size 1.5 rehash-threshold 0.8 data ("bar" nil ...))

ちゃんと nil なのか空ハッシュなのか判別できる!!

というわけで、今までの仕様はバグということにできて修正することができました。 @ さんありがとうございました!!

P.S.

Emacs 24.4 から標準実装されている M-x json-pretty-print も似たような問題が起きていますが
M-x json-pretty-print または M-x json-pretty-print-buffer 実行前に

(setq json-object-type 'hash-table)

とかしておくと、空ハッシュが壊れることはありません。

PHP バージョン毎の php.ini の差分を確認できるサービス phpini-diff

軽く作りました。

http://phpini-diff.herokuapp.com/

f:id:gongoZ:20150924162526g:plain

概要

RailsDiff みたいなやつです。

作成経緯

PHP のバージョン上げる時に php.ini の違いも一応調べないと*1。でも PHPソースコード落としてきて diff するのめんどいし。今なら GitHub にある PHP 本体のリポジトリ でタグ差分で違いみれるけどいちいちバージョン探して指定してーってめんどくさいな」

みたいなことから

Rails だと railsdiff があるよなー」

みたいな感じで php.ini 版があると多少便利になるかな、といった感じです。

ソースコード

github.com

備忘録も兼ねて簡単に内容を

PHP のバージョンは 4.0.0 以上 & (正式版 or RC 版) を対象

  • GitHub でタグ付けされてる分だけ
  • 正式版以外だと alpha とか beta とかあるけど、めんどくさいので RC だけ

php.ini の種類については

プロダクション用(所謂 php.ini-production)を比較対象としています。php.ini-development とかは除外しています。 ちなみに PHP 5.3 未満は php.ini-recommended が production 用っぽかったので、それを採用しています。

各バージョンの php.ini の収集方法

適当にスクリプト書いて 対処しました。

とりあえず JavaScript (Node.js) で

  • フロントは vue.js + webpack で作成
  • サーバ側は express
    • そこは PHP だろみたいなところもあったんですが、 PHP xdiff を heroku で使うのめんどそう
    • いい感じで差分ブロック分けてくれるやつが node にあった flitbit/diff ので、もう統一しようかなと

まとめ

ini ファイル、拡張ライブラリまで手を出そうと思ったけどめんどくさいのでやめました。 そこらへんはファイルサイズもそんなに大きくないし、ひとまずコアな php.ini の差分だけ簡単に見れたら良しとしました。

てきとうにご利用ください

*1:例えば 5.3 → 5.4 みたいな差分は http://php.net/manual/ja/migration54.ini.php とかでも確認できます

YAPC::Asia Tokyo 2015 参加ついでに会社(前)訪問したり飯食ったりしてた

YAPC::Asia Tokyo 2015 参加してきました - Thanks Driven Life

合間のお話

食事

マグロカツカレー。マグロカツ美味しかった

東印度カレー商会 築地場外店 - 築地市場/カレーライス [食べログ]


親子丼

なか卯 勝どき一丁目店 - 勝どき/牛丼 [食べログ]




朝シースー最高!!

店舗詳細 | 東京の寿司 マグロが自慢【すしざんまい】つきじ喜代村


朝ぎゅうどん

松屋 勝どき店(晴海/丼もの) - ぐるなび


ビッグサイト近くで沖縄勢と飲んだ居酒屋の茶漬。店忘れた


最高の肉

the 肉丼の店ホームページ | 高田馬場・晴海・蒲田・赤坂でステーキ丼とローストビーフ丼

会社(の前の写真を撮るための)訪問

GitHub ジャパン!!!

伝説のヒカリエのオフィス受け付け(11F)まで行って写真だけ撮ってすぐ降りました

YAPC::Asia 2015 Hackathon 会場だったというビルいって写真。
若干遠くから撮ったっぽい理由は、警備員いて怖かったからです。

まとめ

飯最高!!