diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index bc4e14a95..b33ddc047 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -112,6 +112,39 @@ jobs: if: startsWith(matrix.os, 'windows') && startsWith(matrix.ruby, 'jruby') run: gem install sassc + testLatestRubygemsVersion: + name: "Test rubygems input set to latest upgrades the default RubyGems version" + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: ./ + with: + ruby-version: 2.6 + rubygems: latest + - run: ruby -e "exit(Gem.rubygems_version > Gem::Version.new('3.0.3'))" + + testFixedRubygemsVersionUpgrades: + name: "Test rubygems input set to a fixed version upgrades RubyGems to that version if the default is older" + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: ./ + with: + ruby-version: 2.6 + rubygems: 3.2.3 + - run: gem --version | grep -F "3.2.3" + + testFixedRubygemsVersionNoop: + name: "Test rubygems input set to a fixed version noops if the default is newer" + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: ./ + with: + ruby-version: 3.1 + rubygems: 3.2.3 + - run: gem --version | grep -F "3.3.3" + testExactBundlerVersion: name: "Test with an exact Bundler version" runs-on: ubuntu-latest diff --git a/README.md b/README.md index 2b71d9a35..a0538131c 100644 --- a/README.md +++ b/README.md @@ -139,6 +139,18 @@ and the [condition and expression syntax](https://help.github.com/en/actions/ref The `working-directory` input can be set to resolve `.ruby-version`, `.tool-versions` and `Gemfile.lock` if they are not at the root of the repository, see [action.yml](action.yml) for details. +## RubyGems + +By default, the default RubyGems version that comes with each Ruby is used. +However, users can optionally customize the RubyGems version that they want by +setting the `rubygems` input. + +See [action.yml](action.yml) for more details about the `rubygems` input. + +If you're running into `ArgumentError: wrong number of arguments (given 4, +expected 1)` errors with a stacktrace including Psych and RubyGems entries, you +should be able to fix them by setting `rubygems: 3.0.0` or higher. + ### Bundler By default, if there is a `Gemfile.lock` file (or `$BUNDLE_GEMFILE.lock` or `gems.locked`) with a `BUNDLED WITH` section, diff --git a/action.yml b/action.yml index 14732f8a5..01a1b5831 100644 --- a/action.yml +++ b/action.yml @@ -9,6 +9,13 @@ inputs: description: 'Engine and version to use, see the syntax in the README. Reads from .ruby-version or .tool-versions if unset.' required: false default: 'default' + rubygems: + description: | + The version of RubyGems to use. Either 'default', 'latest', or a version number (e.g., 3.3.5). + For 'default', no action is taken and the version of RubyGems that comes with Ruby by default is used. + For 'latest', `gem update --system` is run to update to the latest RubyGems version. + Similarly, if a version number is given, `gem update --system ` is run to update to that version of RubyGems, as long as that version is newer than the one provided by default. + Defaults to 'default'. bundler: description: | The version of Bundler to install. Either 'none', 'latest', 'Gemfile.lock', or a version number (e.g., 1, 2, 2.1.4). diff --git a/dist/index.js b/dist/index.js index 56e93f843..2f38272ed 100644 --- a/dist/index.js +++ b/dist/index.js @@ -58953,6 +58953,48 @@ function getLatestHeadBuildURL(platform, engine, version) { } +/***/ }), + +/***/ 160: +/***/ ((__unused_webpack_module, __webpack_exports__, __nccwpck_require__) => { + +"use strict"; +__nccwpck_require__.r(__webpack_exports__); +/* harmony export */ __nccwpck_require__.d(__webpack_exports__, { +/* harmony export */ "rubygemsUpdate": () => (/* binding */ rubygemsUpdate) +/* harmony export */ }); +const path = __nccwpck_require__(5622) +const exec = __nccwpck_require__(1514) +const semver = __nccwpck_require__(5911) + +async function rubygemsUpdate(rubygemsVersionInput, rubyPrefix) { + const gem = path.join(rubyPrefix, 'bin', 'gem') + + let gemVersion = '' + + await exec.exec(gem, ['--version'], { + listeners: { + stdout: (data) => (gemVersion += data.toString()), + } + }); + + gemVersion = semver.coerce(gemVersion.trim()) + console.log(`Default RubyGems version is ${gemVersion}`) + + if (rubygemsVersionInput === 'latest') { + console.log('Updating RubyGems to latest version') + await exec.exec(gem, ['update', '--system']) + } else if (semver.gt(rubygemsVersionInput, gemVersion)) { + console.log(`Updating RubyGems to ${rubygemsVersionInput}`) + await exec.exec(gem, ['update', '--system', rubygemsVersionInput]) + } else { + console.log(`Skipping RubyGems update because the given version (${rubygemsVersionInput}) is not newer than the default version (${gemVersion})`) + } + + return true +} + + /***/ }), /***/ 7223: @@ -59566,12 +59608,14 @@ const fs = __nccwpck_require__(5747) const path = __nccwpck_require__(5622) const core = __nccwpck_require__(2186) const common = __nccwpck_require__(4717) +const rubygems = __nccwpck_require__(160) const bundler = __nccwpck_require__(1641) const windows = common.windows const inputDefaults = { 'ruby-version': 'default', + 'rubygems': 'default', 'bundler': 'default', 'bundler-cache': 'true', 'working-directory': '.', @@ -59623,6 +59667,11 @@ async function setupRuby(options = {}) { const rubyPrefix = await installer.install(platform, engine, version) + if (inputs['rubygems'] !== 'default') { + await common.measure('Updating RubyGems', async () => + rubygems.rubygemsUpdate(inputs['rubygems'], rubyPrefix)) + } + // When setup-ruby is used by other actions, this allows code in them to run // before 'bundle install'. Installed dependencies may require additional // libraries & headers, build tools, etc. diff --git a/index.js b/index.js index a94fa3c58..419d71857 100644 --- a/index.js +++ b/index.js @@ -3,12 +3,14 @@ const fs = require('fs') const path = require('path') const core = require('@actions/core') const common = require('./common') +const rubygems = require('./rubygems') const bundler = require('./bundler') const windows = common.windows const inputDefaults = { 'ruby-version': 'default', + 'rubygems': 'default', 'bundler': 'default', 'bundler-cache': 'true', 'working-directory': '.', @@ -60,6 +62,11 @@ export async function setupRuby(options = {}) { const rubyPrefix = await installer.install(platform, engine, version) + if (inputs['rubygems'] !== 'default') { + await common.measure('Updating RubyGems', async () => + rubygems.rubygemsUpdate(inputs['rubygems'], rubyPrefix)) + } + // When setup-ruby is used by other actions, this allows code in them to run // before 'bundle install'. Installed dependencies may require additional // libraries & headers, build tools, etc. diff --git a/package.json b/package.json index 915464c23..26783d1a2 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,8 @@ "@actions/core": "^1.4.0", "@actions/exec": "^1.1.0", "@actions/io": "^1.1.1", - "@actions/tool-cache": "^1.7.1" + "@actions/tool-cache": "^1.7.1", + "semver": "^6.1.0" }, "devDependencies": { "@vercel/ncc": "^0.31.1" diff --git a/rubygems.js b/rubygems.js new file mode 100644 index 000000000..8b77bd7f3 --- /dev/null +++ b/rubygems.js @@ -0,0 +1,30 @@ +const path = require('path') +const exec = require('@actions/exec') +const semver = require('semver') + +export async function rubygemsUpdate(rubygemsVersionInput, rubyPrefix) { + const gem = path.join(rubyPrefix, 'bin', 'gem') + + let gemVersion = '' + + await exec.exec(gem, ['--version'], { + listeners: { + stdout: (data) => (gemVersion += data.toString()), + } + }); + + gemVersion = semver.coerce(gemVersion.trim()) + console.log(`Default RubyGems version is ${gemVersion}`) + + if (rubygemsVersionInput === 'latest') { + console.log('Updating RubyGems to latest version') + await exec.exec(gem, ['update', '--system']) + } else if (semver.gt(rubygemsVersionInput, gemVersion)) { + console.log(`Updating RubyGems to ${rubygemsVersionInput}`) + await exec.exec(gem, ['update', '--system', rubygemsVersionInput]) + } else { + console.log(`Skipping RubyGems update because the given version (${rubygemsVersionInput}) is not newer than the default version (${gemVersion})`) + } + + return true +}