Compare commits

...

59 Commits
v1.2 ... v1.9.1

Author SHA1 Message Date
Sascha Mann
51f35e7679 Add production dependencies & build 2023-02-09 12:51:42 +01:00
Sascha Mann
029296930b Bump version 2023-02-09 12:50:22 +01:00
Sergio Sánchez Ramírez
294135b6de Include arm64 alias for aarch64 (#134)
This should fix arch lookup in Apple M-series.
2023-02-09 11:49:10 +00:00
Sascha Mann
2f270f0b37 Remove mention of auto-updating versions file (#132)
The workflow to build it is triggered manually as part of the release process now, so this should no longer be an issue and hasn't been one for quite a while.
2023-01-19 11:24:05 -05:00
Sascha Mann
13d92cb7a9 Bump version 2022-12-12 11:46:15 +01:00
Sascha Mann
a7ad2168c4 Add include-all-prereleases input (#127)
fixes #126
2022-12-11 22:03:47 -05:00
Sascha Mann
43c4e31075 Update @actions/core (#125)
* Update @actions/core

* Run npm i
2022-10-13 15:45:44 +02:00
dependabot[bot]
2bfca2816f Bump @actions/core from 1.2.6 to 1.9.1 (#118)
Bumps [@actions/core](https://github.com/actions/toolkit/tree/HEAD/packages/core) from 1.2.6 to 1.9.1.
- [Release notes](https://github.com/actions/toolkit/releases)
- [Changelog](https://github.com/actions/toolkit/blob/main/packages/core/RELEASES.md)
- [Commits](https://github.com/actions/toolkit/commits/HEAD/packages/core)

---
updated-dependencies:
- dependency-name: "@actions/core"
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-12 16:38:20 -04:00
Sascha Mann
87fafcc1ec Bump version 2022-08-10 14:57:53 +02:00
Dilum Aluthge
57ce80e73c macOS: Default to tarball (.tar.gz) if available (#117)
* On macOS, first try to find a tarball (`.tar.gz`) file, but fall back to `.dmg` if we can't find a tarball

* Add an "Example builds" job for Julia 1.2
2022-08-10 14:54:47 +02:00
Sascha Mann
ffea8bb089 Bump version 2022-06-25 09:28:02 +02:00
Dilum Aluthge
3a89763b86 Fix the "default arch" code path with Julia nightly (and add a CI job for that code path) (#115) 2022-06-25 09:26:39 +02:00
Sascha Mann
40f50bc31f Bump version 2022-06-24 14:44:52 +02:00
Dilum Aluthge
8474f0e14d Default to ${{ runner.arch }} instead of to x64 (#114)
* If the user does not specify the `arch` input, default to `${{ runner.arch }}` (instead of defaulting to `x64`)

* Add a CI workflow that tests the default arch (i.e. tests what happens when the user does not specify the `arch` input)
2022-06-24 14:39:02 +02:00
Dilum Aluthge
76f26cb710 Document the architecture synonyms (#113) 2022-06-23 23:04:54 +00:00
Dilum Aluthge
40ab89a96a Allow X64 and X86 as synonyms for x64 and x86, respectively (#108) 2022-06-23 22:26:05 +00:00
Dilum Aluthge
631e68d88a Allow ARM64 as a synonym for aarch64 (#110) 2022-06-23 20:00:43 +02:00
Sascha Mann
a07a9b4c49 Use --legacy-peer-deps to avoid npm bullshit (#112) 2022-06-20 18:34:11 -04:00
Sascha Mann
67db496725 Update default runtime to node16 (#103)
EOL was almost a month ago. Woops.

I don't care about people using an old version of GitHub Enterprise, so I'm not going to annoy every single user of this action with a breaking update like GH did with their core actions. If you're a user of GHE: consider this a breaking update.
2022-05-21 22:10:35 +02:00
Sascha Mann
800ff44572 Bump version 2022-05-21 21:52:30 +02:00
Sascha Mann
6966335537 Add support for aarch64 (#102)
Setting the `arch` input to `aarch64` will install `aarch64` binaries,
intended to be used on aarch64-based self-hosted runners.

Please note that 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.

In a future update, we may choose a default architecture based on the
arch of the runner.

Thanks to @giordano for providing a self-hosted runner for testing.

Co-authored-by: Mosè Giordano <mose@gnu.org>
2022-05-21 21:50:58 +02:00
Sascha Mann
f29cb961e8 Add manual trigger for example builds (#90) 2022-04-28 02:45:33 +00:00
dependabot[bot]
b69122e25a Bump ajv from 6.12.0 to 6.12.6 (#93)
Bumps [ajv](https://github.com/ajv-validator/ajv) from 6.12.0 to 6.12.6.
- [Release notes](https://github.com/ajv-validator/ajv/releases)
- [Commits](https://github.com/ajv-validator/ajv/compare/v6.12.0...v6.12.6)

---
updated-dependencies:
- dependency-name: ajv
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-13 08:52:40 +01:00
dependabot[bot]
1777cc3f15 Bump ws from 5.2.2 to 5.2.3 (#97)
Bumps [ws](https://github.com/websockets/ws) from 5.2.2 to 5.2.3.
- [Release notes](https://github.com/websockets/ws/releases)
- [Commits](https://github.com/websockets/ws/compare/5.2.2...5.2.3)

---
updated-dependencies:
- dependency-name: ws
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-12 22:28:15 +01:00
Sascha Mann
2bb1080a55 Use 1.8-nightly in scheduled tests (#94) 2022-03-12 19:19:06 +01:00
Chris de Graaf
2d69597029 Throw an informative error for non-existent version (#86)
* Throw an informative error for non-existent version

* npm install && npm run build
2021-08-05 16:36:30 +02:00
Sascha Mann
f577b7c336 Use 1.7-nightly in scheduled test builds (#83) 2021-06-27 01:50:21 +02:00
Fons van der Plas
a12d4d2f6d Update README.md (#82) 2021-06-23 04:11:58 -04:00
dependabot[bot]
3dcf5f495f Bump hosted-git-info from 2.8.8 to 2.8.9 (#81)
Bumps [hosted-git-info](https://github.com/npm/hosted-git-info) from 2.8.8 to 2.8.9.
- [Release notes](https://github.com/npm/hosted-git-info/releases)
- [Changelog](https://github.com/npm/hosted-git-info/blob/v2.8.9/CHANGELOG.md)
- [Commits](https://github.com/npm/hosted-git-info/compare/v2.8.8...v2.8.9)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-05-10 14:38:38 +02:00
dependabot[bot]
f473b6b037 Bump lodash from 4.17.19 to 4.17.21 (#80)
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.19 to 4.17.21.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.19...4.17.21)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-05-10 10:02:29 +02:00
dependabot-preview[bot]
afa5e14af0 Upgrade to GitHub-native Dependabot (#79)
Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2021-04-29 15:05:30 -04:00
dependabot-preview[bot]
01d5d7138b [Security] Bump y18n from 4.0.0 to 4.0.1 (#78) 2021-03-29 18:51:03 +00:00
Sascha Mann
6fd5c3fbaf Only allow download URLs pointing at the official S3 URL (#71)
fixes #52
2021-01-13 05:18:46 -05:00
Sascha Mann
d57803fb22 Retry if download fails for any reason (#70)
fixes #35
2021-01-13 10:03:56 +00:00
Sascha Mann
e11d58a9c2 Change show-versioninfo to always print full info for nightlies (#68)
Co-authored-by: Derk-Jan Karrenbeld <derk-jan+github@karrenbeld.info>
2021-01-13 09:35:46 +00:00
Sascha Mann
6c3c1efae0 Bump version 2021-01-08 11:12:56 +01:00
Sascha Mann
531b2e0973 Support release nightlies (#63)
* Support release nightlies

See #62

* Replace == nightly with endsWith nightly

* Use majorMinorMatch, not full match

* Replace more (in-)equality checks

* Reduce number of duplicate CI builds

* Add example to docs

* Tidy up nightly conditions
2021-01-07 23:09:50 -05:00
Sascha Mann
66addd1b2f Don't print version twice if show-versioninfo is enabled 2021-01-03 13:42:52 +01:00
Sascha Mann
3ff0592a25 Use --compile=min -O0 flags for versioninfo
Co-authored-by: Mosè Giordano <giordano@users.noreply.github.com>
2021-01-03 13:42:52 +01:00
dependabot-preview[bot]
995385cfd3 Bump bin from 9ceca17 to 31b4b50 (#60)
Bumps [bin](https://github.com/julia-actions/bin) from `9ceca17` to `31b4b50`.
- [Release notes](https://github.com/julia-actions/bin/releases)
- [Commits](9ceca17c9c...31b4b500a3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-12-29 10:37:08 +01:00
Sascha Mann
749cb24407 Add CodeQL badge (#59) 2020-12-26 16:14:35 +01:00
Sascha Mann
2feb9a10bf Set installed Julia version as output (#58)
* Set installed Julia version as output

(fixes #51)

* Bump version
2020-12-26 15:35:42 +01:00
Sascha Mann
47fa78221c Improve docs (#57)
* Move versioninfo section and update ToC

* Add docs for in- and outputs to README

Inspired by actions/checkout docs
2020-12-26 15:29:46 +01:00
Sascha Mann
cc05ac4a7c Add automated backup workflow (#56) 2020-12-19 13:28:43 +01:00
Sascha Mann
6d01ffa228 [CI] Add CodeQL checks (#55) 2020-12-17 13:41:13 +01:00
Sascha Mann
94342fa38e Make the @julia-actions/reviewers the global code owners for this repo 2020-12-14 14:35:47 +01:00
Tim Holy
5fea736568 Add show-versioninfo to README (#54)
https://github.com/julia-actions/setup-julia/issues/51#issuecomment-743167978
2020-12-12 18:04:57 +01:00
dependabot-preview[bot]
0453d68fd7 [Security] Bump ini from 1.3.5 to 1.3.7 (#53)
Bumps [ini](https://github.com/isaacs/ini) from 1.3.5 to 1.3.7. **This update includes a security fix.**
- [Release notes](https://github.com/isaacs/ini/releases)
- [Commits](https://github.com/isaacs/ini/compare/v1.3.5...v1.3.7)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-12-10 20:13:50 +01:00
Sascha Mann
2bf5fd112f Fix version/sha examples in README 2020-11-16 23:24:14 +01:00
Sascha Mann
405bfcbfbd Release 1.4.1
There are no code changes, this merely updates the README and therefore the Marketplace description
2020-11-09 23:24:45 +01:00
Sascha Mann
b8741b9a13 Update versioning to reflect recent update 2020-11-09 23:23:44 +01:00
Sascha Mann
9956ebe960 Bump version. 2020-11-08 17:17:31 +01:00
Sascha Mann
71b841c6f2 Verify checksums (#49)
Co-authored-by: Derk-Jan Karrenbeld <derk-jan+github@karrenbeld.info>
2020-11-08 17:15:46 +01:00
Sascha Mann
45f46ba622 Get Julia versions from versions.json (#24)
This replaces the hardcoded versions array which will decouple the setup-julia version and the installable Julia versions.
2020-11-08 15:06:21 +01:00
Sascha Mann
c5d801f77b Add security guide to README 2020-10-20 16:07:10 +02:00
Sascha Mann
82b1b42f54 Bump version 2020-10-07 19:17:44 +02:00
dependabot[bot]
3503abc570 Bump @actions/core from 1.2.4 to 1.2.6 (#47)
Bumps [@actions/core](https://github.com/actions/toolkit/tree/HEAD/packages/core) from 1.2.4 to 1.2.6.
- [Release notes](https://github.com/actions/toolkit/releases)
- [Changelog](https://github.com/actions/toolkit/blob/main/packages/core/RELEASES.md)
- [Commits](https://github.com/actions/toolkit/commits/HEAD/packages/core)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-10-01 19:29:31 +02:00
Sascha Mann
def57cde21 Bump version to 1.3.0 2020-09-26 18:24:53 +02:00
Sascha Mann
c639390e13 Handle install directories using tool-cache (#46)
* Make test builds more verbose

* Handle install directories using tool-cache

* Bump version to 1.3.0-DEV
2020-09-26 18:20:43 +02:00
24 changed files with 22024 additions and 267 deletions

1
.github/CODEOWNERS vendored Normal file
View File

@@ -0,0 +1 @@
* @julia-actions/reviewers

7
.github/dependabot.yml vendored Normal file
View File

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

34
.github/workflows/backup.yml vendored Normal file
View File

@@ -0,0 +1,34 @@
name: Backup
on:
schedule:
- cron: '5 4 * * 0'
workflow_dispatch:
jobs:
backup:
runs-on: ubuntu-20.04
timeout-minutes: 60
steps:
- name: Configure cache
uses: actions/cache@v2
with:
path: |
${{ env.GITHUB_WORKSPACE }}
~/.cache/restic
key: ${{ runner.os }}
- name: Install the correct Python version
uses: actions/setup-python@v2
with:
python-version: '3.x'
- name: Run backup action
uses: julia-actions/restic-action@main
env: # Options: https://restic.readthedocs.io/en/latest/040_backup.html#environment-variables
RESTIC_REPOSITORY: b2:${{ secrets.B2_BUCKET }}:${{ github.repository }}
RESTIC_PASSWORD: ${{ secrets.RESTIC_PASSWORD }}
B2_ACCOUNT_ID: ${{ secrets.B2_ACCOUNT_ID }}
B2_ACCOUNT_KEY: ${{ secrets.B2_ACCOUNT_KEY }}

View File

@@ -1,14 +1,21 @@
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
run: npm ci --legacy-peer-deps
- name: "npm run build"
run: npm run build

74
.github/workflows/codeql-analysis.yml vendored Normal file
View File

@@ -0,0 +1,74 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
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/* ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ master ]
schedule:
- cron: '32 22 * * 6'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
language: [ 'javascript' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
# Learn more:
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
steps:
- name: Checkout repository
uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

View File

@@ -0,0 +1,40 @@
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

@@ -0,0 +1,38 @@
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,7 +1,14 @@
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/*']
pull_request:
schedule:
- cron: '37 17 * * *'
@@ -9,28 +16,31 @@ on:
jobs:
test:
runs-on: ${{ matrix.os }}
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
julia-version: [nightly, 1.8-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
npm install --legacy-peer-deps
npm run build
npm run pack
- name: "Set up Julia (nightly)"
- name: "Set up Julia (${{ matrix.julia-version }})"
uses: ./
with:
version: nightly
version: ${{ matrix.julia-version }}
arch: ${{ matrix.julia-arch }}
- run: julia --version
- run: julia --compile=min -O0 -e 'import InteractiveUtils; InteractiveUtils.versioninfo()'

View File

@@ -1,33 +1,46 @@
name: Example builds
on: [push, pull_request]
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.0.5', '1', '^1.5.0-beta1']
julia-version: ['1.0.5', '1.2', '^1.5.0-beta1', '1']
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
npm install --legacy-peer-deps
npm run build
npm run pack
- name: "Set up Julia"
id: setup-julia
uses: ./
with:
version: ${{ matrix.julia-version }}
arch: ${{ matrix.julia-arch }}
- run: julia --version
- run: julia --compile=min -O0 -e 'import InteractiveUtils; InteractiveUtils.versioninfo()'

2
.gitignore vendored
View File

@@ -1,3 +1,3 @@
node_modules/
__tests__/runner/*
dist/
!dist/

133
README.md
View File

@@ -1,5 +1,6 @@
# setup-julia Action
[![CodeQL](https://github.com/julia-actions/setup-julia/workflows/CodeQL/badge.svg)](https://securitylab.github.com/tools/codeql)
[![Dependabot Status](https://api.dependabot.com/badges/status?host=github&repo=julia-actions/setup-julia)](https://dependabot.com)
This action sets up a Julia environment for use in actions by downloading a specified version of Julia and adding it to PATH.
@@ -7,18 +8,80 @@ This action sets up a Julia environment for use in actions by downloading a spec
## Table of Contents
- [Table of Contents](#table-of-contents)
- [Usage](#usage)
- [Inputs](#inputs)
- [Outputs](#outputs)
- [Basic](#basic)
- [Julia Versions](#julia-versions)
- [Matrix Testing](#matrix-testing)
- [versioninfo](#versioninfo)
- [Versioning](#versioning)
- [Debug logs](#debug-logs)
- [Third party information](#third-party-information)
## Usage
See [action.yml](action.yml).
### Inputs
You can find a list of example workflows making use of this action here: [julia-actions/example-workflows](https://github.com/julia-actions/example-workflows).
```yaml
- uses: julia-actions/setup-julia@v1
with:
# The Julia version that will be installed and added as `julia` to the PATH.
# See "Julia Versions" below for a list of valid values.
#
# Warning: It is strongly recommended to wrap this value in quotes.
# Otherwise, the YAML parser used by GitHub Actions parses certain
# versions as numbers which causes the wrong version to be selected.
# For example, `1.0` may be parsed as `1`.
#
# Default: '1'
version: ''
# 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 | 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.
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
#
# Default: false
show-versioninfo: ''
```
### Outputs
```yaml
outputs:
# The installed Julia version.
# May vary from the version input if a version range was given as input.
#
# Example output: '1.5.3'
julia-version: ''
# Path to the directory containing the Julia executable.
# Equivalent to JULIA_BINDIR: https://docs.julialang.org/en/v1/manual/environment-variables/#JULIA_BINDIR
#
# Example output: '/opt/hostedtoolcache/julia/1.5.3/x64/bin'
julia-bindir: ''
```
### Basic
@@ -35,23 +98,49 @@ steps:
You can either specify specific Julia versions or version ranges. If you specify a version range, the **highest** available Julia version that matches the range will be selected.
**Warning:** It is strongly recommended to wrap versions in quotes. Otherwise, the YAML parser used by GitHub Actions parses certain versions as numbers which causes the wrong version to be selected. For example, `1.0` is parsed as `1`.
**Warning:** It is strongly recommended to wrap versions in quotes. Otherwise, the YAML parser used by GitHub Actions parses certain versions as numbers which causes the wrong version to be selected. For example, `1.0` may be parsed as `1`.
#### 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.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 `< 2.0.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`.
- `^1.3.0-rc1` is a **caret** version range that includes pre-releases of `1.3.0` starting at `rc1`. It matches all versions `≥ 1.3.0-rc1` and `< 2.0.0`.
- `~1.3.0-rc1` is a **tilde** version range that includes pre-releases of `1.3.0` 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 of `1.3.0`. 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 of `1.3.0`. 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.
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
#### Prereleases
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.
There are two methods of including pre-releases in version matching:
1. Including the pre-release tag in the version itself, e.g. `^1.3.0-rc1`.
2. Setting the input `include-all-prereleases` to `true`.
These behave slightly differently.
1. If the version `a.b.c` contains pre-release tag, all pre-releases of version `a.b.c` will be included in the version matching.
For example, `^1.3.0-rc1` would match `1.3.0-rc2` but would **not** match `1.4.0-rc1` once released.
2. If `include-preleases` is set to true, **all** pre-releases of all versions will be included in the version matching. In this case, `^1.3.0-rc1` would match `1.4.0-rc1` once released.
**Example:** Without `include-all-prereleases: true`, the version `^1.3.0-rc1` would match `1.3.0-rc1`, `1.3.0-rc2`, `1.3.0`, `1.4.0` once they are released.
With `include-all-prereleases: true`, it would match `1.3.0-rc1`, `1.3.0-rc2`, `1.3.0`, `1.4.0-rc1`, `1.4.0`.
If you want to run tests against the latest tagged version, no matter what version that is, you can use
```yaml
- uses: julia-actions/setup-julia@v1
with:
version: '1'
include-all-prereleases: true
```
#### Recently released versions
The available Julia versions are pulled from [`versions.json`](https://julialang-s3.julialang.org/bin/versions.json).
### Matrix Testing
@@ -67,7 +156,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"
@@ -93,7 +182,7 @@ jobs:
exclude:
- os: macOS-latest
julia-arch: x86
steps:
- uses: actions/checkout@v1.0.0
- name: "Set up Julia"
@@ -120,7 +209,7 @@ jobs:
- os: windows-latest
julia-version: ['1.0.4']
julia-arch: x86
steps:
- uses: actions/checkout@v1.0.0
- name: "Set up Julia"
@@ -131,6 +220,16 @@ jobs:
shell: bash
```
### 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.
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.
## Versioning
This action follows [GitHub's advice](https://help.github.com/en/articles/about-actions#versioning-your-action) on versioning actions, with an additional `latest` tag.
@@ -143,13 +242,17 @@ You can specify commits, branches or tags in your workflows as follows:
```yaml
steps:
- uses: julia-actions/setup-julia@6ae948d # commit SHA
- uses: julia-actions/setup-julia@master # branch
- uses: julia-actions/setup-julia@d3ce119a16594ea9e5d7974813970c73b6ab9e94 # commit SHA of the tagged 1.4.1 commit
- 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@v0.1.0 # specific version tag
- uses: julia-actions/setup-julia@v1.4 # minor version tag
- uses: julia-actions/setup-julia@v1.4.1 # specific version tag
```
If your workflow requires access to secrets, you should always pin it to a commit SHA instead of a tag.
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.

File diff suppressed because it is too large Load Diff

121
__tests__/installer.test.ts Normal file
View File

@@ -0,0 +1,121 @@
// 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('include-prereleases', () => {
it('Chooses the highest available version that matches the input including prereleases', () => {
expect(installer.getJuliaVersion(testVersions, '^1.2.0-0', true)).toEqual('1.3.0-rc4')
expect(installer.getJuliaVersion(testVersions, '1', true)).toEqual('1.3.0-rc4')
expect(installer.getJuliaVersion(testVersions, '^1.2.0-0', false)).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())
})
})
})

View File

@@ -1,50 +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('invalid version range (#38)', () => {
it('Throws an error if a version range does not match any available version', () => {
expect(() => {
installer.getJuliaVersion(['v1.5.0-rc1', 'v1.5.0-beta1', 'v1.4.2', 'v1.4.1', 'v1.4.0', 'v1.4.0-rc2', 'v1.4.0-rc1'], '1.6')
}).toThrowError()
})
})
})
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()
})
})
})
})

View File

@@ -5,16 +5,25 @@ inputs:
version:
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 x64.'
include-all-prereleases:
description: 'Include prereleases when matching the Julia version to available versions.'
required: false
default: 'x64'
default: 'false'
arch:
description: 'Architecture of the Julia binaries. Defaults to the architecture of the runner executing the job.'
required: false
default: '${{ runner.arch }}'
show-versioninfo:
description: 'Display InteractiveUtils.versioninfo() after installing'
required: false
default: 'false'
outputs:
julia-version:
description: 'The installed Julia version. May vary from the version input if a version range was given as input.'
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: 'node12'
using: 'node16'
main: 'dist/index.js'
branding:
icon: 'download'

2
bin

Submodule bin updated: 9ceca17c9c...31b4b500a3

7556
dist/index.js vendored Normal file

File diff suppressed because it is too large Load Diff

BIN
dist/unzip vendored Normal file

Binary file not shown.

284
lib/installer.js generated
View File

@@ -18,25 +18,82 @@ 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 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 = {
'win32': 'winnt',
'darwin': 'mac',
'linux': 'linux'
};
const archMap = {
'x86': 'i686',
'x64': 'x86_64',
'aarch64': 'aarch64'
};
// Store information about the environment
const osPlat = os.platform(); // possible values: win32 (Windows), linux (Linux), darwin (macOS)
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.2', 'v1.5.1', 'v1.5.0', 'v1.5.0-rc2', 'v1.5.0-rc1', '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'];
function getJuliaVersion(availableReleases, versionInput) {
if (semver.valid(versionInput) == versionInput) {
// versionInput is a valid version, use it directly
/**
* @returns The SHA256 checksum of a given file.
*/
function calculateChecksum(file) {
return __awaiter(this, void 0, void 0, function* () {
const hash = crypto.createHash('sha256');
const input = fs.createReadStream(file);
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.
*/
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}`);
}
});
return JSON.parse(fs.readFileSync(versionsFile).toString());
});
}
exports.getJuliaVersionInfo = getJuliaVersionInfo;
/**
* @returns An array of all Julia versions available for download
*/
function getJuliaVersions(versionInfo) {
return __awaiter(this, void 0, void 0, function* () {
let versions = [];
for (let version in versionInfo) {
versions.push(version);
}
return versions;
});
}
exports.getJuliaVersions = getJuliaVersions;
function getJuliaVersion(availableReleases, versionInput, includePrerelease = false) {
if (semver.valid(versionInput) == versionInput || versionInput.endsWith('nightly')) {
// versionInput is a valid version or a nightly version, use it directly
return versionInput;
}
// nightlies
if (versionInput == 'nightly') {
return 'nightly';
}
// Use the highest available version that matches versionInput
let version = semver.maxSatisfying(availableReleases, versionInput);
let version = semver.maxSatisfying(availableReleases, versionInput, { includePrerelease });
if (version == null) {
throw new Error(`Could not find a Julia version that matches ${versionInput}`);
}
@@ -45,94 +102,195 @@ function getJuliaVersion(availableReleases, versionInput) {
return version;
}
exports.getJuliaVersion = getJuliaVersion;
function getMajorMinorVersion(version) {
return version.split('.').slice(0, 2).join('.');
}
function getDownloadURL(version, arch) {
let platform;
if (osPlat === 'win32') { // Windows
platform = 'winnt';
function getDesiredFileExts() {
let fileExt1;
let hasFileExt2;
let fileExt2;
if (osPlat == 'win32') {
fileExt1 = 'exe';
hasFileExt2 = false;
fileExt2 = '';
}
else if (osPlat === 'darwin') { // macOS
if (arch == 'x86') {
throw new Error('32-bit Julia is not available on macOS');
}
platform = 'mac';
else if (osPlat == 'darwin') {
fileExt1 = 'tar.gz';
hasFileExt2 = true;
fileExt2 = 'dmg';
}
else if (osPlat === 'linux') { // Linux
platform = 'linux';
else if (osPlat === 'linux') {
fileExt1 = 'tar.gz';
hasFileExt2 = false;
fileExt2 = '';
}
else {
throw new Error(`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)}`;
return [fileExt1, hasFileExt2, fileExt2];
}
function getFileName(version, arch) {
let versionExt, ext;
if (osPlat === 'win32') { // Windows
function getNightlyFileName(arch) {
let versionExt;
let fileExt1;
[fileExt1, ,] = getDesiredFileExts();
if (osPlat == 'win32') {
versionExt = arch == 'x64' ? '-win64' : '-win32';
ext = 'exe';
}
else if (osPlat === 'darwin') { // macOS
else if (osPlat == 'darwin') {
if (arch == 'x86') {
throw new Error('32-bit Julia is not available on macOS');
}
versionExt = '-mac64';
ext = 'dmg';
}
else if (osPlat === 'linux') { // Linux
if (version == 'latest') { // nightly version
versionExt = arch == 'x64' ? '-linux64' : '-linux32';
}
else {
versionExt = arch == 'x64' ? '-linux-x86_64' : '-linux-i686';
}
ext = 'tar.gz';
else if (osPlat === 'linux') {
versionExt = arch == 'x64' ? '-linux64' : '-linux32';
}
else {
throw new Error(`Platform ${osPlat} is not supported`);
}
return `julia-${version}${versionExt}.${ext}`;
return `julia-latest${versionExt}.${fileExt1}`;
}
function installJulia(version, arch) {
function getFileInfo(versionInfo, version, arch) {
const err = `Could not find ${archMap[arch]}/${version} binaries`;
let fileExt1;
let hasFileExt2;
let fileExt2;
[fileExt1, hasFileExt2, fileExt2] = getDesiredFileExts();
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]) {
if (file.extension == fileExt1) {
return file;
}
}
}
if (hasFileExt2) {
core.debug(`Could not find ${fileExt1}; trying to find ${fileExt2} instead`);
for (let file of versionInfo[version].files) {
if (file.os == osMap[osPlat] && file.arch == archMap[arch]) {
if (file.extension == fileExt2) {
return file;
}
}
}
}
throw err;
}
exports.getFileInfo = getFileInfo;
function getDownloadURL(fileInfo, version, arch) {
const baseURL = `https://julialangnightlies-s3.julialang.org/bin/${osMap[osPlat]}/${arch}`;
// release branch nightlies, e.g. 1.6-nightlies should return .../bin/linux/x64/1.6/julia-latest-linux64.tar.gz
const majorMinorMatches = /^(\d*.\d*)-nightly/.exec(version);
if (majorMinorMatches) {
return `${baseURL}/${majorMinorMatches[1]}/${getNightlyFileName(arch)}`;
}
// nightlies
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;
function installJulia(versionInfo, version, arch) {
return __awaiter(this, void 0, void 0, function* () {
// 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}`);
const juliaDownloadPath = yield tc.downloadTool(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}`);
}
});
// Verify checksum
if (!version.endsWith('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
switch (osPlat) {
case 'linux':
// 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', `${process.env.HOME}/julia`]);
return `${process.env.HOME}/julia`;
yield exec.exec('tar', ['xf', juliaDownloadPath, '--strip-components=1', '-C', tempInstallDir]);
return tempInstallDir;
case 'win32':
const juliaInstallationPath = path.join('C:', 'Julia');
if (version == 'nightly' || semver.gtr(version, '1.3', { includePrerelease: true })) {
if (version.endsWith('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
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 {
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':
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 ${process.env.HOME}`]);
return `${process.env.HOME}/julia`;
if (fileInfo !== null && fileInfo.extension == 'dmg') {
core.debug(`Support for .dmg files is deprecated and may be removed in a future release`);
yield exec.exec('hdiutil', ['attach', juliaDownloadPath]);
yield exec.exec('/bin/bash', ['-c', `cp -a /Volumes/Julia-*/Julia-*.app/Contents/Resources/julia ${tempInstallDir}`]);
return path.join(tempInstallDir, 'julia');
}
else {
// tc.extractTar doesn't support stripping components, so we have to call tar manually
yield exec.exec('tar', ['xf', juliaDownloadPath, '--strip-components=1', '-C', tempInstallDir]);
return tempInstallDir;
}
default:
throw new Error(`Platform ${osPlat} is not supported`);
}
});
}
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;

40
lib/setup-julia.js generated
View File

@@ -16,11 +16,20 @@ 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',
'arm64': 'aarch64'
};
function run() {
return __awaiter(this, void 0, void 0, function* () {
try {
@@ -41,7 +50,8 @@ function run() {
}
// Inputs
const versionInput = core.getInput('version');
const arch = core.getInput('arch');
const includePrereleases = core.getInput('include-all-prereleases') == 'true';
const originalArchInput = 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.
@@ -50,33 +60,37 @@ function run() {
if (!versionInput) {
throw new Error('Version input must not be null');
}
if (!arch) {
if (!originalArchInput) {
throw new Error(`Arch input must not be null`);
}
const availableReleases = installer.juliaVersions;
const version = installer.getJuliaVersion(availableReleases, versionInput);
const arch = archSynonyms[originalArchInput];
const versionInfo = yield installer.getJuliaVersionInfo();
const availableReleases = yield installer.getJuliaVersions(versionInfo);
const version = installer.getJuliaVersion(availableReleases, versionInput, includePrereleases);
core.debug(`selected Julia version: ${arch}/${version}`);
core.setOutput('julia-version', version);
// Search in cache
let juliaPath;
juliaPath = tc.find('julia', version, arch);
if (!juliaPath) {
core.debug(`could not find Julia ${version} in cache`);
const juliaInstallationPath = yield installer.installJulia(version, arch);
core.debug(`could not find Julia ${arch}/${version} in cache`);
const juliaInstallationPath = yield installer.installJulia(versionInfo, version, arch);
// Add it to cache
juliaPath = yield tc.cacheDir(juliaInstallationPath, 'julia', version, arch);
core.debug(`added Julia to cache: ${juliaPath}`);
// Remove temporary dir
fs.rmdirSync(juliaInstallationPath, { recursive: true });
}
else {
core.debug(`using cached version of Julia: ${juliaPath}`);
}
// Add it to PATH
core.addPath(path.join(juliaPath, 'bin'));
// Test if Julia has been installed
exec.exec('julia', ['--version']);
// If enabled, also show the full version info
if (core.getInput('show-versioninfo') == 'true') {
exec.exec('julia', ['-e', 'using InteractiveUtils; versioninfo()']);
}
// 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);
}
catch (error) {
core.setFailed(error.message);

8665
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.2.2",
"version": "1.9.1",
"private": true,
"description": "setup Julia action",
"main": "lib/setup-julia.js",
@@ -21,19 +21,22 @@
"author": "Sascha Mann <git@mail.saschamann.eu>",
"license": "MIT",
"dependencies": {
"@actions/core": "^1.2.4",
"@actions/core": "^1.10.0",
"@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",
"@zeit/ncc": "^0.22.0",
"jest": "^24.8.0",
"jest-circus": "^24.7.1",
"nock": "^11.7.2",
"prettier": "^1.17.1",
"ts-jest": "^26.0.0",
"typescript": "^3.5.1"

View File

@@ -2,31 +2,87 @@ import * as core from '@actions/core'
import * as exec from '@actions/exec'
import * as tc from '@actions/tool-cache'
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'
// Translations between actions input and Julia arch names
const osMap = {
'win32': 'winnt',
'darwin': 'mac',
'linux': 'linux'
}
const archMap = {
'x86': 'i686',
'x64': 'x86_64',
'aarch64': 'aarch64'
}
// Store information about the environment
const osPlat = os.platform() // possible values: win32 (Windows), linux (Linux), darwin (macOS)
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.2', 'v1.5.1', 'v1.5.0', 'v1.5.0-rc2', 'v1.5.0-rc1', '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 function getJuliaVersion(availableReleases: string[], versionInput: string): string {
if (semver.valid(versionInput) == versionInput) {
// versionInput is a valid version, use it directly
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> {
// 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}`)
}
})
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, includePrerelease: boolean = false): string {
if (semver.valid(versionInput) == versionInput || versionInput.endsWith('nightly')) {
// versionInput is a valid version or a nightly version, use it directly
return versionInput
}
// nightlies
if (versionInput == 'nightly') {
return 'nightly'
}
// Use the highest available version that matches versionInput
let version = semver.maxSatisfying(availableReleases, versionInput)
let version = semver.maxSatisfying(availableReleases, versionInput, {includePrerelease})
if (version == null) {
throw new Error(`Could not find a Julia version that matches ${versionInput}`)
}
@@ -37,93 +93,204 @@ export function getJuliaVersion(availableReleases: string[], versionInput: strin
return version
}
function getMajorMinorVersion(version: string): string {
return version.split('.').slice(0, 2).join('.')
}
function getDesiredFileExts(): [string, boolean, string] {
let fileExt1: string
let hasFileExt2: boolean
let fileExt2: string
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 new Error('32-bit Julia is not available on macOS')
}
platform = 'mac'
} else if (osPlat === 'linux') { // Linux
platform = 'linux'
if (osPlat == 'win32') {
fileExt1 = 'exe'
hasFileExt2 = false
fileExt2 = ''
} else if (osPlat == 'darwin') {
fileExt1 = 'tar.gz'
hasFileExt2 = true
fileExt2 = 'dmg'
} else if (osPlat === 'linux') {
fileExt1 = 'tar.gz'
hasFileExt2 = false
fileExt2 = ''
} else {
throw new Error(`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)}`
return [fileExt1, hasFileExt2, fileExt2]
}
function getFileName(version: string, arch: string): string {
let versionExt: string, ext: string
function getNightlyFileName(arch: string): string {
let versionExt: string
let fileExt1: string
[fileExt1, , ] = getDesiredFileExts()
if (osPlat === 'win32') { // Windows
if (osPlat == 'win32') {
versionExt = arch == 'x64' ? '-win64' : '-win32'
ext = 'exe'
} else if (osPlat === 'darwin') { // macOS
} else if (osPlat == 'darwin') {
if (arch == 'x86') {
throw new Error('32-bit Julia is not available on macOS')
}
versionExt = '-mac64'
ext = 'dmg'
} else if (osPlat === 'linux') { // Linux
if (version == 'latest') { // nightly version
versionExt = arch == 'x64' ? '-linux64' : '-linux32'
} else {
versionExt = arch == 'x64' ? '-linux-x86_64' : '-linux-i686'
}
ext = 'tar.gz'
} else if (osPlat === 'linux') {
versionExt = arch == 'x64' ? '-linux64' : '-linux32'
} else {
throw new Error(`Platform ${osPlat} is not supported`)
}
return `julia-${version}${versionExt}.${ext}`
return `julia-latest${versionExt}.${fileExt1}`
}
export async function installJulia(version: string, arch: string): Promise<string> {
export function getFileInfo(versionInfo, version: string, arch: string) {
const err = `Could not find ${archMap[arch]}/${version} binaries`
let fileExt1: string
let hasFileExt2: boolean
let fileExt2: string
[fileExt1, hasFileExt2, fileExt2] = getDesiredFileExts()
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]) {
if (file.extension == fileExt1) {
return file
}
}
}
if (hasFileExt2) {
core.debug(`Could not find ${fileExt1}; trying to find ${fileExt2} instead`)
for (let file of versionInfo[version].files) {
if (file.os == osMap[osPlat] && file.arch == archMap[arch]) {
if (file.extension == fileExt2) {
return file
}
}
}
}
throw err
}
export function getDownloadURL(fileInfo, version: string, arch: string): string {
const baseURL = `https://julialangnightlies-s3.julialang.org/bin/${osMap[osPlat]}/${arch}`
// release branch nightlies, e.g. 1.6-nightlies should return .../bin/linux/x64/1.6/julia-latest-linux64.tar.gz
const majorMinorMatches = /^(\d*.\d*)-nightly/.exec(version)
if (majorMinorMatches) {
return `${baseURL}/${majorMinorMatches[1]}/${getNightlyFileName(arch)}`
}
// nightlies
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
}
export async function installJulia(versionInfo, version: string, arch: string): Promise<string> {
// 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}`)
const juliaDownloadPath = await tc.downloadTool(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}`)
}
})
// Verify checksum
if (!version.endsWith('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
switch (osPlat) {
case 'linux':
// 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', `${process.env.HOME}/julia`])
return `${process.env.HOME}/julia`
await exec.exec('tar', ['xf', juliaDownloadPath, '--strip-components=1', '-C', tempInstallDir])
return tempInstallDir
case 'win32':
const juliaInstallationPath = path.join('C:', 'Julia')
if (version == 'nightly' || semver.gtr(version, '1.3', {includePrerelease: true})) {
if (version.endsWith('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
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 {
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':
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 ${process.env.HOME}`])
return `${process.env.HOME}/julia`
if (fileInfo !== null && fileInfo.extension == 'dmg') {
core.debug(`Support for .dmg files is deprecated and may be removed in a future release`)
await exec.exec('hdiutil', ['attach', juliaDownloadPath])
await exec.exec('/bin/bash', ['-c', `cp -a /Volumes/Julia-*/Julia-*.app/Contents/Resources/julia ${tempInstallDir}`])
return path.join(tempInstallDir, 'julia')
} else {
// tc.extractTar doesn't support stripping components, so we have to call tar manually
await exec.exec('tar', ['xf', juliaDownloadPath, '--strip-components=1', '-C', tempInstallDir])
return tempInstallDir
}
default:
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

@@ -2,11 +2,22 @@ import * as core from '@actions/core'
import * as exec from '@actions/exec'
import * as tc from '@actions/tool-cache'
import * as fs from 'fs'
import * as https from 'https'
import * as path from 'path'
import * as installer from './installer'
const archSynonyms = {
'x86': 'x86',
'X86': 'x86',
'x64': 'x64',
'X64': 'x64',
'aarch64': 'aarch64',
'ARM64': 'aarch64',
'arm64': 'aarch64'
}
async function run() {
try {
// Debugging info
@@ -29,7 +40,8 @@ async function run() {
// Inputs
const versionInput = core.getInput('version')
const arch = core.getInput('arch')
const includePrereleases = core.getInput('include-all-prereleases') == 'true'
const originalArchInput = 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 }}`.
@@ -39,39 +51,45 @@ async function run() {
if (!versionInput) {
throw new Error('Version input must not be null')
}
if (!arch) {
if (!originalArchInput) {
throw new Error(`Arch input must not be null`)
}
const availableReleases = installer.juliaVersions
const version = installer.getJuliaVersion(availableReleases, versionInput)
const arch = archSynonyms[originalArchInput]
const versionInfo = await installer.getJuliaVersionInfo()
const availableReleases = await installer.getJuliaVersions(versionInfo)
const version = installer.getJuliaVersion(availableReleases, versionInput, includePrereleases)
core.debug(`selected Julia version: ${arch}/${version}`)
core.setOutput('julia-version', version)
// Search in cache
let juliaPath: string;
juliaPath = tc.find('julia', version, arch)
if (!juliaPath) {
core.debug(`could not find Julia ${version} in cache`)
const juliaInstallationPath = await installer.installJulia(version, arch);
core.debug(`could not find Julia ${arch}/${version} in cache`)
const juliaInstallationPath = await installer.installJulia(versionInfo, version, arch)
// Add it to cache
juliaPath = await tc.cacheDir(juliaInstallationPath, 'julia', version, arch)
core.debug(`added Julia to cache: ${juliaPath}`)
// Remove temporary dir
fs.rmdirSync(juliaInstallationPath, {recursive: true})
} else {
core.debug(`using cached version of Julia: ${juliaPath}`)
}
// Add it to PATH
core.addPath(path.join(juliaPath, 'bin'))
// Test if Julia has been installed
exec.exec('julia', ['--version'])
// If enabled, also show the full version info
if (core.getInput('show-versioninfo') == 'true') {
exec.exec('julia', ['-e', 'using InteractiveUtils; versioninfo()'])
}
// 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')
await installer.showVersionInfo(showVersionInfoInput, version)
} catch (error) {
core.setFailed(error.message)
}