mirror of
https://github.com/julia-actions/setup-julia.git
synced 2026-02-13 03:26:53 +08:00
Compare commits
44 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d3ce119a16 | ||
|
|
405bfcbfbd | ||
|
|
b8741b9a13 | ||
|
|
9956ebe960 | ||
|
|
71b841c6f2 | ||
|
|
45f46ba622 | ||
|
|
c5d801f77b | ||
|
|
82b1b42f54 | ||
|
|
3503abc570 | ||
|
|
def57cde21 | ||
|
|
c639390e13 | ||
|
|
b469b93959 | ||
|
|
d622e3db7b | ||
|
|
8aadcc1915 | ||
|
|
01ebb7f57a | ||
|
|
44bf6b3b7d | ||
|
|
b4e544c83e | ||
|
|
fc275221aa | ||
|
|
f7961d5fc8 | ||
|
|
19781e4bbc | ||
|
|
1b9230a354 | ||
|
|
a2cbd4a70f | ||
|
|
28af8fd3e2 | ||
|
|
aced07b9c9 | ||
|
|
6b1edeb409 | ||
|
|
4f37a4b06c | ||
|
|
b6c79c651a | ||
|
|
2686c6a9d0 | ||
|
|
55f774e778 | ||
|
|
d2ec2a4741 | ||
|
|
e8b6657769 | ||
|
|
9935e37e60 | ||
|
|
5c7eefcc01 | ||
|
|
226eae6f8c | ||
|
|
415c8550da | ||
|
|
85cbcd387e | ||
|
|
802776bd6a | ||
|
|
477bec664c | ||
|
|
c766abf0da | ||
|
|
3eb3524cb4 | ||
|
|
6ac7df4cef | ||
|
|
c7bbfb8ea8 | ||
|
|
be4aa6964b | ||
|
|
1cabf59107 |
29
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
29
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Create a report to help us improve
|
||||||
|
title: "[BUG] "
|
||||||
|
labels: bug
|
||||||
|
assignees: SaschaMann
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Describe the bug**
|
||||||
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
|
**To Reproduce**
|
||||||
|
Workflow file to reproduce the behavior:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
**Expected behavior**
|
||||||
|
A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
|
**Screenshots/Build logs**
|
||||||
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
|
||||||
|
If possible, set the repo secret `ACTIONS_STEP_DEBUG` to `true` to [enable debug logs](https://github.com/actions/toolkit/blob/master/docs/action-debugging.md#how-to-access-step-debug-logs) and run the build again for more detailled logs.
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context about the problem here.
|
||||||
3
.github/workflows/example-builds-nightly.yml
vendored
3
.github/workflows/example-builds-nightly.yml
vendored
@@ -4,7 +4,7 @@ on:
|
|||||||
push:
|
push:
|
||||||
pull_request:
|
pull_request:
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '0 3 * * *'
|
- cron: '37 17 * * *'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
@@ -33,4 +33,5 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
version: nightly
|
version: nightly
|
||||||
arch: ${{ matrix.julia-arch }}
|
arch: ${{ matrix.julia-arch }}
|
||||||
|
show-versioninfo: 'true'
|
||||||
- run: julia --version
|
- run: julia --version
|
||||||
|
|||||||
2
.github/workflows/example-builds.yml
vendored
2
.github/workflows/example-builds.yml
vendored
@@ -26,8 +26,10 @@ jobs:
|
|||||||
npm run pack
|
npm run pack
|
||||||
|
|
||||||
- name: "Set up Julia"
|
- name: "Set up Julia"
|
||||||
|
id: setup-julia
|
||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
version: ${{ matrix.julia-version }}
|
version: ${{ matrix.julia-version }}
|
||||||
arch: ${{ matrix.julia-arch }}
|
arch: ${{ matrix.julia-arch }}
|
||||||
|
show-versioninfo: 'true'
|
||||||
- run: julia --version
|
- run: julia --version
|
||||||
|
|||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,3 +1,3 @@
|
|||||||
node_modules/
|
node_modules/
|
||||||
__tests__/runner/*
|
__tests__/runner/*
|
||||||
dist/
|
!dist/
|
||||||
|
|||||||
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
[submodule "bin"]
|
||||||
|
path = bin
|
||||||
|
url = git@github.com:julia-actions/bin.git
|
||||||
11
CONTRIBUTING.md
Normal file
11
CONTRIBUTING.md
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# Dev docs / Contributing guide
|
||||||
|
|
||||||
|
## Building and tagging a release (requires write access)
|
||||||
|
|
||||||
|
1. Test your changes, merge into `master`.
|
||||||
|
2. Checkout `master`.
|
||||||
|
3. Bump the version number in [`package.json`](package.json).
|
||||||
|
4. Run `./bin/build-release julia-actions/setup-julia` to create a release branch and build a release.
|
||||||
|
5. Push the branch (**without tags**) and verify that CI is passing on it.
|
||||||
|
6. Run `git push --tags --force` to update the tags.
|
||||||
|
7. Create a release for the `vX.Y.Z` tag.
|
||||||
31
README.md
31
README.md
@@ -11,7 +11,8 @@ This action sets up a Julia environment for use in actions by downloading a spec
|
|||||||
- [Julia Versions](#julia-versions)
|
- [Julia Versions](#julia-versions)
|
||||||
- [Matrix Testing](#matrix-testing)
|
- [Matrix Testing](#matrix-testing)
|
||||||
- [Versioning](#versioning)
|
- [Versioning](#versioning)
|
||||||
- [Licence info](#licence-info)
|
- [Debug logs](#debug-logs)
|
||||||
|
- [Third party information](#third-party-information)
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
@@ -39,16 +40,16 @@ You can either specify specific Julia versions or version ranges. If you specify
|
|||||||
#### Examples
|
#### Examples
|
||||||
|
|
||||||
- `1.2.0` is a valid semver version. The action will try to download exactly this version. If it's not available, the build step will fail.
|
- `1.2.0` is a valid semver version. The action will try to download exactly this version. If it's not available, the build step will fail.
|
||||||
- `1.0` is a version range that will match the highest available Julia version that starts with `1.0`, e.g. `1.0.5`.
|
- `1.0` is a version range that will match the highest available Julia version that starts with `1.0`, e.g. `1.0.5`, excluding pre-releases.
|
||||||
- `^1.3.0-rc1` is a caret version range that includes pre-releases starting at `rc1`. It matches all versions `≥ 1.3.0-rc1` and `< 1.4.0`.
|
- `^1.3.0-rc1` is a **caret** version range that includes pre-releases starting at `rc1`. It matches all versions `≥ 1.3.0-rc1` and `< 2.0.0`.
|
||||||
- `^1.3-0` is a caret version range that includes _all_ pre-releases. It matches all versions `≥ 1.3.0-` and `< 1.4.0`.
|
- `~1.3.0-rc1` is a **tilde** version range that includes pre-releases starting at `rc1`. It matches all versions `≥ 1.3.0-rc1` and `< 1.4.0`.
|
||||||
|
- `^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.
|
- `nightly` will install the latest nightly build.
|
||||||
|
|
||||||
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).
|
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).
|
||||||
|
|
||||||
#### WARNING: Version ranges are experimental and potentially out of date
|
The available Julia versions are pulled from [`versions.json`](https://julialang-s3.julialang.org/bin/versions.json). This file is automatically updated once a day. Therefore it may take up to 24 hours until a newly released Julia version is available in the action.
|
||||||
|
|
||||||
Currently the list of available versions is hardcoded. You have to use the latest version of the action to be able to install the latest Julia versions. Once available we will use a list of versions provided on julialang.org.
|
|
||||||
|
|
||||||
### Matrix Testing
|
### Matrix Testing
|
||||||
|
|
||||||
@@ -140,12 +141,22 @@ You can specify commits, branches or tags in your workflows as follows:
|
|||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
steps:
|
steps:
|
||||||
- uses: julia-actions/setup-julia@6ae948d # commit SHA
|
- uses: julia-actions/setup-julia@d26d1111976eae5f00db04f0515ab744ec9cd79e # commit SHA of the tagged 1.3.1 commit
|
||||||
- uses: julia-actions/setup-julia@master # branch
|
- uses: julia-actions/setup-julia@master # branch
|
||||||
- uses: julia-actions/setup-julia@latest # latest version tag (may break existing workflows)
|
- uses: julia-actions/setup-julia@latest # latest version tag (may break existing workflows)
|
||||||
- uses: julia-actions/setup-julia@v1 # major version tag
|
- uses: julia-actions/setup-julia@v1 # major version tag
|
||||||
- uses: julia-actions/setup-julia@v0.1.0 # specific version tag
|
- uses: julia-actions/setup-julia@v0.1.0 # specific version tag
|
||||||
```
|
```
|
||||||
|
|
||||||
## Licence info
|
If your workflow requires access to secrets, you should always pin it to a commit SHA instead of a tag.
|
||||||
Parts of this software have been derived from the `setup-go` [action](https://github.com/actions/setup-go) and the [TypeScript Action Template](https://github.com/actions/typescript-action), both released by GitHub under the MIT licence.
|
This will protect you in case a bad actor gains access to the setup-julia repo.
|
||||||
|
You can find more information in [GitHub's security hardening guide](https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/security-hardening-for-github-actions#using-third-party-actions).
|
||||||
|
|
||||||
|
## Debug logs
|
||||||
|
|
||||||
|
You can enable [Step Debug Logs](https://github.com/actions/toolkit/blob/main/docs/action-debugging.md#step-debug-logs) for more detailed logs.
|
||||||
|
Note that when debug logs are enabled, a request will be sent to `https://httpbin.julialang.org/ip` and the runner's IP will be printed to the debug logs.
|
||||||
|
|
||||||
|
## Third party information
|
||||||
|
Parts of this software have been derived from other open source software.
|
||||||
|
See [THIRD_PARTY_NOTICE.md](THIRD_PARTY_NOTICE.md) for details.
|
||||||
|
|||||||
55
THIRD_PARTY_NOTICE.md
Normal file
55
THIRD_PARTY_NOTICE.md
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
# Third Party Notices and Information
|
||||||
|
|
||||||
|
Parts of this software have been derived from other open source software.
|
||||||
|
Find their full licence information below.
|
||||||
|
|
||||||
|
- [`setup-go` action](#setup-go-action)
|
||||||
|
- [TypeScript Action Template](#typescript-action-template)
|
||||||
|
|
||||||
|
## [`setup-go` action](https://github.com/actions/setup-go)
|
||||||
|
|
||||||
|
> The MIT License (MIT)
|
||||||
|
>
|
||||||
|
> Copyright (c) 2018 GitHub, Inc. and contributors
|
||||||
|
>
|
||||||
|
> Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
> of this software and associated documentation files (the "Software"), to deal
|
||||||
|
> in the Software without restriction, including without limitation the rights
|
||||||
|
> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
> copies of the Software, and to permit persons to whom the Software is
|
||||||
|
> furnished to do so, subject to the following conditions:
|
||||||
|
>
|
||||||
|
> The above copyright notice and this permission notice shall be included in
|
||||||
|
> all copies or substantial portions of the Software.
|
||||||
|
>
|
||||||
|
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
> THE SOFTWARE.
|
||||||
|
|
||||||
|
## [TypeScript Action Template](https://github.com/actions/typescript-action)
|
||||||
|
|
||||||
|
> The MIT License (MIT)
|
||||||
|
>
|
||||||
|
> Copyright (c) 2018 GitHub, Inc. and contributors
|
||||||
|
>
|
||||||
|
> Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
> of this software and associated documentation files (the "Software"), to deal
|
||||||
|
> in the Software without restriction, including without limitation the rights
|
||||||
|
> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
> copies of the Software, and to permit persons to whom the Software is
|
||||||
|
> furnished to do so, subject to the following conditions:
|
||||||
|
>
|
||||||
|
> The above copyright notice and this permission notice shall be included in
|
||||||
|
> all copies or substantial portions of the Software.
|
||||||
|
>
|
||||||
|
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
> THE SOFTWARE.
|
||||||
4827
__tests__/fixtures/versions.json
Normal file
4827
__tests__/fixtures/versions.json
Normal file
File diff suppressed because it is too large
Load Diff
113
__tests__/installer.test.ts
Normal file
113
__tests__/installer.test.ts
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
// The testing setup has been derived from the actions/setup-go@bc6edb5 action.
|
||||||
|
// Check README.md for licence information.
|
||||||
|
|
||||||
|
import * as path from 'path'
|
||||||
|
|
||||||
|
import * as io from '@actions/io'
|
||||||
|
|
||||||
|
import nock = require('nock')
|
||||||
|
import * as semver from 'semver'
|
||||||
|
|
||||||
|
const testVersions = [
|
||||||
|
'0.1.2', '0.2.0', '0.2.1', '0.3.0',
|
||||||
|
'0.3.1', '0.3.10', '0.3.11', '0.3.12',
|
||||||
|
'0.3.2', '0.3.3', '0.3.4', '0.3.5',
|
||||||
|
'0.3.6', '0.3.7', '0.3.8', '0.3.9',
|
||||||
|
'0.4.0', '0.4.0-rc1', '0.4.0-rc2', '0.4.0-rc3',
|
||||||
|
'0.4.0-rc4', '0.4.1', '0.4.2', '0.4.3',
|
||||||
|
'0.4.4', '0.4.5', '0.4.6', '0.4.7',
|
||||||
|
'0.5.0', '0.5.0-rc0', '0.5.0-rc1', '0.5.0-rc2',
|
||||||
|
'0.5.0-rc3', '0.5.0-rc4', '0.5.1', '0.5.2',
|
||||||
|
'0.6.0', '0.6.0-pre.alpha', '0.6.0-pre.beta', '0.6.0-rc1',
|
||||||
|
'0.6.0-rc2', '0.6.0-rc3', '0.6.1', '0.6.2',
|
||||||
|
'0.6.3', '0.6.4', '0.7.0', '0.7.0-alpha',
|
||||||
|
'0.7.0-beta', '0.7.0-beta2', '0.7.0-rc1', '0.7.0-rc2',
|
||||||
|
'0.7.0-rc3', '1.0.0', '1.0.0-rc1', '1.0.1',
|
||||||
|
'1.0.2', '1.0.3', '1.0.4', '1.0.5',
|
||||||
|
'1.1.0', '1.1.0-rc1', '1.1.0-rc2', '1.1.1',
|
||||||
|
'1.2.0', '1.2.0-rc1', '1.2.0-rc2', '1.2.0-rc3',
|
||||||
|
'1.3.0-alpha', '1.3.0-rc1', '1.3.0-rc2', '1.3.0-rc3',
|
||||||
|
'1.3.0-rc4'
|
||||||
|
]
|
||||||
|
|
||||||
|
const toolDir = path.join(__dirname, 'runner', 'tools')
|
||||||
|
const tempDir = path.join(__dirname, 'runner', 'temp')
|
||||||
|
const fixtureDir = path.join(__dirname, 'fixtures')
|
||||||
|
|
||||||
|
process.env['RUNNER_TOOL_CACHE'] = toolDir
|
||||||
|
process.env['RUNNER_TEMP'] = tempDir
|
||||||
|
|
||||||
|
import * as installer from '../src/installer'
|
||||||
|
|
||||||
|
describe('version matching tests', () => {
|
||||||
|
describe('specific versions', () => {
|
||||||
|
it('Doesn\'t change the version when given a valid semver version', () => {
|
||||||
|
expect(installer.getJuliaVersion([], '1.0.5')).toEqual('1.0.5')
|
||||||
|
expect(installer.getJuliaVersion(['v1.0.5', 'v1.0.6'], '1.0.5')).toEqual('1.0.5')
|
||||||
|
expect(installer.getJuliaVersion(['v1.0.4', 'v1.0.5'], '1.0.5')).toEqual('1.0.5')
|
||||||
|
expect(installer.getJuliaVersion(['v1.0.4'], '1.0.5')).toEqual('1.0.5')
|
||||||
|
expect(installer.getJuliaVersion([], '1.3.0-alpha')).toEqual('1.3.0-alpha')
|
||||||
|
expect(installer.getJuliaVersion(['v1.2.0', 'v1.3.0-alpha', 'v1.3.0-rc1', 'v1.3.0'], '1.3.0-alpha')).toEqual('1.3.0-alpha')
|
||||||
|
expect(installer.getJuliaVersion([], '1.3.0-rc2')).toEqual('1.3.0-rc2')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Doesn\'t change the version when given `nightly`', () => {
|
||||||
|
expect(installer.getJuliaVersion([], 'nightly')).toEqual('nightly')
|
||||||
|
expect(installer.getJuliaVersion(testVersions, 'nightly')).toEqual('nightly')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('version ranges', () => {
|
||||||
|
it('Chooses the highest available version that matches the input', () => {
|
||||||
|
expect(installer.getJuliaVersion(testVersions, '1')).toEqual('1.2.0')
|
||||||
|
expect(installer.getJuliaVersion(testVersions, '1.0')).toEqual('1.0.5')
|
||||||
|
expect(installer.getJuliaVersion(testVersions, '^1.3.0-rc1')).toEqual('1.3.0-rc4')
|
||||||
|
expect(installer.getJuliaVersion(testVersions, '^1.2.0-rc1')).toEqual('1.2.0')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('node-semver behaviour', () => {
|
||||||
|
describe('Windows installer change', () => {
|
||||||
|
it('Correctly understands >1.4.0', () => {
|
||||||
|
expect(semver.gtr('1.4.0-rc1', '1.3', {includePrerelease: true})).toBeTruthy()
|
||||||
|
expect(semver.gtr('1.4.0-DEV', '1.3', {includePrerelease: true})).toBeTruthy()
|
||||||
|
expect(semver.gtr('1.3.1', '1.3', {includePrerelease: true})).toBeFalsy()
|
||||||
|
expect(semver.gtr('1.3.2-rc1', '1.3', {includePrerelease: true})).toBeFalsy()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('installer tests', () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
await io.rmRF(toolDir)
|
||||||
|
await io.rmRF(tempDir)
|
||||||
|
}, 100000)
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
try {
|
||||||
|
await io.rmRF(toolDir)
|
||||||
|
await io.rmRF(tempDir)
|
||||||
|
} catch {
|
||||||
|
console.log('Failed to remove test directories')
|
||||||
|
}
|
||||||
|
}, 100000)
|
||||||
|
|
||||||
|
describe('versions.json parsing', () => {
|
||||||
|
// Instead of downloading versions.json, use fixtures/versions.json
|
||||||
|
beforeEach(() => {
|
||||||
|
nock('https://julialang-s3.julialang.org').persist()
|
||||||
|
.get('/bin/versions.json')
|
||||||
|
.replyWithFile(200, path.join(fixtureDir, 'versions.json'))
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
nock.cleanAll()
|
||||||
|
nock.enableNetConnect()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Extracts the list of available versions', async () => {
|
||||||
|
expect(await (await installer.getJuliaVersions(await installer.getJuliaVersionInfo())).sort()).toEqual(testVersions.sort())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
import * as installer from '../src/installer'
|
|
||||||
|
|
||||||
import * as semver from 'semver'
|
|
||||||
|
|
||||||
const testVersions = ['v1.3.0-rc4', 'v1.3.0-rc3', 'v1.3.0-rc2', 'v1.0.5', 'v1.2.0', 'v1.3.0-rc1', 'v1.2.0-rc3', 'v1.3.0-alpha', 'v1.2.0-rc2', 'v1.2.0-rc1', 'v1.1.1', 'v1.0.4', 'v1.1.0', 'v1.1.0-rc2', 'v1.1.0-rc1', 'v1.0.3', 'v1.0.2', 'v1.0.1', 'v1.0.0']
|
|
||||||
|
|
||||||
describe('installer tests', () => {
|
|
||||||
describe('version matching', () => {
|
|
||||||
describe('specific versions', () => {
|
|
||||||
it('Doesn\'t change the version when given a valid semver version', async () => {
|
|
||||||
expect(await installer.getJuliaVersion([], '1.0.5')).toEqual('1.0.5')
|
|
||||||
expect(await installer.getJuliaVersion(['v1.0.5', 'v1.0.6'], '1.0.5')).toEqual('1.0.5')
|
|
||||||
expect(await installer.getJuliaVersion(['v1.0.4', 'v1.0.5'], '1.0.5')).toEqual('1.0.5')
|
|
||||||
expect(await installer.getJuliaVersion(['v1.0.4'], '1.0.5')).toEqual('1.0.5')
|
|
||||||
expect(await installer.getJuliaVersion([], '1.3.0-alpha')).toEqual('1.3.0-alpha')
|
|
||||||
expect(await installer.getJuliaVersion(['v1.2.0', 'v1.3.0-alpha', 'v1.3.0-rc1', 'v1.3.0'], '1.3.0-alpha')).toEqual('1.3.0-alpha')
|
|
||||||
expect(await installer.getJuliaVersion([], '1.3.0-rc2')).toEqual('1.3.0-rc2')
|
|
||||||
})
|
|
||||||
it('Doesn\'t change the version when given `nightly`', async () => {
|
|
||||||
expect(await installer.getJuliaVersion([], 'nightly')).toEqual('nightly')
|
|
||||||
expect(await installer.getJuliaVersion(testVersions, 'nightly')).toEqual('nightly')
|
|
||||||
})
|
|
||||||
})
|
|
||||||
describe('version ranges', () => {
|
|
||||||
it('Chooses the highest available version that matches the input', async () => {
|
|
||||||
expect(await installer.getJuliaVersion(testVersions, '1')).toEqual('1.2.0')
|
|
||||||
expect(await installer.getJuliaVersion(testVersions, '1.0')).toEqual('1.0.5')
|
|
||||||
expect(await installer.getJuliaVersion(testVersions, '^1.3.0-rc1')).toEqual('1.3.0-rc4')
|
|
||||||
expect(await installer.getJuliaVersion(testVersions, '^1.2.0-rc1')).toEqual('1.2.0')
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
describe('node-semver behaviour', () => {
|
|
||||||
describe('Windows installer change', () => {
|
|
||||||
it('Correctly understands >1.4.0', () => {
|
|
||||||
expect(semver.gtr('1.4.0-rc1', '1.3', {includePrerelease: true})).toBeTruthy()
|
|
||||||
expect(semver.gtr('1.4.0-DEV', '1.3', {includePrerelease: true})).toBeTruthy()
|
|
||||||
expect(semver.gtr('1.3.1', '1.3', {includePrerelease: true})).toBeFalsy()
|
|
||||||
expect(semver.gtr('1.3.2-rc1', '1.3', {includePrerelease: true})).toBeFalsy()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
@@ -13,6 +13,9 @@ inputs:
|
|||||||
description: 'Display InteractiveUtils.versioninfo() after installing'
|
description: 'Display InteractiveUtils.versioninfo() after installing'
|
||||||
required: false
|
required: false
|
||||||
default: 'false'
|
default: 'false'
|
||||||
|
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:
|
runs:
|
||||||
using: 'node12'
|
using: 'node12'
|
||||||
main: 'dist/index.js'
|
main: 'dist/index.js'
|
||||||
|
|||||||
1
bin
Submodule
1
bin
Submodule
Submodule bin added at 9ceca17c9c
@@ -1,44 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
branch_name="$(git symbolic-ref --short -q HEAD)"
|
|
||||||
version="v$(jq -r .version package.json)"
|
|
||||||
repo="$1"
|
|
||||||
|
|
||||||
if [ -z "$repo" ]; then
|
|
||||||
echo "ERROR: must specify repository"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "=== debug info ==="
|
|
||||||
echo "branch: $branch_name"
|
|
||||||
echo "version: $version"
|
|
||||||
echo "repo: $repo"
|
|
||||||
echo "=================="
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check that the version doesn't exist yet
|
|
||||||
version_exists="$(curl -s https://api.github.com/repos/"$repo"/tags -H "Accept: application/vnd.github.v3.full+json" | jq -r '.[] | select(.name == "'"$version"'") | .name')"
|
|
||||||
if [ -n "$version_exists" ]; then
|
|
||||||
echo "ERROR: version $version already exists"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
git checkout -b releases/"$version"
|
|
||||||
|
|
||||||
npm install
|
|
||||||
npm run build
|
|
||||||
npm test
|
|
||||||
npm run pack
|
|
||||||
|
|
||||||
sed -i 's/dist/!dist/g' .gitignore
|
|
||||||
git add dist
|
|
||||||
git commit -a -m "Add production dependencies & build"
|
|
||||||
|
|
||||||
# Tags
|
|
||||||
major_minor="$(sed 's/\.[^.]*$//' <<< "$version")"
|
|
||||||
major="$(sed 's/\.[^.]*$//' <<< "$major_minor")"
|
|
||||||
|
|
||||||
git tag "$version"
|
|
||||||
git tag -f "$major_minor"
|
|
||||||
git tag -f "$major"
|
|
||||||
git tag -f "latest"
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
branch_name="$(git symbolic-ref --short -q HEAD)"
|
|
||||||
version="v$(jq -r .version package.json)"
|
|
||||||
repo="$1"
|
|
||||||
|
|
||||||
if [ -z "$repo" ]; then
|
|
||||||
echo "ERROR: must specify repository"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "=== debug info ==="
|
|
||||||
echo "branch: $branch_name"
|
|
||||||
echo "version: $version"
|
|
||||||
echo "repo: $repo"
|
|
||||||
echo "=================="
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check that the version doesn't exist yet
|
|
||||||
version_exists="$(curl -s https://api.github.com/repos/"$repo"/tags -H "Accept: application/vnd.github.v3.full+json" | jq -r '.[] | select(.name == "'"$version"'") | .name')"
|
|
||||||
if [ -n "$version_exists" ]; then
|
|
||||||
echo "ERROR: version $version already exists"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
git checkout -B test/"$branch_name"/releases/"$version"
|
|
||||||
|
|
||||||
npm install
|
|
||||||
npm run build
|
|
||||||
npm test
|
|
||||||
npm run pack
|
|
||||||
|
|
||||||
# Add dist/ to git and commit it
|
|
||||||
sed -i 's/dist/!dist/g' .gitignore
|
|
||||||
git add dist
|
|
||||||
git commit -a -m "Add production dependencies & build"
|
|
||||||
4797
dist/index.js
vendored
Normal file
4797
dist/index.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
BIN
dist/unzip
vendored
Normal file
BIN
dist/unzip
vendored
Normal file
Binary file not shown.
185
lib/installer.js
generated
185
lib/installer.js
generated
@@ -18,122 +18,167 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|||||||
const core = __importStar(require("@actions/core"));
|
const core = __importStar(require("@actions/core"));
|
||||||
const exec = __importStar(require("@actions/exec"));
|
const exec = __importStar(require("@actions/exec"));
|
||||||
const tc = __importStar(require("@actions/tool-cache"));
|
const tc = __importStar(require("@actions/tool-cache"));
|
||||||
|
const crypto = __importStar(require("crypto"));
|
||||||
|
const fs = __importStar(require("fs"));
|
||||||
const os = __importStar(require("os"));
|
const os = __importStar(require("os"));
|
||||||
const path = __importStar(require("path"));
|
const path = __importStar(require("path"));
|
||||||
const semver = __importStar(require("semver"));
|
const semver = __importStar(require("semver"));
|
||||||
|
// Translations between actions input and Julia arch names
|
||||||
|
const osMap = {
|
||||||
|
'win32': 'winnt',
|
||||||
|
'darwin': 'mac',
|
||||||
|
'linux': 'linux'
|
||||||
|
};
|
||||||
|
const archMap = {
|
||||||
|
'x86': 'i686',
|
||||||
|
'x64': 'x86_64'
|
||||||
|
};
|
||||||
// Store information about the environment
|
// Store information about the environment
|
||||||
const osPlat = os.platform(); // possible values: win32 (Windows), linux (Linux), darwin (macOS)
|
const osPlat = os.platform(); // possible values: win32 (Windows), linux (Linux), darwin (macOS)
|
||||||
core.debug(`platform: ${osPlat}`);
|
core.debug(`platform: ${osPlat}`);
|
||||||
// This is temporary until we have a better way of fetching releases (see #1, #4 for details)
|
/**
|
||||||
exports.juliaVersions = ['v1.5.0-beta1', 'v1.4.2', 'v1.4.1', 'v1.4.0', 'v1.4.0-rc2', 'v1.4.0-rc1', 'v1.3.1', 'v1.3.0', 'v1.3.0-rc5', 'v1.3.0-rc4', 'v1.3.0-rc3', 'v1.3.0-rc2', 'v1.0.5', 'v1.2.0', 'v1.3.0-rc1', 'v1.2.0-rc3', 'v1.3.0-alpha', 'v1.2.0-rc2', 'v1.2.0-rc1', 'v1.1.1', 'v1.0.4', 'v1.1.0', 'v1.1.0-rc2', 'v1.1.0-rc1', 'v1.0.3', 'v1.0.2', 'v1.0.1', 'v1.0.0', 'v0.7.0', 'v1.0.0-rc1', 'v0.7.0-rc3', 'v0.7.0-rc2', 'v0.7.0-rc1', 'v0.7.0-beta2', 'v0.6.4', 'v0.7.0-beta', 'v0.7.0-alpha', 'v0.6.3', 'v0.6.2', 'v0.6.1', 'v0.6.0', 'v0.6.0-rc3', 'v0.6.0-rc2', 'v0.5.2', 'v0.6.0-rc1', 'v0.6.0-pre.beta', 'v0.5.1', 'v0.6.0-pre.alpha', 'v0.5.0', 'v0.4.7', 'v0.5.0-rc4', 'v0.5.0-rc3', 'v0.5.0-rc2', 'v0.5.0-rc1', 'v0.5.0-rc0', 'v0.4.6', 'v0.4.5', 'v0.4.4', 'v0.4.3', 'v0.4.2', 'v0.4.1', 'v0.3.12', 'v0.4.0', 'v0.4.0-rc4', 'v0.4.0-rc3', 'v0.4.0-rc2', 'v0.4.0-rc1', 'v0.3.11', 'v0.3.10', 'v0.3.9', 'v0.3.8', 'v0.3.7', 'v0.3.6', 'v0.3.5', 'v0.3.4', 'v0.3.3', 'v0.3.2', 'v0.3.1', 'v0.3.0', 'v0.3.0-rc4', 'v0.3.0-rc3', 'v0.3.0-rc2', 'v0.3.0-rc1', 'v0.2.0-rc1', 'v0.2.0-rc3', 'v0.2.0-rc4', 'v0.2.0', 'v0.2.0-rc2'];
|
* @returns The SHA256 checksum of a given file.
|
||||||
function getJuliaVersion(availableReleases, versionInput) {
|
*/
|
||||||
|
function calculateChecksum(file) {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
if (semver.valid(versionInput) == versionInput) {
|
const hash = crypto.createHash('sha256');
|
||||||
// versionInput is a valid version, use it directly
|
const input = fs.createReadStream(file);
|
||||||
return versionInput;
|
return new Promise((resolve, reject) => {
|
||||||
}
|
input.on('data', (chunk) => {
|
||||||
// nightlies
|
hash.update(chunk);
|
||||||
if (versionInput == 'nightly') {
|
});
|
||||||
return 'nightly';
|
input.on('end', () => {
|
||||||
}
|
const digest = hash.digest('hex');
|
||||||
// Use the highest available version that matches versionInput
|
digest ? resolve(digest) : reject(new Error(`Could not calculate checksum of file ${file}: digest was empty.`));
|
||||||
let version = semver.maxSatisfying(availableReleases, versionInput);
|
});
|
||||||
if (version == null) {
|
});
|
||||||
throw `Could not find a Julia version that matches ${versionInput}`;
|
|
||||||
}
|
|
||||||
// GitHub tags start with v, remove it
|
|
||||||
version = version.replace(/^v/, '');
|
|
||||||
return version;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
exports.getJuliaVersion = getJuliaVersion;
|
/**
|
||||||
function getMajorMinorVersion(version) {
|
* @returns The content of the downloaded versions.json file as object.
|
||||||
return version.split('.').slice(0, 2).join('.');
|
*/
|
||||||
|
function getJuliaVersionInfo() {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
const versionsFile = yield tc.downloadTool('https://julialang-s3.julialang.org/bin/versions.json');
|
||||||
|
return JSON.parse(fs.readFileSync(versionsFile).toString());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
function getDownloadURL(version, arch) {
|
exports.getJuliaVersionInfo = getJuliaVersionInfo;
|
||||||
let platform;
|
/**
|
||||||
if (osPlat === 'win32') { // Windows
|
* @returns An array of all Julia versions available for download
|
||||||
platform = 'winnt';
|
*/
|
||||||
}
|
function getJuliaVersions(versionInfo) {
|
||||||
else if (osPlat === 'darwin') { // macOS
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
if (arch == 'x86') {
|
let versions = [];
|
||||||
throw '32-bit Julia is not available on macOS';
|
for (let version in versionInfo) {
|
||||||
|
versions.push(version);
|
||||||
}
|
}
|
||||||
platform = 'mac';
|
return versions;
|
||||||
}
|
});
|
||||||
else if (osPlat === 'linux') { // Linux
|
}
|
||||||
platform = 'linux';
|
exports.getJuliaVersions = getJuliaVersions;
|
||||||
}
|
function getJuliaVersion(availableReleases, versionInput) {
|
||||||
else {
|
if (semver.valid(versionInput) == versionInput) {
|
||||||
throw `Platform ${osPlat} is not supported`;
|
// versionInput is a valid version, use it directly
|
||||||
|
return versionInput;
|
||||||
}
|
}
|
||||||
// nightlies
|
// nightlies
|
||||||
if (version == 'nightly') {
|
if (versionInput == 'nightly') {
|
||||||
const baseURL = 'https://julialangnightlies-s3.julialang.org/bin';
|
return 'nightly';
|
||||||
return `${baseURL}/${platform}/${arch}/${getFileName('latest', arch)}`;
|
|
||||||
}
|
}
|
||||||
// normal versions
|
// Use the highest available version that matches versionInput
|
||||||
const baseURL = 'https://julialang-s3.julialang.org/bin';
|
let version = semver.maxSatisfying(availableReleases, versionInput);
|
||||||
const versionDir = getMajorMinorVersion(version);
|
if (version == null) {
|
||||||
return `${baseURL}/${platform}/${arch}/${versionDir}/${getFileName(version, arch)}`;
|
throw new Error(`Could not find a Julia version that matches ${versionInput}`);
|
||||||
|
}
|
||||||
|
// GitHub tags start with v, remove it
|
||||||
|
version = version.replace(/^v/, '');
|
||||||
|
return version;
|
||||||
}
|
}
|
||||||
function getFileName(version, arch) {
|
exports.getJuliaVersion = getJuliaVersion;
|
||||||
|
function getNightlyFileName(arch) {
|
||||||
let versionExt, ext;
|
let versionExt, ext;
|
||||||
if (osPlat === 'win32') { // Windows
|
if (osPlat == 'win32') {
|
||||||
versionExt = arch == 'x64' ? '-win64' : '-win32';
|
versionExt = arch == 'x64' ? '-win64' : '-win32';
|
||||||
ext = 'exe';
|
ext = 'exe';
|
||||||
}
|
}
|
||||||
else if (osPlat === 'darwin') { // macOS
|
else if (osPlat == 'darwin') {
|
||||||
if (arch == 'x86') {
|
if (arch == 'x86') {
|
||||||
throw '32-bit Julia is not available on macOS';
|
throw new Error('32-bit Julia is not available on macOS');
|
||||||
}
|
}
|
||||||
versionExt = '-mac64';
|
versionExt = '-mac64';
|
||||||
ext = 'dmg';
|
ext = 'dmg';
|
||||||
}
|
}
|
||||||
else if (osPlat === 'linux') { // Linux
|
else if (osPlat === 'linux') {
|
||||||
if (version == 'latest') { // nightly version
|
versionExt = arch == 'x64' ? '-linux64' : '-linux32';
|
||||||
versionExt = arch == 'x64' ? '-linux64' : '-linux32';
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
versionExt = arch == 'x64' ? '-linux-x86_64' : '-linux-i686';
|
|
||||||
}
|
|
||||||
ext = 'tar.gz';
|
ext = 'tar.gz';
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw `Platform ${osPlat} is not supported`;
|
throw new Error(`Platform ${osPlat} is not supported`);
|
||||||
}
|
}
|
||||||
return `julia-${version}${versionExt}.${ext}`;
|
return `julia-latest${versionExt}.${ext}`;
|
||||||
}
|
}
|
||||||
function installJulia(version, arch) {
|
function getFileInfo(versionInfo, version, arch) {
|
||||||
|
if (version == 'nightly') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
for (let file of versionInfo[version].files) {
|
||||||
|
if (file.os == osMap[osPlat] && file.arch == archMap[arch]) {
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw `Could not find ${archMap[arch]}/${version} binaries`;
|
||||||
|
}
|
||||||
|
exports.getFileInfo = getFileInfo;
|
||||||
|
function getDownloadURL(fileInfo, version, arch) {
|
||||||
|
// nightlies
|
||||||
|
if (version == 'nightly') {
|
||||||
|
const baseURL = 'https://julialangnightlies-s3.julialang.org/bin';
|
||||||
|
return `${baseURL}/${osMap[osPlat]}/${arch}/${getNightlyFileName(arch)}`;
|
||||||
|
}
|
||||||
|
return fileInfo.url;
|
||||||
|
}
|
||||||
|
exports.getDownloadURL = getDownloadURL;
|
||||||
|
function installJulia(versionInfo, version, arch) {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
// Download Julia
|
// Download Julia
|
||||||
const downloadURL = getDownloadURL(version, arch);
|
const fileInfo = getFileInfo(versionInfo, version, arch);
|
||||||
|
const downloadURL = getDownloadURL(fileInfo, version, arch);
|
||||||
core.debug(`downloading Julia from ${downloadURL}`);
|
core.debug(`downloading Julia from ${downloadURL}`);
|
||||||
const juliaDownloadPath = yield tc.downloadTool(downloadURL);
|
const juliaDownloadPath = yield tc.downloadTool(downloadURL);
|
||||||
|
// Verify checksum
|
||||||
|
if (version != 'nightly') {
|
||||||
|
const checkSum = yield calculateChecksum(juliaDownloadPath);
|
||||||
|
if (fileInfo.sha256 != checkSum) {
|
||||||
|
throw new Error(`Checksum of downloaded file does not match the expected checksum from versions.json.\nExpected: ${fileInfo.sha256}\nGot: ${checkSum}`);
|
||||||
|
}
|
||||||
|
core.debug(`Checksum of downloaded file matches expected checksum: ${checkSum}`);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
core.debug('Skipping checksum check for nightly binaries.');
|
||||||
|
}
|
||||||
|
const tempInstallDir = fs.mkdtempSync(`julia-${arch}-${version}-`);
|
||||||
// Install it
|
// Install it
|
||||||
switch (osPlat) {
|
switch (osPlat) {
|
||||||
case 'linux':
|
case 'linux':
|
||||||
// tc.extractTar doesn't support stripping components, so we have to call tar manually
|
// tc.extractTar doesn't support stripping components, so we have to call tar manually
|
||||||
yield exec.exec('mkdir', [`${process.env.HOME}/julia`]);
|
yield exec.exec('tar', ['xf', juliaDownloadPath, '--strip-components=1', '-C', tempInstallDir]);
|
||||||
yield exec.exec('tar', ['xf', juliaDownloadPath, '--strip-components=1', '-C', `${process.env.HOME}/julia`]);
|
return tempInstallDir;
|
||||||
return `${process.env.HOME}/julia`;
|
|
||||||
case 'win32':
|
case 'win32':
|
||||||
const juliaInstallationPath = path.join('C:', 'Julia');
|
|
||||||
if (version == 'nightly' || semver.gtr(version, '1.3', { includePrerelease: true })) {
|
if (version == 'nightly' || semver.gtr(version, '1.3', { includePrerelease: true })) {
|
||||||
// The installer changed in 1.4: https://github.com/JuliaLang/julia/blob/ef0c9108b12f3ae177c51037934351ffa703b0b5/NEWS.md#build-system-changes
|
// The installer changed in 1.4: https://github.com/JuliaLang/julia/blob/ef0c9108b12f3ae177c51037934351ffa703b0b5/NEWS.md#build-system-changes
|
||||||
yield exec.exec('powershell', ['-Command', `Start-Process -FilePath ${juliaDownloadPath} -ArgumentList "/SILENT /dir=${juliaInstallationPath}" -NoNewWindow -Wait`]);
|
yield exec.exec('powershell', ['-Command', `Start-Process -FilePath ${juliaDownloadPath} -ArgumentList "/SILENT /dir=${path.join(process.cwd(), tempInstallDir)}" -NoNewWindow -Wait`]);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
yield exec.exec('powershell', ['-Command', `Start-Process -FilePath ${juliaDownloadPath} -ArgumentList "/S /D=${juliaInstallationPath}" -NoNewWindow -Wait`]);
|
yield exec.exec('powershell', ['-Command', `Start-Process -FilePath ${juliaDownloadPath} -ArgumentList "/S /D=${path.join(process.cwd(), tempInstallDir)}" -NoNewWindow -Wait`]);
|
||||||
}
|
}
|
||||||
return juliaInstallationPath;
|
return tempInstallDir;
|
||||||
case 'darwin':
|
case 'darwin':
|
||||||
yield exec.exec('hdiutil', ['attach', juliaDownloadPath]);
|
yield exec.exec('hdiutil', ['attach', juliaDownloadPath]);
|
||||||
yield exec.exec('mkdir', [`${process.env.HOME}/julia`]);
|
yield exec.exec('/bin/bash', ['-c', `cp -a /Volumes/Julia-*/Julia-*.app/Contents/Resources/julia ${tempInstallDir}`]);
|
||||||
yield exec.exec('/bin/bash', ['-c', `cp -a /Volumes/Julia-*/Julia-*.app/Contents/Resources/julia ${process.env.HOME}`]);
|
return path.join(tempInstallDir, 'julia');
|
||||||
return `${process.env.HOME}/julia`;
|
|
||||||
default:
|
default:
|
||||||
throw `Platform ${osPlat} is not supported`;
|
throw new Error(`Platform ${osPlat} is not supported`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
42
lib/setup-julia.js
generated
42
lib/setup-julia.js
generated
@@ -18,31 +18,65 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|||||||
const core = __importStar(require("@actions/core"));
|
const core = __importStar(require("@actions/core"));
|
||||||
const exec = __importStar(require("@actions/exec"));
|
const exec = __importStar(require("@actions/exec"));
|
||||||
const tc = __importStar(require("@actions/tool-cache"));
|
const tc = __importStar(require("@actions/tool-cache"));
|
||||||
|
const fs = __importStar(require("fs"));
|
||||||
|
const https = __importStar(require("https"));
|
||||||
const path = __importStar(require("path"));
|
const path = __importStar(require("path"));
|
||||||
const installer = __importStar(require("./installer"));
|
const installer = __importStar(require("./installer"));
|
||||||
function run() {
|
function run() {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
try {
|
try {
|
||||||
|
// Debugging info
|
||||||
|
if (core.isDebug()) {
|
||||||
|
// Log Runner IP Address
|
||||||
|
https.get('https://httpbin.julialang.org/ip', resp => {
|
||||||
|
let data = '';
|
||||||
|
resp.on('data', chunk => {
|
||||||
|
data += chunk;
|
||||||
|
});
|
||||||
|
resp.on('end', () => {
|
||||||
|
core.debug(`Runner IP address: ${JSON.parse(data).origin}`);
|
||||||
|
});
|
||||||
|
}).on('error', err => {
|
||||||
|
core.debug(`ERROR: Could not retrieve runner IP: ${err}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// Inputs
|
||||||
const versionInput = core.getInput('version');
|
const versionInput = core.getInput('version');
|
||||||
const arch = core.getInput('arch');
|
const arch = core.getInput('arch');
|
||||||
const availableReleases = installer.juliaVersions;
|
// It can easily happen that, for example, a workflow file contains an input `version: ${{ matrix.julia-version }}`
|
||||||
const version = yield installer.getJuliaVersion(availableReleases, versionInput);
|
// 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.
|
||||||
|
// We _could_ fall back to the default but that means that builds silently do things differently than they're meant to, which
|
||||||
|
// is worse than failing the build.
|
||||||
|
if (!versionInput) {
|
||||||
|
throw new Error('Version input must not be null');
|
||||||
|
}
|
||||||
|
if (!arch) {
|
||||||
|
throw new Error(`Arch input must not be null`);
|
||||||
|
}
|
||||||
|
const versionInfo = yield installer.getJuliaVersionInfo();
|
||||||
|
const availableReleases = yield installer.getJuliaVersions(versionInfo);
|
||||||
|
const version = installer.getJuliaVersion(availableReleases, versionInput);
|
||||||
core.debug(`selected Julia version: ${arch}/${version}`);
|
core.debug(`selected Julia version: ${arch}/${version}`);
|
||||||
// Search in cache
|
// Search in cache
|
||||||
let juliaPath;
|
let juliaPath;
|
||||||
juliaPath = tc.find('julia', version, arch);
|
juliaPath = tc.find('julia', version, arch);
|
||||||
if (!juliaPath) {
|
if (!juliaPath) {
|
||||||
core.debug(`could not find Julia ${version} in cache`);
|
core.debug(`could not find Julia ${arch}/${version} in cache`);
|
||||||
const juliaInstallationPath = yield installer.installJulia(version, arch);
|
const juliaInstallationPath = yield installer.installJulia(versionInfo, version, arch);
|
||||||
// Add it to cache
|
// Add it to cache
|
||||||
juliaPath = yield tc.cacheDir(juliaInstallationPath, 'julia', version, arch);
|
juliaPath = yield tc.cacheDir(juliaInstallationPath, 'julia', version, arch);
|
||||||
core.debug(`added Julia to cache: ${juliaPath}`);
|
core.debug(`added Julia to cache: ${juliaPath}`);
|
||||||
|
// Remove temporary dir
|
||||||
|
fs.rmdirSync(juliaInstallationPath, { recursive: true });
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
core.debug(`using cached version of Julia: ${juliaPath}`);
|
core.debug(`using cached version of Julia: ${juliaPath}`);
|
||||||
}
|
}
|
||||||
// Add it to PATH
|
// Add it to PATH
|
||||||
core.addPath(path.join(juliaPath, 'bin'));
|
core.addPath(path.join(juliaPath, 'bin'));
|
||||||
|
// Set output
|
||||||
|
core.setOutput('julia-bindir', path.join(juliaPath, 'bin'));
|
||||||
// Test if Julia has been installed
|
// Test if Julia has been installed
|
||||||
exec.exec('julia', ['--version']);
|
exec.exec('julia', ['--version']);
|
||||||
// If enabled, also show the full version info
|
// If enabled, also show the full version info
|
||||||
|
|||||||
50
package-lock.json
generated
50
package-lock.json
generated
@@ -1,13 +1,13 @@
|
|||||||
{
|
{
|
||||||
"name": "setup-julia",
|
"name": "setup-julia",
|
||||||
"version": "1.1.5",
|
"version": "1.4.1",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": {
|
"@actions/core": {
|
||||||
"version": "1.0.0",
|
"version": "1.2.6",
|
||||||
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.2.6.tgz",
|
||||||
"integrity": "sha512-aMIlkx96XH4E/2YZtEOeyrYQfhlas9jIRkfGPqMwXD095Rdkzo4lB6ZmbxPQSzD+e1M+Xsm98ZhuSMYGv/AlqA=="
|
"integrity": "sha512-ZQYitnqiyBc3D+k7LsgSBmMDVkOVidaagDG7j3fOym77jNunWRuYx7VSHa9GNfFZh+zh61xsCjRj4JxMZlDqTA=="
|
||||||
},
|
},
|
||||||
"@actions/exec": {
|
"@actions/exec": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
@@ -5235,9 +5235,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lodash": {
|
"lodash": {
|
||||||
"version": "4.17.15",
|
"version": "4.17.19",
|
||||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
|
||||||
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
|
"integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"lodash.memoize": {
|
"lodash.memoize": {
|
||||||
@@ -5461,6 +5461,36 @@
|
|||||||
"integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
|
"integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"nock": {
|
||||||
|
"version": "11.7.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/nock/-/nock-11.7.2.tgz",
|
||||||
|
"integrity": "sha512-7swr5bL1xBZ5FctyubjxEVySXOSebyqcL7Vy1bx1nS9IUqQWj81cmKjVKJLr8fHhtzI1MV8nyCdENA/cGcY1+Q==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"debug": "^4.1.0",
|
||||||
|
"json-stringify-safe": "^5.0.1",
|
||||||
|
"lodash": "^4.17.13",
|
||||||
|
"mkdirp": "^0.5.0",
|
||||||
|
"propagate": "^2.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"debug": {
|
||||||
|
"version": "4.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
|
||||||
|
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"ms": "^2.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ms": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||||
|
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node-int64": {
|
"node-int64": {
|
||||||
"version": "0.4.0",
|
"version": "0.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
|
||||||
@@ -5821,6 +5851,12 @@
|
|||||||
"sisteransi": "^1.0.4"
|
"sisteransi": "^1.0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"propagate": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"psl": {
|
"psl": {
|
||||||
"version": "1.7.0",
|
"version": "1.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/psl/-/psl-1.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/psl/-/psl-1.7.0.tgz",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "setup-julia",
|
"name": "setup-julia",
|
||||||
"version": "1.1.6",
|
"version": "1.4.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"description": "setup Julia action",
|
"description": "setup Julia action",
|
||||||
"main": "lib/setup-julia.js",
|
"main": "lib/setup-julia.js",
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
"author": "Sascha Mann <git@mail.saschamann.eu>",
|
"author": "Sascha Mann <git@mail.saschamann.eu>",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": "^1.0.0",
|
"@actions/core": "^1.2.6",
|
||||||
"@actions/exec": "^1.0.0",
|
"@actions/exec": "^1.0.0",
|
||||||
"@actions/io": "^1.0.0",
|
"@actions/io": "^1.0.0",
|
||||||
"@actions/tool-cache": "^1.0.0",
|
"@actions/tool-cache": "^1.0.0",
|
||||||
@@ -34,6 +34,7 @@
|
|||||||
"@zeit/ncc": "^0.22.0",
|
"@zeit/ncc": "^0.22.0",
|
||||||
"jest": "^24.8.0",
|
"jest": "^24.8.0",
|
||||||
"jest-circus": "^24.7.1",
|
"jest-circus": "^24.7.1",
|
||||||
|
"nock": "^11.7.2",
|
||||||
"prettier": "^1.17.1",
|
"prettier": "^1.17.1",
|
||||||
"ts-jest": "^26.0.0",
|
"ts-jest": "^26.0.0",
|
||||||
"typescript": "^3.5.1"
|
"typescript": "^3.5.1"
|
||||||
|
|||||||
173
src/installer.ts
173
src/installer.ts
@@ -2,19 +2,70 @@ import * as core from '@actions/core'
|
|||||||
import * as exec from '@actions/exec'
|
import * as exec from '@actions/exec'
|
||||||
import * as tc from '@actions/tool-cache'
|
import * as tc from '@actions/tool-cache'
|
||||||
|
|
||||||
|
import * as crypto from 'crypto'
|
||||||
|
import * as fs from 'fs'
|
||||||
import * as os from 'os'
|
import * as os from 'os'
|
||||||
import * as path from 'path'
|
import * as path from 'path'
|
||||||
|
|
||||||
import * as semver from 'semver'
|
import * as semver from 'semver'
|
||||||
|
|
||||||
|
// Translations between actions input and Julia arch names
|
||||||
|
const osMap = {
|
||||||
|
'win32': 'winnt',
|
||||||
|
'darwin': 'mac',
|
||||||
|
'linux': 'linux'
|
||||||
|
}
|
||||||
|
const archMap = {
|
||||||
|
'x86': 'i686',
|
||||||
|
'x64': 'x86_64'
|
||||||
|
}
|
||||||
|
|
||||||
// Store information about the environment
|
// Store information about the environment
|
||||||
const osPlat = os.platform() // possible values: win32 (Windows), linux (Linux), darwin (macOS)
|
const osPlat = os.platform() // possible values: win32 (Windows), linux (Linux), darwin (macOS)
|
||||||
core.debug(`platform: ${osPlat}`)
|
core.debug(`platform: ${osPlat}`)
|
||||||
|
|
||||||
// This is temporary until we have a better way of fetching releases (see #1, #4 for details)
|
/**
|
||||||
export const juliaVersions = ['v1.5.0-beta1', 'v1.4.2', 'v1.4.1', 'v1.4.0', 'v1.4.0-rc2', 'v1.4.0-rc1', 'v1.3.1', 'v1.3.0', 'v1.3.0-rc5', 'v1.3.0-rc4', 'v1.3.0-rc3', 'v1.3.0-rc2', 'v1.0.5', 'v1.2.0', 'v1.3.0-rc1', 'v1.2.0-rc3', 'v1.3.0-alpha', 'v1.2.0-rc2', 'v1.2.0-rc1', 'v1.1.1', 'v1.0.4', 'v1.1.0', 'v1.1.0-rc2', 'v1.1.0-rc1', 'v1.0.3', 'v1.0.2', 'v1.0.1', 'v1.0.0', 'v0.7.0', 'v1.0.0-rc1', 'v0.7.0-rc3', 'v0.7.0-rc2', 'v0.7.0-rc1', 'v0.7.0-beta2', 'v0.6.4', 'v0.7.0-beta', 'v0.7.0-alpha', 'v0.6.3', 'v0.6.2', 'v0.6.1', 'v0.6.0', 'v0.6.0-rc3', 'v0.6.0-rc2', 'v0.5.2', 'v0.6.0-rc1', 'v0.6.0-pre.beta', 'v0.5.1', 'v0.6.0-pre.alpha', 'v0.5.0', 'v0.4.7', 'v0.5.0-rc4', 'v0.5.0-rc3', 'v0.5.0-rc2', 'v0.5.0-rc1', 'v0.5.0-rc0', 'v0.4.6', 'v0.4.5', 'v0.4.4', 'v0.4.3', 'v0.4.2', 'v0.4.1', 'v0.3.12', 'v0.4.0', 'v0.4.0-rc4', 'v0.4.0-rc3', 'v0.4.0-rc2', 'v0.4.0-rc1', 'v0.3.11', 'v0.3.10', 'v0.3.9', 'v0.3.8', 'v0.3.7', 'v0.3.6', 'v0.3.5', 'v0.3.4', 'v0.3.3', 'v0.3.2', 'v0.3.1', 'v0.3.0', 'v0.3.0-rc4', 'v0.3.0-rc3', 'v0.3.0-rc2', 'v0.3.0-rc1', 'v0.2.0-rc1', 'v0.2.0-rc3', 'v0.2.0-rc4', 'v0.2.0', 'v0.2.0-rc2']
|
* @returns The SHA256 checksum of a given file.
|
||||||
|
*/
|
||||||
|
async function calculateChecksum(file: string): Promise<string> {
|
||||||
|
const hash = crypto.createHash('sha256')
|
||||||
|
const input = fs.createReadStream(file)
|
||||||
|
|
||||||
export async function getJuliaVersion(availableReleases: string[], versionInput: string): Promise<string> {
|
return new Promise((resolve, reject) => {
|
||||||
|
input.on('data', (chunk) => {
|
||||||
|
hash.update(chunk)
|
||||||
|
})
|
||||||
|
|
||||||
|
input.on('end', () => {
|
||||||
|
const digest = hash.digest('hex')
|
||||||
|
digest ? resolve(digest) : reject(new Error(`Could not calculate checksum of file ${file}: digest was empty.`))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns The content of the downloaded versions.json file as object.
|
||||||
|
*/
|
||||||
|
export async function getJuliaVersionInfo(): Promise<object> {
|
||||||
|
const versionsFile = await tc.downloadTool('https://julialang-s3.julialang.org/bin/versions.json')
|
||||||
|
|
||||||
|
return JSON.parse(fs.readFileSync(versionsFile).toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns An array of all Julia versions available for download
|
||||||
|
*/
|
||||||
|
export async function getJuliaVersions(versionInfo): Promise<string[]> {
|
||||||
|
let versions: string[] = []
|
||||||
|
|
||||||
|
for (let version in versionInfo) {
|
||||||
|
versions.push(version)
|
||||||
|
}
|
||||||
|
|
||||||
|
return versions
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getJuliaVersion(availableReleases: string[], versionInput: string): string {
|
||||||
if (semver.valid(versionInput) == versionInput) {
|
if (semver.valid(versionInput) == versionInput) {
|
||||||
// versionInput is a valid version, use it directly
|
// versionInput is a valid version, use it directly
|
||||||
return versionInput
|
return versionInput
|
||||||
@@ -28,7 +79,7 @@ export async function getJuliaVersion(availableReleases: string[], versionInput:
|
|||||||
// Use the highest available version that matches versionInput
|
// Use the highest available version that matches versionInput
|
||||||
let version = semver.maxSatisfying(availableReleases, versionInput)
|
let version = semver.maxSatisfying(availableReleases, versionInput)
|
||||||
if (version == null) {
|
if (version == null) {
|
||||||
throw `Could not find a Julia version that matches ${versionInput}`
|
throw new Error(`Could not find a Julia version that matches ${versionInput}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GitHub tags start with v, remove it
|
// GitHub tags start with v, remove it
|
||||||
@@ -37,93 +88,91 @@ export async function getJuliaVersion(availableReleases: string[], versionInput:
|
|||||||
return version
|
return version
|
||||||
}
|
}
|
||||||
|
|
||||||
function getMajorMinorVersion(version: string): string {
|
function getNightlyFileName(arch: string): string {
|
||||||
return version.split('.').slice(0, 2).join('.')
|
|
||||||
}
|
|
||||||
|
|
||||||
function getDownloadURL(version: string, arch: string): string {
|
|
||||||
let platform: string
|
|
||||||
|
|
||||||
if (osPlat === 'win32') { // Windows
|
|
||||||
platform = 'winnt'
|
|
||||||
} else if (osPlat === 'darwin') { // macOS
|
|
||||||
if (arch == 'x86') {
|
|
||||||
throw '32-bit Julia is not available on macOS'
|
|
||||||
}
|
|
||||||
platform = 'mac'
|
|
||||||
} else if (osPlat === 'linux') { // Linux
|
|
||||||
platform = 'linux'
|
|
||||||
} else {
|
|
||||||
throw `Platform ${osPlat} is not supported`
|
|
||||||
}
|
|
||||||
|
|
||||||
// nightlies
|
|
||||||
if (version == 'nightly') {
|
|
||||||
const baseURL = 'https://julialangnightlies-s3.julialang.org/bin'
|
|
||||||
return `${baseURL}/${platform}/${arch}/${getFileName('latest', arch)}`
|
|
||||||
}
|
|
||||||
|
|
||||||
// normal versions
|
|
||||||
const baseURL = 'https://julialang-s3.julialang.org/bin'
|
|
||||||
const versionDir = getMajorMinorVersion(version)
|
|
||||||
|
|
||||||
return `${baseURL}/${platform}/${arch}/${versionDir}/${getFileName(version, arch)}`
|
|
||||||
}
|
|
||||||
|
|
||||||
function getFileName(version: string, arch: string): string {
|
|
||||||
let versionExt: string, ext: string
|
let versionExt: string, ext: string
|
||||||
|
|
||||||
if (osPlat === 'win32') { // Windows
|
if (osPlat == 'win32') {
|
||||||
versionExt = arch == 'x64' ? '-win64' : '-win32'
|
versionExt = arch == 'x64' ? '-win64' : '-win32'
|
||||||
ext = 'exe'
|
ext = 'exe'
|
||||||
} else if (osPlat === 'darwin') { // macOS
|
} else if (osPlat == 'darwin') {
|
||||||
if (arch == 'x86') {
|
if (arch == 'x86') {
|
||||||
throw '32-bit Julia is not available on macOS'
|
throw new Error('32-bit Julia is not available on macOS')
|
||||||
}
|
}
|
||||||
versionExt = '-mac64'
|
versionExt = '-mac64'
|
||||||
ext = 'dmg'
|
ext = 'dmg'
|
||||||
} else if (osPlat === 'linux') { // Linux
|
} else if (osPlat === 'linux') {
|
||||||
if (version == 'latest') { // nightly version
|
versionExt = arch == 'x64' ? '-linux64' : '-linux32'
|
||||||
versionExt = arch == 'x64' ? '-linux64' : '-linux32'
|
|
||||||
} else {
|
|
||||||
versionExt = arch == 'x64' ? '-linux-x86_64' : '-linux-i686'
|
|
||||||
}
|
|
||||||
ext = 'tar.gz'
|
ext = 'tar.gz'
|
||||||
} else {
|
} else {
|
||||||
throw `Platform ${osPlat} is not supported`
|
throw new Error(`Platform ${osPlat} is not supported`)
|
||||||
}
|
}
|
||||||
|
|
||||||
return `julia-${version}${versionExt}.${ext}`
|
return `julia-latest${versionExt}.${ext}`
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function installJulia(version: string, arch: string): Promise<string> {
|
export function getFileInfo(versionInfo, version: string, arch: string) {
|
||||||
|
if (version == 'nightly') {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let file of versionInfo[version].files) {
|
||||||
|
if (file.os == osMap[osPlat] && file.arch == archMap[arch]) {
|
||||||
|
return file
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw `Could not find ${archMap[arch]}/${version} binaries`
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getDownloadURL(fileInfo, version: string, arch: string): string {
|
||||||
|
// nightlies
|
||||||
|
if (version == 'nightly') {
|
||||||
|
const baseURL = 'https://julialangnightlies-s3.julialang.org/bin'
|
||||||
|
return `${baseURL}/${osMap[osPlat]}/${arch}/${getNightlyFileName(arch)}`
|
||||||
|
}
|
||||||
|
|
||||||
|
return fileInfo.url
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function installJulia(versionInfo, version: string, arch: string): Promise<string> {
|
||||||
// Download Julia
|
// Download Julia
|
||||||
const downloadURL = getDownloadURL(version, arch)
|
const fileInfo = getFileInfo(versionInfo, version, arch)
|
||||||
|
const downloadURL = getDownloadURL(fileInfo, version, arch)
|
||||||
core.debug(`downloading Julia from ${downloadURL}`)
|
core.debug(`downloading Julia from ${downloadURL}`)
|
||||||
const juliaDownloadPath = await tc.downloadTool(downloadURL)
|
const juliaDownloadPath = await tc.downloadTool(downloadURL)
|
||||||
|
|
||||||
|
// Verify checksum
|
||||||
|
if (version != 'nightly') {
|
||||||
|
const checkSum = await calculateChecksum(juliaDownloadPath)
|
||||||
|
if (fileInfo.sha256 != checkSum) {
|
||||||
|
throw new Error(`Checksum of downloaded file does not match the expected checksum from versions.json.\nExpected: ${fileInfo.sha256}\nGot: ${checkSum}`)
|
||||||
|
}
|
||||||
|
core.debug(`Checksum of downloaded file matches expected checksum: ${checkSum}`)
|
||||||
|
} else {
|
||||||
|
core.debug('Skipping checksum check for nightly binaries.')
|
||||||
|
}
|
||||||
|
|
||||||
|
const tempInstallDir = fs.mkdtempSync(`julia-${arch}-${version}-`)
|
||||||
|
|
||||||
// Install it
|
// Install it
|
||||||
switch (osPlat) {
|
switch (osPlat) {
|
||||||
case 'linux':
|
case 'linux':
|
||||||
// tc.extractTar doesn't support stripping components, so we have to call tar manually
|
// tc.extractTar doesn't support stripping components, so we have to call tar manually
|
||||||
await exec.exec('mkdir', [`${process.env.HOME}/julia`])
|
await exec.exec('tar', ['xf', juliaDownloadPath, '--strip-components=1', '-C', tempInstallDir])
|
||||||
await exec.exec('tar', ['xf', juliaDownloadPath, '--strip-components=1', '-C', `${process.env.HOME}/julia`])
|
return tempInstallDir
|
||||||
return `${process.env.HOME}/julia`
|
|
||||||
case 'win32':
|
case 'win32':
|
||||||
const juliaInstallationPath = path.join('C:', 'Julia')
|
|
||||||
if (version == 'nightly' || semver.gtr(version, '1.3', {includePrerelease: true})) {
|
if (version == 'nightly' || semver.gtr(version, '1.3', {includePrerelease: true})) {
|
||||||
// The installer changed in 1.4: https://github.com/JuliaLang/julia/blob/ef0c9108b12f3ae177c51037934351ffa703b0b5/NEWS.md#build-system-changes
|
// The installer changed in 1.4: https://github.com/JuliaLang/julia/blob/ef0c9108b12f3ae177c51037934351ffa703b0b5/NEWS.md#build-system-changes
|
||||||
await exec.exec('powershell', ['-Command', `Start-Process -FilePath ${juliaDownloadPath} -ArgumentList "/SILENT /dir=${juliaInstallationPath}" -NoNewWindow -Wait`])
|
await exec.exec('powershell', ['-Command', `Start-Process -FilePath ${juliaDownloadPath} -ArgumentList "/SILENT /dir=${path.join(process.cwd(), tempInstallDir)}" -NoNewWindow -Wait`])
|
||||||
} else {
|
} else {
|
||||||
await exec.exec('powershell', ['-Command', `Start-Process -FilePath ${juliaDownloadPath} -ArgumentList "/S /D=${juliaInstallationPath}" -NoNewWindow -Wait`])
|
await exec.exec('powershell', ['-Command', `Start-Process -FilePath ${juliaDownloadPath} -ArgumentList "/S /D=${path.join(process.cwd(), tempInstallDir)}" -NoNewWindow -Wait`])
|
||||||
}
|
}
|
||||||
return juliaInstallationPath
|
return tempInstallDir
|
||||||
case 'darwin':
|
case 'darwin':
|
||||||
await exec.exec('hdiutil', ['attach', juliaDownloadPath])
|
await exec.exec('hdiutil', ['attach', juliaDownloadPath])
|
||||||
await exec.exec('mkdir', [`${process.env.HOME}/julia`])
|
await exec.exec('/bin/bash', ['-c', `cp -a /Volumes/Julia-*/Julia-*.app/Contents/Resources/julia ${tempInstallDir}`])
|
||||||
await exec.exec('/bin/bash', ['-c', `cp -a /Volumes/Julia-*/Julia-*.app/Contents/Resources/julia ${process.env.HOME}`])
|
return path.join(tempInstallDir, 'julia')
|
||||||
return `${process.env.HOME}/julia`
|
|
||||||
default:
|
default:
|
||||||
throw `Platform ${osPlat} is not supported`
|
throw new Error(`Platform ${osPlat} is not supported`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,16 +2,51 @@ import * as core from '@actions/core'
|
|||||||
import * as exec from '@actions/exec'
|
import * as exec from '@actions/exec'
|
||||||
import * as tc from '@actions/tool-cache'
|
import * as tc from '@actions/tool-cache'
|
||||||
|
|
||||||
|
import * as fs from 'fs'
|
||||||
|
import * as https from 'https'
|
||||||
import * as path from 'path'
|
import * as path from 'path'
|
||||||
|
|
||||||
import * as installer from './installer'
|
import * as installer from './installer'
|
||||||
|
|
||||||
async function run() {
|
async function run() {
|
||||||
try {
|
try {
|
||||||
|
// Debugging info
|
||||||
|
if (core.isDebug()) {
|
||||||
|
// Log Runner IP Address
|
||||||
|
https.get('https://httpbin.julialang.org/ip', resp => {
|
||||||
|
let data = ''
|
||||||
|
|
||||||
|
resp.on('data', chunk => {
|
||||||
|
data += chunk
|
||||||
|
})
|
||||||
|
|
||||||
|
resp.on('end', () => {
|
||||||
|
core.debug(`Runner IP address: ${JSON.parse(data).origin}`)
|
||||||
|
})
|
||||||
|
}).on('error', err => {
|
||||||
|
core.debug(`ERROR: Could not retrieve runner IP: ${err}`)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inputs
|
||||||
const versionInput = core.getInput('version')
|
const versionInput = core.getInput('version')
|
||||||
const arch = core.getInput('arch')
|
const arch = core.getInput('arch')
|
||||||
const availableReleases = installer.juliaVersions
|
|
||||||
const version = await installer.getJuliaVersion(availableReleases, versionInput)
|
// 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.
|
||||||
|
// We _could_ fall back to the default but that means that builds silently do things differently than they're meant to, which
|
||||||
|
// is worse than failing the build.
|
||||||
|
if (!versionInput) {
|
||||||
|
throw new Error('Version input must not be null')
|
||||||
|
}
|
||||||
|
if (!arch) {
|
||||||
|
throw new Error(`Arch input must not be null`)
|
||||||
|
}
|
||||||
|
|
||||||
|
const versionInfo = await installer.getJuliaVersionInfo()
|
||||||
|
const availableReleases = await installer.getJuliaVersions(versionInfo)
|
||||||
|
const version = installer.getJuliaVersion(availableReleases, versionInput)
|
||||||
core.debug(`selected Julia version: ${arch}/${version}`)
|
core.debug(`selected Julia version: ${arch}/${version}`)
|
||||||
|
|
||||||
// Search in cache
|
// Search in cache
|
||||||
@@ -19,18 +54,24 @@ async function run() {
|
|||||||
juliaPath = tc.find('julia', version, arch)
|
juliaPath = tc.find('julia', version, arch)
|
||||||
|
|
||||||
if (!juliaPath) {
|
if (!juliaPath) {
|
||||||
core.debug(`could not find Julia ${version} in cache`)
|
core.debug(`could not find Julia ${arch}/${version} in cache`)
|
||||||
const juliaInstallationPath = await installer.installJulia(version, arch);
|
const juliaInstallationPath = await installer.installJulia(versionInfo, version, arch)
|
||||||
|
|
||||||
// Add it to cache
|
// Add it to cache
|
||||||
juliaPath = await tc.cacheDir(juliaInstallationPath, 'julia', version, arch)
|
juliaPath = await tc.cacheDir(juliaInstallationPath, 'julia', version, arch)
|
||||||
core.debug(`added Julia to cache: ${juliaPath}`)
|
core.debug(`added Julia to cache: ${juliaPath}`)
|
||||||
|
|
||||||
|
// Remove temporary dir
|
||||||
|
fs.rmdirSync(juliaInstallationPath, {recursive: true})
|
||||||
} else {
|
} else {
|
||||||
core.debug(`using cached version of Julia: ${juliaPath}`)
|
core.debug(`using cached version of Julia: ${juliaPath}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add it to PATH
|
// Add it to PATH
|
||||||
core.addPath(path.join(juliaPath, 'bin'))
|
core.addPath(path.join(juliaPath, 'bin'))
|
||||||
|
|
||||||
|
// Set output
|
||||||
|
core.setOutput('julia-bindir', path.join(juliaPath, 'bin'))
|
||||||
|
|
||||||
// Test if Julia has been installed
|
// Test if Julia has been installed
|
||||||
exec.exec('julia', ['--version'])
|
exec.exec('julia', ['--version'])
|
||||||
|
|||||||
Reference in New Issue
Block a user