mirror of
https://github.com/ruby/setup-ruby.git
synced 2026-09-13 22:44:20 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e5a267414f | ||
|
|
cadade3366 | ||
|
|
d3562e70d9 | ||
|
|
23b2b5e5f1 | ||
|
|
42fc2d3bce | ||
|
|
30f5e2d4cd | ||
|
|
fd1d77b75c | ||
|
|
2a0be7a409 | ||
|
|
bacba738b2 | ||
|
|
21351ecc0a | ||
|
|
4d7e038419 |
@@ -17,17 +17,17 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
os: [ ubuntu-16.04, ubuntu-18.04, ubuntu-20.04, macos-10.15, macos-11.0, windows-2016, windows-2019 ]
|
os: [ ubuntu-16.04, ubuntu-18.04, ubuntu-20.04, macos-10.15, macos-11.0, windows-2016, windows-2019 ]
|
||||||
# Use various version syntax here for testing
|
# Use various version syntax here for testing
|
||||||
ruby: [ 2.1, 2.2, 2.3, 2.4, 2.5, 2.6.6, 2.7, ruby-3.0.0-preview1, ruby-head, debug, jruby-9.1, jruby, jruby-head, truffleruby, truffleruby-head ]
|
ruby: [ 2.1, 2.2, 2.3, 2.4, 2.5, 2.6.6, 2.7, '3.0', ruby-head, debug, jruby-9.1, jruby, jruby-head, truffleruby, truffleruby-head ]
|
||||||
include:
|
include:
|
||||||
- { os: windows-2016, ruby: mingw }
|
- { os: windows-2016, ruby: mingw }
|
||||||
- { os: windows-2019, ruby: mingw }
|
- { os: windows-2019, ruby: mingw }
|
||||||
- { os: windows-2019, ruby: mswin }
|
- { os: windows-2019, ruby: mswin }
|
||||||
exclude:
|
exclude:
|
||||||
- { os: windows-2016, ruby: ruby-3.0.0-preview1 }
|
- { os: windows-2016, ruby: '3.0' }
|
||||||
- { os: windows-2016, ruby: debug }
|
- { os: windows-2016, ruby: debug }
|
||||||
- { os: windows-2016, ruby: truffleruby }
|
- { os: windows-2016, ruby: truffleruby }
|
||||||
- { os: windows-2016, ruby: truffleruby-head }
|
- { os: windows-2016, ruby: truffleruby-head }
|
||||||
- { os: windows-2019, ruby: ruby-3.0.0-preview1 }
|
- { os: windows-2019, ruby: '3.0' }
|
||||||
- { os: windows-2019, ruby: debug }
|
- { os: windows-2019, ruby: debug }
|
||||||
- { os: windows-2019, ruby: truffleruby }
|
- { os: windows-2019, ruby: truffleruby }
|
||||||
- { os: windows-2019, ruby: truffleruby-head }
|
- { os: windows-2019, ruby: truffleruby-head }
|
||||||
|
|||||||
@@ -14,9 +14,9 @@ This action currently supports these versions of MRI, JRuby and TruffleRuby:
|
|||||||
|
|
||||||
| Interpreter | Versions |
|
| Interpreter | Versions |
|
||||||
| ----------- | -------- |
|
| ----------- | -------- |
|
||||||
| Ruby | 2.1.9, 2.2, 2.3.0 - 2.3.8, 2.4.0 - 2.4.10, 2.5.0 - 2.5.8, 2.6.0 - 2.6.6, 2.7.2, head, debug, mingw, mswin |
|
| `ruby` | 2.1.9, 2.2, 2.3.0 - 2.3.8, 2.4.0 - 2.4.10, 2.5.0 - 2.5.8, 2.6.0 - 2.6.6, 2.7.2, head, debug, mingw, mswin |
|
||||||
| JRuby | 9.1.17.0, 9.2.9.0 - 9.2.13.0, head |
|
| `jruby` | 9.1.17.0, 9.2.9.0 - 9.2.13.0, head |
|
||||||
| TruffleRuby | 19.3.0 - 20.3.0, head |
|
| `truffleruby` | 19.3.0 - 20.3.0, head |
|
||||||
|
|
||||||
`ruby-debug` is the same as `ruby-head` but with assertions enabled (`-DRUBY_DEBUG=1`).
|
`ruby-debug` is the same as `ruby-head` but with assertions enabled (`-DRUBY_DEBUG=1`).
|
||||||
On Windows, `mingw` and `mswin` are `ruby-head` builds using the MSYS2/MinGW and the MSVC toolchains respectively.
|
On Windows, `mingw` and `mswin` are `ruby-head` builds using the MSYS2/MinGW and the MSVC toolchains respectively.
|
||||||
@@ -136,6 +136,23 @@ This caching speeds up installing gems significantly and avoids too many request
|
|||||||
It needs a `Gemfile` (or `$BUNDLE_GEMFILE` or `gems.rb`) under the [`working-directory`](#working-directory).
|
It needs a `Gemfile` (or `$BUNDLE_GEMFILE` or `gems.rb`) under the [`working-directory`](#working-directory).
|
||||||
If there is a `Gemfile.lock` (or `$BUNDLE_GEMFILE.lock` or `gems.locked`), `bundle config --local deployment true` is used.
|
If there is a `Gemfile.lock` (or `$BUNDLE_GEMFILE.lock` or `gems.locked`), `bundle config --local deployment true` is used.
|
||||||
|
|
||||||
|
To use a `Gemfile` which is not at the root or has a different name, set `BUNDLE_GEMFILE` in the `env` at the job level, so it is set for all steps:
|
||||||
|
```yaml
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
BUNDLE_GEMFILE: subdir/mygemfile
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: ruby/setup-ruby@v1
|
||||||
|
with:
|
||||||
|
ruby-version: 2.6
|
||||||
|
bundler-cache: true
|
||||||
|
- run: bundle exec rake
|
||||||
|
```
|
||||||
|
Of course you can also use a matrix of gemfiles if you need to test multiple gemfiles.
|
||||||
|
|
||||||
To perform caching, this action will use `bundle config --local path vendor/bundle`.
|
To perform caching, this action will use `bundle config --local path vendor/bundle`.
|
||||||
Therefore, the Bundler `path` should not be changed in your workflow for the cache to work (no `bundle config path`).
|
Therefore, the Bundler `path` should not be changed in your workflow for the cache to work (no `bundle config path`).
|
||||||
|
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ export function getVirtualEnvironmentName() {
|
|||||||
throw new Error(`Unknown ImageOS ${imageOS}`)
|
throw new Error(`Unknown ImageOS ${imageOS}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function shouldExtractInToolCache(engine, version) {
|
export function shouldUseToolCache(engine, version) {
|
||||||
return engine === 'ruby' && !isHeadVersion(version)
|
return engine === 'ruby' && !isHeadVersion(version)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,6 +99,11 @@ export function getToolCacheRubyPrefix(platform, version) {
|
|||||||
return path.join(toolCache, 'Ruby', version, 'x64')
|
return path.join(toolCache, 'Ruby', version, 'x64')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function createToolCacheCompleteFile(toolCacheRubyPrefix) {
|
||||||
|
const completeFile = `${toolCacheRubyPrefix}.complete`
|
||||||
|
fs.writeFileSync(completeFile, '')
|
||||||
|
}
|
||||||
|
|
||||||
// convert windows path like C:\Users\runneradmin to /c/Users/runneradmin
|
// convert windows path like C:\Users\runneradmin to /c/Users/runneradmin
|
||||||
export function win2nix(path) {
|
export function win2nix(path) {
|
||||||
if (/^[A-Z]:/i.test(path)) {
|
if (/^[A-Z]:/i.test(path)) {
|
||||||
|
|||||||
+76
-29
@@ -27712,18 +27712,32 @@ async function install(platform, engine, version) {
|
|||||||
}
|
}
|
||||||
const base = url.slice(url.lastIndexOf('/') + 1, url.length - '.7z'.length)
|
const base = url.slice(url.lastIndexOf('/') + 1, url.length - '.7z'.length)
|
||||||
|
|
||||||
let rubyPrefix
|
let rubyPrefix, inToolCache
|
||||||
if (common.shouldExtractInToolCache(engine, version)) {
|
if (common.shouldUseToolCache(engine, version)) {
|
||||||
rubyPrefix = common.getToolCacheRubyPrefix(platform, version)
|
inToolCache = tc.find('Ruby', version)
|
||||||
|
if (inToolCache) {
|
||||||
|
rubyPrefix = inToolCache
|
||||||
|
} else {
|
||||||
|
rubyPrefix = common.getToolCacheRubyPrefix(platform, version)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
rubyPrefix = `${drive}:\\${base}`
|
rubyPrefix = `${drive}:\\${base}`
|
||||||
}
|
}
|
||||||
const parentDir = path.dirname(rubyPrefix)
|
|
||||||
|
|
||||||
let toolchainPaths = (version === 'mswin') ? await setupMSWin() : await setupMingw(version)
|
let toolchainPaths = (version === 'mswin') ? await setupMSWin() : await setupMingw(version)
|
||||||
|
|
||||||
common.setupPath([`${rubyPrefix}\\bin`, ...toolchainPaths])
|
common.setupPath([`${rubyPrefix}\\bin`, ...toolchainPaths])
|
||||||
|
|
||||||
|
if (!inToolCache) {
|
||||||
|
await downloadAndExtract(engine, version, url, base, rubyPrefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rubyPrefix
|
||||||
|
}
|
||||||
|
|
||||||
|
async function downloadAndExtract(engine, version, url, base, rubyPrefix) {
|
||||||
|
const parentDir = path.dirname(rubyPrefix)
|
||||||
|
|
||||||
const downloadPath = await common.measure('Downloading Ruby', async () => {
|
const downloadPath = await common.measure('Downloading Ruby', async () => {
|
||||||
console.log(url)
|
console.log(url)
|
||||||
return await tc.downloadTool(url)
|
return await tc.downloadTool(url)
|
||||||
@@ -27736,7 +27750,9 @@ async function install(platform, engine, version) {
|
|||||||
await io.mv(path.join(parentDir, base), rubyPrefix)
|
await io.mv(path.join(parentDir, base), rubyPrefix)
|
||||||
}
|
}
|
||||||
|
|
||||||
return rubyPrefix
|
if (common.shouldUseToolCache(engine, version)) {
|
||||||
|
common.createToolCacheCompleteFile(rubyPrefix)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function setupMingw(version) {
|
async function setupMingw(version) {
|
||||||
@@ -32100,8 +32116,9 @@ __webpack_require__.r(__webpack_exports__);
|
|||||||
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isStableVersion", function() { return isStableVersion; });
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isStableVersion", function() { return isStableVersion; });
|
||||||
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "hashFile", function() { return hashFile; });
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "hashFile", function() { return hashFile; });
|
||||||
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getVirtualEnvironmentName", function() { return getVirtualEnvironmentName; });
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getVirtualEnvironmentName", function() { return getVirtualEnvironmentName; });
|
||||||
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "shouldExtractInToolCache", function() { return shouldExtractInToolCache; });
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "shouldUseToolCache", function() { return shouldUseToolCache; });
|
||||||
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getToolCacheRubyPrefix", function() { return getToolCacheRubyPrefix; });
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getToolCacheRubyPrefix", function() { return getToolCacheRubyPrefix; });
|
||||||
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "createToolCacheCompleteFile", function() { return createToolCacheCompleteFile; });
|
||||||
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "win2nix", function() { return win2nix; });
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "win2nix", function() { return win2nix; });
|
||||||
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "setupPath", function() { return setupPath; });
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "setupPath", function() { return setupPath; });
|
||||||
const os = __webpack_require__(87)
|
const os = __webpack_require__(87)
|
||||||
@@ -32183,7 +32200,7 @@ function getVirtualEnvironmentName() {
|
|||||||
throw new Error(`Unknown ImageOS ${imageOS}`)
|
throw new Error(`Unknown ImageOS ${imageOS}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
function shouldExtractInToolCache(engine, version) {
|
function shouldUseToolCache(engine, version) {
|
||||||
return engine === 'ruby' && !isHeadVersion(version)
|
return engine === 'ruby' && !isHeadVersion(version)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32205,6 +32222,11 @@ function getToolCacheRubyPrefix(platform, version) {
|
|||||||
return path.join(toolCache, 'Ruby', version, 'x64')
|
return path.join(toolCache, 'Ruby', version, 'x64')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createToolCacheCompleteFile(toolCacheRubyPrefix) {
|
||||||
|
const completeFile = `${toolCacheRubyPrefix}.complete`
|
||||||
|
fs.writeFileSync(completeFile, '')
|
||||||
|
}
|
||||||
|
|
||||||
// convert windows path like C:\Users\runneradmin to /c/Users/runneradmin
|
// convert windows path like C:\Users\runneradmin to /c/Users/runneradmin
|
||||||
function win2nix(path) {
|
function win2nix(path) {
|
||||||
if (/^[A-Z]:/i.test(path)) {
|
if (/^[A-Z]:/i.test(path)) {
|
||||||
@@ -51235,12 +51257,12 @@ async function setupRuby(options = {}) {
|
|||||||
if (inputs['bundler'] !== 'none') {
|
if (inputs['bundler'] !== 'none') {
|
||||||
const [gemfile, lockFile] = detectGemfiles()
|
const [gemfile, lockFile] = detectGemfiles()
|
||||||
|
|
||||||
await common.measure('Installing Bundler', async () =>
|
const bundlerVersion = await common.measure('Installing Bundler', async () =>
|
||||||
installBundler(inputs['bundler'], lockFile, platform, rubyPrefix, engine, version))
|
installBundler(inputs['bundler'], lockFile, platform, rubyPrefix, engine, version))
|
||||||
|
|
||||||
if (inputs['bundler-cache'] === 'true') {
|
if (inputs['bundler-cache'] === 'true') {
|
||||||
await common.measure('bundle install', async () =>
|
await common.measure('bundle install', async () =>
|
||||||
bundleInstall(gemfile, lockFile, platform, engine, version))
|
bundleInstall(gemfile, lockFile, platform, engine, version, bundlerVersion))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51304,7 +51326,13 @@ function validateRubyEngineAndVersion(platform, engineVersions, engine, parsedVe
|
|||||||
let version = parsedVersion
|
let version = parsedVersion
|
||||||
if (!engineVersions.includes(parsedVersion)) {
|
if (!engineVersions.includes(parsedVersion)) {
|
||||||
const latestToFirstVersion = engineVersions.slice().reverse()
|
const latestToFirstVersion = engineVersions.slice().reverse()
|
||||||
const found = latestToFirstVersion.find(v => common.isStableVersion(v) && v.startsWith(parsedVersion))
|
// Try to match stable versions first, so an empty version (engine-only) matches the latest stable version
|
||||||
|
let found = latestToFirstVersion.find(v => common.isStableVersion(v) && v.startsWith(parsedVersion))
|
||||||
|
if (!found) {
|
||||||
|
// Exclude head versions, they must be exact matches
|
||||||
|
found = latestToFirstVersion.find(v => !common.isHeadVersion(v) && v.startsWith(parsedVersion))
|
||||||
|
}
|
||||||
|
|
||||||
if (found) {
|
if (found) {
|
||||||
version = found
|
version = found
|
||||||
} else {
|
} else {
|
||||||
@@ -51396,32 +51424,37 @@ async function installBundler(bundlerVersionInput, lockFile, platform, rubyPrefi
|
|||||||
const gem = path.join(rubyPrefix, 'bin', 'gem')
|
const gem = path.join(rubyPrefix, 'bin', 'gem')
|
||||||
await exec.exec(gem, ['install', 'bundler', '-v', `~> ${bundlerVersion}`, '--no-document'])
|
await exec.exec(gem, ['install', 'bundler', '-v', `~> ${bundlerVersion}`, '--no-document'])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return bundlerVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
async function bundleInstall(gemfile, lockFile, platform, engine, version) {
|
async function bundleInstall(gemfile, lockFile, platform, engine, rubyVersion, bundlerVersion) {
|
||||||
if (gemfile === null) {
|
if (gemfile === null) {
|
||||||
console.log('Could not determine gemfile path, skipping "bundle install" and caching')
|
console.log('Could not determine gemfile path, skipping "bundle install" and caching')
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Before the lockfile exists, we need to specify which Bundler version to use explicitly
|
||||||
|
const optionsWithBundlerVersion = { env: { ...process.env, BUNDLER_VERSION: bundlerVersion } }
|
||||||
|
|
||||||
// config
|
// config
|
||||||
const path = 'vendor/bundle'
|
const path = 'vendor/bundle'
|
||||||
|
|
||||||
await exec.exec('bundle', ['config', '--local', 'path', path])
|
await exec.exec('bundle', ['config', '--local', 'path', path], optionsWithBundlerVersion)
|
||||||
|
|
||||||
if (fs.existsSync(lockFile)) {
|
if (fs.existsSync(lockFile)) {
|
||||||
await exec.exec('bundle', ['config', '--local', 'deployment', 'true'])
|
await exec.exec('bundle', ['config', '--local', 'deployment', 'true'], optionsWithBundlerVersion)
|
||||||
} else {
|
} else {
|
||||||
// Generate the lockfile so we can use it to compute the cache key.
|
// Generate the lockfile so we can use it to compute the cache key.
|
||||||
// This will also automatically pick up the latest gem versions compatible with the Gemfile.
|
// This will also automatically pick up the latest gem versions compatible with the Gemfile.
|
||||||
await exec.exec('bundle', ['lock'])
|
await exec.exec('bundle', ['lock'], optionsWithBundlerVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
// cache key
|
// cache key
|
||||||
const paths = [path]
|
const paths = [path]
|
||||||
const baseKey = await computeBaseKey(platform, engine, version, lockFile)
|
const baseKey = await computeBaseKey(platform, engine, rubyVersion, lockFile)
|
||||||
const key = `${baseKey}-${await common.hashFile(lockFile)}`
|
const key = `${baseKey}-${await common.hashFile(lockFile)}`
|
||||||
// If only Gemfile.lock changes we can reuse part of the cache (but it will keep old gem versions in the cache)
|
// If only Gemfile.lock changes we can reuse part of the cache, and clean old gem versions below
|
||||||
const restoreKeys = [`${baseKey}-`]
|
const restoreKeys = [`${baseKey}-`]
|
||||||
console.log(`Cache key: ${key}`)
|
console.log(`Cache key: ${key}`)
|
||||||
|
|
||||||
@@ -51446,6 +51479,10 @@ async function bundleInstall(gemfile, lockFile, platform, engine, version) {
|
|||||||
|
|
||||||
// @actions/cache only allows to save for non-existing keys
|
// @actions/cache only allows to save for non-existing keys
|
||||||
if (cachedKey !== key) {
|
if (cachedKey !== key) {
|
||||||
|
if (cachedKey) { // existing cache but Gemfile.lock differs, clean old gems
|
||||||
|
await exec.exec('bundle', ['clean'])
|
||||||
|
}
|
||||||
|
|
||||||
// Error handling from https://github.com/actions/cache/blob/master/src/save.ts
|
// Error handling from https://github.com/actions/cache/blob/master/src/save.ts
|
||||||
console.log('Saving cache')
|
console.log('Saving cache')
|
||||||
try {
|
try {
|
||||||
@@ -52898,7 +52935,6 @@ __webpack_require__.r(__webpack_exports__);
|
|||||||
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "install", function() { return install; });
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "install", function() { return install; });
|
||||||
const os = __webpack_require__(87)
|
const os = __webpack_require__(87)
|
||||||
const path = __webpack_require__(622)
|
const path = __webpack_require__(622)
|
||||||
const core = __webpack_require__(186)
|
|
||||||
const exec = __webpack_require__(514)
|
const exec = __webpack_require__(514)
|
||||||
const io = __webpack_require__(436)
|
const io = __webpack_require__(436)
|
||||||
const tc = __webpack_require__(188)
|
const tc = __webpack_require__(188)
|
||||||
@@ -52915,24 +52951,33 @@ function getAvailableVersions(platform, engine) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function install(platform, engine, version) {
|
async function install(platform, engine, version) {
|
||||||
return await downloadAndExtract(platform, engine, version)
|
let rubyPrefix, inToolCache
|
||||||
}
|
if (common.shouldUseToolCache(engine, version)) {
|
||||||
|
inToolCache = tc.find('Ruby', version)
|
||||||
async function downloadAndExtract(platform, engine, version) {
|
if (inToolCache) {
|
||||||
let rubyPrefix
|
rubyPrefix = inToolCache
|
||||||
if (common.shouldExtractInToolCache(engine, version)) {
|
} else {
|
||||||
rubyPrefix = common.getToolCacheRubyPrefix(platform, version)
|
rubyPrefix = common.getToolCacheRubyPrefix(platform, version)
|
||||||
|
}
|
||||||
} else if (windows) {
|
} else if (windows) {
|
||||||
rubyPrefix = path.join(`${common.drive}:`, `${engine}-${version}`)
|
rubyPrefix = path.join(`${common.drive}:`, `${engine}-${version}`)
|
||||||
} else {
|
} else {
|
||||||
rubyPrefix = path.join(os.homedir(), '.rubies', `${engine}-${version}`)
|
rubyPrefix = path.join(os.homedir(), '.rubies', `${engine}-${version}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
const parentDir = path.dirname(rubyPrefix)
|
|
||||||
|
|
||||||
// Set the PATH now, so the MSYS2 'tar' is in Path on Windows
|
// Set the PATH now, so the MSYS2 'tar' is in Path on Windows
|
||||||
common.setupPath([path.join(rubyPrefix, 'bin')])
|
common.setupPath([path.join(rubyPrefix, 'bin')])
|
||||||
|
|
||||||
|
if (!inToolCache) {
|
||||||
|
await downloadAndExtract(platform, engine, version, rubyPrefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rubyPrefix
|
||||||
|
}
|
||||||
|
|
||||||
|
async function downloadAndExtract(platform, engine, version, rubyPrefix) {
|
||||||
|
const parentDir = path.dirname(rubyPrefix)
|
||||||
|
|
||||||
await io.rmRF(rubyPrefix)
|
await io.rmRF(rubyPrefix)
|
||||||
await io.mkdirP(parentDir)
|
await io.mkdirP(parentDir)
|
||||||
|
|
||||||
@@ -52945,13 +52990,15 @@ async function downloadAndExtract(platform, engine, version) {
|
|||||||
await common.measure('Extracting Ruby', async () => {
|
await common.measure('Extracting Ruby', async () => {
|
||||||
if (windows) {
|
if (windows) {
|
||||||
// Windows 2016 doesn't have system tar, use MSYS2's, it needs unix style paths
|
// Windows 2016 doesn't have system tar, use MSYS2's, it needs unix style paths
|
||||||
await exec.exec('tar', [ '-xz', '-C', common.win2nix(parentDir), '-f', common.win2nix(downloadPath) ])
|
await exec.exec('tar', ['-xz', '-C', common.win2nix(parentDir), '-f', common.win2nix(downloadPath)])
|
||||||
} else {
|
} else {
|
||||||
await exec.exec('tar', [ '-xz', '-C', parentDir, '-f', downloadPath ])
|
await exec.exec('tar', ['-xz', '-C', parentDir, '-f', downloadPath])
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
return rubyPrefix
|
if (common.shouldUseToolCache(engine, version)) {
|
||||||
|
common.createToolCacheCompleteFile(rubyPrefix)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDownloadURL(platform, engine, version) {
|
function getDownloadURL(platform, engine, version) {
|
||||||
|
|||||||
@@ -63,12 +63,12 @@ export async function setupRuby(options = {}) {
|
|||||||
if (inputs['bundler'] !== 'none') {
|
if (inputs['bundler'] !== 'none') {
|
||||||
const [gemfile, lockFile] = detectGemfiles()
|
const [gemfile, lockFile] = detectGemfiles()
|
||||||
|
|
||||||
await common.measure('Installing Bundler', async () =>
|
const bundlerVersion = await common.measure('Installing Bundler', async () =>
|
||||||
installBundler(inputs['bundler'], lockFile, platform, rubyPrefix, engine, version))
|
installBundler(inputs['bundler'], lockFile, platform, rubyPrefix, engine, version))
|
||||||
|
|
||||||
if (inputs['bundler-cache'] === 'true') {
|
if (inputs['bundler-cache'] === 'true') {
|
||||||
await common.measure('bundle install', async () =>
|
await common.measure('bundle install', async () =>
|
||||||
bundleInstall(gemfile, lockFile, platform, engine, version))
|
bundleInstall(gemfile, lockFile, platform, engine, version, bundlerVersion))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,7 +132,13 @@ function validateRubyEngineAndVersion(platform, engineVersions, engine, parsedVe
|
|||||||
let version = parsedVersion
|
let version = parsedVersion
|
||||||
if (!engineVersions.includes(parsedVersion)) {
|
if (!engineVersions.includes(parsedVersion)) {
|
||||||
const latestToFirstVersion = engineVersions.slice().reverse()
|
const latestToFirstVersion = engineVersions.slice().reverse()
|
||||||
const found = latestToFirstVersion.find(v => common.isStableVersion(v) && v.startsWith(parsedVersion))
|
// Try to match stable versions first, so an empty version (engine-only) matches the latest stable version
|
||||||
|
let found = latestToFirstVersion.find(v => common.isStableVersion(v) && v.startsWith(parsedVersion))
|
||||||
|
if (!found) {
|
||||||
|
// Exclude head versions, they must be exact matches
|
||||||
|
found = latestToFirstVersion.find(v => !common.isHeadVersion(v) && v.startsWith(parsedVersion))
|
||||||
|
}
|
||||||
|
|
||||||
if (found) {
|
if (found) {
|
||||||
version = found
|
version = found
|
||||||
} else {
|
} else {
|
||||||
@@ -224,32 +230,37 @@ async function installBundler(bundlerVersionInput, lockFile, platform, rubyPrefi
|
|||||||
const gem = path.join(rubyPrefix, 'bin', 'gem')
|
const gem = path.join(rubyPrefix, 'bin', 'gem')
|
||||||
await exec.exec(gem, ['install', 'bundler', '-v', `~> ${bundlerVersion}`, '--no-document'])
|
await exec.exec(gem, ['install', 'bundler', '-v', `~> ${bundlerVersion}`, '--no-document'])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return bundlerVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
async function bundleInstall(gemfile, lockFile, platform, engine, version) {
|
async function bundleInstall(gemfile, lockFile, platform, engine, rubyVersion, bundlerVersion) {
|
||||||
if (gemfile === null) {
|
if (gemfile === null) {
|
||||||
console.log('Could not determine gemfile path, skipping "bundle install" and caching')
|
console.log('Could not determine gemfile path, skipping "bundle install" and caching')
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Before the lockfile exists, we need to specify which Bundler version to use explicitly
|
||||||
|
const optionsWithBundlerVersion = { env: { ...process.env, BUNDLER_VERSION: bundlerVersion } }
|
||||||
|
|
||||||
// config
|
// config
|
||||||
const path = 'vendor/bundle'
|
const path = 'vendor/bundle'
|
||||||
|
|
||||||
await exec.exec('bundle', ['config', '--local', 'path', path])
|
await exec.exec('bundle', ['config', '--local', 'path', path], optionsWithBundlerVersion)
|
||||||
|
|
||||||
if (fs.existsSync(lockFile)) {
|
if (fs.existsSync(lockFile)) {
|
||||||
await exec.exec('bundle', ['config', '--local', 'deployment', 'true'])
|
await exec.exec('bundle', ['config', '--local', 'deployment', 'true'], optionsWithBundlerVersion)
|
||||||
} else {
|
} else {
|
||||||
// Generate the lockfile so we can use it to compute the cache key.
|
// Generate the lockfile so we can use it to compute the cache key.
|
||||||
// This will also automatically pick up the latest gem versions compatible with the Gemfile.
|
// This will also automatically pick up the latest gem versions compatible with the Gemfile.
|
||||||
await exec.exec('bundle', ['lock'])
|
await exec.exec('bundle', ['lock'], optionsWithBundlerVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
// cache key
|
// cache key
|
||||||
const paths = [path]
|
const paths = [path]
|
||||||
const baseKey = await computeBaseKey(platform, engine, version, lockFile)
|
const baseKey = await computeBaseKey(platform, engine, rubyVersion, lockFile)
|
||||||
const key = `${baseKey}-${await common.hashFile(lockFile)}`
|
const key = `${baseKey}-${await common.hashFile(lockFile)}`
|
||||||
// If only Gemfile.lock changes we can reuse part of the cache (but it will keep old gem versions in the cache)
|
// If only Gemfile.lock changes we can reuse part of the cache, and clean old gem versions below
|
||||||
const restoreKeys = [`${baseKey}-`]
|
const restoreKeys = [`${baseKey}-`]
|
||||||
console.log(`Cache key: ${key}`)
|
console.log(`Cache key: ${key}`)
|
||||||
|
|
||||||
@@ -274,6 +285,10 @@ async function bundleInstall(gemfile, lockFile, platform, engine, version) {
|
|||||||
|
|
||||||
// @actions/cache only allows to save for non-existing keys
|
// @actions/cache only allows to save for non-existing keys
|
||||||
if (cachedKey !== key) {
|
if (cachedKey !== key) {
|
||||||
|
if (cachedKey) { // existing cache but Gemfile.lock differs, clean old gems
|
||||||
|
await exec.exec('bundle', ['clean'])
|
||||||
|
}
|
||||||
|
|
||||||
// Error handling from https://github.com/actions/cache/blob/master/src/save.ts
|
// Error handling from https://github.com/actions/cache/blob/master/src/save.ts
|
||||||
console.log('Saving cache')
|
console.log('Saving cache')
|
||||||
try {
|
try {
|
||||||
|
|||||||
+23
-13
@@ -1,6 +1,5 @@
|
|||||||
const os = require('os')
|
const os = require('os')
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
const core = require('@actions/core')
|
|
||||||
const exec = require('@actions/exec')
|
const exec = require('@actions/exec')
|
||||||
const io = require('@actions/io')
|
const io = require('@actions/io')
|
||||||
const tc = require('@actions/tool-cache')
|
const tc = require('@actions/tool-cache')
|
||||||
@@ -17,24 +16,33 @@ export function getAvailableVersions(platform, engine) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function install(platform, engine, version) {
|
export async function install(platform, engine, version) {
|
||||||
return await downloadAndExtract(platform, engine, version)
|
let rubyPrefix, inToolCache
|
||||||
}
|
if (common.shouldUseToolCache(engine, version)) {
|
||||||
|
inToolCache = tc.find('Ruby', version)
|
||||||
async function downloadAndExtract(platform, engine, version) {
|
if (inToolCache) {
|
||||||
let rubyPrefix
|
rubyPrefix = inToolCache
|
||||||
if (common.shouldExtractInToolCache(engine, version)) {
|
} else {
|
||||||
rubyPrefix = common.getToolCacheRubyPrefix(platform, version)
|
rubyPrefix = common.getToolCacheRubyPrefix(platform, version)
|
||||||
|
}
|
||||||
} else if (windows) {
|
} else if (windows) {
|
||||||
rubyPrefix = path.join(`${common.drive}:`, `${engine}-${version}`)
|
rubyPrefix = path.join(`${common.drive}:`, `${engine}-${version}`)
|
||||||
} else {
|
} else {
|
||||||
rubyPrefix = path.join(os.homedir(), '.rubies', `${engine}-${version}`)
|
rubyPrefix = path.join(os.homedir(), '.rubies', `${engine}-${version}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
const parentDir = path.dirname(rubyPrefix)
|
|
||||||
|
|
||||||
// Set the PATH now, so the MSYS2 'tar' is in Path on Windows
|
// Set the PATH now, so the MSYS2 'tar' is in Path on Windows
|
||||||
common.setupPath([path.join(rubyPrefix, 'bin')])
|
common.setupPath([path.join(rubyPrefix, 'bin')])
|
||||||
|
|
||||||
|
if (!inToolCache) {
|
||||||
|
await downloadAndExtract(platform, engine, version, rubyPrefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rubyPrefix
|
||||||
|
}
|
||||||
|
|
||||||
|
async function downloadAndExtract(platform, engine, version, rubyPrefix) {
|
||||||
|
const parentDir = path.dirname(rubyPrefix)
|
||||||
|
|
||||||
await io.rmRF(rubyPrefix)
|
await io.rmRF(rubyPrefix)
|
||||||
await io.mkdirP(parentDir)
|
await io.mkdirP(parentDir)
|
||||||
|
|
||||||
@@ -47,13 +55,15 @@ async function downloadAndExtract(platform, engine, version) {
|
|||||||
await common.measure('Extracting Ruby', async () => {
|
await common.measure('Extracting Ruby', async () => {
|
||||||
if (windows) {
|
if (windows) {
|
||||||
// Windows 2016 doesn't have system tar, use MSYS2's, it needs unix style paths
|
// Windows 2016 doesn't have system tar, use MSYS2's, it needs unix style paths
|
||||||
await exec.exec('tar', [ '-xz', '-C', common.win2nix(parentDir), '-f', common.win2nix(downloadPath) ])
|
await exec.exec('tar', ['-xz', '-C', common.win2nix(parentDir), '-f', common.win2nix(downloadPath)])
|
||||||
} else {
|
} else {
|
||||||
await exec.exec('tar', [ '-xz', '-C', parentDir, '-f', downloadPath ])
|
await exec.exec('tar', ['-xz', '-C', parentDir, '-f', downloadPath])
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
return rubyPrefix
|
if (common.shouldUseToolCache(engine, version)) {
|
||||||
|
common.createToolCacheCompleteFile(rubyPrefix)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDownloadURL(platform, engine, version) {
|
function getDownloadURL(platform, engine, version) {
|
||||||
|
|||||||
+21
-5
@@ -36,18 +36,32 @@ export async function install(platform, engine, version) {
|
|||||||
}
|
}
|
||||||
const base = url.slice(url.lastIndexOf('/') + 1, url.length - '.7z'.length)
|
const base = url.slice(url.lastIndexOf('/') + 1, url.length - '.7z'.length)
|
||||||
|
|
||||||
let rubyPrefix
|
let rubyPrefix, inToolCache
|
||||||
if (common.shouldExtractInToolCache(engine, version)) {
|
if (common.shouldUseToolCache(engine, version)) {
|
||||||
rubyPrefix = common.getToolCacheRubyPrefix(platform, version)
|
inToolCache = tc.find('Ruby', version)
|
||||||
|
if (inToolCache) {
|
||||||
|
rubyPrefix = inToolCache
|
||||||
|
} else {
|
||||||
|
rubyPrefix = common.getToolCacheRubyPrefix(platform, version)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
rubyPrefix = `${drive}:\\${base}`
|
rubyPrefix = `${drive}:\\${base}`
|
||||||
}
|
}
|
||||||
const parentDir = path.dirname(rubyPrefix)
|
|
||||||
|
|
||||||
let toolchainPaths = (version === 'mswin') ? await setupMSWin() : await setupMingw(version)
|
let toolchainPaths = (version === 'mswin') ? await setupMSWin() : await setupMingw(version)
|
||||||
|
|
||||||
common.setupPath([`${rubyPrefix}\\bin`, ...toolchainPaths])
|
common.setupPath([`${rubyPrefix}\\bin`, ...toolchainPaths])
|
||||||
|
|
||||||
|
if (!inToolCache) {
|
||||||
|
await downloadAndExtract(engine, version, url, base, rubyPrefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rubyPrefix
|
||||||
|
}
|
||||||
|
|
||||||
|
async function downloadAndExtract(engine, version, url, base, rubyPrefix) {
|
||||||
|
const parentDir = path.dirname(rubyPrefix)
|
||||||
|
|
||||||
const downloadPath = await common.measure('Downloading Ruby', async () => {
|
const downloadPath = await common.measure('Downloading Ruby', async () => {
|
||||||
console.log(url)
|
console.log(url)
|
||||||
return await tc.downloadTool(url)
|
return await tc.downloadTool(url)
|
||||||
@@ -60,7 +74,9 @@ export async function install(platform, engine, version) {
|
|||||||
await io.mv(path.join(parentDir, base), rubyPrefix)
|
await io.mv(path.join(parentDir, base), rubyPrefix)
|
||||||
}
|
}
|
||||||
|
|
||||||
return rubyPrefix
|
if (common.shouldUseToolCache(engine, version)) {
|
||||||
|
common.createToolCacheCompleteFile(rubyPrefix)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function setupMingw(version) {
|
async function setupMingw(version) {
|
||||||
|
|||||||
Reference in New Issue
Block a user