mirror of
https://github.com/ruby/setup-ruby.git
synced 2026-09-13 14:34:21 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5aaa89ff0d | ||
|
|
3460195737 | ||
|
|
d195ecb9ec |
@@ -108,8 +108,8 @@ jobs:
|
|||||||
- uses: ./
|
- uses: ./
|
||||||
with:
|
with:
|
||||||
ruby-version: 2.6
|
ruby-version: 2.6
|
||||||
bundler: 2.1.4
|
bundler: 2.2.3
|
||||||
- run: bundle --version | grep -F "Bundler version 2.1.4"
|
- run: bundle --version | grep -F "Bundler version 2.2.3"
|
||||||
|
|
||||||
testDependencyOnBundler1:
|
testDependencyOnBundler1:
|
||||||
name: "Test gemfile depending on Bundler 1"
|
name: "Test gemfile depending on Bundler 1"
|
||||||
@@ -142,6 +142,19 @@ jobs:
|
|||||||
bundler-cache: true
|
bundler-cache: true
|
||||||
- run: bundle exec rails --version
|
- run: bundle exec rails --version
|
||||||
|
|
||||||
|
testTruffleRubyNokogiri:
|
||||||
|
name: "Test installing a Gemfile with nokogiri on TruffleRuby"
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
BUNDLE_GEMFILE: gemfiles/nokogiri.gemfile
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: ./
|
||||||
|
with:
|
||||||
|
ruby-version: truffleruby-head
|
||||||
|
bundler-cache: true
|
||||||
|
- run: bundle list | grep nokogiri
|
||||||
|
|
||||||
lint:
|
lint:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
steps:
|
steps:
|
||||||
|
|||||||
+196
@@ -0,0 +1,196 @@
|
|||||||
|
const fs = require('fs')
|
||||||
|
const path = require('path')
|
||||||
|
const core = require('@actions/core')
|
||||||
|
const exec = require('@actions/exec')
|
||||||
|
const cache = require('@actions/cache')
|
||||||
|
const common = require('./common')
|
||||||
|
|
||||||
|
// The returned gemfile is guaranteed to exist, the lockfile might not exist
|
||||||
|
export function detectGemfiles() {
|
||||||
|
const gemfilePath = process.env['BUNDLE_GEMFILE'] || 'Gemfile'
|
||||||
|
if (fs.existsSync(gemfilePath)) {
|
||||||
|
return [gemfilePath, `${gemfilePath}.lock`]
|
||||||
|
} else if (process.env['BUNDLE_GEMFILE']) {
|
||||||
|
throw new Error(`$BUNDLE_GEMFILE is set to ${gemfilePath} but does not exist`)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fs.existsSync("gems.rb")) {
|
||||||
|
return ["gems.rb", "gems.locked"]
|
||||||
|
}
|
||||||
|
|
||||||
|
return [null, null]
|
||||||
|
}
|
||||||
|
|
||||||
|
function readBundledWithFromGemfileLock(lockFile) {
|
||||||
|
if (lockFile !== null && fs.existsSync(lockFile)) {
|
||||||
|
const contents = fs.readFileSync(lockFile, 'utf8')
|
||||||
|
const lines = contents.split(/\r?\n/)
|
||||||
|
const bundledWithLine = lines.findIndex(line => /^BUNDLED WITH$/.test(line.trim()))
|
||||||
|
if (bundledWithLine !== -1) {
|
||||||
|
const nextLine = lines[bundledWithLine+1]
|
||||||
|
if (nextLine && /^\d+/.test(nextLine.trim())) {
|
||||||
|
const bundlerVersion = nextLine.trim()
|
||||||
|
console.log(`Using Bundler ${bundlerVersion} from ${lockFile} BUNDLED WITH ${bundlerVersion}`)
|
||||||
|
return bundlerVersion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
async function afterLockFile(lockFile, platform, engine) {
|
||||||
|
if (engine === 'truffleruby' && platform.startsWith('ubuntu-')) {
|
||||||
|
const contents = fs.readFileSync(lockFile, 'utf8')
|
||||||
|
if (contents.includes('nokogiri')) {
|
||||||
|
await common.measure('Installing libxml2-dev libxslt-dev, required to install nokogiri on TruffleRuby', async () =>
|
||||||
|
exec.exec('sudo', ['apt-get', '-yqq', 'install', 'libxml2-dev', 'libxslt-dev'], { silent: true }))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function installBundler(bundlerVersionInput, lockFile, platform, rubyPrefix, engine, rubyVersion) {
|
||||||
|
let bundlerVersion = bundlerVersionInput
|
||||||
|
|
||||||
|
if (bundlerVersion === 'default' || bundlerVersion === 'Gemfile.lock') {
|
||||||
|
bundlerVersion = readBundledWithFromGemfileLock(lockFile)
|
||||||
|
|
||||||
|
if (!bundlerVersion) {
|
||||||
|
bundlerVersion = 'latest'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bundlerVersion === 'latest') {
|
||||||
|
bundlerVersion = '2'
|
||||||
|
}
|
||||||
|
|
||||||
|
if (/^\d+/.test(bundlerVersion)) {
|
||||||
|
// OK
|
||||||
|
} else {
|
||||||
|
throw new Error(`Cannot parse bundler input: ${bundlerVersion}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (engine === 'ruby' && rubyVersion.match(/^2\.[012]/)) {
|
||||||
|
console.log('Bundler 2 requires Ruby 2.3+, using Bundler 1 on Ruby <= 2.2')
|
||||||
|
bundlerVersion = '1'
|
||||||
|
} else if (engine === 'ruby' && rubyVersion.startsWith('2.3')) {
|
||||||
|
console.log('Ruby 2.3 has a bug with Bundler 2 (https://github.com/rubygems/rubygems/issues/3570), using Bundler 1 instead on Ruby 2.3')
|
||||||
|
bundlerVersion = '1'
|
||||||
|
} else if (engine === 'jruby' && rubyVersion.startsWith('9.1')) { // JRuby 9.1 targets Ruby 2.3, treat it the same
|
||||||
|
console.log('JRuby 9.1 has a bug with Bundler 2 (https://github.com/ruby/setup-ruby/issues/108), using Bundler 1 instead on JRuby 9.1')
|
||||||
|
bundlerVersion = '1'
|
||||||
|
}
|
||||||
|
|
||||||
|
if (common.isHeadVersion(rubyVersion) && common.isBundler2Default(engine, rubyVersion) && bundlerVersion.startsWith('2')) {
|
||||||
|
console.log(`Using Bundler 2 shipped with ${engine}-${rubyVersion}`)
|
||||||
|
} else if (engine === 'truffleruby' && !common.isHeadVersion(rubyVersion) && bundlerVersion.startsWith('1')) {
|
||||||
|
console.log(`Using Bundler 1 shipped with ${engine}`)
|
||||||
|
} else {
|
||||||
|
const gem = path.join(rubyPrefix, 'bin', 'gem')
|
||||||
|
const bundlerVersionConstraint = bundlerVersion.match(/^\d+\.\d+\.\d+/) ? bundlerVersion : `~> ${bundlerVersion}`
|
||||||
|
await exec.exec(gem, ['install', 'bundler', '-v', bundlerVersionConstraint, '--no-document'])
|
||||||
|
}
|
||||||
|
|
||||||
|
return bundlerVersion
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function bundleInstall(gemfile, lockFile, platform, engine, rubyVersion, bundlerVersion) {
|
||||||
|
if (gemfile === null) {
|
||||||
|
console.log('Could not determine gemfile path, skipping "bundle install" and caching')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
let envOptions = {}
|
||||||
|
if (bundlerVersion.startsWith('1') && common.isBundler2Default(engine, rubyVersion)) {
|
||||||
|
// If Bundler 1 is specified on Rubies which ship with Bundler 2,
|
||||||
|
// we need to specify which Bundler version to use explicitly until the lockfile exists.
|
||||||
|
console.log(`Setting BUNDLER_VERSION=${bundlerVersion} for "bundle config|lock" commands below to ensure Bundler 1 is used`)
|
||||||
|
envOptions = { env: { ...process.env, BUNDLER_VERSION: bundlerVersion } }
|
||||||
|
}
|
||||||
|
|
||||||
|
// config
|
||||||
|
const cachePath = 'vendor/bundle'
|
||||||
|
// An absolute path, so it is reliably under $PWD/vendor/bundle, and not relative to the gemfile's directory
|
||||||
|
const bundleCachePath = path.join(process.cwd(), cachePath)
|
||||||
|
|
||||||
|
await exec.exec('bundle', ['config', '--local', 'path', bundleCachePath], envOptions)
|
||||||
|
|
||||||
|
if (fs.existsSync(lockFile)) {
|
||||||
|
await exec.exec('bundle', ['config', '--local', 'deployment', 'true'], envOptions)
|
||||||
|
} else {
|
||||||
|
// 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.
|
||||||
|
await exec.exec('bundle', ['lock'], envOptions)
|
||||||
|
}
|
||||||
|
|
||||||
|
await afterLockFile(lockFile, platform, engine)
|
||||||
|
|
||||||
|
// cache key
|
||||||
|
const paths = [cachePath]
|
||||||
|
const baseKey = await computeBaseKey(platform, engine, rubyVersion, lockFile)
|
||||||
|
const key = `${baseKey}-${await common.hashFile(lockFile)}`
|
||||||
|
// If only Gemfile.lock changes we can reuse part of the cache, and clean old gem versions below
|
||||||
|
const restoreKeys = [`${baseKey}-`]
|
||||||
|
console.log(`Cache key: ${key}`)
|
||||||
|
|
||||||
|
// restore cache & install
|
||||||
|
let cachedKey = null
|
||||||
|
try {
|
||||||
|
cachedKey = await cache.restoreCache(paths, key, restoreKeys)
|
||||||
|
} catch (error) {
|
||||||
|
if (error.name === cache.ValidationError.name) {
|
||||||
|
throw error;
|
||||||
|
} else {
|
||||||
|
core.info(`[warning] There was an error restoring the cache ${error.message}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cachedKey) {
|
||||||
|
console.log(`Found cache for key: ${cachedKey}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Always run 'bundle install' to list the gems
|
||||||
|
await exec.exec('bundle', ['install', '--jobs', '4'])
|
||||||
|
|
||||||
|
// @actions/cache only allows to save for non-existing keys
|
||||||
|
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
|
||||||
|
console.log('Saving cache')
|
||||||
|
try {
|
||||||
|
await cache.saveCache(paths, key)
|
||||||
|
} catch (error) {
|
||||||
|
if (error.name === cache.ValidationError.name) {
|
||||||
|
throw error;
|
||||||
|
} else if (error.name === cache.ReserveCacheError.name) {
|
||||||
|
core.info(error.message);
|
||||||
|
} else {
|
||||||
|
core.info(`[warning]${error.message}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
async function computeBaseKey(platform, engine, version, lockFile) {
|
||||||
|
let key = `setup-ruby-bundler-cache-v3-${platform}-${engine}-${version}`
|
||||||
|
|
||||||
|
if (engine !== 'jruby' && common.isHeadVersion(version)) {
|
||||||
|
let revision = '';
|
||||||
|
await exec.exec('ruby', ['-e', 'print RUBY_REVISION'], {
|
||||||
|
silent: true,
|
||||||
|
listeners: {
|
||||||
|
stdout: (data) => {
|
||||||
|
revision += data.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
key += `-revision-${revision}`
|
||||||
|
}
|
||||||
|
|
||||||
|
key += `-${lockFile}`
|
||||||
|
return key
|
||||||
|
}
|
||||||
@@ -19,8 +19,10 @@ export function partition(string, separator) {
|
|||||||
return [string.slice(0, i), string.slice(i + separator.length, string.length)]
|
return [string.slice(0, i), string.slice(i + separator.length, string.length)]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let inGroup = false
|
||||||
|
|
||||||
export async function measure(name, block) {
|
export async function measure(name, block) {
|
||||||
return await core.group(name, async () => {
|
const body = async () => {
|
||||||
const start = performance.now()
|
const start = performance.now()
|
||||||
try {
|
try {
|
||||||
return await block()
|
return await block()
|
||||||
@@ -29,7 +31,20 @@ export async function measure(name, block) {
|
|||||||
const duration = (end - start) / 1000.0
|
const duration = (end - start) / 1000.0
|
||||||
console.log(`Took ${duration.toFixed(2).padStart(6)} seconds`)
|
console.log(`Took ${duration.toFixed(2).padStart(6)} seconds`)
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
|
||||||
|
if (inGroup) {
|
||||||
|
// Nested groups are not yet supported on GitHub Actions
|
||||||
|
console.log(`> ${name}`)
|
||||||
|
return await body()
|
||||||
|
} else {
|
||||||
|
inGroup = true
|
||||||
|
try {
|
||||||
|
return await core.group(name, body)
|
||||||
|
} finally {
|
||||||
|
inGroup = false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isHeadVersion(rubyVersion) {
|
export function isHeadVersion(rubyVersion) {
|
||||||
|
|||||||
+304
-262
@@ -3029,7 +3029,7 @@ var os = __webpack_require__(87);
|
|||||||
var stream = __webpack_require__(413);
|
var stream = __webpack_require__(413);
|
||||||
var fs = __webpack_require__(747);
|
var fs = __webpack_require__(747);
|
||||||
var util = __webpack_require__(669);
|
var util = __webpack_require__(669);
|
||||||
var crypto = __webpack_require__(373);
|
var crypto = __webpack_require__(417);
|
||||||
var events = __webpack_require__(614);
|
var events = __webpack_require__(614);
|
||||||
var coreTracing = __webpack_require__(175);
|
var coreTracing = __webpack_require__(175);
|
||||||
var coreLro = __webpack_require__(94);
|
var coreLro = __webpack_require__(94);
|
||||||
@@ -23220,7 +23220,7 @@ Object.defineProperty(exports, "__esModule", {
|
|||||||
});
|
});
|
||||||
exports.default = void 0;
|
exports.default = void 0;
|
||||||
|
|
||||||
var _crypto = _interopRequireDefault(__webpack_require__(373));
|
var _crypto = _interopRequireDefault(__webpack_require__(417));
|
||||||
|
|
||||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||||
|
|
||||||
@@ -28783,7 +28783,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|||||||
const core = __importStar(__webpack_require__(186));
|
const core = __importStar(__webpack_require__(186));
|
||||||
const http_client_1 = __webpack_require__(320);
|
const http_client_1 = __webpack_require__(320);
|
||||||
const auth_1 = __webpack_require__(93);
|
const auth_1 = __webpack_require__(93);
|
||||||
const crypto = __importStar(__webpack_require__(373));
|
const crypto = __importStar(__webpack_require__(417));
|
||||||
const fs = __importStar(__webpack_require__(747));
|
const fs = __importStar(__webpack_require__(747));
|
||||||
const url_1 = __webpack_require__(835);
|
const url_1 = __webpack_require__(835);
|
||||||
const utils = __importStar(__webpack_require__(518));
|
const utils = __importStar(__webpack_require__(518));
|
||||||
@@ -32589,12 +32589,7 @@ exports.Store = Store;
|
|||||||
/* 370 */,
|
/* 370 */,
|
||||||
/* 371 */,
|
/* 371 */,
|
||||||
/* 372 */,
|
/* 372 */,
|
||||||
/* 373 */
|
/* 373 */,
|
||||||
/***/ (function(module) {
|
|
||||||
|
|
||||||
module.exports = require("crypto");
|
|
||||||
|
|
||||||
/***/ }),
|
|
||||||
/* 374 */,
|
/* 374 */,
|
||||||
/* 375 */,
|
/* 375 */,
|
||||||
/* 376 */
|
/* 376 */
|
||||||
@@ -32748,7 +32743,7 @@ Object.defineProperty(exports, "__esModule", {
|
|||||||
});
|
});
|
||||||
exports.default = void 0;
|
exports.default = void 0;
|
||||||
|
|
||||||
var _crypto = _interopRequireDefault(__webpack_require__(373));
|
var _crypto = _interopRequireDefault(__webpack_require__(417));
|
||||||
|
|
||||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||||
|
|
||||||
@@ -32800,7 +32795,7 @@ const path = __webpack_require__(622)
|
|||||||
const fs = __webpack_require__(747)
|
const fs = __webpack_require__(747)
|
||||||
const util = __webpack_require__(669)
|
const util = __webpack_require__(669)
|
||||||
const stream = __webpack_require__(413)
|
const stream = __webpack_require__(413)
|
||||||
const crypto = __webpack_require__(373)
|
const crypto = __webpack_require__(417)
|
||||||
const core = __webpack_require__(186)
|
const core = __webpack_require__(186)
|
||||||
const { performance } = __webpack_require__(630)
|
const { performance } = __webpack_require__(630)
|
||||||
|
|
||||||
@@ -32816,8 +32811,10 @@ function partition(string, separator) {
|
|||||||
return [string.slice(0, i), string.slice(i + separator.length, string.length)]
|
return [string.slice(0, i), string.slice(i + separator.length, string.length)]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let inGroup = false
|
||||||
|
|
||||||
async function measure(name, block) {
|
async function measure(name, block) {
|
||||||
return await core.group(name, async () => {
|
const body = async () => {
|
||||||
const start = performance.now()
|
const start = performance.now()
|
||||||
try {
|
try {
|
||||||
return await block()
|
return await block()
|
||||||
@@ -32826,7 +32823,20 @@ async function measure(name, block) {
|
|||||||
const duration = (end - start) / 1000.0
|
const duration = (end - start) / 1000.0
|
||||||
console.log(`Took ${duration.toFixed(2).padStart(6)} seconds`)
|
console.log(`Took ${duration.toFixed(2).padStart(6)} seconds`)
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
|
||||||
|
if (inGroup) {
|
||||||
|
// Nested groups are not yet supported on GitHub Actions
|
||||||
|
console.log(`> ${name}`)
|
||||||
|
return await body()
|
||||||
|
} else {
|
||||||
|
inGroup = true
|
||||||
|
try {
|
||||||
|
return await core.group(name, body)
|
||||||
|
} finally {
|
||||||
|
inGroup = false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function isHeadVersion(rubyVersion) {
|
function isHeadVersion(rubyVersion) {
|
||||||
@@ -33198,67 +33208,7 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
|
|||||||
/* 417 */
|
/* 417 */
|
||||||
/***/ (function(module) {
|
/***/ (function(module) {
|
||||||
|
|
||||||
"use strict";
|
module.exports = require("crypto");
|
||||||
|
|
||||||
module.exports = balanced;
|
|
||||||
function balanced(a, b, str) {
|
|
||||||
if (a instanceof RegExp) a = maybeMatch(a, str);
|
|
||||||
if (b instanceof RegExp) b = maybeMatch(b, str);
|
|
||||||
|
|
||||||
var r = range(a, b, str);
|
|
||||||
|
|
||||||
return r && {
|
|
||||||
start: r[0],
|
|
||||||
end: r[1],
|
|
||||||
pre: str.slice(0, r[0]),
|
|
||||||
body: str.slice(r[0] + a.length, r[1]),
|
|
||||||
post: str.slice(r[1] + b.length)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function maybeMatch(reg, str) {
|
|
||||||
var m = str.match(reg);
|
|
||||||
return m ? m[0] : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
balanced.range = range;
|
|
||||||
function range(a, b, str) {
|
|
||||||
var begs, beg, left, right, result;
|
|
||||||
var ai = str.indexOf(a);
|
|
||||||
var bi = str.indexOf(b, ai + 1);
|
|
||||||
var i = ai;
|
|
||||||
|
|
||||||
if (ai >= 0 && bi > 0) {
|
|
||||||
begs = [];
|
|
||||||
left = str.length;
|
|
||||||
|
|
||||||
while (i >= 0 && !result) {
|
|
||||||
if (i == ai) {
|
|
||||||
begs.push(i);
|
|
||||||
ai = str.indexOf(a, i + 1);
|
|
||||||
} else if (begs.length == 1) {
|
|
||||||
result = [ begs.pop(), bi ];
|
|
||||||
} else {
|
|
||||||
beg = begs.pop();
|
|
||||||
if (beg < left) {
|
|
||||||
left = beg;
|
|
||||||
right = bi;
|
|
||||||
}
|
|
||||||
|
|
||||||
bi = str.indexOf(b, i + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
i = ai < bi && ai >= 0 ? ai : bi;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (begs.length) {
|
|
||||||
result = [ left, right ];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
/* 418 */
|
/* 418 */
|
||||||
@@ -44576,7 +44526,213 @@ module.exports = require("net");
|
|||||||
/* 638 */,
|
/* 638 */,
|
||||||
/* 639 */,
|
/* 639 */,
|
||||||
/* 640 */,
|
/* 640 */,
|
||||||
/* 641 */,
|
/* 641 */
|
||||||
|
/***/ (function(__unusedmodule, __webpack_exports__, __webpack_require__) {
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
__webpack_require__.r(__webpack_exports__);
|
||||||
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "detectGemfiles", function() { return detectGemfiles; });
|
||||||
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "installBundler", function() { return installBundler; });
|
||||||
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "bundleInstall", function() { return bundleInstall; });
|
||||||
|
const fs = __webpack_require__(747)
|
||||||
|
const path = __webpack_require__(622)
|
||||||
|
const core = __webpack_require__(186)
|
||||||
|
const exec = __webpack_require__(514)
|
||||||
|
const cache = __webpack_require__(799)
|
||||||
|
const common = __webpack_require__(390)
|
||||||
|
|
||||||
|
// The returned gemfile is guaranteed to exist, the lockfile might not exist
|
||||||
|
function detectGemfiles() {
|
||||||
|
const gemfilePath = process.env['BUNDLE_GEMFILE'] || 'Gemfile'
|
||||||
|
if (fs.existsSync(gemfilePath)) {
|
||||||
|
return [gemfilePath, `${gemfilePath}.lock`]
|
||||||
|
} else if (process.env['BUNDLE_GEMFILE']) {
|
||||||
|
throw new Error(`$BUNDLE_GEMFILE is set to ${gemfilePath} but does not exist`)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fs.existsSync("gems.rb")) {
|
||||||
|
return ["gems.rb", "gems.locked"]
|
||||||
|
}
|
||||||
|
|
||||||
|
return [null, null]
|
||||||
|
}
|
||||||
|
|
||||||
|
function readBundledWithFromGemfileLock(lockFile) {
|
||||||
|
if (lockFile !== null && fs.existsSync(lockFile)) {
|
||||||
|
const contents = fs.readFileSync(lockFile, 'utf8')
|
||||||
|
const lines = contents.split(/\r?\n/)
|
||||||
|
const bundledWithLine = lines.findIndex(line => /^BUNDLED WITH$/.test(line.trim()))
|
||||||
|
if (bundledWithLine !== -1) {
|
||||||
|
const nextLine = lines[bundledWithLine+1]
|
||||||
|
if (nextLine && /^\d+/.test(nextLine.trim())) {
|
||||||
|
const bundlerVersion = nextLine.trim()
|
||||||
|
console.log(`Using Bundler ${bundlerVersion} from ${lockFile} BUNDLED WITH ${bundlerVersion}`)
|
||||||
|
return bundlerVersion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
async function afterLockFile(lockFile, platform, engine) {
|
||||||
|
if (engine === 'truffleruby' && platform.startsWith('ubuntu-')) {
|
||||||
|
const contents = fs.readFileSync(lockFile, 'utf8')
|
||||||
|
if (contents.includes('nokogiri')) {
|
||||||
|
await common.measure('Installing libxml2-dev libxslt-dev, required to install nokogiri on TruffleRuby', async () =>
|
||||||
|
exec.exec('sudo', ['apt-get', '-yqq', 'install', 'libxml2-dev', 'libxslt-dev'], { silent: true }))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function installBundler(bundlerVersionInput, lockFile, platform, rubyPrefix, engine, rubyVersion) {
|
||||||
|
let bundlerVersion = bundlerVersionInput
|
||||||
|
|
||||||
|
if (bundlerVersion === 'default' || bundlerVersion === 'Gemfile.lock') {
|
||||||
|
bundlerVersion = readBundledWithFromGemfileLock(lockFile)
|
||||||
|
|
||||||
|
if (!bundlerVersion) {
|
||||||
|
bundlerVersion = 'latest'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bundlerVersion === 'latest') {
|
||||||
|
bundlerVersion = '2'
|
||||||
|
}
|
||||||
|
|
||||||
|
if (/^\d+/.test(bundlerVersion)) {
|
||||||
|
// OK
|
||||||
|
} else {
|
||||||
|
throw new Error(`Cannot parse bundler input: ${bundlerVersion}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (engine === 'ruby' && rubyVersion.match(/^2\.[012]/)) {
|
||||||
|
console.log('Bundler 2 requires Ruby 2.3+, using Bundler 1 on Ruby <= 2.2')
|
||||||
|
bundlerVersion = '1'
|
||||||
|
} else if (engine === 'ruby' && rubyVersion.startsWith('2.3')) {
|
||||||
|
console.log('Ruby 2.3 has a bug with Bundler 2 (https://github.com/rubygems/rubygems/issues/3570), using Bundler 1 instead on Ruby 2.3')
|
||||||
|
bundlerVersion = '1'
|
||||||
|
} else if (engine === 'jruby' && rubyVersion.startsWith('9.1')) { // JRuby 9.1 targets Ruby 2.3, treat it the same
|
||||||
|
console.log('JRuby 9.1 has a bug with Bundler 2 (https://github.com/ruby/setup-ruby/issues/108), using Bundler 1 instead on JRuby 9.1')
|
||||||
|
bundlerVersion = '1'
|
||||||
|
}
|
||||||
|
|
||||||
|
if (common.isHeadVersion(rubyVersion) && common.isBundler2Default(engine, rubyVersion) && bundlerVersion.startsWith('2')) {
|
||||||
|
console.log(`Using Bundler 2 shipped with ${engine}-${rubyVersion}`)
|
||||||
|
} else if (engine === 'truffleruby' && !common.isHeadVersion(rubyVersion) && bundlerVersion.startsWith('1')) {
|
||||||
|
console.log(`Using Bundler 1 shipped with ${engine}`)
|
||||||
|
} else {
|
||||||
|
const gem = path.join(rubyPrefix, 'bin', 'gem')
|
||||||
|
const bundlerVersionConstraint = bundlerVersion.match(/^\d+\.\d+\.\d+/) ? bundlerVersion : `~> ${bundlerVersion}`
|
||||||
|
await exec.exec(gem, ['install', 'bundler', '-v', bundlerVersionConstraint, '--no-document'])
|
||||||
|
}
|
||||||
|
|
||||||
|
return bundlerVersion
|
||||||
|
}
|
||||||
|
|
||||||
|
async function bundleInstall(gemfile, lockFile, platform, engine, rubyVersion, bundlerVersion) {
|
||||||
|
if (gemfile === null) {
|
||||||
|
console.log('Could not determine gemfile path, skipping "bundle install" and caching')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
let envOptions = {}
|
||||||
|
if (bundlerVersion.startsWith('1') && common.isBundler2Default(engine, rubyVersion)) {
|
||||||
|
// If Bundler 1 is specified on Rubies which ship with Bundler 2,
|
||||||
|
// we need to specify which Bundler version to use explicitly until the lockfile exists.
|
||||||
|
console.log(`Setting BUNDLER_VERSION=${bundlerVersion} for "bundle config|lock" commands below to ensure Bundler 1 is used`)
|
||||||
|
envOptions = { env: { ...process.env, BUNDLER_VERSION: bundlerVersion } }
|
||||||
|
}
|
||||||
|
|
||||||
|
// config
|
||||||
|
const cachePath = 'vendor/bundle'
|
||||||
|
// An absolute path, so it is reliably under $PWD/vendor/bundle, and not relative to the gemfile's directory
|
||||||
|
const bundleCachePath = path.join(process.cwd(), cachePath)
|
||||||
|
|
||||||
|
await exec.exec('bundle', ['config', '--local', 'path', bundleCachePath], envOptions)
|
||||||
|
|
||||||
|
if (fs.existsSync(lockFile)) {
|
||||||
|
await exec.exec('bundle', ['config', '--local', 'deployment', 'true'], envOptions)
|
||||||
|
} else {
|
||||||
|
// 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.
|
||||||
|
await exec.exec('bundle', ['lock'], envOptions)
|
||||||
|
}
|
||||||
|
|
||||||
|
await afterLockFile(lockFile, platform, engine)
|
||||||
|
|
||||||
|
// cache key
|
||||||
|
const paths = [cachePath]
|
||||||
|
const baseKey = await computeBaseKey(platform, engine, rubyVersion, lockFile)
|
||||||
|
const key = `${baseKey}-${await common.hashFile(lockFile)}`
|
||||||
|
// If only Gemfile.lock changes we can reuse part of the cache, and clean old gem versions below
|
||||||
|
const restoreKeys = [`${baseKey}-`]
|
||||||
|
console.log(`Cache key: ${key}`)
|
||||||
|
|
||||||
|
// restore cache & install
|
||||||
|
let cachedKey = null
|
||||||
|
try {
|
||||||
|
cachedKey = await cache.restoreCache(paths, key, restoreKeys)
|
||||||
|
} catch (error) {
|
||||||
|
if (error.name === cache.ValidationError.name) {
|
||||||
|
throw error;
|
||||||
|
} else {
|
||||||
|
core.info(`[warning] There was an error restoring the cache ${error.message}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cachedKey) {
|
||||||
|
console.log(`Found cache for key: ${cachedKey}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Always run 'bundle install' to list the gems
|
||||||
|
await exec.exec('bundle', ['install', '--jobs', '4'])
|
||||||
|
|
||||||
|
// @actions/cache only allows to save for non-existing keys
|
||||||
|
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
|
||||||
|
console.log('Saving cache')
|
||||||
|
try {
|
||||||
|
await cache.saveCache(paths, key)
|
||||||
|
} catch (error) {
|
||||||
|
if (error.name === cache.ValidationError.name) {
|
||||||
|
throw error;
|
||||||
|
} else if (error.name === cache.ReserveCacheError.name) {
|
||||||
|
core.info(error.message);
|
||||||
|
} else {
|
||||||
|
core.info(`[warning]${error.message}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
async function computeBaseKey(platform, engine, version, lockFile) {
|
||||||
|
let key = `setup-ruby-bundler-cache-v3-${platform}-${engine}-${version}`
|
||||||
|
|
||||||
|
if (engine !== 'jruby' && common.isHeadVersion(version)) {
|
||||||
|
let revision = '';
|
||||||
|
await exec.exec('ruby', ['-e', 'print RUBY_REVISION'], {
|
||||||
|
silent: true,
|
||||||
|
listeners: {
|
||||||
|
stdout: (data) => {
|
||||||
|
revision += data.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
key += `-revision-${revision}`
|
||||||
|
}
|
||||||
|
|
||||||
|
key += `-${lockFile}`
|
||||||
|
return key
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***/ }),
|
||||||
/* 642 */,
|
/* 642 */,
|
||||||
/* 643 */,
|
/* 643 */,
|
||||||
/* 644 */,
|
/* 644 */,
|
||||||
@@ -47446,7 +47602,72 @@ exports.default = _default;
|
|||||||
/***/ }),
|
/***/ }),
|
||||||
/* 758 */,
|
/* 758 */,
|
||||||
/* 759 */,
|
/* 759 */,
|
||||||
/* 760 */,
|
/* 760 */
|
||||||
|
/***/ (function(module) {
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
module.exports = balanced;
|
||||||
|
function balanced(a, b, str) {
|
||||||
|
if (a instanceof RegExp) a = maybeMatch(a, str);
|
||||||
|
if (b instanceof RegExp) b = maybeMatch(b, str);
|
||||||
|
|
||||||
|
var r = range(a, b, str);
|
||||||
|
|
||||||
|
return r && {
|
||||||
|
start: r[0],
|
||||||
|
end: r[1],
|
||||||
|
pre: str.slice(0, r[0]),
|
||||||
|
body: str.slice(r[0] + a.length, r[1]),
|
||||||
|
post: str.slice(r[1] + b.length)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function maybeMatch(reg, str) {
|
||||||
|
var m = str.match(reg);
|
||||||
|
return m ? m[0] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
balanced.range = range;
|
||||||
|
function range(a, b, str) {
|
||||||
|
var begs, beg, left, right, result;
|
||||||
|
var ai = str.indexOf(a);
|
||||||
|
var bi = str.indexOf(b, ai + 1);
|
||||||
|
var i = ai;
|
||||||
|
|
||||||
|
if (ai >= 0 && bi > 0) {
|
||||||
|
begs = [];
|
||||||
|
left = str.length;
|
||||||
|
|
||||||
|
while (i >= 0 && !result) {
|
||||||
|
if (i == ai) {
|
||||||
|
begs.push(i);
|
||||||
|
ai = str.indexOf(a, i + 1);
|
||||||
|
} else if (begs.length == 1) {
|
||||||
|
result = [ begs.pop(), bi ];
|
||||||
|
} else {
|
||||||
|
beg = begs.pop();
|
||||||
|
if (beg < left) {
|
||||||
|
left = beg;
|
||||||
|
right = bi;
|
||||||
|
}
|
||||||
|
|
||||||
|
bi = str.indexOf(b, i + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
i = ai < bi && ai >= 0 ? ai : bi;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (begs.length) {
|
||||||
|
result = [ left, right ];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***/ }),
|
||||||
/* 761 */
|
/* 761 */
|
||||||
/***/ (function(module) {
|
/***/ (function(module) {
|
||||||
|
|
||||||
@@ -48853,7 +49074,7 @@ exports.safeTrimTrailingSeparator = safeTrimTrailingSeparator;
|
|||||||
/***/ (function(module, __unusedexports, __webpack_require__) {
|
/***/ (function(module, __unusedexports, __webpack_require__) {
|
||||||
|
|
||||||
var concatMap = __webpack_require__(891);
|
var concatMap = __webpack_require__(891);
|
||||||
var balanced = __webpack_require__(417);
|
var balanced = __webpack_require__(760);
|
||||||
|
|
||||||
module.exports = expandTop;
|
module.exports = expandTop;
|
||||||
|
|
||||||
@@ -49141,7 +49362,7 @@ exports.TraceAPI = TraceAPI;
|
|||||||
// Unique ID creation requires a high quality random # generator. In node.js
|
// Unique ID creation requires a high quality random # generator. In node.js
|
||||||
// this is pretty straight-forward - we use the crypto API.
|
// this is pretty straight-forward - we use the crypto API.
|
||||||
|
|
||||||
var crypto = __webpack_require__(373);
|
var crypto = __webpack_require__(417);
|
||||||
|
|
||||||
module.exports = function nodeRNG() {
|
module.exports = function nodeRNG() {
|
||||||
return crypto.randomBytes(16);
|
return crypto.randomBytes(16);
|
||||||
@@ -51831,9 +52052,8 @@ const os = __webpack_require__(87)
|
|||||||
const fs = __webpack_require__(747)
|
const fs = __webpack_require__(747)
|
||||||
const path = __webpack_require__(622)
|
const path = __webpack_require__(622)
|
||||||
const core = __webpack_require__(186)
|
const core = __webpack_require__(186)
|
||||||
const exec = __webpack_require__(514)
|
|
||||||
const cache = __webpack_require__(799)
|
|
||||||
const common = __webpack_require__(390)
|
const common = __webpack_require__(390)
|
||||||
|
const bundler = __webpack_require__(641)
|
||||||
|
|
||||||
const windows = common.windows
|
const windows = common.windows
|
||||||
|
|
||||||
@@ -51890,36 +52110,20 @@ async function setupRuby(options = {}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (inputs['bundler'] !== 'none') {
|
if (inputs['bundler'] !== 'none') {
|
||||||
const [gemfile, lockFile] = detectGemfiles()
|
const [gemfile, lockFile] = bundler.detectGemfiles()
|
||||||
|
|
||||||
const bundlerVersion = await common.measure('Installing Bundler', async () =>
|
const bundlerVersion = await common.measure('Installing Bundler', async () =>
|
||||||
installBundler(inputs['bundler'], lockFile, platform, rubyPrefix, engine, version))
|
bundler.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, bundlerVersion))
|
bundler.bundleInstall(gemfile, lockFile, platform, engine, version, bundlerVersion))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
core.setOutput('ruby-prefix', rubyPrefix)
|
core.setOutput('ruby-prefix', rubyPrefix)
|
||||||
}
|
}
|
||||||
|
|
||||||
// The returned gemfile is guaranteed to exist, the lockfile might not exist
|
|
||||||
function detectGemfiles() {
|
|
||||||
const gemfilePath = process.env['BUNDLE_GEMFILE'] || 'Gemfile'
|
|
||||||
if (fs.existsSync(gemfilePath)) {
|
|
||||||
return [gemfilePath, `${gemfilePath}.lock`]
|
|
||||||
} else if (process.env['BUNDLE_GEMFILE']) {
|
|
||||||
throw new Error(`$BUNDLE_GEMFILE is set to ${gemfilePath} but does not exist`)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fs.existsSync("gems.rb")) {
|
|
||||||
return ["gems.rb", "gems.locked"]
|
|
||||||
}
|
|
||||||
|
|
||||||
return [null, null]
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseRubyEngineAndVersion(rubyVersion) {
|
function parseRubyEngineAndVersion(rubyVersion) {
|
||||||
if (rubyVersion === 'default') {
|
if (rubyVersion === 'default') {
|
||||||
if (fs.existsSync('.ruby-version')) {
|
if (fs.existsSync('.ruby-version')) {
|
||||||
@@ -52003,168 +52207,6 @@ function envPreInstall() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function readBundledWithFromGemfileLock(lockFile) {
|
|
||||||
if (lockFile !== null && fs.existsSync(lockFile)) {
|
|
||||||
const contents = fs.readFileSync(lockFile, 'utf8')
|
|
||||||
const lines = contents.split(/\r?\n/)
|
|
||||||
const bundledWithLine = lines.findIndex(line => /^BUNDLED WITH$/.test(line.trim()))
|
|
||||||
if (bundledWithLine !== -1) {
|
|
||||||
const nextLine = lines[bundledWithLine+1]
|
|
||||||
if (nextLine && /^\d+/.test(nextLine.trim())) {
|
|
||||||
const bundlerVersion = nextLine.trim()
|
|
||||||
console.log(`Using Bundler ${bundlerVersion} from ${lockFile} BUNDLED WITH ${bundlerVersion}`)
|
|
||||||
return bundlerVersion
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
async function installBundler(bundlerVersionInput, lockFile, platform, rubyPrefix, engine, rubyVersion) {
|
|
||||||
let bundlerVersion = bundlerVersionInput
|
|
||||||
|
|
||||||
if (bundlerVersion === 'default' || bundlerVersion === 'Gemfile.lock') {
|
|
||||||
bundlerVersion = readBundledWithFromGemfileLock(lockFile)
|
|
||||||
|
|
||||||
if (!bundlerVersion) {
|
|
||||||
bundlerVersion = 'latest'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bundlerVersion === 'latest') {
|
|
||||||
bundlerVersion = '2'
|
|
||||||
}
|
|
||||||
|
|
||||||
if (/^\d+/.test(bundlerVersion)) {
|
|
||||||
// OK
|
|
||||||
} else {
|
|
||||||
throw new Error(`Cannot parse bundler input: ${bundlerVersion}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (engine === 'ruby' && rubyVersion.match(/^2\.[012]/)) {
|
|
||||||
console.log('Bundler 2 requires Ruby 2.3+, using Bundler 1 on Ruby <= 2.2')
|
|
||||||
bundlerVersion = '1'
|
|
||||||
} else if (engine === 'ruby' && rubyVersion.startsWith('2.3')) {
|
|
||||||
console.log('Ruby 2.3 has a bug with Bundler 2 (https://github.com/rubygems/rubygems/issues/3570), using Bundler 1 instead on Ruby 2.3')
|
|
||||||
bundlerVersion = '1'
|
|
||||||
} else if (engine === 'jruby' && rubyVersion.startsWith('9.1')) { // JRuby 9.1 targets Ruby 2.3, treat it the same
|
|
||||||
console.log('JRuby 9.1 has a bug with Bundler 2 (https://github.com/ruby/setup-ruby/issues/108), using Bundler 1 instead on JRuby 9.1')
|
|
||||||
bundlerVersion = '1'
|
|
||||||
}
|
|
||||||
|
|
||||||
if (common.isHeadVersion(rubyVersion) && common.isBundler2Default(engine, rubyVersion) && bundlerVersion.startsWith('2')) {
|
|
||||||
console.log(`Using Bundler 2 shipped with ${engine}-${rubyVersion}`)
|
|
||||||
} else if (engine === 'truffleruby' && !common.isHeadVersion(rubyVersion) && bundlerVersion.startsWith('1')) {
|
|
||||||
console.log(`Using Bundler 1 shipped with ${engine}`)
|
|
||||||
} else {
|
|
||||||
const gem = path.join(rubyPrefix, 'bin', 'gem')
|
|
||||||
const bundlerVersionConstraint = bundlerVersion.match(/^\d+\.\d+\.\d+/) ? bundlerVersion : `~> ${bundlerVersion}`
|
|
||||||
await exec.exec(gem, ['install', 'bundler', '-v', bundlerVersionConstraint, '--no-document'])
|
|
||||||
}
|
|
||||||
|
|
||||||
return bundlerVersion
|
|
||||||
}
|
|
||||||
|
|
||||||
async function bundleInstall(gemfile, lockFile, platform, engine, rubyVersion, bundlerVersion) {
|
|
||||||
if (gemfile === null) {
|
|
||||||
console.log('Could not determine gemfile path, skipping "bundle install" and caching')
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
let envOptions = {}
|
|
||||||
if (bundlerVersion.startsWith('1') && common.isBundler2Default(engine, rubyVersion)) {
|
|
||||||
// If Bundler 1 is specified on Rubies which ship with Bundler 2,
|
|
||||||
// we need to specify which Bundler version to use explicitly until the lockfile exists.
|
|
||||||
console.log(`Setting BUNDLER_VERSION=${bundlerVersion} for "bundle config|lock" commands below to ensure Bundler 1 is used`)
|
|
||||||
envOptions = { env: { ...process.env, BUNDLER_VERSION: bundlerVersion } }
|
|
||||||
}
|
|
||||||
|
|
||||||
// config
|
|
||||||
const cachePath = 'vendor/bundle'
|
|
||||||
// An absolute path, so it is reliably under $PWD/vendor/bundle, and not relative to the gemfile's directory
|
|
||||||
const bundleCachePath = path.join(process.cwd(), cachePath)
|
|
||||||
|
|
||||||
await exec.exec('bundle', ['config', '--local', 'path', bundleCachePath], envOptions)
|
|
||||||
|
|
||||||
if (fs.existsSync(lockFile)) {
|
|
||||||
await exec.exec('bundle', ['config', '--local', 'deployment', 'true'], envOptions)
|
|
||||||
} else {
|
|
||||||
// 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.
|
|
||||||
await exec.exec('bundle', ['lock'], envOptions)
|
|
||||||
}
|
|
||||||
|
|
||||||
// cache key
|
|
||||||
const paths = [cachePath]
|
|
||||||
const baseKey = await computeBaseKey(platform, engine, rubyVersion, lockFile)
|
|
||||||
const key = `${baseKey}-${await common.hashFile(lockFile)}`
|
|
||||||
// If only Gemfile.lock changes we can reuse part of the cache, and clean old gem versions below
|
|
||||||
const restoreKeys = [`${baseKey}-`]
|
|
||||||
console.log(`Cache key: ${key}`)
|
|
||||||
|
|
||||||
// restore cache & install
|
|
||||||
let cachedKey = null
|
|
||||||
try {
|
|
||||||
cachedKey = await cache.restoreCache(paths, key, restoreKeys)
|
|
||||||
} catch (error) {
|
|
||||||
if (error.name === cache.ValidationError.name) {
|
|
||||||
throw error;
|
|
||||||
} else {
|
|
||||||
core.info(`[warning] There was an error restoring the cache ${error.message}`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cachedKey) {
|
|
||||||
console.log(`Found cache for key: ${cachedKey}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Always run 'bundle install' to list the gems
|
|
||||||
await exec.exec('bundle', ['install', '--jobs', '4'])
|
|
||||||
|
|
||||||
// @actions/cache only allows to save for non-existing keys
|
|
||||||
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
|
|
||||||
console.log('Saving cache')
|
|
||||||
try {
|
|
||||||
await cache.saveCache(paths, key)
|
|
||||||
} catch (error) {
|
|
||||||
if (error.name === cache.ValidationError.name) {
|
|
||||||
throw error;
|
|
||||||
} else if (error.name === cache.ReserveCacheError.name) {
|
|
||||||
core.info(error.message);
|
|
||||||
} else {
|
|
||||||
core.info(`[warning]${error.message}`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
async function computeBaseKey(platform, engine, version, lockFile) {
|
|
||||||
let key = `setup-ruby-bundler-cache-v3-${platform}-${engine}-${version}`
|
|
||||||
|
|
||||||
if (engine !== 'jruby' && common.isHeadVersion(version)) {
|
|
||||||
let revision = '';
|
|
||||||
await exec.exec('ruby', ['-e', 'print RUBY_REVISION'], {
|
|
||||||
silent: true,
|
|
||||||
listeners: {
|
|
||||||
stdout: (data) => {
|
|
||||||
revision += data.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
key += `-revision-${revision}`
|
|
||||||
}
|
|
||||||
|
|
||||||
key += `-${lockFile}`
|
|
||||||
return key
|
|
||||||
}
|
|
||||||
|
|
||||||
if (__filename.endsWith('index.js')) { run() }
|
if (__filename.endsWith('index.js')) { run() }
|
||||||
|
|
||||||
|
|
||||||
@@ -53979,7 +54021,7 @@ Object.defineProperty(exports, "__esModule", {
|
|||||||
});
|
});
|
||||||
exports.default = rng;
|
exports.default = rng;
|
||||||
|
|
||||||
var _crypto = _interopRequireDefault(__webpack_require__(373));
|
var _crypto = _interopRequireDefault(__webpack_require__(417));
|
||||||
|
|
||||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
source "https://rubygems.org"
|
||||||
|
|
||||||
|
gem "nokogiri"
|
||||||
@@ -2,9 +2,8 @@ const os = require('os')
|
|||||||
const fs = require('fs')
|
const fs = require('fs')
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
const core = require('@actions/core')
|
const core = require('@actions/core')
|
||||||
const exec = require('@actions/exec')
|
|
||||||
const cache = require('@actions/cache')
|
|
||||||
const common = require('./common')
|
const common = require('./common')
|
||||||
|
const bundler = require('./bundler')
|
||||||
|
|
||||||
const windows = common.windows
|
const windows = common.windows
|
||||||
|
|
||||||
@@ -61,36 +60,20 @@ export async function setupRuby(options = {}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (inputs['bundler'] !== 'none') {
|
if (inputs['bundler'] !== 'none') {
|
||||||
const [gemfile, lockFile] = detectGemfiles()
|
const [gemfile, lockFile] = bundler.detectGemfiles()
|
||||||
|
|
||||||
const bundlerVersion = await common.measure('Installing Bundler', async () =>
|
const bundlerVersion = await common.measure('Installing Bundler', async () =>
|
||||||
installBundler(inputs['bundler'], lockFile, platform, rubyPrefix, engine, version))
|
bundler.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, bundlerVersion))
|
bundler.bundleInstall(gemfile, lockFile, platform, engine, version, bundlerVersion))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
core.setOutput('ruby-prefix', rubyPrefix)
|
core.setOutput('ruby-prefix', rubyPrefix)
|
||||||
}
|
}
|
||||||
|
|
||||||
// The returned gemfile is guaranteed to exist, the lockfile might not exist
|
|
||||||
function detectGemfiles() {
|
|
||||||
const gemfilePath = process.env['BUNDLE_GEMFILE'] || 'Gemfile'
|
|
||||||
if (fs.existsSync(gemfilePath)) {
|
|
||||||
return [gemfilePath, `${gemfilePath}.lock`]
|
|
||||||
} else if (process.env['BUNDLE_GEMFILE']) {
|
|
||||||
throw new Error(`$BUNDLE_GEMFILE is set to ${gemfilePath} but does not exist`)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fs.existsSync("gems.rb")) {
|
|
||||||
return ["gems.rb", "gems.locked"]
|
|
||||||
}
|
|
||||||
|
|
||||||
return [null, null]
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseRubyEngineAndVersion(rubyVersion) {
|
function parseRubyEngineAndVersion(rubyVersion) {
|
||||||
if (rubyVersion === 'default') {
|
if (rubyVersion === 'default') {
|
||||||
if (fs.existsSync('.ruby-version')) {
|
if (fs.existsSync('.ruby-version')) {
|
||||||
@@ -174,166 +157,4 @@ function envPreInstall() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function readBundledWithFromGemfileLock(lockFile) {
|
|
||||||
if (lockFile !== null && fs.existsSync(lockFile)) {
|
|
||||||
const contents = fs.readFileSync(lockFile, 'utf8')
|
|
||||||
const lines = contents.split(/\r?\n/)
|
|
||||||
const bundledWithLine = lines.findIndex(line => /^BUNDLED WITH$/.test(line.trim()))
|
|
||||||
if (bundledWithLine !== -1) {
|
|
||||||
const nextLine = lines[bundledWithLine+1]
|
|
||||||
if (nextLine && /^\d+/.test(nextLine.trim())) {
|
|
||||||
const bundlerVersion = nextLine.trim()
|
|
||||||
console.log(`Using Bundler ${bundlerVersion} from ${lockFile} BUNDLED WITH ${bundlerVersion}`)
|
|
||||||
return bundlerVersion
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
async function installBundler(bundlerVersionInput, lockFile, platform, rubyPrefix, engine, rubyVersion) {
|
|
||||||
let bundlerVersion = bundlerVersionInput
|
|
||||||
|
|
||||||
if (bundlerVersion === 'default' || bundlerVersion === 'Gemfile.lock') {
|
|
||||||
bundlerVersion = readBundledWithFromGemfileLock(lockFile)
|
|
||||||
|
|
||||||
if (!bundlerVersion) {
|
|
||||||
bundlerVersion = 'latest'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bundlerVersion === 'latest') {
|
|
||||||
bundlerVersion = '2'
|
|
||||||
}
|
|
||||||
|
|
||||||
if (/^\d+/.test(bundlerVersion)) {
|
|
||||||
// OK
|
|
||||||
} else {
|
|
||||||
throw new Error(`Cannot parse bundler input: ${bundlerVersion}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (engine === 'ruby' && rubyVersion.match(/^2\.[012]/)) {
|
|
||||||
console.log('Bundler 2 requires Ruby 2.3+, using Bundler 1 on Ruby <= 2.2')
|
|
||||||
bundlerVersion = '1'
|
|
||||||
} else if (engine === 'ruby' && rubyVersion.startsWith('2.3')) {
|
|
||||||
console.log('Ruby 2.3 has a bug with Bundler 2 (https://github.com/rubygems/rubygems/issues/3570), using Bundler 1 instead on Ruby 2.3')
|
|
||||||
bundlerVersion = '1'
|
|
||||||
} else if (engine === 'jruby' && rubyVersion.startsWith('9.1')) { // JRuby 9.1 targets Ruby 2.3, treat it the same
|
|
||||||
console.log('JRuby 9.1 has a bug with Bundler 2 (https://github.com/ruby/setup-ruby/issues/108), using Bundler 1 instead on JRuby 9.1')
|
|
||||||
bundlerVersion = '1'
|
|
||||||
}
|
|
||||||
|
|
||||||
if (common.isHeadVersion(rubyVersion) && common.isBundler2Default(engine, rubyVersion) && bundlerVersion.startsWith('2')) {
|
|
||||||
console.log(`Using Bundler 2 shipped with ${engine}-${rubyVersion}`)
|
|
||||||
} else if (engine === 'truffleruby' && !common.isHeadVersion(rubyVersion) && bundlerVersion.startsWith('1')) {
|
|
||||||
console.log(`Using Bundler 1 shipped with ${engine}`)
|
|
||||||
} else {
|
|
||||||
const gem = path.join(rubyPrefix, 'bin', 'gem')
|
|
||||||
const bundlerVersionConstraint = bundlerVersion.match(/^\d+\.\d+\.\d+/) ? bundlerVersion : `~> ${bundlerVersion}`
|
|
||||||
await exec.exec(gem, ['install', 'bundler', '-v', bundlerVersionConstraint, '--no-document'])
|
|
||||||
}
|
|
||||||
|
|
||||||
return bundlerVersion
|
|
||||||
}
|
|
||||||
|
|
||||||
async function bundleInstall(gemfile, lockFile, platform, engine, rubyVersion, bundlerVersion) {
|
|
||||||
if (gemfile === null) {
|
|
||||||
console.log('Could not determine gemfile path, skipping "bundle install" and caching')
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
let envOptions = {}
|
|
||||||
if (bundlerVersion.startsWith('1') && common.isBundler2Default(engine, rubyVersion)) {
|
|
||||||
// If Bundler 1 is specified on Rubies which ship with Bundler 2,
|
|
||||||
// we need to specify which Bundler version to use explicitly until the lockfile exists.
|
|
||||||
console.log(`Setting BUNDLER_VERSION=${bundlerVersion} for "bundle config|lock" commands below to ensure Bundler 1 is used`)
|
|
||||||
envOptions = { env: { ...process.env, BUNDLER_VERSION: bundlerVersion } }
|
|
||||||
}
|
|
||||||
|
|
||||||
// config
|
|
||||||
const cachePath = 'vendor/bundle'
|
|
||||||
// An absolute path, so it is reliably under $PWD/vendor/bundle, and not relative to the gemfile's directory
|
|
||||||
const bundleCachePath = path.join(process.cwd(), cachePath)
|
|
||||||
|
|
||||||
await exec.exec('bundle', ['config', '--local', 'path', bundleCachePath], envOptions)
|
|
||||||
|
|
||||||
if (fs.existsSync(lockFile)) {
|
|
||||||
await exec.exec('bundle', ['config', '--local', 'deployment', 'true'], envOptions)
|
|
||||||
} else {
|
|
||||||
// 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.
|
|
||||||
await exec.exec('bundle', ['lock'], envOptions)
|
|
||||||
}
|
|
||||||
|
|
||||||
// cache key
|
|
||||||
const paths = [cachePath]
|
|
||||||
const baseKey = await computeBaseKey(platform, engine, rubyVersion, lockFile)
|
|
||||||
const key = `${baseKey}-${await common.hashFile(lockFile)}`
|
|
||||||
// If only Gemfile.lock changes we can reuse part of the cache, and clean old gem versions below
|
|
||||||
const restoreKeys = [`${baseKey}-`]
|
|
||||||
console.log(`Cache key: ${key}`)
|
|
||||||
|
|
||||||
// restore cache & install
|
|
||||||
let cachedKey = null
|
|
||||||
try {
|
|
||||||
cachedKey = await cache.restoreCache(paths, key, restoreKeys)
|
|
||||||
} catch (error) {
|
|
||||||
if (error.name === cache.ValidationError.name) {
|
|
||||||
throw error;
|
|
||||||
} else {
|
|
||||||
core.info(`[warning] There was an error restoring the cache ${error.message}`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cachedKey) {
|
|
||||||
console.log(`Found cache for key: ${cachedKey}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Always run 'bundle install' to list the gems
|
|
||||||
await exec.exec('bundle', ['install', '--jobs', '4'])
|
|
||||||
|
|
||||||
// @actions/cache only allows to save for non-existing keys
|
|
||||||
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
|
|
||||||
console.log('Saving cache')
|
|
||||||
try {
|
|
||||||
await cache.saveCache(paths, key)
|
|
||||||
} catch (error) {
|
|
||||||
if (error.name === cache.ValidationError.name) {
|
|
||||||
throw error;
|
|
||||||
} else if (error.name === cache.ReserveCacheError.name) {
|
|
||||||
core.info(error.message);
|
|
||||||
} else {
|
|
||||||
core.info(`[warning]${error.message}`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
async function computeBaseKey(platform, engine, version, lockFile) {
|
|
||||||
let key = `setup-ruby-bundler-cache-v3-${platform}-${engine}-${version}`
|
|
||||||
|
|
||||||
if (engine !== 'jruby' && common.isHeadVersion(version)) {
|
|
||||||
let revision = '';
|
|
||||||
await exec.exec('ruby', ['-e', 'print RUBY_REVISION'], {
|
|
||||||
silent: true,
|
|
||||||
listeners: {
|
|
||||||
stdout: (data) => {
|
|
||||||
revision += data.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
key += `-revision-${revision}`
|
|
||||||
}
|
|
||||||
|
|
||||||
key += `-${lockFile}`
|
|
||||||
return key
|
|
||||||
}
|
|
||||||
|
|
||||||
if (__filename.endsWith('index.js')) { run() }
|
if (__filename.endsWith('index.js')) { run() }
|
||||||
|
|||||||
Reference in New Issue
Block a user