From 0d75597992bea8095cb31c8a209766af131434c3 Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Fri, 3 Mar 2023 16:59:46 +0100 Subject: [PATCH 1/3] Consider a different $RUNNER_TOOL_CACHE than the default as a self-hosted runner * Fixes https://github.com/ruby/setup-ruby/issues/242 --- common.js | 30 ++++++++++++++++++------------ dist/index.js | 33 ++++++++++++++++++++------------- ruby-builder.js | 2 +- 3 files changed, 39 insertions(+), 26 deletions(-) diff --git a/common.js b/common.js index e1de56945..5ec89a194 100644 --- a/common.js +++ b/common.js @@ -162,9 +162,12 @@ const GitHubHostedPlatforms = [ 'windows-2022-x64', ] -// Actually a self-hosted runner which does not correspond to a GitHub-hosted runner image +// Actually a self-hosted runner for which either +// * the OS and OS version does not correspond to a GitHub-hosted runner image, +// * or the hosted tool cache is different from the default tool cache path export function isSelfHostedRunner() { - return !GitHubHostedPlatforms.includes(getOSNameVersionArch()) + return !GitHubHostedPlatforms.includes(getOSNameVersionArch()) || + getRunnerToolCache() !== getDefaultToolCachePath() } let virtualEnvironmentName = undefined @@ -213,28 +216,31 @@ export function shouldUseToolCache(engine, version) { return (engine === 'ruby' && !isHeadVersion(version)) || isSelfHostedRunner() } -function getPlatformToolCache(platform) { - if (isSelfHostedRunner()) { - const runnerToolCache = process.env['RUNNER_TOOL_CACHE'] - if (!runnerToolCache) { - throw new Error('$RUNNER_TOOL_CACHE must be set on self-hosted runners') - } - return runnerToolCache +export function getRunnerToolCache() { + const runnerToolCache = process.env['RUNNER_TOOL_CACHE'] + if (!runnerToolCache) { + throw new Error('$RUNNER_TOOL_CACHE must be set') } - // Hardcode paths rather than using $RUNNER_TOOL_CACHE because the prebuilt Rubies cannot be moved anyway + return runnerToolCache +} + +// Rubies prebuilt by this action embed this path rather than using $RUNNER_TOOL_CACHE, +// so they can only be used if the two paths are the same +function getDefaultToolCachePath() { + const platform = getVirtualEnvironmentName() if (platform.startsWith('ubuntu-')) { return '/opt/hostedtoolcache' } else if (platform.startsWith('macos-')) { return '/Users/runner/hostedtoolcache' } else if (platform.startsWith('windows-')) { - return 'C:/hostedtoolcache/windows' + return 'C:\\hostedtoolcache\\windows' } else { throw new Error('Unknown platform') } } export function getToolCacheRubyPrefix(platform, engine, version) { - const toolCache = getPlatformToolCache(platform) + const toolCache = getRunnerToolCache() const name = { ruby: 'Ruby', jruby: 'JRuby', diff --git a/dist/index.js b/dist/index.js index 21810eadb..977d2e67a 100644 --- a/dist/index.js +++ b/dist/index.js @@ -291,6 +291,7 @@ __nccwpck_require__.d(__webpack_exports__, { "drive": () => (/* binding */ drive), "floatVersion": () => (/* binding */ floatVersion), "getOSNameVersionArch": () => (/* binding */ getOSNameVersionArch), + "getRunnerToolCache": () => (/* binding */ getRunnerToolCache), "getToolCacheRubyPrefix": () => (/* binding */ getToolCacheRubyPrefix), "getVirtualEnvironmentName": () => (/* binding */ getVirtualEnvironmentName), "hasBundlerDefaultGem": () => (/* binding */ hasBundlerDefaultGem), @@ -514,9 +515,12 @@ const GitHubHostedPlatforms = [ 'windows-2022-x64', ] -// Actually a self-hosted runner which does not correspond to a GitHub-hosted runner image +// Actually a self-hosted runner for which either +// * the OS and OS version does not correspond to a GitHub-hosted runner image, +// * or the hosted tool cache is different from the default tool cache path function isSelfHostedRunner() { - return !GitHubHostedPlatforms.includes(getOSNameVersionArch()) + return !GitHubHostedPlatforms.includes(getOSNameVersionArch()) || + getRunnerToolCache() !== getDefaultToolCachePath() } let virtualEnvironmentName = undefined @@ -565,28 +569,31 @@ function shouldUseToolCache(engine, version) { return (engine === 'ruby' && !isHeadVersion(version)) || isSelfHostedRunner() } -function getPlatformToolCache(platform) { - if (isSelfHostedRunner()) { - const runnerToolCache = process.env['RUNNER_TOOL_CACHE'] - if (!runnerToolCache) { - throw new Error('$RUNNER_TOOL_CACHE must be set on self-hosted runners') - } - return runnerToolCache +function getRunnerToolCache() { + const runnerToolCache = process.env['RUNNER_TOOL_CACHE'] + if (!runnerToolCache) { + throw new Error('$RUNNER_TOOL_CACHE must be set') } - // Hardcode paths rather than using $RUNNER_TOOL_CACHE because the prebuilt Rubies cannot be moved anyway + return runnerToolCache +} + +// Rubies prebuilt by this action embed this path rather than using $RUNNER_TOOL_CACHE, +// so they can only be used if the two paths are the same +function getDefaultToolCachePath() { + const platform = getVirtualEnvironmentName() if (platform.startsWith('ubuntu-')) { return '/opt/hostedtoolcache' } else if (platform.startsWith('macos-')) { return '/Users/runner/hostedtoolcache' } else if (platform.startsWith('windows-')) { - return 'C:/hostedtoolcache/windows' + return 'C:\\hostedtoolcache\\windows' } else { throw new Error('Unknown platform') } } function getToolCacheRubyPrefix(platform, engine, version) { - const toolCache = getPlatformToolCache(platform) + const toolCache = getRunnerToolCache() const name = { ruby: 'Ruby', jruby: 'JRuby', @@ -68253,7 +68260,7 @@ async function install(platform, engine, version) { if (common.isSelfHostedRunner()) { const rubyBuildDefinition = engine === 'ruby' ? version : `${engine}-${version}` core.error( - `The current runner (${common.getOSNameVersionArch()}) was detected as self-hosted and not matching a GitHub-hosted runner image.\n` + + `The current runner (${common.getOSNameVersionArch()}, RUNNER_TOOL_CACHE=${common.getRunnerToolCache()}) was detected as self-hosted and not matching a GitHub-hosted runner image.\n` + `In such a case, you should install Ruby in the $RUNNER_TOOL_CACHE yourself, for example using https://github.com/rbenv/ruby-build:\n` + `You can take inspiration from this workflow for more details: https://github.com/ruby/ruby-builder/blob/master/.github/workflows/build.yml\n` + `$ ruby-build ${rubyBuildDefinition} ${toolCacheRubyPrefix}\n` + diff --git a/ruby-builder.js b/ruby-builder.js index 4b124a35f..917ca0680 100644 --- a/ruby-builder.js +++ b/ruby-builder.js @@ -28,7 +28,7 @@ export async function install(platform, engine, version) { if (common.isSelfHostedRunner()) { const rubyBuildDefinition = engine === 'ruby' ? version : `${engine}-${version}` core.error( - `The current runner (${common.getOSNameVersionArch()}) was detected as self-hosted and not matching a GitHub-hosted runner image.\n` + + `The current runner (${common.getOSNameVersionArch()}, RUNNER_TOOL_CACHE=${common.getRunnerToolCache()}) was detected as self-hosted and not matching a GitHub-hosted runner image.\n` + `In such a case, you should install Ruby in the $RUNNER_TOOL_CACHE yourself, for example using https://github.com/rbenv/ruby-build:\n` + `You can take inspiration from this workflow for more details: https://github.com/ruby/ruby-builder/blob/master/.github/workflows/build.yml\n` + `$ ruby-build ${rubyBuildDefinition} ${toolCacheRubyPrefix}\n` + From d08d24c15851206eddc1f86e36f4f6adbca1188b Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Fri, 3 Mar 2023 17:10:02 +0100 Subject: [PATCH 2/3] Add a self-hosted input to force considering the current runner as self-hosted * Since checking for self-hosted is based on guessing as there is no proper predicate for it in GitHub Actions (AFAIK). --- action.yml | 5 +++++ common.js | 13 +++++++++++-- dist/index.js | 16 ++++++++++++++-- index.js | 2 ++ 4 files changed, 32 insertions(+), 4 deletions(-) diff --git a/action.yml b/action.yml index 9328b12c2..55dbb3e1f 100644 --- a/action.yml +++ b/action.yml @@ -30,6 +30,11 @@ inputs: description: | Arbitrary string that will be added to the cache key of the bundler cache. Set or change it if you need to invalidate the cache. + self-hosted: + description: | + Consider the runner as a self-hosted runner, which means not using prebuilt Ruby binaries which only work + on GitHub-hosted runners or self-hosted runners with a very similar image to the ones used by GitHub runners. + The default is to detect this automatically based on the OS, OS version and $RUNNER_TOOL_CACHE. outputs: ruby-prefix: description: 'The prefix of the installed ruby' diff --git a/common.js b/common.js index 5ec89a194..9e591c4b0 100644 --- a/common.js +++ b/common.js @@ -13,6 +13,10 @@ export const windows = (os.platform() === 'win32') // Extract to SSD on Windows, see https://github.com/ruby/setup-ruby/pull/14 export const drive = (windows ? (process.env['GITHUB_WORKSPACE'] || 'C')[0] : undefined) +export const inputs = { + selfHosted: undefined +} + export function partition(string, separator) { const i = string.indexOf(separator) if (i === -1) { @@ -166,8 +170,13 @@ const GitHubHostedPlatforms = [ // * the OS and OS version does not correspond to a GitHub-hosted runner image, // * or the hosted tool cache is different from the default tool cache path export function isSelfHostedRunner() { - return !GitHubHostedPlatforms.includes(getOSNameVersionArch()) || - getRunnerToolCache() !== getDefaultToolCachePath() + if (inputs.selfHosted === undefined) { + throw new Error('inputs.selfHosted should have been already set') + } + + return inputs.selfHosted === 'true' || + !GitHubHostedPlatforms.includes(getOSNameVersionArch()) || + getRunnerToolCache() !== getDefaultToolCachePath() } let virtualEnvironmentName = undefined diff --git a/dist/index.js b/dist/index.js index 977d2e67a..99c9c7278 100644 --- a/dist/index.js +++ b/dist/index.js @@ -296,6 +296,7 @@ __nccwpck_require__.d(__webpack_exports__, { "getVirtualEnvironmentName": () => (/* binding */ getVirtualEnvironmentName), "hasBundlerDefaultGem": () => (/* binding */ hasBundlerDefaultGem), "hashFile": () => (/* binding */ hashFile), + "inputs": () => (/* binding */ inputs), "isBundler1Default": () => (/* binding */ isBundler1Default), "isBundler2Default": () => (/* binding */ isBundler2Default), "isBundler2dot2Default": () => (/* binding */ isBundler2dot2Default), @@ -366,6 +367,10 @@ const windows = (os.platform() === 'win32') // Extract to SSD on Windows, see https://github.com/ruby/setup-ruby/pull/14 const drive = (windows ? (process.env['GITHUB_WORKSPACE'] || 'C')[0] : undefined) +const inputs = { + selfHosted: undefined +} + function partition(string, separator) { const i = string.indexOf(separator) if (i === -1) { @@ -519,8 +524,13 @@ const GitHubHostedPlatforms = [ // * the OS and OS version does not correspond to a GitHub-hosted runner image, // * or the hosted tool cache is different from the default tool cache path function isSelfHostedRunner() { - return !GitHubHostedPlatforms.includes(getOSNameVersionArch()) || - getRunnerToolCache() !== getDefaultToolCachePath() + if (inputs.selfHosted === undefined) { + throw new Error('inputs.selfHosted should have been already set') + } + + return inputs.selfHosted === 'true' || + !GitHubHostedPlatforms.includes(getOSNameVersionArch()) || + getRunnerToolCache() !== getDefaultToolCachePath() } let virtualEnvironmentName = undefined @@ -69022,6 +69032,7 @@ const inputDefaults = { 'bundler-cache': 'false', 'working-directory': '.', 'cache-version': bundler.DEFAULT_CACHE_VERSION, + 'self-hosted': 'false', } // entry point when this action is run on its own @@ -69045,6 +69056,7 @@ async function setupRuby(options = {}) { inputs[key] = core.getInput(key) || inputDefaults[key] } } + common.inputs.selfHosted = inputs['self-hosted'] process.chdir(inputs['working-directory']) diff --git a/index.js b/index.js index 2fe5aca97..bb8af7097 100644 --- a/index.js +++ b/index.js @@ -16,6 +16,7 @@ const inputDefaults = { 'bundler-cache': 'false', 'working-directory': '.', 'cache-version': bundler.DEFAULT_CACHE_VERSION, + 'self-hosted': 'false', } // entry point when this action is run on its own @@ -39,6 +40,7 @@ export async function setupRuby(options = {}) { inputs[key] = core.getInput(key) || inputDefaults[key] } } + common.inputs.selfHosted = inputs['self-hosted'] process.chdir(inputs['working-directory']) From 4c648530fe570082fc47d079b5be1c0ea86a7261 Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Fri, 3 Mar 2023 17:53:40 +0100 Subject: [PATCH 3/3] Explain why it was detected as self-hosted --- common.js | 12 ++++++++++++ dist/index.js | 17 +++++++++++++++-- ruby-builder.js | 4 ++-- 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/common.js b/common.js index 9e591c4b0..8fe2529f0 100644 --- a/common.js +++ b/common.js @@ -179,6 +179,18 @@ export function isSelfHostedRunner() { getRunnerToolCache() !== getDefaultToolCachePath() } +export function selfHostedRunnerReason() { + if (inputs.selfHosted === 'true') { + return 'the self-hosted input was set' + } else if (!GitHubHostedPlatforms.includes(getOSNameVersionArch())) { + return 'the platform does not match a GitHub-hosted runner image (or that image is deprecated and no longer supported)' + } else if (getRunnerToolCache() !== getDefaultToolCachePath()) { + return 'the $RUNNER_TOOL_CACHE is different than the default tool cache path (they must be the same to reuse prebuilt Ruby binaries)' + } else { + return 'unknown reason' + } +} + let virtualEnvironmentName = undefined export function getVirtualEnvironmentName() { diff --git a/dist/index.js b/dist/index.js index 99c9c7278..1312e715b 100644 --- a/dist/index.js +++ b/dist/index.js @@ -305,6 +305,7 @@ __nccwpck_require__.d(__webpack_exports__, { "isStableVersion": () => (/* binding */ isStableVersion), "measure": () => (/* binding */ measure), "partition": () => (/* binding */ partition), + "selfHostedRunnerReason": () => (/* binding */ selfHostedRunnerReason), "setupPath": () => (/* binding */ setupPath), "shouldUseToolCache": () => (/* binding */ shouldUseToolCache), "targetRubyVersion": () => (/* binding */ targetRubyVersion), @@ -533,6 +534,18 @@ function isSelfHostedRunner() { getRunnerToolCache() !== getDefaultToolCachePath() } +function selfHostedRunnerReason() { + if (inputs.selfHosted === 'true') { + return 'the self-hosted input was set' + } else if (!GitHubHostedPlatforms.includes(getOSNameVersionArch())) { + return 'the platform does not match a GitHub-hosted runner image (or that image is deprecated and no longer supported)' + } else if (getRunnerToolCache() !== getDefaultToolCachePath()) { + return 'the $RUNNER_TOOL_CACHE is different than the default tool cache path (they must be the same to reuse prebuilt Ruby binaries)' + } else { + return 'unknown reason' + } +} + let virtualEnvironmentName = undefined function getVirtualEnvironmentName() { @@ -68270,8 +68283,8 @@ async function install(platform, engine, version) { if (common.isSelfHostedRunner()) { const rubyBuildDefinition = engine === 'ruby' ? version : `${engine}-${version}` core.error( - `The current runner (${common.getOSNameVersionArch()}, RUNNER_TOOL_CACHE=${common.getRunnerToolCache()}) was detected as self-hosted and not matching a GitHub-hosted runner image.\n` + - `In such a case, you should install Ruby in the $RUNNER_TOOL_CACHE yourself, for example using https://github.com/rbenv/ruby-build:\n` + + `The current runner (${common.getOSNameVersionArch()}, RUNNER_TOOL_CACHE=${common.getRunnerToolCache()}) was detected as self-hosted because ${common.selfHostedRunnerReason()}.\n` + + `In such a case, you should install Ruby in the $RUNNER_TOOL_CACHE yourself, for example using https://github.com/rbenv/ruby-build\n` + `You can take inspiration from this workflow for more details: https://github.com/ruby/ruby-builder/blob/master/.github/workflows/build.yml\n` + `$ ruby-build ${rubyBuildDefinition} ${toolCacheRubyPrefix}\n` + `Once that completes successfully, mark it as complete with:\n` + diff --git a/ruby-builder.js b/ruby-builder.js index 917ca0680..60388fde0 100644 --- a/ruby-builder.js +++ b/ruby-builder.js @@ -28,8 +28,8 @@ export async function install(platform, engine, version) { if (common.isSelfHostedRunner()) { const rubyBuildDefinition = engine === 'ruby' ? version : `${engine}-${version}` core.error( - `The current runner (${common.getOSNameVersionArch()}, RUNNER_TOOL_CACHE=${common.getRunnerToolCache()}) was detected as self-hosted and not matching a GitHub-hosted runner image.\n` + - `In such a case, you should install Ruby in the $RUNNER_TOOL_CACHE yourself, for example using https://github.com/rbenv/ruby-build:\n` + + `The current runner (${common.getOSNameVersionArch()}, RUNNER_TOOL_CACHE=${common.getRunnerToolCache()}) was detected as self-hosted because ${common.selfHostedRunnerReason()}.\n` + + `In such a case, you should install Ruby in the $RUNNER_TOOL_CACHE yourself, for example using https://github.com/rbenv/ruby-build\n` + `You can take inspiration from this workflow for more details: https://github.com/ruby/ruby-builder/blob/master/.github/workflows/build.yml\n` + `$ ruby-build ${rubyBuildDefinition} ${toolCacheRubyPrefix}\n` + `Once that completes successfully, mark it as complete with:\n` +