Skip to content

Commit bca5f07

Browse files
committed
Automatically fetch latest ruby-build version with 24h cache
1 parent ed89440 commit bca5f07

3 files changed

Lines changed: 107 additions & 19 deletions

File tree

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
ruby-build
2+
ruby-build-source
3+
.ruby-build-version-cache

README.md

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,20 @@ RUBY_APPLY_PATCHES=$'dir/1.patch\n2.patch\nhttp://example.com/3.patch' asdf inst
2727
RUBY_APPLY_PATCHES=$(curl -s https://raw.githubusercontent.com/rvm/rvm/master/patchsets/ruby/2.1.1/railsexpress) asdf install ruby 2.1.1
2828
```
2929

30-
> [!NOTE]
31-
> This plugin does not automatically fetch new Ruby versions. Running `asdf plugin update ruby` will update asdf-ruby and ensure the latest versions of Ruby are available to install. If the desired ruby version is still not showing up see the below [Troubleshooting](https://github.com/asdf-vm/asdf-ruby?tab=readme-ov-file#troubleshooting) section.
30+
By default asdf-ruby automatically fetches the latest release of ruby-build, so new Ruby versions are available as soon as ruby-build supports them.
3231

33-
By default asdf-ruby uses a recent release of ruby-build, however instead you can choose your own branch/tag through the `ASDF_RUBY_BUILD_VERSION` variable:
32+
You can override this behavior with the following environment variables:
3433

35-
```
36-
ASDF_RUBY_BUILD_VERSION=master asdf install ruby 2.6.4
37-
```
34+
- `ASDF_RUBY_BUILD_VERSION` - Pin to a specific ruby-build version/branch/tag:
35+
```
36+
ASDF_RUBY_BUILD_VERSION=v20240101 asdf install ruby 3.3.0
37+
ASDF_RUBY_BUILD_VERSION=master asdf install ruby 3.3.0
38+
```
39+
40+
- `ASDF_RUBY_BUILD_CACHE_CLEAR` - Bypass the 24-hour cache and fetch the latest version:
41+
```
42+
ASDF_RUBY_BUILD_CACHE_CLEAR=1 asdf list-all ruby
43+
```
3844

3945
## Default gems
4046

@@ -68,7 +74,7 @@ note that you might have to change `.ruby-version` to include full version (e.g.
6874
## Troubleshooting
6975

7076
> [!NOTE]
71-
> The most common issue reported for this plugin is a missing Ruby version. If you are not seeing a recent Ruby version in the list of available Ruby versions it's likely due to having an older version of this plugin. Run `asdf plugin update ruby` to get the most recent list of Ruby versions. If it is still not showing up then this plugin's `RUBY_BUILD_VERSION` in lib/utils.sh likely needs updated with the latest ruby-build release https://github.com/rbenv/ruby-build/releases. Please check for an existing PR before submitting a new one. If there is not one, please fork the repo and submit one. If this plugin's ruby-build needs updated, you can workaround it with `ASDF_RUBY_BUILD_VERSION`. A note in the above [Use](https://github.com/asdf-vm/asdf-ruby?tab=readme-ov-file#use) section describes how to do this.
77+
> If you are not seeing a recent Ruby version, try bypassing the version cache with `ASDF_RUBY_BUILD_CACHE_CLEAR=1 asdf list-all ruby` to fetch the latest ruby-build version. If the version still doesn't appear, check ruby-build's releases at https://github.com/rbenv/ruby-build/releases to see if it's been added yet.
7278
7379
If you are moving to asdf-ruby from another Ruby version manager, it is recommended to completely uninstall the old Ruby version manager before installing asdf-ruby.
7480

lib/utils.sh

Lines changed: 92 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
#!/usr/bin/env bash
22

3-
RUBY_BUILD_VERSION="${ASDF_RUBY_BUILD_VERSION:-v20260114}"
4-
RUBY_BUILD_TAG="$RUBY_BUILD_VERSION"
5-
63
echoerr() {
74
echo >&2 -e "\033[0;31m$1\033[0m"
85
}
@@ -17,30 +14,39 @@ ensure_ruby_build_setup() {
1714
}
1815

1916
ensure_ruby_build_installed() {
20-
local current_ruby_build_version
17+
local current_ruby_build_version target_version
18+
19+
target_version="$(get_ruby_build_version)"
2120

2221
if [ ! -f "$(ruby_build_path)" ]; then
23-
download_ruby_build
24-
else
22+
# No ruby-build installed - we must have a version to download
23+
if [ -z "$target_version" ]; then
24+
errorexit "Could not determine ruby-build version. Check your network connection."
25+
fi
26+
download_ruby_build "$target_version"
27+
elif [ -n "$target_version" ]; then
28+
# ruby-build exists and we have a target version - check if update needed
2529
current_ruby_build_version="$("$(ruby_build_path)" --version | cut -d ' ' -f2)"
2630
# If ruby-build version does not start with 'v',
2731
# add 'v' to beginning of version
2832
# shellcheck disable=SC2086
2933
if [ ${current_ruby_build_version:0:1} != "v" ]; then
3034
current_ruby_build_version="v$current_ruby_build_version"
3135
fi
32-
if [ "$current_ruby_build_version" != "$RUBY_BUILD_VERSION" ]; then
36+
if [ "$current_ruby_build_version" != "$target_version" ]; then
3337
# If the ruby-build directory already exists and the version does not
3438
# match, remove it and download the correct version
3539
rm -rf "$(ruby_build_dir)"
36-
download_ruby_build
40+
download_ruby_build "$target_version"
3741
fi
3842
fi
43+
# If ruby-build exists but we couldn't get a target version, just use what's installed
3944
}
4045

4146
download_ruby_build() {
47+
local version="$1"
4248
# Print to stderr so asdf doesn't assume this string is a list of versions
43-
echoerr "Downloading ruby-build..."
49+
echoerr "Downloading ruby-build ${version}..."
4450
# shellcheck disable=SC2155
4551
local build_dir="$(ruby_build_source_dir)"
4652

@@ -51,11 +57,13 @@ download_ruby_build() {
5157
git clone https://github.com/rbenv/ruby-build.git "$build_dir" >/dev/null 2>&1
5258
(
5359
cd "$build_dir" || exit
54-
git checkout "$RUBY_BUILD_TAG" >/dev/null 2>&1
60+
git checkout "$version" >/dev/null 2>&1
5561
)
5662

57-
# Install in the ruby-build dir
58-
PREFIX="$(ruby_build_dir)" "$build_dir/install.sh"
63+
# Install in the ruby-build dir (must use absolute path as install.sh changes directory)
64+
local install_dir
65+
install_dir="$(cd "$(asdf_ruby_plugin_path)" && pwd)/ruby-build"
66+
PREFIX="$install_dir" "$build_dir/install.sh"
5967

6068
# Remove ruby-build source dir
6169
rm -rf "$build_dir"
@@ -76,3 +84,75 @@ ruby_build_source_dir() {
7684
ruby_build_path() {
7785
echo "$(ruby_build_dir)/bin/ruby-build"
7886
}
87+
88+
ruby_build_version_cache_path() {
89+
echo "$(asdf_ruby_plugin_path)/.ruby-build-version-cache"
90+
}
91+
92+
# Get file modification time in seconds since epoch (cross-platform)
93+
get_file_mtime() {
94+
local file="$1"
95+
# Try GNU stat first (Linux), then BSD stat (macOS)
96+
stat -c %Y "$file" 2>/dev/null || stat -f %m "$file" 2>/dev/null
97+
}
98+
99+
# Fetch the latest ruby-build version tag from GitHub
100+
fetch_latest_ruby_build_version() {
101+
timeout 10 git ls-remote --tags --sort=-version:refname https://github.com/rbenv/ruby-build.git 2>/dev/null |
102+
grep -oE 'refs/tags/v[0-9]+$' |
103+
head -1 |
104+
sed 's|refs/tags/||'
105+
}
106+
107+
# Get the ruby-build version to use, with caching
108+
# Priority: ASDF_RUBY_BUILD_VERSION env var > cached latest > fetched latest > installed version
109+
get_ruby_build_version() {
110+
# If user explicitly set a version, use that
111+
if [ -n "${ASDF_RUBY_BUILD_VERSION:-}" ]; then
112+
echo "$ASDF_RUBY_BUILD_VERSION"
113+
return 0
114+
fi
115+
116+
local cache_file
117+
cache_file="$(ruby_build_version_cache_path)"
118+
119+
# Check cache first (unless ASDF_RUBY_BUILD_CACHE_CLEAR is set)
120+
if [ -z "${ASDF_RUBY_BUILD_CACHE_CLEAR:-}" ] && [ -f "$cache_file" ]; then
121+
local cache_mtime current_time age
122+
cache_mtime="$(get_file_mtime "$cache_file")"
123+
current_time="$(date +%s)"
124+
age=$((current_time - cache_mtime))
125+
126+
# Cache for 24 hours
127+
if [ "$age" -lt 86400 ]; then
128+
cat "$cache_file"
129+
return 0
130+
fi
131+
fi
132+
133+
# Fetch latest version from GitHub
134+
local latest_version
135+
latest_version="$(fetch_latest_ruby_build_version)"
136+
137+
if [ -n "$latest_version" ]; then
138+
echo "$latest_version" >"$cache_file"
139+
echo "$latest_version"
140+
return 0
141+
fi
142+
143+
# Fallback: if ruby-build is already installed, use its version
144+
# (if we can't reach GitHub, we likely can't download a new version anyway)
145+
if [ -f "$(ruby_build_path)" ]; then
146+
local installed_version
147+
installed_version="$("$(ruby_build_path)" --version | cut -d ' ' -f2)"
148+
if [ "${installed_version:0:1}" != "v" ]; then
149+
installed_version="v$installed_version"
150+
fi
151+
echoerr "Warning: Could not fetch latest ruby-build version, using installed version ${installed_version}"
152+
echo "$installed_version"
153+
return 0
154+
fi
155+
156+
# No version available
157+
return 1
158+
}

0 commit comments

Comments
 (0)