diff --git a/README.md b/README.md index 44a86be27..a24d22c43 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,10 @@ Not all combinations of runner images and versions are supported. The list of available Ruby versions can be seen in [ruby-builder-versions.json](ruby-builder-versions.json) for Ubuntu and macOS (although some combinations are not available, see [the full list](https://github.com/ruby/ruby-builder/releases/tag/toolcache)) and in [windows-versions.json](windows-versions.json) for Windows. +Newer runner images usually only have builds of the latest patch release of each series, +so prefer a short version like `'3.4'` over an exact one like `'3.4.2'` in `ruby-version` or `.ruby-version`. +For example, `ubuntu-26.04` (which `ubuntu-latest` moves to, see [this announcement](https://github.com/actions/runner-images/issues/14748)) +only has builds of CRuby 3.2 and newer, as older CRuby versions do not compile on it. The prebuilt releases are generated by [ruby-builder](https://github.com/ruby/ruby-builder) and on Windows by [RubyInstaller2](https://github.com/oneclick/rubyinstaller2). diff --git a/dist/index.js b/dist/index.js index e11589521..ebcff2703 100644 --- a/dist/index.js +++ b/dist/index.js @@ -50281,7 +50281,7 @@ async function downloadAndExtract(platform, engine, version, rubyPrefix) { } catch (error) { if (error.message.includes('404')) { throw new Error(`Unavailable version ${version} for ${engine} on ${platform} - You can request it at https://github.com/ruby/setup-ruby/issues + ${await unavailableVersionHint(platform, engine, version)} Cause: ${error.message}`) } else { throw error @@ -50303,6 +50303,42 @@ async function downloadAndExtract(platform, engine, version, rubyPrefix) { } } +// Newer runner images usually only have builds of the latest patch release of each series, +// so point to that release if it is available, or explain that the series is not available. +async function unavailableVersionHint(platform, engine, version) { + const request = 'You can request it at https://github.com/ruby/setup-ruby/issues' + const series = version.split('.').slice(0, 2).join('.') + const latest = getAvailableVersions(platform, engine) + .filter(v => v.startsWith(`${series}.`) && common.isStableVersion(engine, v)) + .pop() + if (common.isHeadVersion(version) || latest === undefined) { + return request + } + + const input = v => engine === 'ruby' ? v : `${engine}-${v}` + if (latest !== version) { + let response + try { + response = await fetch(getDownloadURL(platform, engine, latest), { method: 'HEAD', signal: AbortSignal.timeout(10000) }) + } catch { + return request + } + if (response.ok) { + return `Only the latest patch release of each series is built for newer runner images. + ${engine}-${latest} is available on ${platform}: use ruby-version: '${input(latest)}', or '${input(series)}' to always use the latest ${series}.x release.` + } else if (response.status !== 404) { + return request + } + } + + const latestUnavailable = latest === version + ? `${engine}-${version} is the latest ${series}.x release.` + : `${engine}-${latest}, the latest ${series}.x release, is not available on ${platform} either.` + return `${latestUnavailable} + Use a newer ${engine} version on ${platform}, or an older runner image for ${engine} ${series}. + Note that ubuntu-latest and macos-latest move to newer runner images over time.` +} + function getDownloadURL(platform, engine, version) { let builderPlatform = null if (platform.startsWith('windows-')) { diff --git a/ruby-builder.js b/ruby-builder.js index 52041c889..502779080 100644 --- a/ruby-builder.js +++ b/ruby-builder.js @@ -78,7 +78,7 @@ async function downloadAndExtract(platform, engine, version, rubyPrefix) { } catch (error) { if (error.message.includes('404')) { throw new Error(`Unavailable version ${version} for ${engine} on ${platform} - You can request it at https://github.com/ruby/setup-ruby/issues + ${await unavailableVersionHint(platform, engine, version)} Cause: ${error.message}`) } else { throw error @@ -100,6 +100,42 @@ async function downloadAndExtract(platform, engine, version, rubyPrefix) { } } +// Newer runner images usually only have builds of the latest patch release of each series, +// so point to that release if it is available, or explain that the series is not available. +async function unavailableVersionHint(platform, engine, version) { + const request = 'You can request it at https://github.com/ruby/setup-ruby/issues' + const series = version.split('.').slice(0, 2).join('.') + const latest = getAvailableVersions(platform, engine) + .filter(v => v.startsWith(`${series}.`) && common.isStableVersion(engine, v)) + .pop() + if (common.isHeadVersion(version) || latest === undefined) { + return request + } + + const input = v => engine === 'ruby' ? v : `${engine}-${v}` + if (latest !== version) { + let response + try { + response = await fetch(getDownloadURL(platform, engine, latest), { method: 'HEAD', signal: AbortSignal.timeout(10000) }) + } catch { + return request + } + if (response.ok) { + return `Only the latest patch release of each series is built for newer runner images. + ${engine}-${latest} is available on ${platform}: use ruby-version: '${input(latest)}', or '${input(series)}' to always use the latest ${series}.x release.` + } else if (response.status !== 404) { + return request + } + } + + const latestUnavailable = latest === version + ? `${engine}-${version} is the latest ${series}.x release.` + : `${engine}-${latest}, the latest ${series}.x release, is not available on ${platform} either.` + return `${latestUnavailable} + Use a newer ${engine} version on ${platform}, or an older runner image for ${engine} ${series}. + Note that ubuntu-latest and macos-latest move to newer runner images over time.` +} + function getDownloadURL(platform, engine, version) { let builderPlatform = null if (platform.startsWith('windows-')) {