Netlify build doesn't honor the RUBY_VERSION environment variable

I’ve a blog site that is built using a Ruby gem.

Site name: non-compos-mentis

It seems Netlify is installing the Ruby version specified in the netlify.toml RUBY_VERSION = "3.3.2", but not honoring it during the build, since I get the error “Your Ruby version is 2.7.2, but your Gemfile specified ~> 3.3”.

Gemfile

source "https://rubygems.org"
# Version to be installed is specified in netlify.toml
ruby "~> 3.3"

gem "jekyll", "~> 4"
gem "jekyll-include-cache"
gem "jekyll-archives"
gem "minimal-mistakes-jekyll"
gem "html-proofer", "~> 5"
gem "jemoji"
gem "kramdown", "~> 2"
gem 'kramdown-parser-gfm'

Build Logs

Failed during stage 'building site': Build script returned non-zero exit code: 2 (https://ntl.fyi/exit-code-2)
Your Ruby version is 2.7.2, but your Gemfile specified ~> 3.3

"build.command" failed                                        
────────────────────────────────────────────────────────────────

  Error message
  Command failed with exit code 18: ./script/cibuild (https://ntl.fyi/exit-code-18)

  Error location
  In build.command from netlify.toml:
  ./script/cibuild

  Resolved config
  build:
    command: ./script/cibuild
    commandOrigin: config
    environment:
      - JEKYLL_ENV
      - RUBY_VERSION
    publish: /opt/build/repo/public
    publishOrigin: config
  redirects:
    ...

Initialization logs clearly show the desired version of Ruby being installed.

12:19:32 AM: Installing Ruby from source to: /opt/buildhome/.rvm/rubies/ruby-3.3.2, this may take a while depending on your cpu(s)...
12:19:32 AM: ruby-3.3.2 - #downloading ruby-3.3.2, this may take a while depending on your connection...
12:19:32 AM: No checksum for downloaded archive, recording checksum in user configuration.
12:19:33 AM: ruby-3.3.2 - #extracting ruby-3.3.2 to /opt/buildhome/.rvm/src/ruby-3.3.2.....
12:20:02 AM: ruby-3.3.2 - #configuring..................................................................
12:20:02 AM: ruby-3.3.2 - #post-configuration..
12:21:57 AM: ruby-3.3.2 - #compiling........................................................................................................
12:22:02 AM: ruby-3.3.2 - #installing......................
12:22:02 AM: ruby-3.3.2 - #making binaries executable...

After hours of debugging, I’ve found the root cause and believe it to be most certainly a bug.

The login shell is /usr/sbin/nologin.

~/.bashrc

# Add RVM to PATH for scripting. Make sure this is the last PATH variable change.
export PATH="$PATH:$HOME/.rvm/bin"
. "$HOME/.cargo/env"

This is missing sourcing of the file $HOME/.rvm/scripts/rvm as instructed in the RVM docs for a single user installation.

Thus, when a script is executed using bash shebang, the above file is not sourced, and neither is the Ruby version set. Doing the following in the shell script solved the Ruby version conflict.

if [[ -f "$HOME/.rvm/scripts/rvm" ]]; then
  source "$HOME/.rvm/scripts/rvm"
  rvm use "$RUBY_VERSION" --default
fi

This was reported here as well: Ruby not installed automatically, but was left unanswered by the user. I’ve passed this new info to the devs.

@hrishikesh That seems to be a completely different issue regarding the location of .ruby-verison, please don’t conflate the two.

I further inspected the Netlify build image, and found that the "$HOME/.rvm/scripts/rvm" is sourced in the ~/.profile. As I mentioned above, because the buildbot user doesn’t have a login shell, this file is not executed. When I ran my CI script with a #!/bin/bash -l shebang, it picked up the ~/.profile file, and the rvm script was sourced as expected. The code block shown above was no longer required.

In conclusion, this is a documentation gap more than a software bug. The average user not looking into Netlify custom build image would not know to force execute the ~/.profile, and run into all sorts of path issues.