Skip to content

Commit fbbff8d

Browse files
CyberNativeAIeregon
authored andcommitted
Suggest the latest patch release when a version is unavailable
Newer runner images such as ubuntu-26.04 only have builds of the latest patch release of each series, so an exact version like 3.4.2 from .ruby-version fails with a 404 and only a link to request the build. On a 404, check whether the latest release of the same series exists for the platform. If it does, name it and the short version that always picks it. If it does not, say so and suggest a newer version or an older runner image. If that check fails for another reason, keep the previous message. Also document this in the README.
1 parent 651ff0d commit fbbff8d

3 files changed

Lines changed: 78 additions & 2 deletions

File tree

‎README.md‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ Not all combinations of runner images and versions are supported.
5757
The list of available Ruby versions can be seen in [ruby-builder-versions.json](ruby-builder-versions.json) for Ubuntu and macOS
5858
(although some combinations are not available, see [the full list](https://github.com/ruby/ruby-builder/releases/tag/toolcache))
5959
and in [windows-versions.json](windows-versions.json) for Windows.
60+
Newer runner images usually only have builds of the latest patch release of each series,
61+
so prefer a short version like `'3.4'` over an exact one like `'3.4.2'` in `ruby-version` or `.ruby-version`.
62+
For example, `ubuntu-26.04` (which `ubuntu-latest` moves to, see [this announcement](https://github.com/actions/runner-images/issues/14748))
63+
only has builds of CRuby 3.2 and newer, as older CRuby versions do not compile on it.
6064

6165
The prebuilt releases are generated by [ruby-builder](https://github.com/ruby/ruby-builder)
6266
and on Windows by [RubyInstaller2](https://github.com/oneclick/rubyinstaller2).

‎dist/index.js‎

Lines changed: 37 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎ruby-builder.js‎

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ async function downloadAndExtract(platform, engine, version, rubyPrefix) {
7878
} catch (error) {
7979
if (error.message.includes('404')) {
8080
throw new Error(`Unavailable version ${version} for ${engine} on ${platform}
81-
You can request it at https://github.com/ruby/setup-ruby/issues
81+
${await unavailableVersionHint(platform, engine, version)}
8282
Cause: ${error.message}`)
8383
} else {
8484
throw error
@@ -100,6 +100,42 @@ async function downloadAndExtract(platform, engine, version, rubyPrefix) {
100100
}
101101
}
102102

103+
// Newer runner images usually only have builds of the latest patch release of each series,
104+
// so point to that release if it is available, or explain that the series is not available.
105+
async function unavailableVersionHint(platform, engine, version) {
106+
const request = 'You can request it at https://github.com/ruby/setup-ruby/issues'
107+
const series = version.split('.').slice(0, 2).join('.')
108+
const latest = getAvailableVersions(platform, engine)
109+
.filter(v => v.startsWith(`${series}.`) && common.isStableVersion(engine, v))
110+
.pop()
111+
if (common.isHeadVersion(version) || latest === undefined) {
112+
return request
113+
}
114+
115+
const input = v => engine === 'ruby' ? v : `${engine}-${v}`
116+
if (latest !== version) {
117+
let response
118+
try {
119+
response = await fetch(getDownloadURL(platform, engine, latest), { method: 'HEAD', signal: AbortSignal.timeout(10000) })
120+
} catch {
121+
return request
122+
}
123+
if (response.ok) {
124+
return `Only the latest patch release of each series is built for newer runner images.
125+
${engine}-${latest} is available on ${platform}: use ruby-version: '${input(latest)}', or '${input(series)}' to always use the latest ${series}.x release.`
126+
} else if (response.status !== 404) {
127+
return request
128+
}
129+
}
130+
131+
const latestUnavailable = latest === version
132+
? `${engine}-${version} is the latest ${series}.x release.`
133+
: `${engine}-${latest}, the latest ${series}.x release, is not available on ${platform} either.`
134+
return `${latestUnavailable}
135+
Use a newer ${engine} version on ${platform}, or an older runner image for ${engine} ${series}.
136+
Note that ubuntu-latest and macos-latest move to newer runner images over time.`
137+
}
138+
103139
function getDownloadURL(platform, engine, version) {
104140
let builderPlatform = null
105141
if (platform.startsWith('windows-')) {

0 commit comments

Comments
 (0)