diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..8051b7e --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +/dist/index.js linguist-generated +/package-lock.json linguist-generated diff --git a/.github/workflows/direct.yml b/.github/workflows/direct.yml index f84deab..16eb3fd 100644 --- a/.github/workflows/direct.yml +++ b/.github/workflows/direct.yml @@ -6,12 +6,13 @@ jobs: fail-fast: false matrix: os: [ 'ubuntu-16.04', 'ubuntu-18.04', 'macos-latest' ] - ruby: [ 'ruby-2.6.5', 'ruby-2.7.0' ] + ruby: [ 'ruby-2.6.5', 'ruby-2.7.0', 'truffleruby-19.3.0', 'jruby-9.2.9.0' ] runs-on: ${{ matrix.os }} steps: - run: echo ::set-env name=HOME::$HOME - run: mkdir ~/.rubies - - run: wget -O ~/.rubies/${{ matrix.ruby }}-${{ matrix.os }}.tar.gz https://github.com/eregon/ruby-install-builder/releases/download/builds/${{ matrix.ruby }}-${{ matrix.os }}.tar.gz + - run: wget https://github.com/eregon/ruby-install-builder/releases/download/builds/${{ matrix.ruby }}-${{ matrix.os }}.tar.gz + working-directory: ${{ env.HOME }}/.rubies - run: tar xf ${{ matrix.ruby }}-${{ matrix.os }}.tar.gz working-directory: ${{ env.HOME }}/.rubies - run: echo "::add-path::${{ env.HOME }}/.rubies/${{ matrix.ruby }}/bin" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index af0b35e..9e2352a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,25 +1,17 @@ -name: "units-test" -on: - pull_request: - push: - branches: - - master - - 'releases/*' - +name: Test this action +on: [push] jobs: - # unit tests - units: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v1 - - run: npm ci - - run: npm test - - # test action works running from the graph test: - runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + os: [ 'ubuntu-16.04', 'ubuntu-18.04', 'macos-latest' ] + ruby: [ 'ruby-2.6.5', 'ruby-2.7.0', 'truffleruby-19.3.0', 'jruby-9.2.9.0' ] + runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v2 - uses: ./ with: - milliseconds: 1000 + ruby-version: ${{ matrix.ruby }} + - run: ruby -v + - run: ruby -ropen-uri -e 'puts open("https://rubygems.org/") { |f| f.read(2014) }' diff --git a/LICENSE b/LICENSE index de88db8..1652841 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2019 GitHub Actions +Copyright (c) 2019 Benoit Daloze Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 6732c58..8a07bb8 100644 --- a/README.md +++ b/README.md @@ -1,114 +1,57 @@ +# use-ruby -

- javscript-action status -

+This action downloads a prebuilt ruby and adds it to `$PATH`. -# Create a JavaScript Action +It currently supports the latest stable versions of MRI, JRuby and TruffleRuby. -Use this template to bootstrap the creation of a JavaScript action.:rocket: - -This template includes tests, linting, a validation workflow, publishing, and versioning guidance. - -If you are new, there's also a simpler introduction. See the [Hello World JavaScript Action](https://github.com/actions/hello-world-javascript-action) - -## Create an action from this template - -Click the `Use this Template` and provide the new repo details for your action - -## Code in Master - -Install the dependencies -```bash -$ npm install -``` - -Run the tests :heavy_check_mark: -```bash -$ npm test - - PASS ./index.test.js - ✓ throws invalid number (3ms) - ✓ wait 500 ms (504ms) - ✓ test runs (95ms) - -... -``` - -## Change action.yml - -The action.yml contains defines the inputs and output for your action. - -Update the action.yml with your name, description, inputs and outputs for your action. - -See the [documentation](https://help.github.com/en/articles/metadata-syntax-for-github-actions) - -## Change the Code - -Most toolkit and CI/CD operations involve async operations so the action is run in an async function. - -```javascript -const core = require('@actions/core'); -... - -async function run() { - try { - ... - } - catch (error) { - core.setFailed(error.message); - } -} - -run() -``` - -See the [toolkit documentation](https://github.com/actions/toolkit/blob/master/README.md#packages) for the various packages. - -## Package for distribution - -GitHub Actions will run the entry point from the action.yml. Packaging assembles the code into one file that can be checked in to Git, enabling fast and reliable execution and preventing the need to check in node_modules. - -Actions are run from GitHub repos. Packaging the action will create a packaged action in the dist folder. - -Run package - -```bash -npm run package -``` - -Since the packaged index.js is run from the dist folder. - -```bash -git add dist -``` - -## Create a release branch - -Users shouldn't consume the action from master since that would be latest code and actions can break compatibility between major versions. - -Checkin to the v1 release branch - -```bash -$ git checkout -b v1 -$ git commit -a -m "v1 release" -``` - -```bash -$ git push origin v1 -``` - -Your action is now published! :rocket: - -See the [versioning documentation](https://github.com/actions/toolkit/blob/master/docs/action-versioning.md) +See https://github.com/eregon/ruby-install-builder/releases/tag/builds for the +available Ruby versions. ## Usage -You can now consume the action by referencing the v1 branch +Single job: ```yaml -uses: actions/javascript-action@v1 -with: - milliseconds: 1000 +name: My workflow +on: [push] +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: eregon/use-ruby-action@master + with: + ruby-version: ruby-2.6.5 + - run: ruby -v ``` -See the [actions tab](https://github.com/actions/javascript-action/actions) for runs of this action! :rocket: +Matrix: + +```yaml +name: My workflow +on: [push] +jobs: + test: + strategy: + fail-fast: false + matrix: + os: [ 'ubuntu-latest', 'macos-latest' ] + ruby: [ 'ruby-2.6.5', 'ruby-2.7.0', 'truffleruby-19.3.0', 'jruby-9.2.9.0' ] + 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 + +* 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. diff --git a/action.yml b/action.yml index 110d5ca..2c4b88b 100644 --- a/action.yml +++ b/action.yml @@ -1,13 +1,12 @@ -name: 'Wait' -description: 'Wait a designated number of milliseconds' +name: 'use-ruby' +description: 'Download a prebuilt ruby and add it to $PATH' inputs: - milliseconds: # id of input - description: 'number of milliseconds to wait' + ruby-version: + description: 'Version of ruby to use in the format "X.Y.Z"' required: true - default: '1000' outputs: - time: # output will be available to future steps - description: 'The message to output' + ruby-prefix: + description: 'The prefix of the installed ruby' runs: using: 'node12' main: 'dist/index.js' diff --git a/index.js b/index.js index ee57a25..c2c822e 100644 --- a/index.js +++ b/index.js @@ -1,21 +1,56 @@ -const core = require('@actions/core'); -const wait = require('./wait'); +const core = require('@actions/core') +const io = require('@actions/io') +const tc = require('@actions/tool-cache') +const os = require('os') +const fs = require('fs') - -// most @actions toolkit packages have async methods async function run() { - try { - const ms = core.getInput('milliseconds'); - console.log(`Waiting ${ms} milliseconds ...`) + try { + const rubyVersion = core.getInput('ruby-version') - core.debug((new Date()).toTimeString()) - wait(parseInt(ms)); - core.debug((new Date()).toTimeString()) + let ruby = rubyVersion + if (!ruby.includes('-')) { + ruby = 'ruby-' + ruby; + } - core.setOutput('time', new Date().toTimeString()); - } - catch (error) { - core.setFailed(error.message); + const rubiesDir = `${process.env.HOME}/.rubies` + await io.mkdirP(rubiesDir) + + const platform = getVirtualEnvironmentName() + const url = `https://github.com/eregon/ruby-install-builder/releases/download/builds/${ruby}-${platform}.tar.gz` + 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) + } catch (error) { + core.setFailed(error.message) + } +} + +function getVirtualEnvironmentName() { + const platform = os.platform() + if (platform == 'linux') { + return `ubuntu-${findUbuntuVersion()}` + } else if (platform == 'darwin') { + return 'macos-latest' + } else if (platform == 'win32') { + return 'windows-latest' + } else { + throw new Error(`Unknown platform ${platform}`) + } +} + +function findUbuntuVersion() { + const lsb_release = fs.readFileSync('/etc/lsb-release', 'utf8') + const match = lsb_release.match(/^DISTRIB_RELEASE=(\d+\.\d+)$/m) + if (match) { + return match[1] + } else { + throw new Error('Could not find Ubuntu version') } } diff --git a/index.test.js b/index.test.js deleted file mode 100644 index 9725109..0000000 --- a/index.test.js +++ /dev/null @@ -1,23 +0,0 @@ -const wait = require('./wait'); -const process = require('process'); -const cp = require('child_process'); -const path = require('path'); - -test('throws invalid number', async() => { - await expect(wait('foo')).rejects.toThrow('milleseconds not a number'); -}); - -test('wait 500 ms', async() => { - const start = new Date(); - await wait(500); - const end = new Date(); - var delta = Math.abs(end - start); - expect(delta).toBeGreaterThan(450); -}); - -// shows how the runner will run a javascript action with env / stdout protocol -test('test runs', () => { - process.env['INPUT_MILLISECONDS'] = 500; - const ip = path.join(__dirname, 'index.js'); - console.log(cp.execSync(`node ${ip}`).toString()); -}) diff --git a/package.json b/package.json index 693ad24..2fd70bc 100644 --- a/package.json +++ b/package.json @@ -1,34 +1,34 @@ { - "name": "javascript-action", - "version": "1.0.0", - "description": "JavaScript Action Template", + "name": "use-ruby-action", + "version": "0.1.0", + "description": "Download a prebuilt ruby and add it to $PATH", "main": "index.js", "scripts": { "lint": "eslint index.js", - "package": "ncc build index.js -o dist", - "test": "eslint index.js && jest" + "package": "ncc build index.js -o dist" }, "repository": { "type": "git", - "url": "git+https://github.com/actions/javascript-action.git" + "url": "git+https://github.com/eregon/use-ruby-action.git" }, "keywords": [ "GitHub", "Actions", - "JavaScript" + "Ruby" ], - "author": "GitHub", + "author": "Benoit Daloze", "license": "MIT", "bugs": { - "url": "https://github.com/actions/javascript-action/issues" + "url": "https://github.com/eregon/use-ruby-action/issues" }, - "homepage": "https://github.com/actions/javascript-action#readme", + "homepage": "https://github.com/eregon/use-ruby-action", "dependencies": { - "@actions/core": "^1.1.1" + "@actions/core": "^1.1.1", + "@actions/io": "^1.0.1", + "@actions/tool-cache": "^1.1.2" }, "devDependencies": { "@zeit/ncc": "^0.20.5", - "eslint": "^6.3.0", - "jest": "^24.9.0" + "eslint": "^6.3.0" } } diff --git a/wait.js b/wait.js deleted file mode 100644 index b83924d..0000000 --- a/wait.js +++ /dev/null @@ -1,11 +0,0 @@ -let wait = function(milliseconds) { - return new Promise((resolve, reject) => { - if (typeof(milliseconds) !== 'number') { - throw new Error('milleseconds not a number'); - } - - setTimeout(() => resolve("done!"), milliseconds) - }); -} - -module.exports = wait;