Compare commits

..

1 Commits

Author SHA1 Message Date
Sascha Mann
27ff99664b Add production dependencies & build 2021-01-08 11:14:58 +01:00
17 changed files with 111 additions and 9303 deletions

View File

@@ -1,7 +0,0 @@
version: 2
updates:
- package-ecosystem: gitsubmodule
directory: "/"
schedule:
interval: daily
open-pull-requests-limit: 10

View File

@@ -9,7 +9,6 @@ on:
jobs:
backup:
runs-on: ubuntu-20.04
timeout-minutes: 60
steps:
- name: Configure cache

View File

@@ -1,21 +1,14 @@
name: "PR Checks"
on: [pull_request, push]
concurrency:
# Skip intermediate builds: all builds except for builds on the `master`, `main`, or `release-*` branches
# Cancel intermediate builds: only pull request builds
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.ref != 'refs/heads/master' || github.ref != 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release-') || github.run_number }}
cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }}
jobs:
check_pr:
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- uses: actions/checkout@v1
- name: "npm ci"
run: npm ci --legacy-peer-deps
run: npm ci
- name: "npm run build"
run: npm run build

View File

@@ -11,12 +11,6 @@
#
name: "CodeQL"
concurrency:
# Skip intermediate builds: all builds except for builds on the `master`, `main`, or `release-*` branches
# Cancel intermediate builds: only pull request builds
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.ref != 'refs/heads/master' || github.ref != 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release-') || github.run_number }}
cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }}
on:
push:
branches: [ master, releases/* ]
@@ -30,7 +24,6 @@ jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
timeout-minutes: 60
strategy:
fail-fast: false

View File

@@ -1,40 +0,0 @@
name: Example builds (default arch)
concurrency:
# Skip intermediate builds: all builds except for builds on the `master`, `main`, or `release-*` branches
# Cancel intermediate builds: only pull request builds
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.ref != 'refs/heads/master' || github.ref != 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release-') || github.run_number }}
cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }}
on:
push:
branches: ['main', 'master', 'releases/*']
pull_request:
workflow_dispatch:
jobs:
test:
runs-on: ${{ matrix.os }}
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
julia-version: ['1']
os: [ubuntu-latest, macOS-latest, windows-latest]
steps:
- uses: actions/checkout@v1.0.0
- name: "Install dependencies"
run: |
npm install --legacy-peer-deps
npm run build
npm run pack
- name: "Set up Julia"
id: setup-julia
uses: ./
with:
version: ${{ matrix.julia-version }}
- run: julia --version
- run: julia --compile=min -O0 -e 'import InteractiveUtils; InteractiveUtils.versioninfo()'

View File

@@ -1,38 +0,0 @@
name: Example builds (nightly, default arch)
concurrency:
# Skip intermediate builds: all builds except for builds on the `master`, `main`, or `release-*` branches
# Cancel intermediate builds: only pull request builds
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.ref != 'refs/heads/master' || github.ref != 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release-') || github.run_number }}
cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }}
on:
push:
branches: ['main', 'master', 'releases/*']
pull_request:
jobs:
test:
runs-on: ${{ matrix.os }}
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
julia-version: [nightly, 1.8-nightly]
os: [ubuntu-latest, macOS-latest, windows-latest]
steps:
- uses: actions/checkout@v1.0.0
- name: "Install dependencies"
run: |
npm install --legacy-peer-deps
npm run build
npm run pack
- name: "Set up Julia (${{ matrix.julia-version }})"
uses: ./
with:
version: ${{ matrix.julia-version }}
- run: julia --version
- run: julia --compile=min -O0 -e 'import InteractiveUtils; InteractiveUtils.versioninfo()'

View File

@@ -1,11 +1,5 @@
name: Example builds (nightly)
concurrency:
# Skip intermediate builds: all builds except for builds on the `master`, `main`, or `release-*` branches
# Cancel intermediate builds: only pull request builds
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.ref != 'refs/heads/master' || github.ref != 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release-') || github.run_number }}
cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }}
on:
push:
branches: ['main', 'master', 'releases/*']
@@ -16,24 +10,23 @@ on:
jobs:
test:
runs-on: ${{ matrix.os }}
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
julia-version: [nightly, 1.8-nightly]
julia-version: [nightly, 1.6-nightly]
julia-arch: [x64, x86]
os: [ubuntu-latest, macOS-latest, windows-latest]
# 32-bit Julia binaries are not available on macOS
exclude:
- os: macOS-latest
julia-arch: x86
steps:
- uses: actions/checkout@v1.0.0
- name: "Install dependencies"
run: |
npm install --legacy-peer-deps
npm install
npm run build
npm run pack
@@ -42,5 +35,5 @@ jobs:
with:
version: ${{ matrix.julia-version }}
arch: ${{ matrix.julia-arch }}
show-versioninfo: 'true'
- run: julia --version
- run: julia --compile=min -O0 -e 'import InteractiveUtils; InteractiveUtils.versioninfo()'

View File

@@ -1,21 +1,13 @@
name: Example builds
concurrency:
# Skip intermediate builds: all builds except for builds on the `master`, `main`, or `release-*` branches
# Cancel intermediate builds: only pull request builds
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.ref != 'refs/heads/master' || github.ref != 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release-') || github.run_number }}
cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }}
on:
push:
branches: ['main', 'master', 'releases/*']
pull_request:
workflow_dispatch:
jobs:
test:
runs-on: ${{ matrix.os }}
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
@@ -26,13 +18,13 @@ jobs:
exclude:
- os: macOS-latest
julia-arch: x86
steps:
- uses: actions/checkout@v1.0.0
- name: "Install dependencies"
run: |
npm install --legacy-peer-deps
npm install
npm run build
npm run pack
@@ -42,5 +34,5 @@ jobs:
with:
version: ${{ matrix.julia-version }}
arch: ${{ matrix.julia-arch }}
show-versioninfo: 'true'
- run: julia --version
- run: julia --compile=min -O0 -e 'import InteractiveUtils; InteractiveUtils.versioninfo()'

View File

@@ -38,29 +38,13 @@ This action sets up a Julia environment for use in actions by downloading a spec
# The architecture of the Julia binaries.
#
# Please note that installing aarch64 binaries only makes sense on self-hosted aarch64 runners.
# We currently don't run test builds on that architecture, so we cannot guarantee that the input won't break randomly,
# although there is no reason why it would.
# Supported values: x64 | x86
#
# Supported values: x64 | x86 | aarch64 (untested)
#
# Note: you can use X64, X86, and ARM64 as synonyms for x64, x86, and aarch64, respectively.
#
# Defaults to the architecture of the runner executing the job.
# Default: x64
arch: ''
# Set the display setting for printing InteractiveUtils.versioninfo() after installing.
#
# Starting Julia and running InteractiveUtils.versioninfo() takes a significant amount of time (1s or ~10% of the total build time in testing),
# so you may not want to run it in every build, in particular on paid runners, as this cost will add up quickly.
#
# See "versioninfo" below for example usage and further explanations.
#
# Supported values: true | false | never
#
# true: Always print versioninfo
# false: Only print versioninfo for nightly Julia
# never: Never print versioninfo
# If true, display the output of InteractiveUtils.versioninfo() after installing.
# See "versioninfo" below for example usage.
#
# Default: false
show-versioninfo: ''
@@ -109,7 +93,7 @@ You can either specify specific Julia versions or version ranges. If you specify
- `^1.3.0-0` is a **caret** version range that includes _all_ pre-releases. It matches all versions `≥ 1.3.0-` and `< 2.0.0`.
- `~1.3.0-0` is a **tilde** version range that includes _all_ pre-releases. It matches all versions `≥ 1.3.0-` and `< 1.4.0`.
- `nightly` will install the latest nightly build.
- `1.7-nightly` will install the latest nightly build for the upcoming 1.7 release. This version will only be available during certain phases of the Julia release cycle.
- `1.6-nightly` will install the latest nightly build for the upcoming 1.6 release. This version will only be available during certain phases of the Julia release cycle.
Internally the action uses node's semver package to resolve version ranges. Its [documentation](https://github.com/npm/node-semver#advanced-range-syntax) contains more details on the version range syntax. You can test what version will be selected for a given input in this JavaScript [REPL](https://repl.it/@SaschaMann/setup-julia-version-logic).
@@ -129,7 +113,7 @@ jobs:
matrix:
julia-version: ['1.0', '1.2.0', '^1.3.0-rc1']
os: [ubuntu-latest, windows-latest, macOS-latest]
steps:
- uses: actions/checkout@v1.0.0
- name: "Set up Julia"
@@ -155,7 +139,7 @@ jobs:
exclude:
- os: macOS-latest
julia-arch: x86
steps:
- uses: actions/checkout@v1.0.0
- name: "Set up Julia"
@@ -182,7 +166,7 @@ jobs:
- os: windows-latest
julia-version: ['1.0.4']
julia-arch: x86
steps:
- uses: actions/checkout@v1.0.0
- name: "Set up Julia"
@@ -195,13 +179,18 @@ jobs:
### versioninfo
By default, only the output of `julia --version` is printed as verification that Julia has been installed for stable versions of Julia.
`InteractiveUtils.versioninfo()` is run by default for nightly builds.
By default, only a brief version identifier is printed in the run log. You can display the full `versioninfo` by adding `show-versioninfo`.
Here's an example that prints this information just for `nightly`:
Starting Julia and printing the full versioninfo takes a significant amount of time (1s or ~10% of the total build time in testing), so you may not want to run it in every build, in particular on paid runners as this cost will add up quickly.
However, `julia --version` does not provide sufficient information to know which commit a nightly binary was built from, therefore it is useful to show the full versioninfo on nightly builds regardless.
You can override this behaviour by changing the input to `never` if you never want to run `InteractiveUtils.versioninfo()` or to `true` if you always want to run `InteractiveUtils.versioninfo()`, even on stable Julia builds.
```yaml
- uses: julia-actions/setup-julia@v1
with:
version: ${{ matrix.version }}
arch: ${{ matrix.arch }}
show-versioninfo: ${{ matrix.version == 'nightly' }}
```
You use `'true'` if you want it printed for all Julia versions.
## Versioning

View File

@@ -6,9 +6,9 @@ inputs:
description: 'The Julia version to download (if necessary) and use. Example: 1.0.4'
default: '1'
arch:
description: 'Architecture of the Julia binaries. Defaults to the architecture of the runner executing the job.'
description: 'Architecture of the Julia binaries. Defaults to x64.'
required: false
default: '${{ runner.arch }}'
default: 'x64'
show-versioninfo:
description: 'Display InteractiveUtils.versioninfo() after installing'
required: false
@@ -19,7 +19,7 @@ outputs:
julia-bindir:
description: 'Path to the directory containing the Julia executable. Equivalent to JULIA_BINDIR: https://docs.julialang.org/en/v1/manual/environment-variables/#JULIA_BINDIR'
runs:
using: 'node16'
using: 'node12'
main: 'dist/index.js'
branding:
icon: 'download'

442
dist/index.js vendored
View File

@@ -2880,13 +2880,6 @@ function coerce (version, options) {
}
/***/ }),
/***/ 321:
/***/ (function(module, __unusedexports, __webpack_require__) {
module.exports = __webpack_require__(600);
/***/ }),
/***/ 357:
@@ -3240,73 +3233,6 @@ function getState(name) {
exports.getState = getState;
//# sourceMappingURL=core.js.map
/***/ }),
/***/ 523:
/***/ (function(module, __unusedexports, __webpack_require__) {
// Packages
var retrier = __webpack_require__(321);
function retry(fn, opts) {
function run(resolve, reject) {
var options = opts || {};
// Default `randomize` to true
if (!('randomize' in options)) {
options.randomize = true;
}
var op = retrier.operation(options);
// We allow the user to abort retrying
// this makes sense in the cases where
// knowledge is obtained that retrying
// would be futile (e.g.: auth errors)
function bail(err) {
reject(err || new Error('Aborted'));
}
function onError(err, num) {
if (err.bail) {
bail(err);
return;
}
if (!op.retry(err)) {
reject(op.mainError());
} else if (options.onRetry) {
options.onRetry(err, num);
}
}
function runAttempt(num) {
var val;
try {
val = fn(bail, num);
} catch (err) {
onError(err, num);
return;
}
Promise.resolve(val)
.then(resolve)
.catch(function catchIt(err) {
onError(err, num);
});
}
op.attempt(runAttempt);
}
return new Promise(run);
}
module.exports = retry;
/***/ }),
/***/ 533:
@@ -3750,113 +3676,6 @@ function _evaluateVersions(versions, versionSpec) {
}
//# sourceMappingURL=tool-cache.js.map
/***/ }),
/***/ 600:
/***/ (function(__unusedmodule, exports, __webpack_require__) {
var RetryOperation = __webpack_require__(988);
exports.operation = function(options) {
var timeouts = exports.timeouts(options);
return new RetryOperation(timeouts, {
forever: options && options.forever,
unref: options && options.unref,
maxRetryTime: options && options.maxRetryTime
});
};
exports.timeouts = function(options) {
if (options instanceof Array) {
return [].concat(options);
}
var opts = {
retries: 10,
factor: 2,
minTimeout: 1 * 1000,
maxTimeout: Infinity,
randomize: false
};
for (var key in options) {
opts[key] = options[key];
}
if (opts.minTimeout > opts.maxTimeout) {
throw new Error('minTimeout is greater than maxTimeout');
}
var timeouts = [];
for (var i = 0; i < opts.retries; i++) {
timeouts.push(this.createTimeout(i, opts));
}
if (options && options.forever && !timeouts.length) {
timeouts.push(this.createTimeout(i, opts));
}
// sort the array numerically ascending
timeouts.sort(function(a,b) {
return a - b;
});
return timeouts;
};
exports.createTimeout = function(attempt, opts) {
var random = (opts.randomize)
? (Math.random() + 1)
: 1;
var timeout = Math.round(random * opts.minTimeout * Math.pow(opts.factor, attempt));
timeout = Math.min(timeout, opts.maxTimeout);
return timeout;
};
exports.wrap = function(obj, options, methods) {
if (options instanceof Array) {
methods = options;
options = null;
}
if (!methods) {
methods = [];
for (var key in obj) {
if (typeof obj[key] === 'function') {
methods.push(key);
}
}
}
for (var i = 0; i < methods.length; i++) {
var method = methods[i];
var original = obj[method];
obj[method] = function retryWrapper(original) {
var op = exports.operation(options);
var args = Array.prototype.slice.call(arguments, 1);
var callback = args.pop();
args.push(function(err) {
if (op.retry(err)) {
return;
}
if (err) {
arguments[0] = op.mainError();
}
callback.apply(this, arguments);
});
op.attempt(function() {
original.apply(obj, args);
});
}.bind(obj, original);
obj[method].options = options;
}
};
/***/ }),
/***/ 605:
@@ -4148,19 +3967,12 @@ var __importStar = (this && this.__importStar) || function (mod) {
};
Object.defineProperty(exports, "__esModule", { value: true });
const core = __importStar(__webpack_require__(470));
const exec = __importStar(__webpack_require__(986));
const tc = __importStar(__webpack_require__(533));
const fs = __importStar(__webpack_require__(747));
const https = __importStar(__webpack_require__(211));
const path = __importStar(__webpack_require__(622));
const installer = __importStar(__webpack_require__(749));
const archSynonyms = {
'x86': 'x86',
'X86': 'x86',
'x64': 'x64',
'X64': 'x64',
'aarch64': 'aarch64',
'ARM64': 'aarch64'
};
function run() {
return __awaiter(this, void 0, void 0, function* () {
try {
@@ -4181,7 +3993,7 @@ function run() {
}
// Inputs
const versionInput = core.getInput('version');
const originalArchInput = core.getInput('arch');
const arch = core.getInput('arch');
// It can easily happen that, for example, a workflow file contains an input `version: ${{ matrix.julia-version }}`
// while the strategy matrix only contains a key `${{ matrix.version }}`.
// In that case, we want the action to fail, rather than trying to download julia from an URL that's missing parts and 404ing.
@@ -4190,10 +4002,9 @@ function run() {
if (!versionInput) {
throw new Error('Version input must not be null');
}
if (!originalArchInput) {
if (!arch) {
throw new Error(`Arch input must not be null`);
}
const arch = archSynonyms[originalArchInput];
const versionInfo = yield installer.getJuliaVersionInfo();
const availableReleases = yield installer.getJuliaVersions(versionInfo);
const version = installer.getJuliaVersion(availableReleases, versionInput);
@@ -4219,8 +4030,15 @@ function run() {
// Set output
core.setOutput('julia-bindir', path.join(juliaPath, 'bin'));
// Test if Julia has been installed and print the version
const showVersionInfoInput = core.getInput('show-versioninfo');
yield installer.showVersionInfo(showVersionInfoInput, version);
if (core.getInput('show-versioninfo') == 'true') {
// If enabled, show the full version info
// --compile=min -O0 reduces the time from ~1.8-1.9s to ~0.8-0.9s
exec.exec('julia', ['--compile=min', '-O0', '-e', 'using InteractiveUtils; versioninfo()']);
}
else {
// Otherwise only print julia --version to save time
exec.exec('julia', ['--version']);
}
}
catch (error) {
core.setFailed(error.message);
@@ -4267,7 +4085,6 @@ const crypto = __importStar(__webpack_require__(417));
const fs = __importStar(__webpack_require__(747));
const os = __importStar(__webpack_require__(87));
const path = __importStar(__webpack_require__(622));
const retry = __webpack_require__(523);
const semver = __importStar(__webpack_require__(280));
// Translations between actions input and Julia arch names
const osMap = {
@@ -4277,8 +4094,7 @@ const osMap = {
};
const archMap = {
'x86': 'i686',
'x64': 'x86_64',
'aarch64': 'aarch64'
'x64': 'x86_64'
};
// Store information about the environment
const osPlat = os.platform(); // possible values: win32 (Windows), linux (Linux), darwin (macOS)
@@ -4306,15 +4122,7 @@ function calculateChecksum(file) {
*/
function getJuliaVersionInfo() {
return __awaiter(this, void 0, void 0, function* () {
// Occasionally the connection is reset for unknown reasons
// In those cases, retry the download
const versionsFile = yield retry((bail) => __awaiter(this, void 0, void 0, function* () {
return yield tc.downloadTool('https://julialang-s3.julialang.org/bin/versions.json');
}), {
onRetry: (err) => {
core.debug(`Download of versions.json failed, trying again. Error: ${err}`);
}
});
const versionsFile = yield tc.downloadTool('https://julialang-s3.julialang.org/bin/versions.json');
return JSON.parse(fs.readFileSync(versionsFile).toString());
});
}
@@ -4370,19 +4178,15 @@ function getNightlyFileName(arch) {
return `julia-latest${versionExt}.${ext}`;
}
function getFileInfo(versionInfo, version, arch) {
const err = `Could not find ${archMap[arch]}/${version} binaries`;
if (version.endsWith('nightly')) {
return null;
}
if (!versionInfo[version]) {
throw err;
}
for (let file of versionInfo[version].files) {
if (file.os == osMap[osPlat] && file.arch == archMap[arch]) {
return file;
}
}
throw err;
throw `Could not find ${archMap[arch]}/${version} binaries`;
}
exports.getFileInfo = getFileInfo;
function getDownloadURL(fileInfo, version, arch) {
@@ -4396,10 +4200,6 @@ function getDownloadURL(fileInfo, version, arch) {
if (version == 'nightly') {
return `${baseURL}/${getNightlyFileName(arch)}`;
}
// Verify that fileInfo.url points at the official Julia download servers
if (!fileInfo.url.startsWith('https://julialang-s3.julialang.org/')) {
throw new Error(`versions.json points at a download location outside of Julia's download server: ${fileInfo.url}. Aborting for security reasons.`);
}
return fileInfo.url;
}
exports.getDownloadURL = getDownloadURL;
@@ -4409,15 +4209,7 @@ function installJulia(versionInfo, version, arch) {
const fileInfo = getFileInfo(versionInfo, version, arch);
const downloadURL = getDownloadURL(fileInfo, version, arch);
core.debug(`downloading Julia from ${downloadURL}`);
// Occasionally the connection is reset for unknown reasons
// In those cases, retry the download
const juliaDownloadPath = yield retry((bail) => __awaiter(this, void 0, void 0, function* () {
return yield tc.downloadTool(downloadURL);
}), {
onRetry: (err) => {
core.debug(`Download of ${downloadURL} failed, trying again. Error: ${err}`);
}
});
const juliaDownloadPath = yield tc.downloadTool(downloadURL);
// Verify checksum
if (!version.endsWith('nightly')) {
const checkSum = yield calculateChecksum(juliaDownloadPath);
@@ -4455,43 +4247,6 @@ function installJulia(versionInfo, version, arch) {
});
}
exports.installJulia = installJulia;
/**
* Test if Julia has been installed and print the version.
*
* true => always show versioninfo
* false => only show on nightlies
* never => never show it anywhere
*
* @param showVersionInfoInput
*/
function showVersionInfo(showVersionInfoInput, version) {
return __awaiter(this, void 0, void 0, function* () {
// --compile=min -O0 reduces the time from ~1.8-1.9s to ~0.8-0.9s
let exitCode;
switch (showVersionInfoInput) {
case 'true':
exitCode = yield exec.exec('julia', ['--compile=min', '-O0', '-e', 'using InteractiveUtils; versioninfo()']);
break;
case 'false':
if (version.endsWith('nightly')) {
exitCode = yield exec.exec('julia', ['--compile=min', '-O0', '-e', 'using InteractiveUtils; versioninfo()']);
}
else {
exitCode = yield exec.exec('julia', ['--version']);
}
break;
case 'never':
exitCode = yield exec.exec('julia', ['--version']);
break;
default:
throw new Error(`${showVersionInfoInput} is not a valid value for show-versioninfo. Supported values: true | false | never`);
}
if (exitCode !== 0) {
throw new Error(`Julia could not be installed properly. Exit code: ${exitCode}`);
}
});
}
exports.showVersionInfo = showVersionInfo;
/***/ }),
@@ -5043,171 +4798,6 @@ function exec(commandLine, args, options) {
exports.exec = exec;
//# sourceMappingURL=exec.js.map
/***/ }),
/***/ 988:
/***/ (function(module) {
function RetryOperation(timeouts, options) {
// Compatibility for the old (timeouts, retryForever) signature
if (typeof options === 'boolean') {
options = { forever: options };
}
this._originalTimeouts = JSON.parse(JSON.stringify(timeouts));
this._timeouts = timeouts;
this._options = options || {};
this._maxRetryTime = options && options.maxRetryTime || Infinity;
this._fn = null;
this._errors = [];
this._attempts = 1;
this._operationTimeout = null;
this._operationTimeoutCb = null;
this._timeout = null;
this._operationStart = null;
if (this._options.forever) {
this._cachedTimeouts = this._timeouts.slice(0);
}
}
module.exports = RetryOperation;
RetryOperation.prototype.reset = function() {
this._attempts = 1;
this._timeouts = this._originalTimeouts;
}
RetryOperation.prototype.stop = function() {
if (this._timeout) {
clearTimeout(this._timeout);
}
this._timeouts = [];
this._cachedTimeouts = null;
};
RetryOperation.prototype.retry = function(err) {
if (this._timeout) {
clearTimeout(this._timeout);
}
if (!err) {
return false;
}
var currentTime = new Date().getTime();
if (err && currentTime - this._operationStart >= this._maxRetryTime) {
this._errors.unshift(new Error('RetryOperation timeout occurred'));
return false;
}
this._errors.push(err);
var timeout = this._timeouts.shift();
if (timeout === undefined) {
if (this._cachedTimeouts) {
// retry forever, only keep last error
this._errors.splice(this._errors.length - 1, this._errors.length);
this._timeouts = this._cachedTimeouts.slice(0);
timeout = this._timeouts.shift();
} else {
return false;
}
}
var self = this;
var timer = setTimeout(function() {
self._attempts++;
if (self._operationTimeoutCb) {
self._timeout = setTimeout(function() {
self._operationTimeoutCb(self._attempts);
}, self._operationTimeout);
if (self._options.unref) {
self._timeout.unref();
}
}
self._fn(self._attempts);
}, timeout);
if (this._options.unref) {
timer.unref();
}
return true;
};
RetryOperation.prototype.attempt = function(fn, timeoutOps) {
this._fn = fn;
if (timeoutOps) {
if (timeoutOps.timeout) {
this._operationTimeout = timeoutOps.timeout;
}
if (timeoutOps.cb) {
this._operationTimeoutCb = timeoutOps.cb;
}
}
var self = this;
if (this._operationTimeoutCb) {
this._timeout = setTimeout(function() {
self._operationTimeoutCb();
}, self._operationTimeout);
}
this._operationStart = new Date().getTime();
this._fn(this._attempts);
};
RetryOperation.prototype.try = function(fn) {
console.log('Using RetryOperation.try() is deprecated');
this.attempt(fn);
};
RetryOperation.prototype.start = function(fn) {
console.log('Using RetryOperation.start() is deprecated');
this.attempt(fn);
};
RetryOperation.prototype.start = RetryOperation.prototype.try;
RetryOperation.prototype.errors = function() {
return this._errors;
};
RetryOperation.prototype.attempts = function() {
return this._attempts;
};
RetryOperation.prototype.mainError = function() {
if (this._errors.length === 0) {
return null;
}
var counts = {};
var mainError = null;
var mainErrorCount = 0;
for (var i = 0; i < this._errors.length; i++) {
var error = this._errors[i];
var message = error.message;
var count = (counts[message] || 0) + 1;
counts[message] = count;
if (count >= mainErrorCount) {
mainError = error;
mainErrorCount = count;
}
}
return mainError;
};
/***/ })
/******/ });

71
lib/installer.js generated
View File

@@ -22,7 +22,6 @@ const crypto = __importStar(require("crypto"));
const fs = __importStar(require("fs"));
const os = __importStar(require("os"));
const path = __importStar(require("path"));
const retry = require("async-retry");
const semver = __importStar(require("semver"));
// Translations between actions input and Julia arch names
const osMap = {
@@ -32,8 +31,7 @@ const osMap = {
};
const archMap = {
'x86': 'i686',
'x64': 'x86_64',
'aarch64': 'aarch64'
'x64': 'x86_64'
};
// Store information about the environment
const osPlat = os.platform(); // possible values: win32 (Windows), linux (Linux), darwin (macOS)
@@ -61,15 +59,7 @@ function calculateChecksum(file) {
*/
function getJuliaVersionInfo() {
return __awaiter(this, void 0, void 0, function* () {
// Occasionally the connection is reset for unknown reasons
// In those cases, retry the download
const versionsFile = yield retry((bail) => __awaiter(this, void 0, void 0, function* () {
return yield tc.downloadTool('https://julialang-s3.julialang.org/bin/versions.json');
}), {
onRetry: (err) => {
core.debug(`Download of versions.json failed, trying again. Error: ${err}`);
}
});
const versionsFile = yield tc.downloadTool('https://julialang-s3.julialang.org/bin/versions.json');
return JSON.parse(fs.readFileSync(versionsFile).toString());
});
}
@@ -125,19 +115,15 @@ function getNightlyFileName(arch) {
return `julia-latest${versionExt}.${ext}`;
}
function getFileInfo(versionInfo, version, arch) {
const err = `Could not find ${archMap[arch]}/${version} binaries`;
if (version.endsWith('nightly')) {
return null;
}
if (!versionInfo[version]) {
throw err;
}
for (let file of versionInfo[version].files) {
if (file.os == osMap[osPlat] && file.arch == archMap[arch]) {
return file;
}
}
throw err;
throw `Could not find ${archMap[arch]}/${version} binaries`;
}
exports.getFileInfo = getFileInfo;
function getDownloadURL(fileInfo, version, arch) {
@@ -151,10 +137,6 @@ function getDownloadURL(fileInfo, version, arch) {
if (version == 'nightly') {
return `${baseURL}/${getNightlyFileName(arch)}`;
}
// Verify that fileInfo.url points at the official Julia download servers
if (!fileInfo.url.startsWith('https://julialang-s3.julialang.org/')) {
throw new Error(`versions.json points at a download location outside of Julia's download server: ${fileInfo.url}. Aborting for security reasons.`);
}
return fileInfo.url;
}
exports.getDownloadURL = getDownloadURL;
@@ -164,15 +146,7 @@ function installJulia(versionInfo, version, arch) {
const fileInfo = getFileInfo(versionInfo, version, arch);
const downloadURL = getDownloadURL(fileInfo, version, arch);
core.debug(`downloading Julia from ${downloadURL}`);
// Occasionally the connection is reset for unknown reasons
// In those cases, retry the download
const juliaDownloadPath = yield retry((bail) => __awaiter(this, void 0, void 0, function* () {
return yield tc.downloadTool(downloadURL);
}), {
onRetry: (err) => {
core.debug(`Download of ${downloadURL} failed, trying again. Error: ${err}`);
}
});
const juliaDownloadPath = yield tc.downloadTool(downloadURL);
// Verify checksum
if (!version.endsWith('nightly')) {
const checkSum = yield calculateChecksum(juliaDownloadPath);
@@ -210,40 +184,3 @@ function installJulia(versionInfo, version, arch) {
});
}
exports.installJulia = installJulia;
/**
* Test if Julia has been installed and print the version.
*
* true => always show versioninfo
* false => only show on nightlies
* never => never show it anywhere
*
* @param showVersionInfoInput
*/
function showVersionInfo(showVersionInfoInput, version) {
return __awaiter(this, void 0, void 0, function* () {
// --compile=min -O0 reduces the time from ~1.8-1.9s to ~0.8-0.9s
let exitCode;
switch (showVersionInfoInput) {
case 'true':
exitCode = yield exec.exec('julia', ['--compile=min', '-O0', '-e', 'using InteractiveUtils; versioninfo()']);
break;
case 'false':
if (version.endsWith('nightly')) {
exitCode = yield exec.exec('julia', ['--compile=min', '-O0', '-e', 'using InteractiveUtils; versioninfo()']);
}
else {
exitCode = yield exec.exec('julia', ['--version']);
}
break;
case 'never':
exitCode = yield exec.exec('julia', ['--version']);
break;
default:
throw new Error(`${showVersionInfoInput} is not a valid value for show-versioninfo. Supported values: true | false | never`);
}
if (exitCode !== 0) {
throw new Error(`Julia could not be installed properly. Exit code: ${exitCode}`);
}
});
}
exports.showVersionInfo = showVersionInfo;

25
lib/setup-julia.js generated
View File

@@ -16,19 +16,12 @@ var __importStar = (this && this.__importStar) || function (mod) {
};
Object.defineProperty(exports, "__esModule", { value: true });
const core = __importStar(require("@actions/core"));
const exec = __importStar(require("@actions/exec"));
const tc = __importStar(require("@actions/tool-cache"));
const fs = __importStar(require("fs"));
const https = __importStar(require("https"));
const path = __importStar(require("path"));
const installer = __importStar(require("./installer"));
const archSynonyms = {
'x86': 'x86',
'X86': 'x86',
'x64': 'x64',
'X64': 'x64',
'aarch64': 'aarch64',
'ARM64': 'aarch64'
};
function run() {
return __awaiter(this, void 0, void 0, function* () {
try {
@@ -49,7 +42,7 @@ function run() {
}
// Inputs
const versionInput = core.getInput('version');
const originalArchInput = core.getInput('arch');
const arch = core.getInput('arch');
// It can easily happen that, for example, a workflow file contains an input `version: ${{ matrix.julia-version }}`
// while the strategy matrix only contains a key `${{ matrix.version }}`.
// In that case, we want the action to fail, rather than trying to download julia from an URL that's missing parts and 404ing.
@@ -58,10 +51,9 @@ function run() {
if (!versionInput) {
throw new Error('Version input must not be null');
}
if (!originalArchInput) {
if (!arch) {
throw new Error(`Arch input must not be null`);
}
const arch = archSynonyms[originalArchInput];
const versionInfo = yield installer.getJuliaVersionInfo();
const availableReleases = yield installer.getJuliaVersions(versionInfo);
const version = installer.getJuliaVersion(availableReleases, versionInput);
@@ -87,8 +79,15 @@ function run() {
// Set output
core.setOutput('julia-bindir', path.join(juliaPath, 'bin'));
// Test if Julia has been installed and print the version
const showVersionInfoInput = core.getInput('show-versioninfo');
yield installer.showVersionInfo(showVersionInfoInput, version);
if (core.getInput('show-versioninfo') == 'true') {
// If enabled, show the full version info
// --compile=min -O0 reduces the time from ~1.8-1.9s to ~0.8-0.9s
exec.exec('julia', ['--compile=min', '-O0', '-e', 'using InteractiveUtils; versioninfo()']);
}
else {
// Otherwise only print julia --version to save time
exec.exec('julia', ['--version']);
}
}
catch (error) {
core.setFailed(error.message);

8582
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "setup-julia",
"version": "1.8.1",
"version": "1.5.2",
"private": true,
"description": "setup Julia action",
"main": "lib/setup-julia.js",
@@ -25,11 +25,9 @@
"@actions/exec": "^1.0.0",
"@actions/io": "^1.0.0",
"@actions/tool-cache": "^1.0.0",
"async-retry": "^1.3.1",
"semver": "^6.3.0"
},
"devDependencies": {
"@types/async-retry": "^1.4.2",
"@types/jest": "^24.0.13",
"@types/node": "^12.12.7",
"@types/semver": "^6.0.0",

View File

@@ -6,7 +6,6 @@ import * as crypto from 'crypto'
import * as fs from 'fs'
import * as os from 'os'
import * as path from 'path'
import retry = require('async-retry')
import * as semver from 'semver'
@@ -18,8 +17,7 @@ const osMap = {
}
const archMap = {
'x86': 'i686',
'x64': 'x86_64',
'aarch64': 'aarch64'
'x64': 'x86_64'
}
// Store information about the environment
@@ -49,15 +47,7 @@ async function calculateChecksum(file: string): Promise<string> {
* @returns The content of the downloaded versions.json file as object.
*/
export async function getJuliaVersionInfo(): Promise<object> {
// Occasionally the connection is reset for unknown reasons
// In those cases, retry the download
const versionsFile = await retry(async (bail: Function) => {
return await tc.downloadTool('https://julialang-s3.julialang.org/bin/versions.json')
}, {
onRetry: (err: Error) => {
core.debug(`Download of versions.json failed, trying again. Error: ${err}`)
}
})
const versionsFile = await tc.downloadTool('https://julialang-s3.julialang.org/bin/versions.json')
return JSON.parse(fs.readFileSync(versionsFile).toString())
}
@@ -116,23 +106,17 @@ function getNightlyFileName(arch: string): string {
}
export function getFileInfo(versionInfo, version: string, arch: string) {
const err = `Could not find ${archMap[arch]}/${version} binaries`
if (version.endsWith('nightly')) {
return null
}
if (!versionInfo[version]) {
throw err
}
for (let file of versionInfo[version].files) {
if (file.os == osMap[osPlat] && file.arch == archMap[arch]) {
return file
}
}
throw err
throw `Could not find ${archMap[arch]}/${version} binaries`
}
export function getDownloadURL(fileInfo, version: string, arch: string): string {
@@ -149,10 +133,6 @@ export function getDownloadURL(fileInfo, version: string, arch: string): string
return `${baseURL}/${getNightlyFileName(arch)}`
}
// Verify that fileInfo.url points at the official Julia download servers
if (!fileInfo.url.startsWith('https://julialang-s3.julialang.org/')) {
throw new Error(`versions.json points at a download location outside of Julia's download server: ${fileInfo.url}. Aborting for security reasons.`)
}
return fileInfo.url
}
@@ -161,17 +141,7 @@ export async function installJulia(versionInfo, version: string, arch: string):
const fileInfo = getFileInfo(versionInfo, version, arch)
const downloadURL = getDownloadURL(fileInfo, version, arch)
core.debug(`downloading Julia from ${downloadURL}`)
// Occasionally the connection is reset for unknown reasons
// In those cases, retry the download
const juliaDownloadPath = await retry(async (bail: Function) => {
return await tc.downloadTool(downloadURL)
}, {
onRetry: (err: Error) => {
core.debug(`Download of ${downloadURL} failed, trying again. Error: ${err}`)
}
})
const juliaDownloadPath = await tc.downloadTool(downloadURL)
// Verify checksum
if (!version.endsWith('nightly')) {
@@ -208,42 +178,3 @@ export async function installJulia(versionInfo, version: string, arch: string):
throw new Error(`Platform ${osPlat} is not supported`)
}
}
/**
* Test if Julia has been installed and print the version.
*
* true => always show versioninfo
* false => only show on nightlies
* never => never show it anywhere
*
* @param showVersionInfoInput
*/
export async function showVersionInfo(showVersionInfoInput: string, version: string): Promise<void> {
// --compile=min -O0 reduces the time from ~1.8-1.9s to ~0.8-0.9s
let exitCode: number
switch (showVersionInfoInput) {
case 'true':
exitCode = await exec.exec('julia', ['--compile=min', '-O0', '-e', 'using InteractiveUtils; versioninfo()'])
break
case 'false':
if (version.endsWith('nightly')) {
exitCode = await exec.exec('julia', ['--compile=min', '-O0', '-e', 'using InteractiveUtils; versioninfo()'])
} else {
exitCode = await exec.exec('julia', ['--version'])
}
break
case 'never':
exitCode = await exec.exec('julia', ['--version'])
break
default:
throw new Error(`${showVersionInfoInput} is not a valid value for show-versioninfo. Supported values: true | false | never`)
}
if (exitCode !== 0) {
throw new Error(`Julia could not be installed properly. Exit code: ${exitCode}`)
}
}

View File

@@ -8,15 +8,6 @@ import * as path from 'path'
import * as installer from './installer'
const archSynonyms = {
'x86': 'x86',
'X86': 'x86',
'x64': 'x64',
'X64': 'x64',
'aarch64': 'aarch64',
'ARM64': 'aarch64'
}
async function run() {
try {
// Debugging info
@@ -39,7 +30,7 @@ async function run() {
// Inputs
const versionInput = core.getInput('version')
const originalArchInput = core.getInput('arch')
const arch = core.getInput('arch')
// It can easily happen that, for example, a workflow file contains an input `version: ${{ matrix.julia-version }}`
// while the strategy matrix only contains a key `${{ matrix.version }}`.
@@ -49,12 +40,10 @@ async function run() {
if (!versionInput) {
throw new Error('Version input must not be null')
}
if (!originalArchInput) {
if (!arch) {
throw new Error(`Arch input must not be null`)
}
const arch = archSynonyms[originalArchInput]
const versionInfo = await installer.getJuliaVersionInfo()
const availableReleases = await installer.getJuliaVersions(versionInfo)
const version = installer.getJuliaVersion(availableReleases, versionInput)
@@ -86,8 +75,14 @@ async function run() {
core.setOutput('julia-bindir', path.join(juliaPath, 'bin'))
// Test if Julia has been installed and print the version
const showVersionInfoInput = core.getInput('show-versioninfo')
await installer.showVersionInfo(showVersionInfoInput, version)
if (core.getInput('show-versioninfo') == 'true') {
// If enabled, show the full version info
// --compile=min -O0 reduces the time from ~1.8-1.9s to ~0.8-0.9s
exec.exec('julia', ['--compile=min', '-O0', '-e', 'using InteractiveUtils; versioninfo()'])
} else {
// Otherwise only print julia --version to save time
exec.exec('julia', ['--version'])
}
} catch (error) {
core.setFailed(error.message)
}