LoginSignup
9
5

More than 3 years have passed since last update.

digdag の rb オペレータで bundle exec を使う3つの方法

Last updated at Posted at 2019-02-21

EDIT: 0.9.35 でruby オプションを指定できるようになったので追記

前提知識

ruby の前提知識および現在の digdag ができること、できないこと。

読み飛ばし可能。

digdag 0.9.33 から ruby へのパスを指定できるようになった

_export:
  rb:
    ruby: /path/to/ruby

もしくは

+task:
  rb>: MyWorkflow.method
  ruby: /path/to/ruby

しかし /path/to/bundle exec /path/to/ruby のような書き方はできない。また、できたとしても Gemfile が置いてあるパスに cd しなければならない

bundle exec は Gemfile をワーキングディレクトリに要求する

Gemfile, Gemfile.lock, .bundle/config がおいてあるディレクトリに cd して実行する必要がある。

cd /path/to/bundle
bundle exec ruby

しかし、digdag の rb オペレータには working directory を指定するようなオプションはない。

BUNDLE_GEMFILE 環境変数と -rbundler/setup

cd したくない(or できない)場合は BUNDLE_GEMFILE 環境変数で Gemfile のパスを指定して、bundler/setup を require すれば bundle exec と同じ効果を出せる。

FYI: bundle install --binstubs した bin スクリプトを読むとそんな感じの処理が書いてある

env BUNDLE_GEMFILE=/path/to/Gemfile ruby -rbundler/setup

RUBYOPT の解釈は ruby オプションより後

RUBYOPT=-rbundle/setup のように環境変数を設定すると ruby は -rbundle/setup オプションを指定したものとして扱ってくれるが、

env BUNDLE_GEMFILE=/path/to/Gemfile RUBYOPT=-rbundler/setup ruby -ryour_lib

のように書くと ruby は your_lib.rb を load してから bundler/setup を load する。 ref. https://bugs.ruby-lang.org/issues/5445

digdag の rb オペレータは require: your_lib のように指定したスクリプトを ruby -ryour_lib のように require するので、RUBYOPT よりも先に読み込んでしまい、RUBYOPT=-rbundler/setup を指定しても役に立たない(ことが多い)。

digdag 0.9.35 から ruby パスに加えてオプションを指定できるようになった

_export:
  rb:
    ruby: ["/path/to/ruby", "-rbundler/setup"]

+task:
  rb>: MyWorkflow.method
  require: tasks/my_workflow

もしくは

+task:
  rb>: MyWorkflow.method
  ruby: ["/path/to/ruby", "-rbundler/setup"]
  require: tasks/my_workflow

こちらの場合は ruby -rbundler/setup -rtasks/my_workflow のような順番で require するので、bundler が有効になってから、 tasks/my_workflow が require されて tasks ファイル中で gem を使える。

やりたいこと

digdag の project root をワーキングディレクトリにしたまま、別のディレクトリにある Gemfile を指定して ruby 実行したい。

あらかじめ bundle install しておいたdocker イメージを使って rb>: オペレータを使いたい場合、digdag ホストの project root ではなく、コンテナ内の別のパスに Gemfile を置いているはずなので、その場合のシステム要件でもある。

やり方

方法1: BUNDLE_GEMFILE を指定して task ファイルで require 'bundler/setup' する

tasks/workflow.rb
require 'bundler/setup'
require 'your_favorite_gem'

class Workflow
  def foo
  end
end
sample.dig
+task:
  _env:
    BUNDLE_GEMFILE: /path/to/Gemfile
  rb>: Workflow.foo
  require: tasks/workflow

_export: docker: で rb オペレータを動かすのに docker を使っている時も使える。

sample_docker.dig
+task:
  _export:
    docker:
      image: your_image_bundle_installed_inside
  _env:
    BUNDLE_GEMFILE: /path/to/Gemfile/in/docker
  rb>: Workflow.foo
  require: tasks/workflow

欠点: 普通に ruby スクリプトを書くと require 'bundler/setup' を手書きすることはまず無いので違和感はある

方法2: BUNDLE_GEMFILE を指定して ruby オプションに -rbundler/setup を指定する

digdag >= 0.9.35 で有効。
方法1の欠点がない方法。

tasks/workflow.rb
require 'your_favorite_gem'

class Workflow
  def foo
  end
end
sample.dig
+task:
  _env:
    BUNDLE_GEMFILE: /path/to/Gemfile
  rb>: Workflow.foo
  ruby: ["ruby", "-rbundler/setup"]
  require: tasks/workflow

_export: docker: で rb オペレータを動かすのに docker を使っている時も使える。

sample_docker.dig
+task:
  _export:
    docker:
      image: your_image_bundle_installed_inside
    rb: 
      ruby: ["ruby", "-rbundler/setup"]
  _env:
    BUNDLE_GEMFILE: /path/to/Gemfile/in/docker
  rb>: Workflow.foo
  require: tasks/workflow

方法3: ラッパースクリプトを用意する

digdag >= 0.9.33 で有効

bundle_exec_ruby
#!/bin/bash

export BUNDLE_GEMFILE=/path/to/Gemfile
exec /path/to/ruby -rbundle/setup $*
tasks/workflow.rb
require 'your_favorite_gem'

class Workflow
  def foo
  end
end
sample.dig
+task:
  rb>: Workflow.foo
  require: tasks/workflow
  ruby: /path/to/bundle_exec_ruby

_export: docker: で rb オペレータを動かすのに docker を使っている時は docker イメージにスクリプトを入れ込めば使える。

sample_docker.rb
+task:
  _export:
    docker:
      image: your_image_bundle_installed_inside
  rb>: Workflow.foo
  require: tasks/workflow
  ruby: /path/to/bundle_exec_ruby/in/docker

欠点: bash スクリプトを用意するというひと手間が必要。

おわりに

個人的には .dig の外での準備が不要という点で、方法2が良いかとおもっている。

9
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
5