Skip to content
14 changes: 10 additions & 4 deletions src/ruby/devcontainer-feature.json
Original file line number Diff line number Diff line change
@@ -1,21 +1,27 @@
{
"id": "ruby",
"version": "1.2.0",
"name": "Ruby (via rvm)",
"version": "1.2.0", // TODO - Is this a major or a minor update? Major, probably.
"name": "Ruby",
"documentationURL": "https://github.com/devcontainers/features/tree/main/src/ruby",
"description": "Installs Ruby, rvm, rbenv, common Ruby utilities, and needed dependencies.",
"options": {
"version": {
"type": "string",
"proposals": [
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implementing an os-provided Ruby is difficult.

The mcr.microsoft.com/devcontainers/base:bullseye image does not include Ruby. The Ruby devcontainer image (images/src/ruby/.devcontainer/Dockerfile in the devcontainer/images repository) is based upon a Ruby image from the official Ruby Docker images and not an image in the Microsoft container registry, which does include an installed Ruby. This is why my (not yet committed) test and change to handle this os-provided option isn't working.

I'm even hesitant to include a "none" option. But I did aim for parity with the Node Feature, and it offers a none option which just installs NVM. So I carried that option over here. I did notice, though, that Node also has the issue where their devcontainer image is based on an official Node docker image and not an image in the MCR.

"latest",
"os-provided",
"none",
"3.2",
"3.1",
"3.0",
"2.7"
"3.0"
],
"default": "latest",
"description": "Select or enter a Ruby version to install"
},
"additionalVersions": {
"type": "string",
"default": "",
"description": "Enter additional versions, separated by commas."
}
},
"customizations": {
Expand Down
95 changes: 15 additions & 80 deletions src/ruby/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,21 @@
# Docs: https://github.com/microsoft/vscode-dev-containers/blob/main/script-library/docs/ruby.md
# Maintainer: The VS Code and Codespaces Teams

RUBY_VERSION="${VERSION:-"latest"}"

USERNAME="${USERNAME:-"${_REMOTE_USER:-"automatic"}"}"
UPDATE_RC="${UPDATE_RC:-"true"}"
INSTALL_RUBY_TOOLS="${INSTALL_RUBY_TOOLS:-"true"}"
export RUBY_VERSION="${VERSION:-"latest"}"

# Comma-separated list of ruby versions to be installed (with rvm)
# alongside RUBY_VERSION, but not set as default.
ADDITIONAL_VERSIONS="${ADDITIONALVERSIONS:-""}"

# Note: ruby-debug-ide will install the right version of debase if missing and
# installing debase directly fails on Ruby 3.1.0 as of 1/7/2022, so omitting.
# installing ruby-debug-ide on debian fails, so omitting.
DEFAULT_GEMS="rake"
GPG_KEY_SERVERS="keyserver hkps://keys.openpgp.org
keyserver hkp://keyserver.pgp.com
keyserver hkp://pgp.mit.edu
keyserver hkp://ipv4.pool.sks-keyservers.net
keyserver hkp://keyserver.ubuntu.com
keyserver hkp://keyserver.ubuntu.com:80"
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added the keyservers recommended in the RVM documentation in addition to the ones previously included.


RVM_GPG_KEYS="409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB"
GPG_KEY_SERVERS="keyserver hkp://keyserver.ubuntu.com
keyserver hkp://keyserver.ubuntu.com:80
keyserver hkps://keys.openpgp.org
keyserver hkp://keyserver.pgp.com"
USERNAME="${USERNAME:-"${_REMOTE_USER:-"automatic"}"}"
UPDATE_RC="${UPDATE_RC:-"true"}"

set -e

Expand Down Expand Up @@ -106,7 +101,7 @@ receive_gpg_keys() {
fi
}

# Figure out correct version of a three part version number is not passed
# Figure out correct version if a three part version number is not passed
find_version_from_git_tags() {
local variable_name=$1
local requested_version=${!variable_name}
Expand Down Expand Up @@ -169,33 +164,32 @@ fi
check_packages curl ca-certificates software-properties-common build-essential gnupg2 libreadline-dev \
procps dirmngr gawk autoconf automake bison libffi-dev libgdbm-dev libncurses5-dev \
libsqlite3-dev libtool libyaml-dev pkg-config sqlite3 zlib1g-dev libgmp-dev libssl-dev

if ! type git > /dev/null 2>&1; then
check_packages git
fi


# Figure out correct version of a three part version number is not passed
find_version_from_git_tags RUBY_VERSION "https://github.com/ruby/ruby" "tags/v" "_"

# Just install Ruby if RVM already installed
if rvm --version > /dev/null; then
echo "Ruby Version Manager already exists."
if [[ "$(ruby -v)" = *"${RUBY_VERSION}"* ]]; then
echo "(!) Ruby is already installed with version ${RUBY_VERSION}. Skipping..."
echo "(!) Ruby is already installed with version ${RUBY_VERSION}."
elif [ "${RUBY_VERSION}" != "none" ]; then
echo "Installing specified Ruby version."
su ${USERNAME} -c "rvm install ruby ${RUBY_VERSION}"
fi
SKIP_GEM_INSTALL="false"
SKIP_RBENV_RBUILD="true"
else
# Install RVM
RVM_GPG_KEYS="409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB"
receive_gpg_keys RVM_GPG_KEYS
# Determine appropriate settings for rvm installer
if [ "${RUBY_VERSION}" = "none" ]; then
RVM_INSTALL_ARGS=""
elif [[ "$(ruby -v)" = *"${RUBY_VERSION}"* ]]; then
echo "(!) Ruby is already installed with version ${RUBY_VERSION}. Skipping..."
echo "(!) Ruby is already installed with version ${RUBY_VERSION}."
RVM_INSTALL_ARGS=""
else
if [ "${RUBY_VERSION}" = "latest" ] || [ "${RUBY_VERSION}" = "current" ] || [ "${RUBY_VERSION}" = "lts" ]; then
Expand All @@ -204,31 +198,19 @@ else
else
RVM_INSTALL_ARGS="--ruby=${RUBY_VERSION}"
fi
if [ "${INSTALL_RUBY_TOOLS}" = "true" ]; then
SKIP_GEM_INSTALL="true"
else
DEFAULT_GEMS=""
fi
fi
# Create rvm group as a system group to reduce the odds of conflict with local user UIDs
if ! cat /etc/group | grep -e "^rvm:" > /dev/null 2>&1; then
groupadd -r rvm
fi
# Install rvm
curl -sSL https://get.rvm.io | bash -s stable --ignore-dotfiles ${RVM_INSTALL_ARGS} --with-default-gems="${DEFAULT_GEMS}" 2>&1
curl -sSL https://get.rvm.io | bash -s stable --ignore-dotfiles ${RVM_INSTALL_ARGS} 2>&1
usermod -aG rvm ${USERNAME}
source /usr/local/rvm/scripts/rvm
rvm fix-permissions system
rm -rf ${GNUPGHOME}
fi

if [ "${INSTALL_RUBY_TOOLS}" = "true" ]; then
# Non-root user may not have "gem" in path when script is run and no ruby version
# is installed by rvm, so handle this by using root's default gem in this case
ROOT_GEM="$(which gem || echo "")"
${ROOT_GEM} install ${DEFAULT_GEMS}
fi

# VS Code server usually first in the path, so silence annoying rvm warning (that does not apply) and then source it
updaterc "if ! grep rvm_silence_path_mismatch_check_flag \$HOME/.rvmrc > /dev/null 2>&1; then echo 'rvm_silence_path_mismatch_check_flag=1' >> \$HOME/.rvmrc; fi\nsource /usr/local/rvm/scripts/rvm > /dev/null 2>&1"

Expand All @@ -246,59 +228,12 @@ if [ ! -z "${ADDITIONAL_VERSIONS}" ]; then
IFS=$OLDIFS
fi

# Install rbenv/ruby-build for good measure
if [ "${SKIP_RBENV_RBUILD}" != "true" ]; then

if [[ ! -d "/usr/local/share/rbenv" ]]; then
git clone --depth=1 \
-c core.eol=lf \
-c core.autocrlf=false \
-c fsck.zeroPaddedFilemode=ignore \
-c fetch.fsck.zeroPaddedFilemode=ignore \
-c receive.fsck.zeroPaddedFilemode=ignore \
https://github.com/rbenv/rbenv.git /usr/local/share/rbenv
fi

if [[ ! -d "/usr/local/share/ruby-build" ]]; then
git clone --depth=1 \
-c core.eol=lf \
-c core.autocrlf=false \
-c fsck.zeroPaddedFilemode=ignore \
-c fetch.fsck.zeroPaddedFilemode=ignore \
-c receive.fsck.zeroPaddedFilemode=ignore \
https://github.com/rbenv/ruby-build.git /usr/local/share/ruby-build
mkdir -p /root/.rbenv/plugins

ln -s /usr/local/share/ruby-build /root/.rbenv/plugins/ruby-build
fi

if [ "${USERNAME}" != "root" ]; then
mkdir -p /home/${USERNAME}/.rbenv/plugins

if [[ ! -d "/home/${USERNAME}/.rbenv/plugins/ruby-build" ]]; then
ln -s /usr/local/share/ruby-build /home/${USERNAME}/.rbenv/plugins/ruby-build
fi

# Oryx expects ruby to be installed in this specific path, else it breaks the oryx magic for ruby projects.
if [ ! -f /usr/local/rvm/gems/default/bin/ruby ]; then
ln -s /usr/local/rvm/rubies/default/bin/ruby /usr/local/rvm/gems/default/bin
fi

chown -R "${USERNAME}:rvm" "/home/${USERNAME}/.rbenv/"
chmod -R g+r+w "/home/${USERNAME}/.rbenv"
find "/home/${USERNAME}/.rbenv" -type d | xargs -n 1 chmod g+s
fi
fi

chown -R "${USERNAME}:rvm" "/usr/local/rvm/"
chmod -R g+r+w "/usr/local/rvm/"
find "/usr/local/rvm/" -type d | xargs -n 1 chmod g+s

# Clean up
rvm cleanup all
${ROOT_GEM} cleanup

# Clean up
rm -rf /var/lib/apt/lists/*

echo "Done!"
12 changes: 12 additions & 0 deletions test/ruby/additional_versions.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/bin/bash

set -e

# Optional: Import test library
source dev-container-features-test-lib

check "3.0.6 installed" bash -c "rvm list | fgrep 3.0.6"
check "2.7.8 installed" bash -c "rvm list | fgrep 2.7.8"

# Report result
reportResults
16 changes: 0 additions & 16 deletions test/ruby/install_additional_ruby.sh

This file was deleted.

4 changes: 2 additions & 2 deletions test/ruby/ruby_debian.sh → test/ruby/no_version.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ set -e
# Optional: Import test library
source dev-container-features-test-lib

check "ruby" ruby -v
check "rake" bash -c "gem list | grep rake"
# Definition specific tests
check "rvm" rvm --version

# Report result
reportResults
13 changes: 13 additions & 0 deletions test/ruby/non_root_user.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/bin/bash

set -e

# Optional: Import test library
source dev-container-features-test-lib

# Definition specific tests
check "version" rvm --version
check "ruby version" ruby --version

# Report result
reportResults
12 changes: 12 additions & 0 deletions test/ruby/older_version.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/bin/bash

set -e

# Optional: Import test library
source dev-container-features-test-lib

# Definition specific tests
check "ruby installed" bash -c "ruby --version | grep 3.0.6"

# Report result
reportResults
33 changes: 26 additions & 7 deletions test/ruby/scenarios.json
Original file line number Diff line number Diff line change
@@ -1,17 +1,36 @@
{
"install_additional_ruby": {
"image": "ubuntu:focal",
"non_root_user": {
"image": "mcr.microsoft.com/devcontainers/base:bullseye",
"remoteUser": "vscode",
"features": {
"ruby": {
"version": "latest"
}
}
},
"additional_versions": {
"image": "mcr.microsoft.com/devcontainers/base:bullseye",
"features": {
"ruby": {
"version": "3.1.2",
"additionalVersions": "2.5,3.0.4"
"version": "latest",
"additionalVersions": "3.0.6,2.7.8"
}
}
},
"ruby_debian": {
"older_version": {
"image": "mcr.microsoft.com/devcontainers/base:bullseye",
"features": {
"ruby": {}
"ruby": {
"version": "3.0.6"
}
}
},
"no_version": {
"image": "mcr.microsoft.com/devcontainers/base:bullseye",
"features": {
"ruby": {
"version": "none"
}
}
}
}
}