rbenv
The RBENV plugin - install rbenv and specific Ruby versions.
Installs and wires up rbenv (+ ruby-build) on the deploy hosts, ensures the Ruby versions your app needs are built, and makes rbenv available to every subsequent whoosh task — all before the new release goes live.
The plugin ships in the default whoosh binary. If you use whoosh-core, add it to a custom build:
whoosh build --with github.com/yousysadmin/whoosh/plugins/rbenv
(see Installation -> With custom plugins) - then list it under plugins:.
What it does
Listing the plugin is enough. Its startup hook contributes a task (rbenv:setup)
and auto-wires it to run before the deploy:updated phase — you don’t add
anything to hooks:. On each run, on every targeted host, it:
- Checks whether rbenv is installed — under
root($HOME/.rbenvby default) or already onPATH— and, if not, git-clones rbenv intoroot. - Installs the builder — clones ruby-build into
<root>/plugins/ruby-buildsorbenv installworks (skipped wheninstall_ruby: false). - Registers rbenv in the shell rc files (
.bashrc,.zshrc, …) via a marker-guarded, idempotentrbenv initblock. - Ensures the desired Ruby versions are installed — the union of the
versions:param and any.ruby-versionfile (read on the operator at load time, and from the previous release on the host). Withprune: true, versions not in that set are uninstalled (globalis always kept). Optionally runsrbenv global. - Injects rbenv into whoosh’s env context — prepends
<root>/binand<root>/shimstoPATHand exportsRBENV_ROOTfor every later task, sobundle,rails, andrakeresolve the rbenv Ruby with no extra config. Also exposed to templates as{{ .rbenv.root }}.
Everything is idempotent, so leaving the plugin listed across deploys is cheap.
Requirements on the host
git(to clone rbenv / ruby-build).To build Ruby: the usual ruby-build toolchain — a C compiler and the openssl / readline / zlib development headers.
The plugin does not install system packages, see the official ruby-build wiki.
Configuration
plugins:
- name: rbenv
params:
root: "$HOME/.rbenv" # install dir, "~" expands to $HOME (default $HOME/.rbenv)
versions: ["3.3.0", "3.2.2"] # Ruby versions to ensure (union with .ruby-version)
global: "3.3.0" # optional: rbenv global (always kept from pruning)
prune: false # uninstall Ruby versions not in the desired set (opt-in)
read_ruby_version: true # also derive versions from .ruby-version (default true)
ruby_version_file: ".ruby-version" # operator-side path, relative to the Deployfile dir
update: false # git pull rbenv/ruby-build when already present
install_ruby: true # false = install only rbenv, no Ruby builds
shells: ["bash", "zsh"] # shell rc files to register rbenv init in
roles: ["app"] # restrict to these roles (default: all deployable hosts)
inject_path: true # prepend rbenv bin+shims to whoosh's PATH (default true)
build_env: # extra env for ruby-build at compile time
RUBY_CONFIGURE_OPTS: "--with-jemalloc --enable-yjit"
MAKEOPTS: "-j 1"
default_gems: # gems installed into every Ruby (rbenv-default-gems)
- bundler
- bcat ~>0.6
- rails --pre
plugins: # extra rbenv plugins to git-clone
- { name: rbenv-vars, repo: https://github.com/rbenv/rbenv-vars.git, version: v1.2.0 }
rbenv_repo: "https://github.com/rbenv/rbenv.git"
ruby_build_repo: "https://github.com/rbenv/ruby-build.git"
default_gems_repo: "https://github.com/rbenv/rbenv-default-gems.git"
# Advanced: move the setup hook.
task_name: "rbenv:setup" # name of the contributed task
phase: "deploy:updated" # phase to anchor the hook to
when: "before" # "before" (default) or "after"
How Ruby versions are resolved
The desired set is the union of:
versions:(explicit),global:(when set),- the operator-side
.ruby-version(read at load fromruby_version_file, relative to the Deployfile directory) — this is the version of the app you are deploying, and - the previous release’s
.ruby-versionon each host ($CURRENT_PATH/.ruby-version).
The setup runs before the release is published, so on the host it only sees the
previous release’s .ruby-version (via the current symlink) — the version of
the app being deployed is picked up operator-side: run whoosh from your app
repo (or point ruby_version_file at it). Set read_ruby_version: false to use
only the explicit versions:/global:.
Ruby build options
build_env is exported for the setup task, so ruby-build sees it when it compiles
Ruby — e.g. RUBY_CONFIGURE_OPTS: "--with-jemalloc --enable-yjit" or
MAKEOPTS: "-j 1". Values are shell-expanded on the host, so "-j $(nproc)"
works. The plugin’s own RBENV_* control variables always take precedence over
build_env.
Default gems
When default_gems is set, the plugin installs the
rbenv-default-gems plugin and writes
the list to $RBENV_ROOT/default-gems (one entry per line), so every Ruby built
by rbenv install automatically gets those gems. Each entry is a gem name optionally
followed by a version requirement or gem options, matching the default-gems file
format:
default_gems:
- bundler # latest
- bcat ~>0.6 # version requirement
- rails --pre # gem options
The setup runs before the Ruby-install step, so the list applies to versions built
in the same run. Leave default_gems unset to skip the plugin entirely. Override the
plugin source with default_gems_repo.
Extra rbenv plugins
plugins git-clones additional rbenv plugins into $RBENV_ROOT/plugins/<name> (the
same place ruby-build and rbenv-default-gems live). Each entry needs a name (the
plugin dir) and a repo URL, and may pin a version — a tag, branch, or commit SHA:
plugins:
- { name: rbenv-vars, repo: https://github.com/rbenv/rbenv-vars.git, version: v1.2.0 }
- { name: rbenv-update, repo: https://github.com/rkh/rbenv-update.git, version: 1961fa180280bb50b64cbbffe6a5df7cf70f5e50 }
- { name: rbenv-installer, repo: https://github.com/rbenv/rbenv-installer.git } # latest
With a version, the plugin is fully cloned and checked out at that ref (so any commit
SHA is reachable), without one it is a shallow clone of the default branch. It is
idempotent: on a re-run a pinned plugin is fetched and re-checked-out at its version,
and an unpinned one is git pulled only when update: true. Each is cloned before the
Ruby-install step so install-time plugins take effect. ruby-build and rbenv-default-gems
are managed by their own pinned options and need not be listed here.
Running it standalone
The contributed task is a normal task, so you can run it outside a deploy: phases.
whoosh <stage> rbenv:setup