mirror of
https://github.com/julia-actions/setup-julia.git
synced 2026-02-12 19:16:54 +08:00
Compare commits
67 Commits
releases/v
...
ib/force_a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
60d0df7300 | ||
|
|
ab8c34a8eb | ||
|
|
75f97ff30b | ||
|
|
99376169b2 | ||
|
|
946b8945ed | ||
|
|
9ededf8091 | ||
|
|
45280051d6 | ||
|
|
b3ecfef5e8 | ||
|
|
5d51882ecc | ||
|
|
14bdca5404 | ||
|
|
ca8072aa45 | ||
|
|
32e4823075 | ||
|
|
d0db705ab1 | ||
|
|
3e78fcb3ae | ||
|
|
72fa5ed0d6 | ||
|
|
fcde44f420 | ||
|
|
9e20c521eb | ||
|
|
83661cac11 | ||
|
|
68c5d57bec | ||
|
|
1fccbf1fae | ||
|
|
154fe254d8 | ||
|
|
89905e6bd4 | ||
|
|
ef03891851 | ||
|
|
2e147ef522 | ||
|
|
60afaeb367 | ||
|
|
887a1b8574 | ||
|
|
1e6e69ac02 | ||
|
|
2edba243f1 | ||
|
|
e4eeff6f60 | ||
|
|
3094e57881 | ||
|
|
8cc4ff0bf6 | ||
|
|
5c9647d97b | ||
|
|
17468e89a3 | ||
|
|
c861e46bed | ||
|
|
2fa18025fe | ||
|
|
05e75bd682 | ||
|
|
9b79636afc | ||
|
|
0360370b20 | ||
|
|
4e3f1d687a | ||
|
|
1068b5ed3f | ||
|
|
f42f7fb072 | ||
|
|
a06d998188 | ||
|
|
83c1b1f3c9 | ||
|
|
be1659352d | ||
|
|
d6ffb3065b | ||
|
|
95d7bc0174 | ||
|
|
6cb24233ff | ||
|
|
a0a0978e28 | ||
|
|
54be0dc244 | ||
|
|
014c323ee0 | ||
|
|
b83c8a20db | ||
|
|
8c3db01273 | ||
|
|
f8f6acf37c | ||
|
|
f2dfec4deb | ||
|
|
3bc2a872da | ||
|
|
0c4130534d | ||
|
|
5956f5ed17 | ||
|
|
a9e17d5c78 | ||
|
|
f2f2b89a9f | ||
|
|
f9eef78196 | ||
|
|
3511533b57 | ||
|
|
8db9e52340 | ||
|
|
1da1716a18 | ||
|
|
7653693003 | ||
|
|
e1580df3b6 | ||
|
|
ba42af3a54 | ||
|
|
4778d3d0c8 |
15
.github/dependabot.yml
vendored
15
.github/dependabot.yml
vendored
@@ -5,15 +5,30 @@ updates:
|
||||
schedule:
|
||||
interval: monthly
|
||||
open-pull-requests-limit: 99
|
||||
groups:
|
||||
# Group all Git submodules PRs into a single PR:
|
||||
all-gitsubmodule-actions:
|
||||
patterns:
|
||||
- "*"
|
||||
|
||||
- package-ecosystem: 'github-actions'
|
||||
directory: '/'
|
||||
schedule:
|
||||
interval: 'monthly'
|
||||
open-pull-requests-limit: 99
|
||||
groups:
|
||||
# Group all GitHub Actions PRs into a single PR:
|
||||
all-github-actions:
|
||||
patterns:
|
||||
- "*"
|
||||
|
||||
- package-ecosystem: npm
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: monthly
|
||||
open-pull-requests-limit: 99
|
||||
groups:
|
||||
# Group all NPM PRs into a single PR:
|
||||
all-npm-actions:
|
||||
patterns:
|
||||
- "*"
|
||||
|
||||
36
.github/workflows/checkin.yml
vendored
36
.github/workflows/checkin.yml
vendored
@@ -1,36 +0,0 @@
|
||||
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@v4
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.tool-versions'
|
||||
|
||||
- name: "npm ci"
|
||||
run: npm ci
|
||||
|
||||
- name: "npm run build"
|
||||
run: npm run build
|
||||
|
||||
- name: "npm run test"
|
||||
run: npm run test
|
||||
|
||||
- name: "check for uncommitted changes"
|
||||
# Ensure no changes, but ignore node_modules dir since dev/fresh ci deps installed.
|
||||
run: |
|
||||
git diff --exit-code --stat -- . ':!node_modules' \
|
||||
|| (echo "##[error] found changed files after build. please 'npm run build && npm run format'" \
|
||||
"and check in all changes" \
|
||||
&& exit 1)
|
||||
@@ -22,11 +22,9 @@ jobs:
|
||||
os:
|
||||
- ubuntu-latest
|
||||
- windows-latest
|
||||
# - macos-11 # Intel
|
||||
- macos-12 # Intel
|
||||
- macos-13 # Intel
|
||||
- macos-14 # Apple Silicon
|
||||
- macos-latest # Currently Intel, but will probably point to Apple Silicon in the future
|
||||
- macos-latest # Apple Silicon
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
10
.github/workflows/example-builds.yml
vendored
10
.github/workflows/example-builds.yml
vendored
@@ -19,13 +19,21 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
julia-version: ['1.0.5', '1.2', '^1.5.0-beta1', '1', 'lts', 'pre']
|
||||
# include '1.6' here to test info message about lts tag existing
|
||||
julia-version: ['1.0.5', '1.2', '^1.5.0-beta1', '1', '1.6', 'lts', 'pre']
|
||||
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
|
||||
include:
|
||||
- os: macOS-latest
|
||||
julia-arch: aarch64
|
||||
julia-version: 'lts'
|
||||
- os: macOS-latest
|
||||
julia-arch: aarch64
|
||||
julia-version: '1'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
222
.github/workflows/pr_checks.yml
vendored
Normal file
222
.github/workflows/pr_checks.yml
vendored
Normal file
@@ -0,0 +1,222 @@
|
||||
name: PR Checks
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
tags: '*'
|
||||
concurrency:
|
||||
# Skip intermediate builds: all builds except for builds on the `master` branch
|
||||
# Cancel intermediate builds: only pull request builds
|
||||
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.ref != 'refs/heads/master' || github.run_number }}
|
||||
cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }}
|
||||
permissions:
|
||||
contents: read
|
||||
jobs:
|
||||
finalize-pr-checks:
|
||||
if: always() # this line is important to keep the `finalize` job from being marked as skipped; do not change or delete this line
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
needs:
|
||||
- checked-in-files
|
||||
- build
|
||||
- npm-run-test
|
||||
- make-targets
|
||||
- stalecheck-npm-install
|
||||
steps:
|
||||
- run: |
|
||||
echo checked-in-files: ${{ needs.checked-in-files.result }}
|
||||
echo build: ${{ needs.build.result }}
|
||||
echo npm-run-test: ${{ needs.npm-run-test.result }}
|
||||
echo make-targets: ${{ needs.make-targets.result }}
|
||||
echo stalecheck-npm-install: ${{ needs.stalecheck-npm-install.result }}
|
||||
- run: exit 1
|
||||
if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') || contains(needs.*.result, 'skipped') }}
|
||||
checked-in-files:
|
||||
timeout-minutes: 30
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
steps:
|
||||
### Check out the repo:
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
|
||||
with:
|
||||
persist-credentials: false
|
||||
### Cleanall:
|
||||
- run: make cleanall
|
||||
### Install NodeJS
|
||||
# Unix (non-Windows):
|
||||
- uses: asdf-vm/actions/setup@1902764435ca0dd2f3388eea723a4f92a4eb8302
|
||||
if: runner.os != 'Windows'
|
||||
- run: make unix-asdf-install
|
||||
if: runner.os != 'Windows'
|
||||
# Windows:
|
||||
# Windows does not support asdf, so we have to use `actions/setup-node`
|
||||
# to install asdf:
|
||||
- uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b
|
||||
if: runner.os == 'Windows'
|
||||
with:
|
||||
node-version-file: '.tool-versions'
|
||||
### Install the NodeJS packages that we depend on:
|
||||
- run: make install-packages
|
||||
### Print some debugging info:
|
||||
- name: Print the NodeJS version (for debugging)
|
||||
run: |
|
||||
which -a node
|
||||
node --version
|
||||
which -a npm
|
||||
npm --version
|
||||
### Build:
|
||||
- run: make pack
|
||||
### Clean (not cleanall!):
|
||||
- run: make clean
|
||||
### Make sure there are no uncommited changes
|
||||
- uses: julia-actions/setup-julia@5c9647d97b78a5debe5164e9eec09d653d29bd71 # v2.6.1
|
||||
with:
|
||||
version: '1'
|
||||
- run: git --no-pager status
|
||||
- run: git --no-pager diff
|
||||
- run: julia ./ci/check_uncommitted_changes.jl
|
||||
build:
|
||||
timeout-minutes: 30
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
### Check out the repo:
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
|
||||
with:
|
||||
persist-credentials: false
|
||||
### Cleanall:
|
||||
- run: make cleanall
|
||||
### Install NodeJS
|
||||
# Unix (non-Windows):
|
||||
- uses: asdf-vm/actions/setup@1902764435ca0dd2f3388eea723a4f92a4eb8302
|
||||
if: runner.os != 'Windows'
|
||||
- run: make unix-asdf-install
|
||||
if: runner.os != 'Windows'
|
||||
# Windows:
|
||||
# Windows does not support asdf, so we have to use `actions/setup-node`
|
||||
# to install asdf:
|
||||
- uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b
|
||||
if: runner.os == 'Windows'
|
||||
with:
|
||||
node-version-file: '.tool-versions'
|
||||
### Install the NodeJS packages that we depend on:
|
||||
- run: make install-packages
|
||||
### Print some debugging info:
|
||||
- name: Print the NodeJS version (for debugging)
|
||||
run: |
|
||||
which -a node
|
||||
node --version
|
||||
which -a npm
|
||||
npm --version
|
||||
### Build:
|
||||
- run: make build
|
||||
- run: make pack
|
||||
### Make sure some other `make` targets don't bitrot:
|
||||
- name: Run some other `make` targets to ensure that they don't bitrot
|
||||
run: |
|
||||
make clean
|
||||
make cleanall
|
||||
- name: Run all of the "cleaning" `make` targets to ensure that they don't bitrot
|
||||
run: |
|
||||
make clean
|
||||
make cleanall
|
||||
npm-run-test:
|
||||
timeout-minutes: 30
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
### Check out the repo:
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
|
||||
with:
|
||||
persist-credentials: false
|
||||
### Cleanall:
|
||||
- run: make cleanall
|
||||
### Install NodeJS
|
||||
# Unix (non-Windows):
|
||||
- uses: asdf-vm/actions/setup@1902764435ca0dd2f3388eea723a4f92a4eb8302
|
||||
if: runner.os != 'Windows'
|
||||
- run: make unix-asdf-install
|
||||
if: runner.os != 'Windows'
|
||||
# Windows:
|
||||
# Windows does not support asdf, so we have to use `actions/setup-node`
|
||||
# to install asdf:
|
||||
- uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b
|
||||
if: runner.os == 'Windows'
|
||||
with:
|
||||
node-version-file: '.tool-versions'
|
||||
### Install the NodeJS packages that we depend on:
|
||||
- run: make install-packages
|
||||
### Print some debugging info:
|
||||
- name: Print the NodeJS version (for debugging)
|
||||
run: |
|
||||
which -a node
|
||||
node --version
|
||||
which -a npm
|
||||
npm --version
|
||||
### Build:
|
||||
- run: make build
|
||||
- run: make test
|
||||
make-targets: # This is a job to make sure that none of the `make` targets bitrot
|
||||
timeout-minutes: 30
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
### Check out the repo:
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
|
||||
with:
|
||||
persist-credentials: false
|
||||
### Cleanall:
|
||||
- run: make cleanall
|
||||
### Install NodeJS
|
||||
# Unix (non-Windows):
|
||||
- uses: asdf-vm/actions/setup@1902764435ca0dd2f3388eea723a4f92a4eb8302
|
||||
if: runner.os != 'Windows'
|
||||
- run: make unix-asdf-install
|
||||
if: runner.os != 'Windows'
|
||||
### Install the NodeJS packages that we depend on:
|
||||
- run: make install-packages
|
||||
### Make sure some other `make` targets don't bitrot:
|
||||
- name: Run some other `make` targets to ensure that they don't bitrot
|
||||
run: |
|
||||
make unix-asdf-install
|
||||
make install-packages
|
||||
make build
|
||||
make pack
|
||||
make everything-from-scratch
|
||||
- name: Run all of the "cleaning" `make` targets to ensure that they don't bitrot
|
||||
run: |
|
||||
make clean
|
||||
make cleanall
|
||||
stalecheck-npm-install:
|
||||
# In this job, we are basically trying to check if `package-lock.json` is in
|
||||
# sync with `package-lock.json`.
|
||||
#
|
||||
# So, for example, if someone manually edits the `package.json` file, we want
|
||||
# to make sure that the `package-lock.json` file is not out of sync with the
|
||||
# `package.json` file.
|
||||
timeout-minutes: 30
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
steps:
|
||||
### Check out the repo:
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
|
||||
with:
|
||||
persist-credentials: false
|
||||
### Install NodeJS
|
||||
# Unix (non-Windows):
|
||||
- uses: asdf-vm/actions/setup@1902764435ca0dd2f3388eea723a4f92a4eb8302
|
||||
if: runner.os != 'Windows'
|
||||
- run: make unix-asdf-install
|
||||
if: runner.os != 'Windows'
|
||||
### Run the master commands for this job:
|
||||
- run: make clean
|
||||
- run: npm ci
|
||||
# - run: npm install --package-lock-only
|
||||
- run: npm install
|
||||
### Make sure there are no uncommited changes
|
||||
- uses: julia-actions/setup-julia@5c9647d97b78a5debe5164e9eec09d653d29bd71 # v2.6.1
|
||||
with:
|
||||
version: '1'
|
||||
- run: git --no-pager status
|
||||
- run: git --no-pager diff
|
||||
- run: julia ./ci/check_uncommitted_changes.jl
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,3 +1,2 @@
|
||||
node_modules/
|
||||
__tests__/runner/*
|
||||
dist/
|
||||
|
||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -1,3 +0,0 @@
|
||||
[submodule "bin"]
|
||||
path = bin
|
||||
url = git@github.com:julia-actions/bin.git
|
||||
|
||||
49
Makefile
Normal file
49
Makefile
Normal file
@@ -0,0 +1,49 @@
|
||||
.NOTPARALLEL:
|
||||
|
||||
# This is the default target:
|
||||
.PHONY: pack
|
||||
pack: build
|
||||
npm run pack
|
||||
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
.PHONY: everything-from-scratch
|
||||
everything-from-scratch: cleanall install-packages build pack clean
|
||||
|
||||
# build does `npm run build`, but does not run `npm run pack`
|
||||
.PHONY: build
|
||||
build:
|
||||
npm run build
|
||||
|
||||
.PHONY: test
|
||||
test:
|
||||
npm run test
|
||||
|
||||
.PHONY: install-packages
|
||||
install-packages:
|
||||
rm -rf node_modules/
|
||||
# Note: we use `npm ci` instead of `npm install`, because we want to make sure
|
||||
# that we respect the versions in the `package-lock.json` lockfile.
|
||||
npm ci
|
||||
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf node_modules/
|
||||
|
||||
.PHONY: cleanall
|
||||
cleanall: clean
|
||||
rm -rf lib/
|
||||
rm -rf dist/
|
||||
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
# asdf does not support Windows.
|
||||
# On Windows, users need to install the correct version of NodeJS themselves.
|
||||
.PHONY: unix-asdf-install
|
||||
unix-asdf-install:
|
||||
asdf plugin add nodejs # update this list when we add more tools to `.tool-versions`
|
||||
asdf install
|
||||
|
||||
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
71
README.md
71
README.md
@@ -5,17 +5,25 @@
|
||||
This action sets up a Julia environment for use in actions by downloading a specified version of Julia and adding it to PATH.
|
||||
|
||||
## 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)
|
||||
- [setup-julia Action](#setup-julia-action)
|
||||
- [Table of Contents](#table-of-contents)
|
||||
- [Usage](#usage)
|
||||
- [Inputs](#inputs)
|
||||
- [Outputs](#outputs)
|
||||
- [Basic](#basic)
|
||||
- [Julia Versions](#julia-versions)
|
||||
- [Examples](#examples)
|
||||
- [Prereleases](#prereleases)
|
||||
- [Recently released versions](#recently-released-versions)
|
||||
- [Matrix Testing](#matrix-testing)
|
||||
- [64-bit Julia only](#64-bit-julia-only)
|
||||
- [32-bit Julia](#32-bit-julia)
|
||||
- [versioninfo](#versioninfo)
|
||||
- [Versioning](#versioning)
|
||||
- [Using Dependabot version updates to keep your GitHub Actions up to date](#using-dependabot-version-updates-to-keep-your-github-actions-up-to-date)
|
||||
- [Debug logs](#debug-logs)
|
||||
- [Third party information](#third-party-information)
|
||||
- [Contributing to this repo](#contributing-to-this-repo)
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -30,10 +38,10 @@ This action sets up a Julia environment for use in actions by downloading a spec
|
||||
# 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`.
|
||||
# For example, `1.10` may be parsed as `1.1`.
|
||||
#
|
||||
# Default: '1'
|
||||
version: ''
|
||||
version: '1'
|
||||
|
||||
# The architecture of the Julia binaries.
|
||||
#
|
||||
@@ -45,8 +53,20 @@ This action sets up a Julia environment for use in actions by downloading a spec
|
||||
#
|
||||
# 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: ''
|
||||
# Specifying 'default' uses the architecture of the runner executing the job.
|
||||
arch: 'default'
|
||||
|
||||
# Force the use of the specified architecture even when it may be suboptimal on the runner.
|
||||
#
|
||||
# By default, requesting x86 or x64 on an aarch64 macOS runner (Apple Silicon) will fail with an error,
|
||||
# as this is usually a misconfiguration. Set this to 'true' to override the error and allow the installation.
|
||||
#
|
||||
# Note: x64 Julia can run on Apple Silicon via Rosetta 2, but native aarch64 is typically preferred.
|
||||
#
|
||||
# Supported values: true | false
|
||||
#
|
||||
# Default: false
|
||||
force-arch: 'false'
|
||||
|
||||
# Set the display setting for printing InteractiveUtils.versioninfo() after installing.
|
||||
#
|
||||
@@ -62,7 +82,12 @@ This action sets up a Julia environment for use in actions by downloading a spec
|
||||
# never: Never print versioninfo
|
||||
#
|
||||
# Default: false
|
||||
show-versioninfo: ''
|
||||
show-versioninfo: 'false'
|
||||
|
||||
# Set the path to the project directory or file to use when resolving some versions (e.g. `min`).
|
||||
#
|
||||
# Defaults to using JULIA_PROJECT if defined, otherwise '.'
|
||||
project: ${{ env.JULIA_PROJECT }} or '.' (if JULIA_PROJECT is unset)
|
||||
```
|
||||
|
||||
### Outputs
|
||||
@@ -109,10 +134,12 @@ You can either specify specific Julia versions or version ranges. If you specify
|
||||
- `'~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`.
|
||||
- `'1'` will install the latest v1 version of Julia.
|
||||
- `'lts'` will install the latest LTS build.
|
||||
- `'pre'` will install the latest prerelease build.
|
||||
- `'pre'` will install the latest prerelease build (RCs, betas, and alphas).
|
||||
- `'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.
|
||||
- `'min'` will install the earliest supported version of Julia compatible with the project. Especially useful in monorepos.
|
||||
|
||||
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).
|
||||
|
||||
@@ -179,12 +206,18 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
julia-version: ['1.0', '1.2.0', '^1.3.0-rc1']
|
||||
julia-arch: [x64, x86]
|
||||
julia-arch: [x64, x86, aarch64]
|
||||
os: [ubuntu-latest, windows-latest, macOS-latest]
|
||||
# 32-bit Julia binaries are not available on macOS
|
||||
# exclude unavailable/unwanted architectures
|
||||
exclude:
|
||||
- os: macOS-latest
|
||||
julia-arch: x86
|
||||
- os: macOS-latest
|
||||
julia-arch: x64 # can be run but via rosetta on apple silicon runners
|
||||
- os: ubuntu-latest
|
||||
julia-arch: aarch64
|
||||
- os: windows-latest
|
||||
julia-arch: aarch64
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
0
__tests__/fixtures/PkgA/Project.toml
Normal file
0
__tests__/fixtures/PkgA/Project.toml
Normal file
0
__tests__/fixtures/PkgB/JuliaProject.toml
Normal file
0
__tests__/fixtures/PkgB/JuliaProject.toml
Normal file
0
__tests__/fixtures/PkgC/JuliaProject.toml
Normal file
0
__tests__/fixtures/PkgC/JuliaProject.toml
Normal file
0
__tests__/fixtures/PkgC/Project.toml
Normal file
0
__tests__/fixtures/PkgC/Project.toml
Normal file
File diff suppressed because it is too large
Load Diff
@@ -26,8 +26,8 @@ const testVersions = [
|
||||
'1.7.0', '1.7.0-beta1', '1.7.0-beta2', '1.7.0-beta3', '1.7.0-beta4', '1.7.0-rc1', '1.7.0-rc2', '1.7.0-rc3', '1.7.1', '1.7.2', '1.7.3',
|
||||
'1.8.0', '1.8.0-beta1', '1.8.0-beta2', '1.8.0-beta3', '1.8.0-rc1', '1.8.0-rc2', '1.8.0-rc3', '1.8.0-rc4', '1.8.1', '1.8.2', '1.8.3', '1.8.4', '1.8.5',
|
||||
'1.9.0', '1.9.0-alpha1', '1.9.0-beta1', '1.9.0-beta2', '1.9.0-beta3', '1.9.0-beta4', '1.9.0-rc1', '1.9.0-rc2', '1.9.0-rc3', '1.9.1', '1.9.2', '1.9.3', '1.9.4',
|
||||
'1.10.0', '1.10.0-alpha1', '1.10.0-beta1', '1.10.0-beta2', '1.10.0-beta3', '1.10.0-rc1', '1.10.0-rc2', '1.10.0-rc3', '1.10.1', '1.10.2',
|
||||
'1.11.0-alpha1', '1.11.0-alpha2', '1.11.0-beta1'
|
||||
'1.10.0', '1.10.0-alpha1', '1.10.0-beta1', '1.10.0-beta2', '1.10.0-beta3', '1.10.0-rc1', '1.10.0-rc2', '1.10.0-rc3', '1.10.1', '1.10.2', '1.10.3', '1.10.4', '1.10.5',
|
||||
'1.11.0', '1.11.0-alpha1', '1.11.0-alpha2', '1.11.0-beta1', '1.11.0-beta2', '1.11.0-rc1', '1.11.0-rc2', '1.11.0-rc3', '1.11.0-rc4',
|
||||
]
|
||||
|
||||
const toolDir = path.join(__dirname, 'runner', 'tools')
|
||||
@@ -38,6 +38,135 @@ process.env['RUNNER_TOOL_CACHE'] = toolDir
|
||||
process.env['RUNNER_TEMP'] = tempDir
|
||||
|
||||
import * as installer from '../src/installer'
|
||||
import exp from 'constants'
|
||||
|
||||
describe("getProjectFilePath tests", () => {
|
||||
let orgJuliaProject
|
||||
let orgWorkingDir
|
||||
|
||||
beforeEach(() => {
|
||||
orgJuliaProject = process.env["JULIA_PROJECT"]
|
||||
orgWorkingDir = process.cwd()
|
||||
delete process.env["JULIA_PROJECT"]
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
process.env["JULIA_PROJECT"] = orgJuliaProject
|
||||
process.chdir(orgWorkingDir)
|
||||
})
|
||||
|
||||
it("Can determine project file is missing", () => {
|
||||
expect(() => installer.getProjectFilePath("DNE.toml")).toThrow("Unable to locate project file")
|
||||
expect(() => installer.getProjectFilePath(fixtureDir)).toThrow("Unable to locate project file")
|
||||
expect(() => installer.getProjectFilePath()).toThrow("Unable to locate project file")
|
||||
})
|
||||
|
||||
it('Can determine project file from a directory', () => {
|
||||
expect(installer.getProjectFilePath(path.join(fixtureDir, "PkgA"))).toEqual(path.join(fixtureDir, "PkgA", "Project.toml"))
|
||||
expect(installer.getProjectFilePath(path.join(fixtureDir, "PkgB"))).toEqual(path.join(fixtureDir, "PkgB", "JuliaProject.toml"))
|
||||
})
|
||||
|
||||
it("Prefers using JuliaProject.toml over Project.toml", () => {
|
||||
expect(installer.getProjectFilePath(path.join(fixtureDir, "PkgC"))).toEqual(path.join(fixtureDir, "PkgC", "JuliaProject.toml"))
|
||||
})
|
||||
|
||||
it("Can determine project from JULIA_PROJECT", () => {
|
||||
process.env["JULIA_PROJECT"] = path.join(fixtureDir, "PkgA")
|
||||
expect(installer.getProjectFilePath()).toEqual(path.join(fixtureDir, "PkgA", "Project.toml"))
|
||||
})
|
||||
|
||||
it("Can determine project from the current working directory", () => {
|
||||
process.chdir(path.join(fixtureDir, "PkgA"));
|
||||
expect(installer.getProjectFilePath()).toEqual("Project.toml")
|
||||
})
|
||||
|
||||
it("Ignores JULIA_PROJECT when argument is used", () => {
|
||||
process.env["JULIA_PROJECT"] = path.join(fixtureDir, "PkgB")
|
||||
expect(installer.getProjectFilePath(path.join(fixtureDir, "PkgA"))).toEqual(path.join(fixtureDir, "PkgA", "Project.toml"))
|
||||
})
|
||||
})
|
||||
|
||||
describe("validJuliaCompatRange tests", () => {
|
||||
it('Handles default caret specifier', () => {
|
||||
expect(installer.validJuliaCompatRange("1")).toEqual(semver.validRange("^1"))
|
||||
expect(installer.validJuliaCompatRange("1.2")).toEqual(semver.validRange("^1.2"))
|
||||
expect(installer.validJuliaCompatRange("1.2.3")).toEqual(semver.validRange("^1.2.3"))
|
||||
|
||||
// TODO: Pkg.jl currently does not support pre-release entries in compat so ideally this would fail
|
||||
expect(installer.validJuliaCompatRange("1.2.3-rc1")).toEqual(semver.validRange("^1.2.3-rc1"))
|
||||
})
|
||||
|
||||
it('Handle surrounding whitespace', () => {
|
||||
expect(installer.validJuliaCompatRange(" 1")).toEqual(semver.validRange("^1"))
|
||||
expect(installer.validJuliaCompatRange("1 ")).toEqual(semver.validRange("^1"))
|
||||
expect(installer.validJuliaCompatRange(" 1 ")).toEqual(semver.validRange("^1"))
|
||||
})
|
||||
|
||||
it('Handles version ranges with specifiers', () => {
|
||||
expect(installer.validJuliaCompatRange("^1.2.3")).toEqual(semver.validRange("^1.2.3"))
|
||||
expect(installer.validJuliaCompatRange("~1.2.3")).toEqual(semver.validRange("~1.2.3"))
|
||||
expect(installer.validJuliaCompatRange("=1.2.3")).toEqual(semver.validRange("=1.2.3"))
|
||||
expect(installer.validJuliaCompatRange(">=1.2.3")).toEqual(">=1.2.3")
|
||||
expect(installer.validJuliaCompatRange("≥1.2.3")).toEqual(">=1.2.3")
|
||||
expect(installer.validJuliaCompatRange("<1.2.3")).toEqual("<1.2.3")
|
||||
})
|
||||
|
||||
it('Handles whitespace after specifiers', () => {
|
||||
expect(installer.validJuliaCompatRange("^ 1.2.3")).toBeNull()
|
||||
expect(installer.validJuliaCompatRange("~ 1.2.3")).toBeNull()
|
||||
expect(installer.validJuliaCompatRange("= 1.2.3")).toBeNull()
|
||||
expect(installer.validJuliaCompatRange(">= 1.2.3")).toEqual(">=1.2.3")
|
||||
expect(installer.validJuliaCompatRange("≥ 1.2.3")).toEqual(">=1.2.3")
|
||||
expect(installer.validJuliaCompatRange("< 1.2.3")).toEqual("<1.2.3")
|
||||
})
|
||||
|
||||
it('Handles hypen ranges', () => {
|
||||
expect(installer.validJuliaCompatRange("1.2.3 - 4.5.6")).toEqual(semver.validRange("1.2.3 - 4.5.6"))
|
||||
expect(installer.validJuliaCompatRange("1.2.3-rc1 - 4.5.6")).toEqual(semver.validRange("1.2.3-rc1 - 4.5.6"))
|
||||
expect(installer.validJuliaCompatRange("1.2.3-rc1-4.5.6")).toEqual(semver.validRange("^1.2.3-rc1-4.5.6")) // A version number and not a hypen range
|
||||
expect(installer.validJuliaCompatRange("1.2.3-rc1 -4.5.6")).toBeNull()
|
||||
expect(installer.validJuliaCompatRange("1.2.3-rc1- 4.5.6")).toBeNull() // Whitespace separate version ranges
|
||||
})
|
||||
|
||||
it("Returns null AND operator on version ranges", () => {
|
||||
expect(installer.validJuliaCompatRange("")).toBeNull()
|
||||
expect(installer.validJuliaCompatRange("1 2 3")).toBeNull()
|
||||
expect(installer.validJuliaCompatRange("1- 2")).toBeNull()
|
||||
expect(installer.validJuliaCompatRange("<1 <1")).toBeNull()
|
||||
expect(installer.validJuliaCompatRange("< 1 < 1")).toBeNull()
|
||||
expect(installer.validJuliaCompatRange("< 1 < 1")).toBeNull()
|
||||
})
|
||||
|
||||
it('Returns null with invalid specifiers', () => {
|
||||
expect(installer.validJuliaCompatRange("<=1.2.3")).toBeNull()
|
||||
expect(installer.validJuliaCompatRange("≤1.2.3")).toBeNull()
|
||||
expect(installer.validJuliaCompatRange("*")).toBeNull()
|
||||
})
|
||||
|
||||
it("Handles OR operator on version ranges", () => {
|
||||
expect(installer.validJuliaCompatRange("1, 2, 3")).toEqual(semver.validRange("^1 || ^2 || ^3"))
|
||||
expect(installer.validJuliaCompatRange("1, 2 - 3, ≥ 4")).toEqual(semver.validRange("^1 || >=2 <=3 || >=4"))
|
||||
expect(installer.validJuliaCompatRange(",")).toBeNull()
|
||||
})
|
||||
})
|
||||
|
||||
describe("readJuliaCompatRange tests", () => {
|
||||
it('Can determine Julia compat entries', () => {
|
||||
const toml = '[compat]\njulia = "1, ^1.1, ~1.2, >=1.3, 1.4 - 1.5"'
|
||||
expect(installer.readJuliaCompatRange(toml)).toEqual(semver.validRange("^1 || ^1.1 || ~1.2 || >=1.3 || 1.4 - 1.5"))
|
||||
})
|
||||
|
||||
it('Throws with invalid version ranges', () => {
|
||||
expect(() => installer.readJuliaCompatRange('[compat]\njulia = ""')).toThrow("Invalid version range")
|
||||
expect(() => installer.readJuliaCompatRange('[compat]\njulia = "1 2 3"')).toThrow("Invalid version range")
|
||||
})
|
||||
|
||||
it('Handle missing compat entries', () => {
|
||||
expect(installer.readJuliaCompatRange("")).toEqual("*")
|
||||
expect(installer.readJuliaCompatRange("[compat]")).toEqual("*")
|
||||
|
||||
})
|
||||
})
|
||||
|
||||
describe('version matching tests', () => {
|
||||
describe('specific versions', () => {
|
||||
@@ -58,30 +187,30 @@ describe('version matching tests', () => {
|
||||
|
||||
it('LTS', () => {
|
||||
// Update test when LTS is updated
|
||||
expect(installer.getJuliaVersion(testVersions, 'lts')).toEqual(installer.getJuliaVersion(testVersions, '1.6'))
|
||||
expect(installer.getJuliaVersion(testVersions, 'lts')).toEqual('1.6.7')
|
||||
expect(installer.getJuliaVersion(testVersions, 'lts')).toEqual(installer.getJuliaVersion(testVersions, '1.10'))
|
||||
expect(installer.getJuliaVersion(testVersions, 'lts')).toEqual('1.10.5')
|
||||
})
|
||||
|
||||
it('pre', () => {
|
||||
expect(installer.getJuliaVersion(testVersions, 'pre')).toEqual('1.11.0-beta1')
|
||||
expect(installer.getJuliaVersion(testVersions, 'pre')).toEqual('1.11.0')
|
||||
})
|
||||
})
|
||||
|
||||
describe('version ranges', () => {
|
||||
it('Chooses the highest available version that matches the input', () => {
|
||||
expect(installer.getJuliaVersion(testVersions, '1')).toEqual('1.10.2')
|
||||
expect(installer.getJuliaVersion(testVersions, '1')).toEqual('1.11.0')
|
||||
expect(installer.getJuliaVersion(testVersions, '1.0')).toEqual('1.0.5')
|
||||
expect(installer.getJuliaVersion(testVersions, '^1.3.0-rc1')).toEqual('1.10.2')
|
||||
expect(installer.getJuliaVersion(testVersions, '^1.2.0-rc1')).toEqual('1.10.2')
|
||||
expect(installer.getJuliaVersion(testVersions, '^1.10.0-rc1')).toEqual('1.10.2')
|
||||
expect(installer.getJuliaVersion(testVersions, '^1.3.0-rc1')).toEqual('1.11.0')
|
||||
expect(installer.getJuliaVersion(testVersions, '^1.2.0-rc1')).toEqual('1.11.0')
|
||||
expect(installer.getJuliaVersion(testVersions, '^1.10.0-rc1')).toEqual('1.11.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.11.0-beta1')
|
||||
expect(installer.getJuliaVersion(testVersions, '1', true)).toEqual('1.11.0-beta1')
|
||||
expect(installer.getJuliaVersion(testVersions, '^1.2.0-0', false)).toEqual('1.10.2')
|
||||
expect(installer.getJuliaVersion(testVersions, '^1.2.0-0', true)).toEqual('1.11.0')
|
||||
expect(installer.getJuliaVersion(testVersions, '1', true)).toEqual('1.11.0')
|
||||
expect(installer.getJuliaVersion(testVersions, '^1.2.0-0', false)).toEqual('1.11.0')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -95,6 +224,34 @@ describe('version matching tests', () => {
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('julia compat versions', () => {
|
||||
it('Understands "min"', () => {
|
||||
let versions = ["1.6.7", "1.7.1-rc1", "1.7.1-rc2", "1.7.1", "1.7.2", "1.8.0"]
|
||||
expect(installer.getJuliaVersion(versions, "min", false, "^1.7")).toEqual("1.7.1")
|
||||
expect(installer.getJuliaVersion(versions, "min", true, "^1.7")).toEqual("1.7.1-rc1")
|
||||
|
||||
versions = ["1.6.7", "1.7.3-rc1", "1.7.3-rc2", "1.8.0"]
|
||||
expect(installer.getJuliaVersion(versions, "min", false, "^1.7")).toEqual("1.8.0")
|
||||
expect(installer.getJuliaVersion(versions, "min", true, "^1.7")).toEqual("1.7.3-rc1")
|
||||
|
||||
expect(installer.getJuliaVersion(versions, "min", false, "~1.7 || ~1.8 || ~1.9")).toEqual("1.8.0")
|
||||
expect(installer.getJuliaVersion(versions, "min", true, "~1.7 || ~1.8 || ~1.9")).toEqual("1.7.3-rc1")
|
||||
expect(installer.getJuliaVersion(versions, "min", false, "~1.8 || ~1.7 || ~1.9")).toEqual("1.8.0")
|
||||
expect(installer.getJuliaVersion(versions, "min", true, "~1.8 || ~1.7 || ~1.9")).toEqual("1.7.3-rc1")
|
||||
|
||||
expect(installer.getJuliaVersion(versions, "min", false, "1.7 - 1.9")).toEqual("1.8.0")
|
||||
expect(installer.getJuliaVersion(versions, "min", true, "1.7 - 1.9")).toEqual("1.7.3-rc1")
|
||||
|
||||
expect(installer.getJuliaVersion(versions, "min", true, "< 1.9.0")).toEqual("1.6.7")
|
||||
expect(installer.getJuliaVersion(versions, "min", true, ">= 1.6.0")).toEqual("1.6.7")
|
||||
|
||||
// NPM's semver package treats "1.7" as "~1.7" instead of "^1.7" like Julia
|
||||
expect(() => installer.getJuliaVersion(versions, "min", false, "1.7")).toThrow("Could not find a Julia version that matches")
|
||||
|
||||
expect(() => installer.getJuliaVersion(versions, "min", true, "")).toThrow("Julia project file does not specify a compat for Julia")
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('installer tests', () => {
|
||||
|
||||
14
action.yml
14
action.yml
@@ -1,9 +1,9 @@
|
||||
name: 'Setup Julia environment'
|
||||
description: 'Setup a Julia environment and add it to the PATH'
|
||||
author: 'Sascha Mann'
|
||||
inputs:
|
||||
inputs:
|
||||
version:
|
||||
description: 'The Julia version to download (if necessary) and use. Example: 1.0.4'
|
||||
description: 'The Julia version to download (if necessary) and use. Use a string input to avoid unwanted decimal conversion e.g. 1.10 without quotes will be interpreted as 1.1. Examples: "1", "1.10", "lts", "pre"'
|
||||
default: '1'
|
||||
include-all-prereleases:
|
||||
description: 'Include prereleases when matching the Julia version to available versions.'
|
||||
@@ -12,11 +12,19 @@ inputs:
|
||||
arch:
|
||||
description: 'Architecture of the Julia binaries. Defaults to the architecture of the runner executing the job.'
|
||||
required: false
|
||||
default: '${{ runner.arch }}'
|
||||
default: 'default'
|
||||
force-arch:
|
||||
description: 'Force the use of the specified architecture even when it may be suboptimal on the runner (e.g., x86 on Apple Silicon macOS runners). By default, requesting x86/x64 on aarch64 macOS runners will fail with an error.'
|
||||
required: false
|
||||
default: 'false'
|
||||
show-versioninfo:
|
||||
description: 'Display InteractiveUtils.versioninfo() after installing'
|
||||
required: false
|
||||
default: 'false'
|
||||
project:
|
||||
description: 'The path to the project directory or file to use when resolving some versions (e.g. min)'
|
||||
required: false
|
||||
default: '' # Special value which fallsback to using JULIA_PROJECT if defined, otherwise "."
|
||||
outputs:
|
||||
julia-version:
|
||||
description: 'The installed Julia version. May vary from the version input if a version range was given as input.'
|
||||
|
||||
1
bin
1
bin
Submodule bin deleted from 31b4b500a3
16
ci/check_uncommitted_changes.jl
Normal file
16
ci/check_uncommitted_changes.jl
Normal file
@@ -0,0 +1,16 @@
|
||||
const cmd = `git --no-pager diff --exit-code --stat`
|
||||
|
||||
const proc = run(pipeline(cmd; stdin, stdout, stderr); wait = false)
|
||||
|
||||
wait(proc)
|
||||
|
||||
@info "" success(proc) proc.exitcode
|
||||
|
||||
if !success(proc)
|
||||
recommended_cmd = "make everything-from-scratch"
|
||||
msg = "##[error] found changed files after build. " *
|
||||
"Please run `$(recommended_cmd)` and " *
|
||||
"then check in all changes."
|
||||
println(stderr, msg)
|
||||
exit(1)
|
||||
end
|
||||
@@ -42,6 +42,8 @@ First, `cd` to your clone of the repo. Now you can run the following commands:
|
||||
npm ci
|
||||
|
||||
npm run build
|
||||
|
||||
npm run pack
|
||||
```
|
||||
|
||||
When you are ready, you can commit your changes and push them to your PR.
|
||||
|
||||
@@ -1,128 +1,56 @@
|
||||
# Making a new release of this action (requires commit access)
|
||||
|
||||
If you have commit access to this repo, you can make a new release.
|
||||
In this guide, as an example, `v2.2.0` refers to the version number of the new release that you want to make.
|
||||
|
||||
Here are the instructions.
|
||||
## Part 1: Use the Git CLI to create and push the Git tags
|
||||
|
||||
## Step 1: Clone a fresh copy of the repo
|
||||
|
||||
We intentionally work in a brand-new copy of the repo.
|
||||
Step 1: Create a new lightweight tag of the form `vMAJOR.MINOR.PATCH`.
|
||||
|
||||
```bash
|
||||
git clone git@github.com:julia-actions/setup-julia.git
|
||||
cd setup-julia
|
||||
git checkout master
|
||||
git submodule init
|
||||
git submodule update
|
||||
git fetch --all --tags
|
||||
|
||||
git checkout main
|
||||
|
||||
git --no-pager log -1
|
||||
# Take note of the commit hash here.
|
||||
|
||||
# Now, create a new lightweight tag of the form `vMAJOR.MINOR.PATCH`.
|
||||
#
|
||||
# Replace `commit_hash` with the commit hash that you obtained from the
|
||||
# `git log -1` step.
|
||||
#
|
||||
# Replace `v2.2.0` with the actual version number that you want to use.
|
||||
git tag v2.2.0 commit_hash
|
||||
```
|
||||
|
||||
## Step 2: Make sure you have the right version of NodeJS
|
||||
|
||||
If you use [`asdf`](https://asdf-vm.com/), this is as simple as:
|
||||
Step 2: Once you've created the new release, you need to update the `v2` tag to point to the new release. For example, suppose that the previous release was `v2.1.0`, and suppose that you just created the new release `v2.2.0`. You need to update the `v2` tag so that it points to `v2.2.0`. Here are the commands:
|
||||
|
||||
```bash
|
||||
asdf plugin add nodejs
|
||||
asdf install
|
||||
# Create/update the new v2 tag locally, where the new v2 tag will point to the
|
||||
# release that you created in the previous step.
|
||||
#
|
||||
# Make sure to change `v2.2.0` to the actual value for the tag that you just
|
||||
# created in the previous step.
|
||||
#
|
||||
# The `-f` flag forcibly overwrites the old
|
||||
# `v2` tag (if it exists).
|
||||
git tag -f v2 v2.2.0
|
||||
```
|
||||
|
||||
If you don't use `asdf`, then you need to:
|
||||
1. Open the `./tool-versions` file in the root of the repo.
|
||||
2. Make note of the NodeJS version listed in the `.tool-versions` file.
|
||||
3. Install that same version of NodeJS on your machine.
|
||||
4. Make sure that you are currently using that version of NodeJS (i.e. it is at the front of your PATH).
|
||||
|
||||
## Step 3: Edit the `version` field in `package.json`
|
||||
Step 3: Now you need to push the tags:
|
||||
|
||||
```bash
|
||||
vim package.json
|
||||
# Regular-push the new `v2.2.0` tag:
|
||||
git push origin tag v2.2.0
|
||||
|
||||
# Edit the `version` number (should be line 2)
|
||||
# Save your changes in Vim. Then exit Vim.
|
||||
|
||||
# For the remaining of this guide, let MAJOR.MINOR.PATCH refer
|
||||
# to the new version number that you set.
|
||||
|
||||
git add package.json
|
||||
|
||||
# No need to commit yet.
|
||||
# The release script will run `git commit`.
|
||||
# Force-push the new v2 tag:
|
||||
git push origin tag v2 --force
|
||||
```
|
||||
|
||||
## Step 4: Remove the `dist/` line from the `.gitignore` file
|
||||
## Part 2: Create the GitHub Release
|
||||
|
||||
```bash
|
||||
vim .gitignore
|
||||
# Delete the line that says `dist/` (it should be line 3)
|
||||
# Save your changes in Vim. Then exit Vim.
|
||||
Go to the [Releases](https://github.com/julia-actions/setup-julia/releases) section of this repo and create a new release (using the GitHub web interface).
|
||||
|
||||
git add .gitignore
|
||||
|
||||
# No need to commit yet.
|
||||
# The release script will run `git commit`.
|
||||
```
|
||||
|
||||
## Step 5: Make sure you have the necessary dependencies
|
||||
|
||||
The `build-release.sh` script requires the following dependencies:
|
||||
|
||||
1. Bash
|
||||
2. `curl`
|
||||
3. `git`
|
||||
4. `jq`
|
||||
5. `sed`
|
||||
|
||||
## Step 6: Run the `build-release.sh` script
|
||||
|
||||
```bash
|
||||
ls -l bin/build-release.sh
|
||||
chmod +x bin/build-release.sh
|
||||
ls -l bin/build-release.sh
|
||||
|
||||
./bin/build-release.sh julia-actions/setup-julia
|
||||
```
|
||||
|
||||
Wait a minute or two. The script will build everything and will create a new release branch named `releases/vMAJOR.MINOR.PATCH`.
|
||||
|
||||
## Step 7: Push ONLY the `releases/vMAJOR.MINOR.PATCH` branch
|
||||
|
||||
Only push the `releases/` branch. Do NOT push any tags yet.
|
||||
|
||||
```bash
|
||||
git push origin releases/vMAJOR.MINOR.PATCH
|
||||
```
|
||||
|
||||
Now you need to go to https://github.com/julia-actions/setup-julia/tree/releases/vMAJOR.MINOR.PATCH and wait for CI to finish running.
|
||||
|
||||
Do NOT proceed to the next step until CI is all green on the `releases/vMAJOR.MINOR.PATCH` branch.
|
||||
|
||||
## Step 8: Push the tags (only after CI is all green)
|
||||
|
||||
Once CI is all green on the `releases/vMAJOR.MINOR.PATCH` branch, you can push the tags.
|
||||
|
||||
You need to force-push.
|
||||
|
||||
```bash
|
||||
git push --tags --force
|
||||
```
|
||||
|
||||
## Step 9: Use the GitHub web UI to create a new GitHub Release
|
||||
|
||||
Go to https://github.com/julia-actions/setup-julia/releases and create a new release for the now-existant `vMAJOR.MINOR.PATCH` tag using the GitHub web interface.
|
||||
|
||||
## Step 10: Clean up your local repo
|
||||
|
||||
```bash
|
||||
git submodule deinit --force .
|
||||
git submodule update --init
|
||||
git fetch --all --prune
|
||||
git checkout master
|
||||
git reset --hard origin/master
|
||||
```
|
||||
|
||||
## Step 11: Delete your local repo
|
||||
|
||||
```bash
|
||||
cd ..
|
||||
ls setup-julia
|
||||
rm -rf setup-julia
|
||||
```
|
||||
For the "choose a tag" drop-down field, select the `v2.2.0` tag that you created and pushed in Part 1 of this guide.
|
||||
|
||||
37898
dist/index.js
vendored
Normal file
37898
dist/index.js
vendored
Normal file
File diff suppressed because one or more lines are too long
176
lib/installer.js
generated
176
lib/installer.js
generated
@@ -15,13 +15,23 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
var __importStar = (this && this.__importStar) || (function () {
|
||||
var ownKeys = function(o) {
|
||||
ownKeys = Object.getOwnPropertyNames || function (o) {
|
||||
var ar = [];
|
||||
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
||||
return ar;
|
||||
};
|
||||
return ownKeys(o);
|
||||
};
|
||||
return function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
})();
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
@@ -32,7 +42,16 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
||||
});
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.showVersionInfo = exports.installJulia = exports.getDownloadURL = exports.getFileInfo = exports.getJuliaVersion = exports.getJuliaVersions = exports.getJuliaVersionInfo = void 0;
|
||||
exports.getJuliaVersionInfo = getJuliaVersionInfo;
|
||||
exports.getJuliaVersions = getJuliaVersions;
|
||||
exports.getProjectFilePath = getProjectFilePath;
|
||||
exports.validJuliaCompatRange = validJuliaCompatRange;
|
||||
exports.readJuliaCompatRange = readJuliaCompatRange;
|
||||
exports.getJuliaVersion = getJuliaVersion;
|
||||
exports.getFileInfo = getFileInfo;
|
||||
exports.getDownloadURL = getDownloadURL;
|
||||
exports.installJulia = installJulia;
|
||||
exports.showVersionInfo = showVersionInfo;
|
||||
const core = __importStar(require("@actions/core"));
|
||||
const exec = __importStar(require("@actions/exec"));
|
||||
const tc = __importStar(require("@actions/tool-cache"));
|
||||
@@ -42,7 +61,8 @@ const os = __importStar(require("os"));
|
||||
const path = __importStar(require("path"));
|
||||
const retry = require("async-retry");
|
||||
const semver = __importStar(require("semver"));
|
||||
const LTS_VERSION = '1.6';
|
||||
const toml = __importStar(require("toml"));
|
||||
const LTS_VERSION = '1.10';
|
||||
const MAJOR_VERSION = '1'; // Could be deduced from versions.json
|
||||
// Translations between actions input and Julia arch names
|
||||
const osMap = {
|
||||
@@ -94,7 +114,6 @@ function getJuliaVersionInfo() {
|
||||
return JSON.parse(fs.readFileSync(versionsFile).toString());
|
||||
});
|
||||
}
|
||||
exports.getJuliaVersionInfo = getJuliaVersionInfo;
|
||||
/**
|
||||
* @returns An array of all Julia versions available for download
|
||||
*/
|
||||
@@ -107,28 +126,112 @@ function getJuliaVersions(versionInfo) {
|
||||
return versions;
|
||||
});
|
||||
}
|
||||
exports.getJuliaVersions = getJuliaVersions;
|
||||
function getJuliaVersion(availableReleases, versionInput, includePrerelease = false) {
|
||||
/**
|
||||
* @returns The path to the Julia project file
|
||||
*/
|
||||
function getProjectFilePath(projectInput = "") {
|
||||
let projectFilePath = "";
|
||||
// Default value for projectInput
|
||||
if (!projectInput) {
|
||||
projectInput = process.env.JULIA_PROJECT || ".";
|
||||
}
|
||||
if (fs.existsSync(projectInput) && fs.lstatSync(projectInput).isFile()) {
|
||||
projectFilePath = projectInput;
|
||||
}
|
||||
else {
|
||||
for (let projectFilename of ["JuliaProject.toml", "Project.toml"]) {
|
||||
let p = path.join(projectInput, projectFilename);
|
||||
if (fs.existsSync(p) && fs.lstatSync(p).isFile()) {
|
||||
projectFilePath = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!projectFilePath) {
|
||||
throw new Error(`Unable to locate project file with project input: ${projectInput}`);
|
||||
}
|
||||
return projectFilePath;
|
||||
}
|
||||
/**
|
||||
* @returns A valid NPM semver range from a Julia compat range or null if it's not valid
|
||||
*/
|
||||
function validJuliaCompatRange(compatRange) {
|
||||
let ranges = [];
|
||||
for (let range of compatRange.split(",")) {
|
||||
range = range.trim();
|
||||
// An empty range isn't supported by Julia
|
||||
if (!range) {
|
||||
return null;
|
||||
}
|
||||
// NPM's semver doesn't understand unicode characters such as `≥` so we'll convert to alternatives
|
||||
range = range.replace("≥", ">=").replace("≤", "<=");
|
||||
// Cleanup whitespace. Julia only allows whitespace between the specifier and version with certain specifiers
|
||||
range = range.replace(/\s+/g, " ").replace(/(?<=(>|>=|≥|<)) (?=\d)/g, "");
|
||||
if (!semver.validRange(range) || range.split(/(?<! -) (?!- )/).length > 1 || range.startsWith("<=") || range === "*") {
|
||||
return null;
|
||||
}
|
||||
else if (range.search(/^\d/) === 0 && !range.includes(" ")) {
|
||||
// Compat version is just a basic version number (e.g. 1.2.3). Since Julia's Pkg.jl's uses caret
|
||||
// as the default specifier (e.g. `1.2.3 == ^1.2.3`) and NPM's semver uses tilde as the default
|
||||
// specifier (e.g. `1.2.3 == 1.2.x == ~1.2.3`) we will introduce the caret specifier to ensure the
|
||||
// orignal intent is respected.
|
||||
// https://pkgdocs.julialang.org/v1/compatibility/#Version-specifier-format
|
||||
// https://github.com/npm/node-semver#x-ranges-12x-1x-12-
|
||||
range = "^" + range;
|
||||
}
|
||||
ranges.push(range);
|
||||
}
|
||||
return semver.validRange(ranges.join(" || "));
|
||||
}
|
||||
/**
|
||||
* @returns An array of version ranges compatible with the Julia project
|
||||
*/
|
||||
function readJuliaCompatRange(projectFileContent) {
|
||||
var _a;
|
||||
let compatRange;
|
||||
let meta = toml.parse(projectFileContent);
|
||||
if (((_a = meta.compat) === null || _a === void 0 ? void 0 : _a.julia) !== undefined) {
|
||||
compatRange = validJuliaCompatRange(meta.compat.julia);
|
||||
}
|
||||
else {
|
||||
compatRange = "*";
|
||||
}
|
||||
if (!compatRange) {
|
||||
throw new Error(`Invalid version range found in Julia compat: ${compatRange}`);
|
||||
}
|
||||
return compatRange;
|
||||
}
|
||||
function getJuliaVersion(availableReleases, versionInput, includePrerelease = false, juliaCompatRange = "") {
|
||||
// Note: `juliaCompatRange` is ignored unless `versionInput` is `min`
|
||||
let version;
|
||||
if (semver.valid(versionInput) == versionInput || versionInput.endsWith('nightly')) {
|
||||
// versionInput is a valid version or a nightly version, use it directly
|
||||
return versionInput;
|
||||
version = versionInput;
|
||||
}
|
||||
if (versionInput == 'lts') {
|
||||
return getJuliaVersion(availableReleases, LTS_VERSION, false);
|
||||
else if (versionInput == "min") {
|
||||
// Resolve "min" to the minimum supported Julia version compatible with the project file
|
||||
if (!juliaCompatRange) {
|
||||
throw new Error('Unable to use version "min" when the Julia project file does not specify a compat for Julia');
|
||||
}
|
||||
version = semver.minSatisfying(availableReleases, juliaCompatRange, { includePrerelease });
|
||||
}
|
||||
if (versionInput == 'pre') {
|
||||
return getJuliaVersion(availableReleases, MAJOR_VERSION, true);
|
||||
else if (versionInput == "lts") {
|
||||
version = semver.maxSatisfying(availableReleases, LTS_VERSION, { includePrerelease: false });
|
||||
}
|
||||
// Use the highest available version that matches versionInput
|
||||
let version = semver.maxSatisfying(availableReleases, versionInput, { includePrerelease });
|
||||
if (version == null) {
|
||||
else if (versionInput == "pre") {
|
||||
version = semver.maxSatisfying(availableReleases, MAJOR_VERSION, { includePrerelease: true });
|
||||
}
|
||||
else {
|
||||
// Use the highest available version that matches versionInput
|
||||
version = semver.maxSatisfying(availableReleases, versionInput, { includePrerelease });
|
||||
}
|
||||
if (!version) {
|
||||
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;
|
||||
}
|
||||
exports.getJuliaVersion = getJuliaVersion;
|
||||
function getDesiredFileExts() {
|
||||
let fileExt1;
|
||||
let hasFileExt2;
|
||||
@@ -214,6 +317,7 @@ function getFileInfo(versionInfo, version, arch) {
|
||||
return null;
|
||||
}
|
||||
if (!versionInfo[version]) {
|
||||
core.error(`Encountered error: ${err}`);
|
||||
throw err;
|
||||
}
|
||||
for (let file of versionInfo[version].files) {
|
||||
@@ -232,10 +336,35 @@ function getFileInfo(versionInfo, version, arch) {
|
||||
}
|
||||
}
|
||||
}
|
||||
// The following block is just to provide improved log messages in the CI logs.
|
||||
// We specifically want to improve the case where someone is trying to install
|
||||
// Julia 1.6 or 1.7 on Apple Silicon (aarch64) macOS.
|
||||
{
|
||||
const one_fileext_is_targz = (fileExt1 == "tar.gz") || (fileExt2 == "tar.gz");
|
||||
const one_fileext_is_dmg = (fileExt1 == "dmg") || (fileExt2 == "dmg");
|
||||
const one_fileext_is_targz_and_other_is_dmg = one_fileext_is_targz && one_fileext_is_dmg;
|
||||
// We say that "this Julia version does NOT have native binaries for Apple Silicon"
|
||||
// if and only if "this Julia version is < 1.8.0"
|
||||
const this_julia_version_does_NOT_have_native_binaries_for_apple_silicon = semver.lt(version, '1.8.0');
|
||||
const this_is_macos = osPlat == 'darwin';
|
||||
if (this_is_macos && one_fileext_is_targz_and_other_is_dmg && this_julia_version_does_NOT_have_native_binaries_for_apple_silicon) {
|
||||
const msg = `It looks like you are trying to install Julia 1.6 or 1.7 on ` +
|
||||
`the "macos-latest" runners.\n` +
|
||||
`"macos-latest" now resolves to "macos-14", which run on Apple ` +
|
||||
`Silicon (aarch64) macOS machines.\n` +
|
||||
`Unfortunately, Julia 1.6 and 1.7 do not have native binaries ` +
|
||||
`available for Apple Silicon macOS.\n` +
|
||||
`Therefore, it is not possible to install Julia with the current ` +
|
||||
`constraints.\n` +
|
||||
`For instructions on how to fix this error, please see the following Discourse post: ` +
|
||||
`https://discourse.julialang.org/t/how-to-fix-github-actions-ci-failures-with-julia-1-6-or-1-7-on-macos-latest-and-macos-14/117019`;
|
||||
core.error(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
core.error(`Encountered error: ${err}`);
|
||||
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
|
||||
@@ -253,7 +382,6 @@ function getDownloadURL(fileInfo, version, arch) {
|
||||
}
|
||||
return fileInfo.url;
|
||||
}
|
||||
exports.getDownloadURL = getDownloadURL;
|
||||
function installJulia(dest, versionInfo, version, arch) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
// Download Julia
|
||||
@@ -321,7 +449,6 @@ function installJulia(dest, versionInfo, version, arch) {
|
||||
}
|
||||
});
|
||||
}
|
||||
exports.installJulia = installJulia;
|
||||
/**
|
||||
* Test if Julia has been installed and print the version.
|
||||
*
|
||||
@@ -358,4 +485,3 @@ function showVersionInfo(showVersionInfoInput, version) {
|
||||
}
|
||||
});
|
||||
}
|
||||
exports.showVersionInfo = showVersionInfo;
|
||||
|
||||
76
lib/setup-julia.js
generated
76
lib/setup-julia.js
generated
@@ -15,13 +15,23 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
var __importStar = (this && this.__importStar) || (function () {
|
||||
var ownKeys = function(o) {
|
||||
ownKeys = Object.getOwnPropertyNames || function (o) {
|
||||
var ar = [];
|
||||
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
||||
return ar;
|
||||
};
|
||||
return ownKeys(o);
|
||||
};
|
||||
return function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
})();
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
@@ -36,15 +46,18 @@ const core = __importStar(require("@actions/core"));
|
||||
const tc = __importStar(require("@actions/tool-cache"));
|
||||
const fs = __importStar(require("fs"));
|
||||
const https = __importStar(require("https"));
|
||||
const os = __importStar(require("os"));
|
||||
const path = __importStar(require("path"));
|
||||
const installer = __importStar(require("./installer"));
|
||||
// Note: before we index into this dict, we always first do `.toLowerCase()` on
|
||||
// the key.
|
||||
//
|
||||
// Therefore, this dict does not need to account for differences in case.
|
||||
const archSynonyms = {
|
||||
'x86': 'x86',
|
||||
'X86': 'x86',
|
||||
'x64': 'x64',
|
||||
'X64': 'x64',
|
||||
'x86_64': 'x64',
|
||||
'aarch64': 'aarch64',
|
||||
'ARM64': 'aarch64',
|
||||
'arm64': 'aarch64'
|
||||
};
|
||||
function run() {
|
||||
@@ -65,25 +78,52 @@ function run() {
|
||||
core.debug(`ERROR: Could not retrieve runner IP: ${err}`);
|
||||
});
|
||||
}
|
||||
// Inputs
|
||||
const versionInput = core.getInput('version');
|
||||
const includePrereleases = core.getInput('include-all-prereleases') == 'true';
|
||||
const originalArchInput = core.getInput('arch');
|
||||
// Inputs.
|
||||
// Note that we intentionally strip leading and lagging whitespace by using `.trim()`
|
||||
const versionInput = core.getInput('version').trim();
|
||||
const includePrereleases = core.getInput('include-all-prereleases').trim() == 'true';
|
||||
const originalArchInput = core.getInput('arch').trim();
|
||||
const projectInput = core.getInput('project').trim(); // Julia project file
|
||||
// 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) {
|
||||
if (!versionInput) { // if `versionInput` is an empty string
|
||||
throw new Error('Version input must not be null');
|
||||
}
|
||||
if (!originalArchInput) {
|
||||
if (versionInput == '1.6') {
|
||||
core.notice('[setup-julia] If you are testing 1.6 as a Long Term Support (lts) version, consider using the new "lts" version specifier instead of "1.6" explicitly, which will automatically resolve the current lts.');
|
||||
}
|
||||
if (!originalArchInput) { // if `originalArchInput` is an empty string
|
||||
throw new Error(`Arch input must not be null`);
|
||||
}
|
||||
const arch = archSynonyms[originalArchInput];
|
||||
if (originalArchInput == 'x64' && os.platform() == 'darwin' && os.arch() == 'arm64') {
|
||||
core.warning('[setup-julia] x64 arch has been requested on a macOS runner that has an arm64 (Apple Silicon) architecture. You may have meant to use the "aarch64" arch instead (or left it unspecified for the correct default).');
|
||||
}
|
||||
let processedArchInput;
|
||||
if (originalArchInput == "default") {
|
||||
// If the user sets the `arch` input to `default`, then we use the
|
||||
// architecture of the machine that we are running on.
|
||||
processedArchInput = os.arch();
|
||||
core.debug(`The "arch" input is "default", so we will use the machine arch: ${processedArchInput}`);
|
||||
}
|
||||
else {
|
||||
processedArchInput = originalArchInput;
|
||||
}
|
||||
// Note: we convert the key `processedArchInput` to lower case
|
||||
// before we index into the `archSynonyms` dict.
|
||||
const arch = archSynonyms[processedArchInput.toLowerCase()];
|
||||
core.debug(`Mapped the "arch" from ${processedArchInput} to ${arch}`);
|
||||
// Determine the Julia compat ranges as specified by the Project.toml only for special versions that require them.
|
||||
let juliaCompatRange = "";
|
||||
if (versionInput === "min") {
|
||||
const projectFilePath = installer.getProjectFilePath(projectInput);
|
||||
juliaCompatRange = installer.readJuliaCompatRange(fs.readFileSync(projectFilePath).toString());
|
||||
}
|
||||
const versionInfo = yield installer.getJuliaVersionInfo();
|
||||
const availableReleases = yield installer.getJuliaVersions(versionInfo);
|
||||
const version = installer.getJuliaVersion(availableReleases, versionInput, includePrereleases);
|
||||
const version = installer.getJuliaVersion(availableReleases, versionInput, includePrereleases, juliaCompatRange);
|
||||
core.debug(`selected Julia version: ${arch}/${version}`);
|
||||
core.setOutput('julia-version', version);
|
||||
// Search in cache
|
||||
|
||||
8605
package-lock.json
generated
8605
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
30
package.json
30
package.json
@@ -1,6 +1,5 @@
|
||||
{
|
||||
"name": "setup-julia",
|
||||
"version": "2.2.0",
|
||||
"private": true,
|
||||
"description": "setup Julia action",
|
||||
"main": "lib/setup-julia.js",
|
||||
@@ -21,25 +20,26 @@
|
||||
"author": "Sascha Mann <git@mail.saschamann.eu>",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.10.1",
|
||||
"@actions/core": "^1.11.1",
|
||||
"@actions/exec": "^1.1.1",
|
||||
"@actions/io": "^1.1.3",
|
||||
"@actions/tool-cache": "^2.0.1",
|
||||
"@actions/tool-cache": "^2.0.2",
|
||||
"async-retry": "^1.3.3",
|
||||
"semver": "^7.6.2"
|
||||
"semver": "^7.7.0",
|
||||
"toml": "^3.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/async-retry": "^1.4.8",
|
||||
"@types/jest": "^29.5.12",
|
||||
"@types/node": "^20.14.6",
|
||||
"@types/async-retry": "^1.4.9",
|
||||
"@types/jest": "^30.0.0",
|
||||
"@types/node": "^24.1.0",
|
||||
"@types/retry": "^0.12.5",
|
||||
"@types/semver": "^7.5.8",
|
||||
"@vercel/ncc": "^0.38.1",
|
||||
"jest": "^29.7.0",
|
||||
"jest-circus": "^29.7.0",
|
||||
"nock": "^13.5.4",
|
||||
"prettier": "^3.3.2",
|
||||
"ts-jest": "^29.1.5",
|
||||
"typescript": "^5.4.5"
|
||||
"@types/semver": "^7.7.0",
|
||||
"@vercel/ncc": "^0.38.3",
|
||||
"jest": "^30.0.5",
|
||||
"jest-circus": "^30.0.3",
|
||||
"nock": "^14.0.8",
|
||||
"prettier": "^3.6.2",
|
||||
"ts-jest": "^29.4.0",
|
||||
"typescript": "^5.9.2"
|
||||
}
|
||||
}
|
||||
|
||||
154
src/installer.ts
154
src/installer.ts
@@ -9,8 +9,9 @@ import * as path from 'path'
|
||||
import retry = require('async-retry')
|
||||
|
||||
import * as semver from 'semver'
|
||||
import * as toml from 'toml'
|
||||
|
||||
const LTS_VERSION = '1.6'
|
||||
const LTS_VERSION = '1.10'
|
||||
const MAJOR_VERSION = '1' // Could be deduced from versions.json
|
||||
|
||||
// Translations between actions input and Julia arch names
|
||||
@@ -79,23 +80,116 @@ export async function getJuliaVersions(versionInfo): Promise<string[]> {
|
||||
return versions
|
||||
}
|
||||
|
||||
export function getJuliaVersion(availableReleases: string[], versionInput: string, includePrerelease: boolean = false): string {
|
||||
/**
|
||||
* @returns The path to the Julia project file
|
||||
*/
|
||||
export function getProjectFilePath(projectInput: string = ""): string {
|
||||
let projectFilePath: string = ""
|
||||
|
||||
// Default value for projectInput
|
||||
if (!projectInput) {
|
||||
projectInput = process.env.JULIA_PROJECT || "."
|
||||
}
|
||||
|
||||
if (fs.existsSync(projectInput) && fs.lstatSync(projectInput).isFile()) {
|
||||
projectFilePath = projectInput
|
||||
} else {
|
||||
for (let projectFilename of ["JuliaProject.toml", "Project.toml"]) {
|
||||
let p = path.join(projectInput, projectFilename)
|
||||
if (fs.existsSync(p) && fs.lstatSync(p).isFile()) {
|
||||
projectFilePath = p
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!projectFilePath) {
|
||||
throw new Error(`Unable to locate project file with project input: ${projectInput}`)
|
||||
}
|
||||
|
||||
return projectFilePath
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns A valid NPM semver range from a Julia compat range or null if it's not valid
|
||||
*/
|
||||
export function validJuliaCompatRange(compatRange: string): string | null {
|
||||
let ranges: Array<string> = []
|
||||
for(let range of compatRange.split(",")) {
|
||||
range = range.trim()
|
||||
|
||||
// An empty range isn't supported by Julia
|
||||
if (!range) {
|
||||
return null
|
||||
}
|
||||
|
||||
// NPM's semver doesn't understand unicode characters such as `≥` so we'll convert to alternatives
|
||||
range = range.replace("≥", ">=").replace("≤", "<=")
|
||||
|
||||
// Cleanup whitespace. Julia only allows whitespace between the specifier and version with certain specifiers
|
||||
range = range.replace(/\s+/g, " ").replace(/(?<=(>|>=|≥|<)) (?=\d)/g, "")
|
||||
|
||||
if (!semver.validRange(range) || range.split(/(?<! -) (?!- )/).length > 1 || range.startsWith("<=") || range === "*") {
|
||||
return null
|
||||
} else if (range.search(/^\d/) === 0 && !range.includes(" ")) {
|
||||
// Compat version is just a basic version number (e.g. 1.2.3). Since Julia's Pkg.jl's uses caret
|
||||
// as the default specifier (e.g. `1.2.3 == ^1.2.3`) and NPM's semver uses tilde as the default
|
||||
// specifier (e.g. `1.2.3 == 1.2.x == ~1.2.3`) we will introduce the caret specifier to ensure the
|
||||
// orignal intent is respected.
|
||||
// https://pkgdocs.julialang.org/v1/compatibility/#Version-specifier-format
|
||||
// https://github.com/npm/node-semver#x-ranges-12x-1x-12-
|
||||
range = "^" + range
|
||||
}
|
||||
|
||||
ranges.push(range)
|
||||
}
|
||||
|
||||
return semver.validRange(ranges.join(" || "))
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns An array of version ranges compatible with the Julia project
|
||||
*/
|
||||
export function readJuliaCompatRange(projectFileContent: string): string {
|
||||
let compatRange: string | null
|
||||
let meta = toml.parse(projectFileContent)
|
||||
|
||||
if (meta.compat?.julia !== undefined) {
|
||||
compatRange = validJuliaCompatRange(meta.compat.julia)
|
||||
} else {
|
||||
compatRange = "*"
|
||||
}
|
||||
|
||||
if (!compatRange) {
|
||||
throw new Error(`Invalid version range found in Julia compat: ${compatRange}`)
|
||||
}
|
||||
|
||||
return compatRange
|
||||
}
|
||||
|
||||
export function getJuliaVersion(availableReleases: string[], versionInput: string, includePrerelease: boolean = false, juliaCompatRange: string = ""): string {
|
||||
// Note: `juliaCompatRange` is ignored unless `versionInput` is `min`
|
||||
let version: string | null
|
||||
|
||||
if (semver.valid(versionInput) == versionInput || versionInput.endsWith('nightly')) {
|
||||
// versionInput is a valid version or a nightly version, use it directly
|
||||
return versionInput
|
||||
version = versionInput
|
||||
} else if (versionInput == "min") {
|
||||
// Resolve "min" to the minimum supported Julia version compatible with the project file
|
||||
if (!juliaCompatRange) {
|
||||
throw new Error('Unable to use version "min" when the Julia project file does not specify a compat for Julia')
|
||||
}
|
||||
version = semver.minSatisfying(availableReleases, juliaCompatRange, {includePrerelease})
|
||||
} else if (versionInput == "lts") {
|
||||
version = semver.maxSatisfying(availableReleases, LTS_VERSION, { includePrerelease: false });
|
||||
} else if (versionInput == "pre") {
|
||||
version = semver.maxSatisfying(availableReleases, MAJOR_VERSION, { includePrerelease: true });
|
||||
} else {
|
||||
// Use the highest available version that matches versionInput
|
||||
version = semver.maxSatisfying(availableReleases, versionInput, {includePrerelease})
|
||||
}
|
||||
|
||||
if (versionInput == 'lts') {
|
||||
return getJuliaVersion(availableReleases, LTS_VERSION, false)
|
||||
}
|
||||
|
||||
if (versionInput == 'pre') {
|
||||
return getJuliaVersion(availableReleases, MAJOR_VERSION, true)
|
||||
}
|
||||
|
||||
// Use the highest available version that matches versionInput
|
||||
let version = semver.maxSatisfying(availableReleases, versionInput, {includePrerelease})
|
||||
if (version == null) {
|
||||
if (!version) {
|
||||
throw new Error(`Could not find a Julia version that matches ${versionInput}`)
|
||||
}
|
||||
|
||||
@@ -184,6 +278,7 @@ export function getFileInfo(versionInfo, version: string, arch: string) {
|
||||
}
|
||||
|
||||
if (!versionInfo[version]) {
|
||||
core.error(`Encountered error: ${err}`)
|
||||
throw err
|
||||
}
|
||||
|
||||
@@ -204,8 +299,39 @@ export function getFileInfo(versionInfo, version: string, arch: string) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The following block is just to provide improved log messages in the CI logs.
|
||||
// We specifically want to improve the case where someone is trying to install
|
||||
// Julia 1.6 or 1.7 on Apple Silicon (aarch64) macOS.
|
||||
{
|
||||
const one_fileext_is_targz = (fileExt1 == "tar.gz") || (fileExt2 == "tar.gz");
|
||||
const one_fileext_is_dmg = (fileExt1 == "dmg") || (fileExt2 == "dmg");
|
||||
const one_fileext_is_targz_and_other_is_dmg = one_fileext_is_targz && one_fileext_is_dmg;
|
||||
|
||||
// We say that "this Julia version does NOT have native binaries for Apple Silicon"
|
||||
// if and only if "this Julia version is < 1.8.0"
|
||||
const this_julia_version_does_NOT_have_native_binaries_for_apple_silicon = semver.lt(
|
||||
version,
|
||||
'1.8.0',
|
||||
);
|
||||
const this_is_macos = osPlat == 'darwin';
|
||||
if (this_is_macos && one_fileext_is_targz_and_other_is_dmg && this_julia_version_does_NOT_have_native_binaries_for_apple_silicon) {
|
||||
const msg = `It looks like you are trying to install Julia 1.6 or 1.7 on ` +
|
||||
`the "macos-latest" runners.\n` +
|
||||
`"macos-latest" now resolves to "macos-14", which run on Apple ` +
|
||||
`Silicon (aarch64) macOS machines.\n` +
|
||||
`Unfortunately, Julia 1.6 and 1.7 do not have native binaries ` +
|
||||
`available for Apple Silicon macOS.\n` +
|
||||
`Therefore, it is not possible to install Julia with the current ` +
|
||||
`constraints.\n` +
|
||||
`For instructions on how to fix this error, please see the following Discourse post: ` +
|
||||
`https://discourse.julialang.org/t/how-to-fix-github-actions-ci-failures-with-julia-1-6-or-1-7-on-macos-latest-and-macos-14/117019`
|
||||
core.error(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
core.error(`Encountered error: ${err}`)
|
||||
throw err
|
||||
}
|
||||
|
||||
|
||||
@@ -3,17 +3,20 @@ import * as tc from '@actions/tool-cache'
|
||||
|
||||
import * as fs from 'fs'
|
||||
import * as https from 'https'
|
||||
import * as os from 'os'
|
||||
import * as path from 'path'
|
||||
|
||||
import * as installer from './installer'
|
||||
|
||||
// Note: before we index into this dict, we always first do `.toLowerCase()` on
|
||||
// the key.
|
||||
//
|
||||
// Therefore, this dict does not need to account for differences in case.
|
||||
const archSynonyms = {
|
||||
'x86': 'x86',
|
||||
'X86': 'x86',
|
||||
'x64': 'x64',
|
||||
'X64': 'x64',
|
||||
'x86_64': 'x64',
|
||||
'aarch64': 'aarch64',
|
||||
'ARM64': 'aarch64',
|
||||
'arm64': 'aarch64'
|
||||
}
|
||||
|
||||
@@ -37,28 +40,61 @@ async function run() {
|
||||
})
|
||||
}
|
||||
|
||||
// Inputs
|
||||
const versionInput = core.getInput('version')
|
||||
const includePrereleases = core.getInput('include-all-prereleases') == 'true'
|
||||
const originalArchInput = core.getInput('arch')
|
||||
// Inputs.
|
||||
// Note that we intentionally strip leading and lagging whitespace by using `.trim()`
|
||||
const versionInput = core.getInput('version').trim()
|
||||
const includePrereleases = core.getInput('include-all-prereleases').trim() == 'true'
|
||||
const originalArchInput = core.getInput('arch').trim()
|
||||
const forceArch = core.getInput('force-arch').trim() == 'true'
|
||||
const projectInput = core.getInput('project').trim() // Julia project file
|
||||
|
||||
// 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) {
|
||||
if (!versionInput) { // if `versionInput` is an empty string
|
||||
throw new Error('Version input must not be null')
|
||||
}
|
||||
if (!originalArchInput) {
|
||||
if (versionInput == '1.6') {
|
||||
core.notice('[setup-julia] If you are testing 1.6 as a Long Term Support (lts) version, consider using the new "lts" version specifier instead of "1.6" explicitly, which will automatically resolve the current lts.')
|
||||
}
|
||||
if (!originalArchInput) { // if `originalArchInput` is an empty string
|
||||
throw new Error(`Arch input must not be null`)
|
||||
}
|
||||
|
||||
const arch = archSynonyms[originalArchInput]
|
||||
if (originalArchInput == 'x64' && os.platform() == 'darwin' && os.arch() == 'arm64') {
|
||||
if (forceArch) {
|
||||
core.warning('[setup-julia] x64 arch has been requested on a macOS runner that has an arm64 (Apple Silicon) architecture. The "force-arch" input is set to "true", so proceeding with x64 installation. Note that this will mean Julia will be run under Rosetta emulation.')
|
||||
} else {
|
||||
throw new Error('[setup-julia] x64 arch has been requested on a macOS runner that has an arm64 (Apple Silicon) architecture. You may have meant to use the "aarch64" arch instead (or "default" or left it unspecified for the correct default). To force the use of x64 on this runner, set the "force-arch" input to "true".')
|
||||
}
|
||||
}
|
||||
|
||||
let processedArchInput: string;
|
||||
if (originalArchInput == "default") {
|
||||
// If the user sets the `arch` input to `default`, then we use the
|
||||
// architecture of the machine that we are running on.
|
||||
processedArchInput = os.arch();
|
||||
core.debug(`The "arch" input is "default", so we will use the machine arch: ${processedArchInput}`)
|
||||
} else {
|
||||
processedArchInput = originalArchInput;
|
||||
}
|
||||
// Note: we convert the key `processedArchInput` to lower case
|
||||
// before we index into the `archSynonyms` dict.
|
||||
const arch = archSynonyms[processedArchInput.toLowerCase()]
|
||||
core.debug(`Mapped the "arch" from ${processedArchInput} to ${arch}`)
|
||||
|
||||
// Determine the Julia compat ranges as specified by the Project.toml only for special versions that require them.
|
||||
let juliaCompatRange: string = "";
|
||||
if (versionInput === "min") {
|
||||
const projectFilePath = installer.getProjectFilePath(projectInput)
|
||||
juliaCompatRange = installer.readJuliaCompatRange(fs.readFileSync(projectFilePath).toString())
|
||||
}
|
||||
|
||||
const versionInfo = await installer.getJuliaVersionInfo()
|
||||
const availableReleases = await installer.getJuliaVersions(versionInfo)
|
||||
const version = installer.getJuliaVersion(availableReleases, versionInput, includePrereleases)
|
||||
const version = installer.getJuliaVersion(availableReleases, versionInput, includePrereleases, juliaCompatRange)
|
||||
core.debug(`selected Julia version: ${arch}/${version}`)
|
||||
core.setOutput('julia-version', version)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user