22時に寝ようと思って2時に寝る。

備忘録や日記を書いてます。きょうは早く寝よう。

CircleCI - macOS イメージを使用するときに Ruby のバージョンを指定する

はじめに

CircleCI が用意している macOS イメージを使用する際に、任意のバージョンの Ruby を使いたい場合があると思います。この記事では、macOS イメージにプリインストールされている chruby を用いて、Ruby バージョンを切り替える方法を紹介します。

macOS Container の Ruby 環境について

既に複数バージョンの Ruby が用意されている

macOS が用意しているコンテナイメージには、コンテナがビルドされた時点で最新である安定版の Ruby と、その他にもいくつかのバージョンの Ruby が用意されています。各イメージのマニフェストを確認することで、それぞれのイメージで用意されている Ruby の一覧を確認できます。

例えば、サポートされている Xcode Versions 一覧 から 11.3.0 (Build 11C29) の Installed Software を確認すると、

  • デフォルトで使用される System Rubyruby 2.6.3p62
  • chruby で使用可能な Ruby2.5.72.6.5

が、それぞれ用意されていることが分かります。

使用するイメージによって chruby の Auto-Switching 機能の設定が違う

chruby には、各プロジェクトに配置された .ruby-version を見て、Ruby のバージョンを自動で切り替えてくれる Auto-Switching 機能があります。

macOS 10.14 (Mojave) / Xcode 11.1 とそれ以前のイメージでは、この Auto-Switching 機能がデフォルトで有効に設定されていましたが、macOS 10.15 (Catalina) / Xcode 11.2 とそれ以降のイメージでは、自分で Auto-Switching 機能を有効に設定する必要があります。

なお、この仕様変更の理由が気になったので調べてみると、こちらのディスカッションで言及されていて、

The reason that I decided to leave it off by default, is that it’s easier for users who don’t expect it to understand the system. There is no “magic” happening in the default image. To enable autoswitching, you will have to add an explicit step to your build.

In my opinion (and I’m not claiming to be right), it’s easier to explain to someone that they need to enable the autoswitcher to select different versions of Ruby, than to explain to someone that they need to remove the autoswitcher from their bash profile to disable it.

要約すると、以下のような理由から変更したようです。

  • Auto-Switching 機能をデフォルトで有効でなくした理由は、Auto-Switching することを期待していないユーザーにもよりシステムを理解してもらいやすい
  • Auto-Switching しないように ~/.bash_profile から Auto-Switching するコードを削除する必要があることを説明するよりも、有効にする方法を説明するほうが簡単

この記事では、macOS 10.15 (Catalina) / Xcode 11.2 とそれ以降のイメージを使用することを想定して説明します。

chruby を使用して任意のバージョンの Ruby を指定する

chruby の Auto-Switching 機能を有効にする

chruby の README.md を参考に Auto-Switching を有効にするコマンドを追加しました。

commands:
  fix_ruby_version:
    steps:
      - run:
          name: Auto-Switching ruby version with chruby
          command: |
            echo 'source /usr/local/share/chruby/chruby.sh' >> $BASH_ENV
            echo 'source /usr/local/share/chruby/auto.sh' >> $BASH_ENV
            source $BASH_ENV
      - run:
          name: Install Bundler gem
          command: gem install -N bundler

また、切り替えた先の Ruby に Bundler がインストールされていないことがあるので、このタイミングで一緒にインストールするようにしています。

Ruby バージョンを指定するための .ruby-version を用意する

プロジェクトのルートディレクトリに、.ruby-version ファイルを作成し、イメージで用意されている任意の Ruby のバージョンを記述します。

ruby-2.6.5

各ジョブからコマンドを呼び出す

各ジョブで Ruby を使用する(Ruby gems をインストールするなど)より前に fix_ruby_version コマンドを呼び出すと良いと思います。

さいごに

ふとした時、なぜか .ruby-version で指定したバージョンに切り替わっていないことに気づき、調べてみると macOS 10.15 (Catalina) / Xcode 11.2 以降は Auto-Switching 機能の設定が必要だったということが分かった、、、ということがあり、今回記事にしてみました。

ちなみに、CircleCI の日本語ドキュメントにはいまのところ仕様変更への言及はなかったので、まずは英語ドキュメントをあたってみる心構えが大事なのかも、という気付きもありました。

参考