From a6686a5cda27c16f9611242c2ef57d53ad4ff6c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Fri, 21 Jan 2022 08:55:27 +0100 Subject: [PATCH 1/5] Add a new input to optionally update RubyGems --- .github/workflows/test.yml | 22 ++++++++++++++++++++++ action.yml | 7 +++++++ dist/index.js | 30 ++++++++++++++++++++++++++++++ index.js | 7 +++++++ rubygems.js | 11 +++++++++++ 5 files changed, 77 insertions(+) create mode 100644 rubygems.js diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index bc4e14a95..4d302d3db 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -112,6 +112,28 @@ 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'))" + + testFixedRubygemsVersion: + name: "Test rubygems input set to a fixed version upgrades RubyGems to that versoin" + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: ./ + with: + ruby-version: 2.6 + rubygems: 3.3.5 + - run: gem --version | grep -F "3.3.5" + testExactBundlerVersion: name: "Test with an exact Bundler version" runs-on: ubuntu-latest diff --git a/action.yml b/action.yml index 14732f8a5..23d1772e0 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. + 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..9700cf584 100644 --- a/dist/index.js +++ b/dist/index.js @@ -58953,6 +58953,29 @@ 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) + +async function rubygemsUpdate(rubygemsVersionInput, rubyPrefix) { + const gem = path.join(rubyPrefix, 'bin', 'gem') + const rubygemsVersion = (rubygemsVersionInput === 'latest') ? [] : [rubygemsVersionInput] + + await exec.exec(gem, ['update', '--system', ...rubygemsVersion]) + + return true +} + + /***/ }), /***/ 7223: @@ -59566,12 +59589,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 +59648,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/rubygems.js b/rubygems.js new file mode 100644 index 000000000..105f61d26 --- /dev/null +++ b/rubygems.js @@ -0,0 +1,11 @@ +const path = require('path') +const exec = require('@actions/exec') + +export async function rubygemsUpdate(rubygemsVersionInput, rubyPrefix) { + const gem = path.join(rubyPrefix, 'bin', 'gem') + const rubygemsVersion = (rubygemsVersionInput === 'latest') ? [] : [rubygemsVersionInput] + + await exec.exec(gem, ['update', '--system', ...rubygemsVersion]) + + return true +} From 89e3371085b3c81a3e5043e9d9e7b63dbf7789d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Sat, 22 Jan 2022 06:18:30 +0100 Subject: [PATCH 2/5] Add a short README section about the RubyGems version --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 2b71d9a35..61d21c4da 100644 --- a/README.md +++ b/README.md @@ -139,6 +139,14 @@ 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 + +See [action.yml](action.yml) for more details about the `rubygems` input. + ### Bundler By default, if there is a `Gemfile.lock` file (or `$BUNDLE_GEMFILE.lock` or `gems.locked`) with a `BUNDLED WITH` section, From 4242b2ea6ca61ddcfc602570b118468391a2edcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Sat, 22 Jan 2022 06:24:52 +0100 Subject: [PATCH 3/5] Tweak rubygems input behavior When a fixed version is passed, it should be the minimum RubyGems version for the whole matrix, i.e., RubyGems should not be dowgraded past the default version of the oldest Ruby in the matrix. --- .github/workflows/test.yml | 19 +++++++++++++++---- action.yml | 2 +- dist/index.js | 23 +++++++++++++++++++++-- package.json | 3 ++- rubygems.js | 23 +++++++++++++++++++++-- 5 files changed, 60 insertions(+), 10 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4d302d3db..b33ddc047 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -123,16 +123,27 @@ jobs: rubygems: latest - run: ruby -e "exit(Gem.rubygems_version > Gem::Version.new('3.0.3'))" - testFixedRubygemsVersion: - name: "Test rubygems input set to a fixed version upgrades RubyGems to that versoin" + 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.3.5 - - run: gem --version | grep -F "3.3.5" + 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" diff --git a/action.yml b/action.yml index 23d1772e0..01a1b5831 100644 --- a/action.yml +++ b/action.yml @@ -14,7 +14,7 @@ inputs: 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. + 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: | diff --git a/dist/index.js b/dist/index.js index 9700cf584..2f38272ed 100644 --- a/dist/index.js +++ b/dist/index.js @@ -58965,12 +58965,31 @@ __nccwpck_require__.r(__webpack_exports__); /* 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') - const rubygemsVersion = (rubygemsVersionInput === 'latest') ? [] : [rubygemsVersionInput] - await exec.exec(gem, ['update', '--system', ...rubygemsVersion]) + 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 } 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 index 105f61d26..8b77bd7f3 100644 --- a/rubygems.js +++ b/rubygems.js @@ -1,11 +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') - const rubygemsVersion = (rubygemsVersionInput === 'latest') ? [] : [rubygemsVersionInput] - await exec.exec(gem, ['update', '--system', ...rubygemsVersion]) + 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 } From 189345b108ca7857f0846aaa721e689937b57f5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Sat, 22 Jan 2022 08:03:37 +0100 Subject: [PATCH 4/5] Add a note about Psych + RubyGems issue --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 61d21c4da..f135818e2 100644 --- a/README.md +++ b/README.md @@ -147,6 +147,10 @@ setting the `rubygems` input. See 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, From b1243c804d7c3032f9cf2d7279a89a7c5655556d Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Sat, 22 Jan 2022 17:28:29 +0100 Subject: [PATCH 5/5] Small cleanup --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f135818e2..a0538131c 100644 --- a/README.md +++ b/README.md @@ -143,7 +143,7 @@ if they are not at the root of the repository, see [action.yml](action.yml) for 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 +setting the `rubygems` input. See [action.yml](action.yml) for more details about the `rubygems` input.