Skip to content

Commit 101f62d

Browse files
committed
Add support for Windows
1 parent 9432c89 commit 101f62d

File tree

7 files changed

+231
-36
lines changed

7 files changed

+231
-36
lines changed

.eslintrc.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
"SharedArrayBuffer": "readonly"
1111
},
1212
"parserOptions": {
13-
"ecmaVersion": 2018
13+
"ecmaVersion": 2018,
14+
"sourceType": "module"
1415
},
1516
"rules": {
1617
}

.github/workflows/test.yml

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,24 @@ jobs:
55
strategy:
66
fail-fast: false
77
matrix:
8-
os: [ ubuntu-16.04, ubuntu-18.04, macos-latest ]
8+
os: [ ubuntu-16.04, ubuntu-18.04, macos-latest, windows-latest ]
99
# Use various version syntaxes here for testing
1010
ruby: [ 2.3, ruby-2.4, 2.5, ruby-2.6.5, 2.7.0, jruby, truffleruby ]
11+
exclude:
12+
- os: windows-latest
13+
ruby: 2.3
14+
- os: windows-latest
15+
ruby: jruby
16+
- os: windows-latest
17+
ruby: truffleruby
1118
runs-on: ${{ matrix.os }}
1219
steps:
1320
- uses: actions/checkout@v2
1421
- uses: ./
1522
with:
1623
ruby-version: ${{ matrix.ruby }}
1724
- run: ruby -v
18-
- run: ruby -ropen-uri -e 'puts open("https://rubygems.org/") { |f| f.read(2014) }'
25+
- run: ridk version
26+
if: matrix.os == 'windows-latest'
27+
- run: ruby -ropen-uri -e 'puts open(%{https://rubygems.org/}) { |f| f.read(2014) }'
28+
- run: gem install json --no-document

README.md

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,13 @@ which means Ruby 2.3 is unmaintained and considered insecure.
2727

2828
### Supported Platforms
2929

30-
The action works for the `ubuntu-16.04`, `ubuntu-18.04` and `macos-latest` GitHub-hosted runners.
31-
`windows-latest` is not yet supported.
30+
The action works for all GitHub-hosted runners:
31+
`ubuntu-16.04`, `ubuntu-18.04`, `macos-latest` and `windows-latest`.
3232

33-
The prebuilt rubies are generated by https://github.com/eregon/ruby-install-builder.
33+
Ruby 2.3, JRuby and TruffleRuby are not yet supported on `windows-latest`.
34+
35+
The prebuilt rubies are generated by https://github.com/eregon/ruby-install-builder
36+
and on Windows by https://github.com/oneclick/rubyinstaller2.
3437

3538
## Usage
3639

@@ -82,6 +85,8 @@ jobs:
8285

8386
## Limitations
8487

85-
* Currently does not work on Windows since the builder doesn't build on Windows.
86-
https://github.com/MSP-Greg/actions-ruby is an alternative on Windows.
8788
* This action currently only works with GitHub-hosted runners, not private runners.
89+
90+
## Credits
91+
92+
Most of the Windows logic is from https://github.com/MSP-Greg/actions-ruby by MSP-Greg.

dist/index.js

Lines changed: 123 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

index.js

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,33 +4,43 @@ const core = require('@actions/core')
44
const io = require('@actions/io')
55
const tc = require('@actions/tool-cache')
66
const axios = require('axios')
7+
const windows = require('./windows')
78

89
const releasesURL = 'https://github.com/eregon/ruby-install-builder/releases'
910
const metadataURL = 'https://raw.githubusercontent.com/eregon/ruby-install-builder/metadata'
1011

1112
async function run() {
1213
try {
13-
const ruby = await getRubyEngineAndVersion(core.getInput('ruby-version'))
14-
15-
const rubiesDir = `${process.env.HOME}/.rubies`
16-
await io.mkdirP(rubiesDir)
17-
1814
const platform = getVirtualEnvironmentName()
19-
const tag = await getLatestReleaseTag()
20-
const url = `${releasesURL}/download/${tag}/${ruby}-${platform}.tar.gz`
21-
console.log(url)
22-
23-
const downloadPath = await tc.downloadTool(url)
24-
await tc.extractTar(downloadPath, rubiesDir)
15+
const ruby = await getRubyEngineAndVersion(core.getInput('ruby-version'))
2516

26-
const rubyPrefix = `${rubiesDir}/${ruby}`
27-
core.addPath(`${rubyPrefix}/bin`)
17+
let rubyPrefix
18+
if (platform === 'windows-latest') {
19+
rubyPrefix = await windows.downloadExtractAndSetPATH(ruby)
20+
} else {
21+
rubyPrefix = await downloadAndExtract(platform, ruby)
22+
core.addPath(`${rubyPrefix}/bin`)
23+
}
2824
core.setOutput('ruby-prefix', rubyPrefix)
2925
} catch (error) {
3026
core.setFailed(error.message)
3127
}
3228
}
3329

30+
async function downloadAndExtract(platform, ruby) {
31+
const rubiesDir = `${process.env.HOME}/.rubies`
32+
await io.mkdirP(rubiesDir)
33+
34+
const tag = await getLatestReleaseTag()
35+
const url = `${releasesURL}/download/${tag}/${ruby}-${platform}.tar.gz`
36+
console.log(url)
37+
38+
const downloadPath = await tc.downloadTool(url)
39+
await tc.extractTar(downloadPath, rubiesDir)
40+
41+
return `${rubiesDir}/${ruby}`
42+
}
43+
3444
async function getLatestReleaseTag() {
3545
const response = await axios.get(`${metadataURL}/latest_release.tag`)
3646
return response.data.trim()

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"description": "Download a prebuilt ruby and add it to $PATH",
55
"main": "index.js",
66
"scripts": {
7-
"lint": "eslint index.js",
7+
"lint": "eslint *.js",
88
"package": "ncc build index.js -o dist"
99
},
1010
"repository": {

windows.js

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// Most of this logic is from
2+
// https://github.com/MSP-Greg/actions-ruby/blob/master/lib/main.js
3+
4+
const core = require('@actions/core')
5+
const exec = require('@actions/exec')
6+
const tc = require('@actions/tool-cache')
7+
8+
const releasesURL = 'https://github.com/oneclick/rubyinstaller2/releases'
9+
10+
export async function downloadExtractAndSetPATH(ruby) {
11+
const version = ruby.split('-', 2)[1]
12+
if (!ruby.startsWith('ruby-') || version.startsWith('2.3')) {
13+
throw new Error(`Only ruby >= 2.4 is supported on Windows currently (input: ${ruby})`)
14+
}
15+
const tag = `RubyInstaller-${version}-1`
16+
const base = `${tag.toLowerCase()}-x64`
17+
18+
const url = `${releasesURL}/download/${tag}/${base}.7z`
19+
console.log(url)
20+
21+
const downloadPath = await tc.downloadTool(url)
22+
await exec.exec(`7z x ${downloadPath} -xr!${base}\\share\\doc -oC:\\`)
23+
const rubyPrefix = `C:\\${base}`
24+
25+
const msys2 = await linkMSYS2()
26+
const newPath = setupPath(msys2, rubyPrefix)
27+
core.exportVariable('PATH', newPath)
28+
29+
return rubyPrefix
30+
}
31+
32+
async function linkMSYS2() {
33+
const toolCacheVersions = tc.findAllVersions('Ruby')
34+
toolCacheVersions.sort()
35+
const latestVersion = toolCacheVersions.slice(-1)[0]
36+
const latestHostedRuby = tc.find('Ruby', latestVersion)
37+
38+
const hostedMSYS2 = `${latestHostedRuby}\\msys64`
39+
const msys2 = 'C:\\msys64'
40+
await exec.exec(`cmd /c mklink /D ${msys2} ${hostedMSYS2}`)
41+
return msys2
42+
}
43+
44+
function setupPath(msys2, rubyPrefix) {
45+
let path = process.env['PATH'].split(';')
46+
47+
// Remove conflicting dev tools from PATH
48+
path = path.filter(e => !e.match(/\b(Chocolatey|CMake|mingw64|OpenSSL|Strawberry)\b/))
49+
50+
// Remove default Ruby in PATH
51+
path = path.filter(e => !e.match(/\bRuby\b/))
52+
53+
// Add MSYS2 in PATH
54+
path.unshift(`${msys2}\\mingw64`, `${msys2}\\usr`)
55+
56+
// Add the downloaded Ruby in PATH
57+
path.unshift(`${rubyPrefix}\\bin`)
58+
59+
return path.join(';')
60+
}

0 commit comments

Comments
 (0)