以前embulkのjava pluginをbundlerっぽくgithubからインストールして実行できるラッパーを作った - Qiitaという記事を書いた。
要はJava製のプラグインをgithubから直接インストールしてリリース前のものを使いたいというものだ。
で、コマンドをラップするgemを作ってみたのだが、DSLの挙動をちゃんと制御するのは面倒だしコマンドをラップするのは色々とポータビリティが悪い。
しかし、ある時天啓が降りてきた。
「Bundlerを弄ればいいや」と。
で、ソースコード読んで、gemspecの判別がどうなってるのかとモンキーパッチを当てるのにちょうど良い場所を探して試してみた所、とてもシンプルなハックで上手くいった。
Gemfile上でBundlerにモンキーパッチを当てるというダーティさに目を瞑れば割と便利ではないだろうか。
こんな風に書く。
require 'bundler/source/git/git_proxy'
module AddGradlewHookForEmbulkPlugin
def copy_to(destination, submodules=false)
super
if destination.join("./gradlew").exist?
system("./gradlew gem", chdir: destination.to_s)
Dir[destination.expand_path.join("{,*,*/*}", "build", "gemspec").to_s].each do |gemspec|
system("cp", gemspec, File.expand_path("../../plugin.gemspec", gemspec))
end
end
end
end
Bundler::Source::Git::GitProxy.prepend(AddGradlewHookForEmbulkPlugin)
source 'https://rubygems.org/'
gem "embulk-input-postgresql", github: "embulk/embulk-input-jdbc"
gem "embulk-output-bigquery", github: "joker1007/embulk-output-bigquery", branch: "multithread-upload"
gem "embulk-filter-column"
gem "embulk-filter-ruby_proc", path: "~/srcs/embulk-filter-ruby_proc"
単純にgithubからcloneしてきた後に、そのディレクトリにgradlewがあればそれでgemをビルドして出力されたgemspecを適当な名前で置き直すだけ。
この程度なら、bundlerがよっぽど大規模に書き変わらない限りさしてメンテコストもない。
この方法のメリットは、単純に-bオプションでbundleディレクトリを指定するだけで、普通にプラグインが読み込めることだ。
というわけで、拙作のembulk_javundlerは早くもお役御免になった。
embulk-coreには確かbundlerが同梱されてるはずなんだけど、そのbundlerを弄ってembulk用にこういう機能を公式で組み込んで欲しい感じはする。
しかし、やり方がやり方なのでそんなに強い要望ではないw
bundler自体にちゃんとフックポイントが用意されていれば良いんだろうけど、普通はそんな用途無いよなあ……。