Compare commits

...
9 Commits
Author SHA1 Message Date
Benoit Daloze 3c644cf2fc Better error if MSYS2 is missing 2020-01-05 19:47:18 +01:00
Benoit Daloze 101f62de1d Add support for Windows 2020-01-05 19:33:14 +01:00
Benoit Daloze 9432c89d1a Recommend the short version syntax
* It's safer long-term and ensures to use the latest release with the most bug fixes.
2020-01-05 13:11:27 +01:00
Benoit Daloze 4c00b61136 Simplify the README 2020-01-05 13:03:07 +01:00
Benoit Daloze d49a90aea9 tmp 2020-01-05 13:02:10 +01:00
Benoit Daloze 1d7622c155 Use a consistent ordering for JRuby and TruffleRuby 2020-01-05 13:00:17 +01:00
Benoit Daloze a90d45f642 Improve the README 2020-01-05 12:55:52 +01:00
Benoit Daloze d9cd49386b Add support for Ruby 2.3
* Fixes https://github.com/eregon/use-ruby-action/issues/3
2020-01-05 12:50:37 +01:00
Benoit Daloze 7d189e2075 Improve error message when a version is not available 2020-01-04 16:18:37 +01:00
8 changed files with 280 additions and 77 deletions
+2 -1
View File
@@ -10,7 +10,8 @@
"SharedArrayBuffer": "readonly" "SharedArrayBuffer": "readonly"
}, },
"parserOptions": { "parserOptions": {
"ecmaVersion": 2018 "ecmaVersion": 2018,
"sourceType": "module"
}, },
"rules": { "rules": {
} }
+14 -3
View File
@@ -5,8 +5,16 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
os: [ ubuntu-16.04, ubuntu-18.04, macos-latest ] os: [ ubuntu-16.04, ubuntu-18.04, macos-latest, windows-latest ]
ruby: [ ruby-2.4, 2.5, ruby-2.6.5, 2.7.0, truffleruby, jruby ] # Use various version syntaxes here for testing
ruby: [ 2.3, ruby-2.4, 2.5, ruby-2.6.5, 2.7.0, jruby, truffleruby ]
exclude:
- os: windows-latest
ruby: 2.3
- os: windows-latest
ruby: jruby
- os: windows-latest
ruby: truffleruby
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
@@ -14,4 +22,7 @@ jobs:
with: with:
ruby-version: ${{ matrix.ruby }} ruby-version: ${{ matrix.ruby }}
- run: ruby -v - run: ruby -v
- run: ruby -ropen-uri -e 'puts open("https://rubygems.org/") { |f| f.read(2014) }' - run: ridk version
if: matrix.os == 'windows-latest'
- run: ruby -ropen-uri -e 'puts open(%{https://rubygems.org/}) { |f| f.read(2014) }'
- run: gem install json --no-document
+36 -36
View File
@@ -2,15 +2,38 @@
This action downloads a prebuilt ruby and adds it to `$PATH`. This action downloads a prebuilt ruby and adds it to `$PATH`.
It currently supports the latest stable versions of MRI, JRuby and TruffleRuby. It is very efficient and takes about 5 seconds to download, extract and add the given Ruby to `$PATH`.
No extra packages need to be installed.
### Supported Versions
This action currently supports these versions of MRI, JRuby and TruffleRuby:
| Interpreter | Versions |
| ----------- | -------- |
| Ruby | 2.3.8, 2.4.9, 2.5.7, 2.6.5, 2.7.0 |
| JRuby | 9.2.9.0 |
| TruffleRuby | 19.3.0 |
The recommended way to refer to these versions is:
`2.3`, `2.4`, `2.5`, `2.6`, `2.7`, `jruby`, `truffleruby`.
That way, the latest compatible release is used, which contains the most bug fixes.
See https://github.com/eregon/ruby-install-builder/blob/metadata/versions.json See https://github.com/eregon/ruby-install-builder/blob/metadata/versions.json
for the available Ruby versions. for the always up-to-date list of available Ruby versions.
The action works for the `ubuntu-16.04`, `ubuntu-18.04` and `macos-latest` GitHub-hosted runners. Note that Ruby 2.3 and the OpenSSL version it needs (1.0.2) are both end-of-life,
`windows-latest` is not yet supported. which means Ruby 2.3 is unmaintained and considered insecure.
The prebuilt rubies are generated by https://github.com/eregon/ruby-install-builder. ### Supported Platforms
The action works for all GitHub-hosted runners:
`ubuntu-16.04`, `ubuntu-18.04`, `macos-latest` and `windows-latest`.
Ruby 2.3, JRuby and TruffleRuby are not yet supported on `windows-latest`.
The prebuilt rubies are generated by https://github.com/eregon/ruby-install-builder
and on Windows by https://github.com/oneclick/rubyinstaller2.
## Usage ## Usage
@@ -26,12 +49,14 @@ jobs:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- uses: eregon/use-ruby-action@master - uses: eregon/use-ruby-action@master
with: with:
ruby-version: ruby-2.6 ruby-version: 2.6
- run: ruby -v - run: ruby -v
``` ```
### Matrix ### Matrix
This matrix tests all stable releases of MRI, JRuby and TruffleRuby on Ubuntu and macOS.
```yaml ```yaml
name: My workflow name: My workflow
on: [push] on: [push]
@@ -41,7 +66,7 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
os: [ ubuntu-latest, macos-latest ] os: [ ubuntu-latest, macos-latest ]
ruby: [ ruby-2.6, ruby-2.7, truffleruby-19.3.0, jruby-9.2.9.0 ] ruby: [ 2.4, 2.5, 2.6, 2.7, jruby, truffleruby ]
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
@@ -58,35 +83,10 @@ jobs:
* version only like `2.6.5`, assumes MRI for the engine * version only like `2.6.5`, assumes MRI for the engine
* engine only like `truffleruby`, uses the latest stable release of that implementation * engine only like `truffleruby`, uses the latest stable release of that implementation
### All Stable Versions
With that, we can test on all stable releases of MRI, JRuby and TruffleRuby with:
```yaml
name: My workflow
on: [push]
jobs:
test:
strategy:
fail-fast: false
matrix:
os: [ ubuntu-latest, macos-latest ]
ruby: [ 2.4, 2.5, 2.6, 2.7, truffleruby, jruby ]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
- uses: eregon/use-ruby-action@master
with:
ruby-version: ${{ matrix.ruby }}
- run: ruby -v
```
## Efficiency
It takes about 5 seconds to setup the given Ruby.
## Limitations ## Limitations
* Currently does not work on Windows since the builder doesn't build on Windows.
https://github.com/MSP-Greg/actions-ruby is an alternative on Windows.
* This action currently only works with GitHub-hosted runners, not private runners. * This action currently only works with GitHub-hosted runners, not private runners.
## Credits
Most of the Windows logic is from https://github.com/MSP-Greg/actions-ruby by MSP-Greg.
+1 -1
View File
@@ -6,7 +6,7 @@ branding:
icon: download icon: download
inputs: inputs:
ruby-version: ruby-version:
description: 'Engine and version to use in the format "myruby-X.Y.Z"' description: 'Engine and version to use, see the syntax in the README'
required: true required: true
outputs: outputs:
ruby-prefix: ruby-prefix:
Generated Vendored
+133 -18
View File
@@ -36,6 +36,8 @@ module.exports =
/******/ // Load entry module and return exports /******/ // Load entry module and return exports
/******/ return __webpack_require__(104); /******/ return __webpack_require__(104);
/******/ }; /******/ };
/******/ // initialize runtime
/******/ runtime(__webpack_require__);
/******/ /******/
/******/ // run startup /******/ // run startup
/******/ return startup(); /******/ return startup();
@@ -1383,33 +1385,43 @@ const core = __webpack_require__(470)
const io = __webpack_require__(1) const io = __webpack_require__(1)
const tc = __webpack_require__(533) const tc = __webpack_require__(533)
const axios = __webpack_require__(53) const axios = __webpack_require__(53)
const windows = __webpack_require__(664)
const releasesURL = 'https://github.com/eregon/ruby-install-builder/releases' const releasesURL = 'https://github.com/eregon/ruby-install-builder/releases'
const metadataURL = 'https://raw.githubusercontent.com/eregon/ruby-install-builder/metadata' const metadataURL = 'https://raw.githubusercontent.com/eregon/ruby-install-builder/metadata'
async function run() { async function run() {
try { try {
const platform = getVirtualEnvironmentName()
const ruby = await getRubyEngineAndVersion(core.getInput('ruby-version')) const ruby = await getRubyEngineAndVersion(core.getInput('ruby-version'))
const rubiesDir = `${process.env.HOME}/.rubies` let rubyPrefix
await io.mkdirP(rubiesDir) if (platform === 'windows-latest') {
rubyPrefix = await windows.downloadExtractAndSetPATH(ruby)
const platform = getVirtualEnvironmentName() } else {
const tag = await getLatestReleaseTag() rubyPrefix = await downloadAndExtract(platform, ruby)
const url = `${releasesURL}/download/${tag}/${ruby}-${platform}.tar.gz` core.addPath(`${rubyPrefix}/bin`)
console.log(url) }
const downloadPath = await tc.downloadTool(url)
await tc.extractTar(downloadPath, rubiesDir)
const rubyPrefix = `${rubiesDir}/${ruby}`
core.addPath(`${rubyPrefix}/bin`)
core.setOutput('ruby-prefix', rubyPrefix) core.setOutput('ruby-prefix', rubyPrefix)
} catch (error) { } catch (error) {
core.setFailed(error.message) core.setFailed(error.message)
} }
} }
async function downloadAndExtract(platform, ruby) {
const rubiesDir = `${process.env.HOME}/.rubies`
await io.mkdirP(rubiesDir)
const tag = await getLatestReleaseTag()
const url = `${releasesURL}/download/${tag}/${ruby}-${platform}.tar.gz`
console.log(url)
const downloadPath = await tc.downloadTool(url)
await tc.extractTar(downloadPath, rubiesDir)
return `${rubiesDir}/${ruby}`
}
async function getLatestReleaseTag() { async function getLatestReleaseTag() {
const response = await axios.get(`${metadataURL}/latest_release.tag`) const response = await axios.get(`${metadataURL}/latest_release.tag`)
return response.data.trim() return response.data.trim()
@@ -1431,16 +1443,19 @@ async function getRubyEngineAndVersion(rubyVersion) {
const stableVersions = response.data const stableVersions = response.data
const engineVersions = stableVersions[engine] const engineVersions = stableVersions[engine]
if (!engineVersions) { if (!engineVersions) {
throw new Error(`Unknown engine ${engine} (${rubyVersion})`) throw new Error(`Unknown engine ${engine} (input: ${rubyVersion})`)
} }
if (!engineVersions.includes(version)) { if (!engineVersions.includes(version)) {
engineVersions.reverse() // inplace! const latestToFirstVersion = engineVersions.slice().reverse()
let found = engineVersions.find(v => v.startsWith(version)) const found = latestToFirstVersion.find(v => v.startsWith(version))
if (found) { if (found) {
version = found version = found
} else { } else {
throw new Error(`Unknown version ${version} (${rubyVersion})`) throw new Error(`Unknown version ${version} for ${engine}
input: ${rubyVersion}
available versions for ${engine}: ${engineVersions.join(', ')}
File an issue at https://github.com/eregon/ruby-install-builder/issues if would like support for a new version`)
} }
} }
@@ -6437,6 +6452,79 @@ function plural(ms, n, name) {
} }
/***/ }),
/***/ 664:
/***/ (function(__unusedmodule, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "downloadExtractAndSetPATH", function() { return downloadExtractAndSetPATH; });
// Most of this logic is from
// https://github.com/MSP-Greg/actions-ruby/blob/master/lib/main.js
const core = __webpack_require__(470)
const exec = __webpack_require__(986)
const tc = __webpack_require__(533)
const releasesURL = 'https://github.com/oneclick/rubyinstaller2/releases'
async function downloadExtractAndSetPATH(ruby) {
const version = ruby.split('-', 2)[1]
if (!ruby.startsWith('ruby-') || version.startsWith('2.3')) {
throw new Error(`Only ruby >= 2.4 is supported on Windows currently (input: ${ruby})`)
}
const tag = `RubyInstaller-${version}-1`
const base = `${tag.toLowerCase()}-x64`
const url = `${releasesURL}/download/${tag}/${base}.7z`
console.log(url)
const downloadPath = await tc.downloadTool(url)
await exec.exec(`7z x ${downloadPath} -xr!${base}\\share\\doc -oC:\\`)
const rubyPrefix = `C:\\${base}`
const msys2 = await linkMSYS2()
const newPath = setupPath(msys2, rubyPrefix)
core.exportVariable('PATH', newPath)
return rubyPrefix
}
async function linkMSYS2() {
const toolCacheVersions = tc.findAllVersions('Ruby')
toolCacheVersions.sort()
if (toolCacheVersions.length == 0) {
throw new Error('Could not find MSYS2 in the toolcache')
}
const latestVersion = toolCacheVersions.slice(-1)[0]
const latestHostedRuby = tc.find('Ruby', latestVersion)
const hostedMSYS2 = `${latestHostedRuby}\\msys64`
const msys2 = 'C:\\msys64'
await exec.exec(`cmd /c mklink /D ${msys2} ${hostedMSYS2}`)
return msys2
}
function setupPath(msys2, rubyPrefix) {
let path = process.env['PATH'].split(';')
// Remove conflicting dev tools from PATH
path = path.filter(e => !e.match(/\b(Chocolatey|CMake|mingw64|OpenSSL|Strawberry)\b/))
// Remove default Ruby in PATH
path = path.filter(e => !e.match(/\bRuby\b/))
// Add MSYS2 in PATH
path.unshift(`${msys2}\\mingw64`, `${msys2}\\usr`)
// Add the downloaded Ruby in PATH
path.unshift(`${rubyPrefix}\\bin`)
return path.join(';')
}
/***/ }), /***/ }),
/***/ 669: /***/ 669:
@@ -8759,4 +8847,31 @@ exports.exec = exec;
/***/ }) /***/ })
/******/ }); /******/ },
/******/ function(__webpack_require__) { // webpackRuntimeModules
/******/ "use strict";
/******/
/******/ /* webpack/runtime/make namespace object */
/******/ !function() {
/******/ // define __esModule on exports
/******/ __webpack_require__.r = function(exports) {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/ }();
/******/
/******/ /* webpack/runtime/define property getter */
/******/ !function() {
/******/ // define getter function for harmony exports
/******/ var hasOwnProperty = Object.prototype.hasOwnProperty;
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!hasOwnProperty.call(exports, name)) {
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
/******/ }
/******/ };
/******/ }();
/******/
/******/ }
);
+30 -17
View File
@@ -4,33 +4,43 @@ const core = require('@actions/core')
const io = require('@actions/io') const io = require('@actions/io')
const tc = require('@actions/tool-cache') const tc = require('@actions/tool-cache')
const axios = require('axios') const axios = require('axios')
const windows = require('./windows')
const releasesURL = 'https://github.com/eregon/ruby-install-builder/releases' const releasesURL = 'https://github.com/eregon/ruby-install-builder/releases'
const metadataURL = 'https://raw.githubusercontent.com/eregon/ruby-install-builder/metadata' const metadataURL = 'https://raw.githubusercontent.com/eregon/ruby-install-builder/metadata'
async function run() { async function run() {
try { try {
const platform = getVirtualEnvironmentName()
const ruby = await getRubyEngineAndVersion(core.getInput('ruby-version')) const ruby = await getRubyEngineAndVersion(core.getInput('ruby-version'))
const rubiesDir = `${process.env.HOME}/.rubies` let rubyPrefix
await io.mkdirP(rubiesDir) if (platform === 'windows-latest') {
rubyPrefix = await windows.downloadExtractAndSetPATH(ruby)
const platform = getVirtualEnvironmentName() } else {
const tag = await getLatestReleaseTag() rubyPrefix = await downloadAndExtract(platform, ruby)
const url = `${releasesURL}/download/${tag}/${ruby}-${platform}.tar.gz` core.addPath(`${rubyPrefix}/bin`)
console.log(url) }
const downloadPath = await tc.downloadTool(url)
await tc.extractTar(downloadPath, rubiesDir)
const rubyPrefix = `${rubiesDir}/${ruby}`
core.addPath(`${rubyPrefix}/bin`)
core.setOutput('ruby-prefix', rubyPrefix) core.setOutput('ruby-prefix', rubyPrefix)
} catch (error) { } catch (error) {
core.setFailed(error.message) core.setFailed(error.message)
} }
} }
async function downloadAndExtract(platform, ruby) {
const rubiesDir = `${process.env.HOME}/.rubies`
await io.mkdirP(rubiesDir)
const tag = await getLatestReleaseTag()
const url = `${releasesURL}/download/${tag}/${ruby}-${platform}.tar.gz`
console.log(url)
const downloadPath = await tc.downloadTool(url)
await tc.extractTar(downloadPath, rubiesDir)
return `${rubiesDir}/${ruby}`
}
async function getLatestReleaseTag() { async function getLatestReleaseTag() {
const response = await axios.get(`${metadataURL}/latest_release.tag`) const response = await axios.get(`${metadataURL}/latest_release.tag`)
return response.data.trim() return response.data.trim()
@@ -52,16 +62,19 @@ async function getRubyEngineAndVersion(rubyVersion) {
const stableVersions = response.data const stableVersions = response.data
const engineVersions = stableVersions[engine] const engineVersions = stableVersions[engine]
if (!engineVersions) { if (!engineVersions) {
throw new Error(`Unknown engine ${engine} (${rubyVersion})`) throw new Error(`Unknown engine ${engine} (input: ${rubyVersion})`)
} }
if (!engineVersions.includes(version)) { if (!engineVersions.includes(version)) {
engineVersions.reverse() // inplace! const latestToFirstVersion = engineVersions.slice().reverse()
let found = engineVersions.find(v => v.startsWith(version)) const found = latestToFirstVersion.find(v => v.startsWith(version))
if (found) { if (found) {
version = found version = found
} else { } else {
throw new Error(`Unknown version ${version} (${rubyVersion})`) throw new Error(`Unknown version ${version} for ${engine}
input: ${rubyVersion}
available versions for ${engine}: ${engineVersions.join(', ')}
File an issue at https://github.com/eregon/ruby-install-builder/issues if would like support for a new version`)
} }
} }
+1 -1
View File
@@ -4,7 +4,7 @@
"description": "Download a prebuilt ruby and add it to $PATH", "description": "Download a prebuilt ruby and add it to $PATH",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"lint": "eslint index.js", "lint": "eslint *.js",
"package": "ncc build index.js -o dist" "package": "ncc build index.js -o dist"
}, },
"repository": { "repository": {
+63
View File
@@ -0,0 +1,63 @@
// Most of this logic is from
// https://github.com/MSP-Greg/actions-ruby/blob/master/lib/main.js
const core = require('@actions/core')
const exec = require('@actions/exec')
const tc = require('@actions/tool-cache')
const releasesURL = 'https://github.com/oneclick/rubyinstaller2/releases'
export async function downloadExtractAndSetPATH(ruby) {
const version = ruby.split('-', 2)[1]
if (!ruby.startsWith('ruby-') || version.startsWith('2.3')) {
throw new Error(`Only ruby >= 2.4 is supported on Windows currently (input: ${ruby})`)
}
const tag = `RubyInstaller-${version}-1`
const base = `${tag.toLowerCase()}-x64`
const url = `${releasesURL}/download/${tag}/${base}.7z`
console.log(url)
const downloadPath = await tc.downloadTool(url)
await exec.exec(`7z x ${downloadPath} -xr!${base}\\share\\doc -oC:\\`)
const rubyPrefix = `C:\\${base}`
const msys2 = await linkMSYS2()
const newPath = setupPath(msys2, rubyPrefix)
core.exportVariable('PATH', newPath)
return rubyPrefix
}
async function linkMSYS2() {
const toolCacheVersions = tc.findAllVersions('Ruby')
toolCacheVersions.sort()
if (toolCacheVersions.length == 0) {
throw new Error('Could not find MSYS2 in the toolcache')
}
const latestVersion = toolCacheVersions.slice(-1)[0]
const latestHostedRuby = tc.find('Ruby', latestVersion)
const hostedMSYS2 = `${latestHostedRuby}\\msys64`
const msys2 = 'C:\\msys64'
await exec.exec(`cmd /c mklink /D ${msys2} ${hostedMSYS2}`)
return msys2
}
function setupPath(msys2, rubyPrefix) {
let path = process.env['PATH'].split(';')
// Remove conflicting dev tools from PATH
path = path.filter(e => !e.match(/\b(Chocolatey|CMake|mingw64|OpenSSL|Strawberry)\b/))
// Remove default Ruby in PATH
path = path.filter(e => !e.match(/\bRuby\b/))
// Add MSYS2 in PATH
path.unshift(`${msys2}\\mingw64`, `${msys2}\\usr`)
// Add the downloaded Ruby in PATH
path.unshift(`${rubyPrefix}\\bin`)
return path.join(';')
}