gemモジュール使用時は必ずversionを指定する

もうすぐ2.7が出るというのに今頃Rubyを2.6系にアップデートを行ったところ、動かなくなってしまった。

状況

ansibleで以下を行っている

  1. rbenvをインストール
  2. rbenv install を実行し、Ruby 2.6をインストール
  3. gemモジュールでrbenv以下のgemコマンドを指定してbundlerをインストール

それぞれのplaybookは次のようなイメージ

- name: create rbenv versions dir
  file:
    path: "{{ rbenv_root }}/versions"
    state: directory
    owner: root
    group: root
    mode: 0755

- name: check installed ruby
  command: "ls {{ rbenv_root }}/versions"
  check_mode: no
  register: installed_ruby_versions

- name: "install ruby {{ ruby_version }}"
  command: "bash -lc 'rbenv install {{ ruby_version }}'"
  when: installed_ruby_versions.stdout_lines.count(ruby_version) == 0

- name: "set global ruby to {{ ruby_version }}"
  command: "bash -lc 'rbenv global {{ ruby_version }}'"

- name: install bundler
  gem:
    name: "bundler"
    executable: "{{ rbenv_root }}/shims/gem"
    user_install: no
  environment:
    RBENV_VERSION: "{{ ruby_version }}"

起動しない原因

アプリ起動にbundler 2.0が必要だが、入っていない

なぜbundler 2.0が入らなかったのか

  • Ruby 2.6系はbundlerがプリインストールされている
  • ただしバージョン1.7、必要なバージョンは2.0
  • gemモジュールは既に対象のgemが入っていれば何もしないのがデフォルト。
  • 1.7が入っているため、2.0がインストールされなかった

なぜ2.5では問題なかったのか?

Ruby 2.5付属のgemにはbundlerが入っていないため、ansibleで最新版bundlerがインストールされた

対応

gemモジュールでstate: latest指定するか、version指定する

- name: install bundler
  gem:
    name: "bundler"
    version: "{{ bundler_version }}"
    executable: "{{ rbenv_root }}/shims/gem"
    user_install: no
  environment:
    RBENV_VERSION: "{{ ruby_version }}"

versionは必須ではないが、ansibleというツールの性質を考えると常にversionを指定した方がいいだろう。latestは予期せず最新版にアップデートされて何が起こるか分からないので避けた方が良いだろう。

community.general.gem – Manage Ruby gems — Ansible Documentation