あいつの日誌β

働きながら旅しています。

heroku の buildpack について覚えた事を書き残す

あらすじ

heroku 上で groonga が使えるようになったので heroku + groonga + Node.js でアプリを作ってやろうとしたら絶賛苦戦中。

heroku に push を試みたが...

% cat .buildpacks 
https://github.com/groonga/heroku-buildpack-groonga
https://github.com/heroku/heroku-buildpack-nodejs

% heroku create --buildpack https://github.com/ddollar/heroku-buildpack-multi.git
% git push heroku master

だがしかしエラー

26 error Failed at the nroonga@0.2.5 install script.
26 error This is most likely a problem with the nroonga package,
26 error not with npm itself.
26 error Tell the author that this fails on your system:
26 error     node-gyp rebuild
26 error You can get their info via:
26 error     npm owner ls nroonga
26 error There is likely additional logging output above.
27 error System Linux 3.8.11-ec2
28 error command "/tmp/build_5fa69e77-7239-4574-8e66-91bf9c2d5ed3/vendor/node/bin/node" "/tmp/build_5fa69e77-7239-4574-8e66-91bf9c2d5ed3/vendor/node/bin/npm" "install" "--userconfig" "/tmp/build_5fa69e77-7239-4574-8e66-91bf9c2d5ed3/.npmrc" "--production"
29 error cwd /tmp/build_5fa69e77-7239-4574-8e66-91bf9c2d5ed3
30 error node -v v0.10.29
31 error npm -v 1.4.14
32 error code ELIFECYCLE
33 verbose exit [ 1, true ]

 !     Push rejected, failed to compile Multipack app

どうした?

heroku-buildpack-multi で何をしているのか考えます。この記事で登場した .buildpacks の場合以下の処理を順番に行っています

  • heroku-buildpack-groonga の bin/detect を子プロセスに実行させる
  • heroku-buildpack-groonga の bin/compile を子プロセスに実行させる
  • heroku-buildpack-groonga の bin/release を子プロセスに実行させる
  • heroku-buildpack-nodejs の bin/detect を子プロセスに実行させる
  • heroku-buildpack-nodejs の bin/compile を子プロセスに実行させる
  • heroku-buildpack-nodejs の bin/release を子プロセスに実行させる

そして調べたところ heroku-buildpack-nodejs で npm install が実行されるのですがここでエラーが起きています。

私は nroonga を使いたいのですがどうやら node-gyp build をする時に pkgconfg が groonga を発見できていないようです。

というわけで環境変数を親プロセスに伝えたら上手く行きそうです。

どうする?

heroku では ENV_DIR に環境変数を記す作法があるようです。https://devcenter.heroku.com/articles/buildpack-api

bin/compile の第3引数で指定されたディレクトリに以下のようなファイルを作成します。

#{env_dir}/LD_LIBRARY_PATH

そしてファイル内で以下の記述をします。

#{build_dir}/vendor/groonga/lib

コマンドで表すとこんな感じになります。

% cat #{env_dir}/LD_LIBRARY_PATH
#{build_dir}/vendor/groonga/lib:$LD_LIBRARY_PATH

修正してみた

このようにしました。

% git diff 435e0ea62242a747fee7fedf35178b461ee8b013
diff --git a/bin/compile b/bin/compile
index ce6cecf..a89a36c 100755
--- a/bin/compile
+++ b/bin/compile
@@ -81,4 +81,12 @@ Dir.chdir(build_dir) do
     sh("groonga", "--file", grn, database_path)
     rm(grn)
   end
+
+  open("#{env_dir}/LD_LIBRARY_PATH", "w"){|f| f.write("#{absolete_prefix}/lib:$LD_LIBRARY_PATH"
+  open("#{env_dir}/PKG_CONFIG_PATH", "w"){|f| f.write("#{absolete_prefix}/lib/pkgconfig:$PKG_CO
+
+  app_dir = ENV["HOME"] 
+  profile_dir="#{build_dir}/.profile.d"
+  FileUtils.mkdir_p(profile_dir) unless FileTest.exist?(profile_dir)  
+  open("#{profile_dir}/groonga.sh", "w"){|f| f.write("export LD_LIBRARY_PATH=#{app_dir}/#{prefi
 end

そして pull request しました。

ところで

YAPC 2014 が今年も開催されます。実は誰にも気づかれないように僕も応募しています。もし heroku か groonga に興味がある方は誰にも気づかれないようにイイネしてれるとうれしいです。

http://yapcasia.org/2014/talk/show/acf68466-01ee-11e4-9357-07b16aeab6a4