New option to work with one or more hex.pm mirrors (#197)

* New option to work with one or more hex.pm mirrors

Add a new option called `hexpm-mirrors` for one or more hex.pm mirrors.
Default list is `builds.hex.pm`, so behavior is unaffected unless option is
used.

Signed-off-by: Paul Guyot <pguyot@kallisys.net>

* Implement suggested rewording changes from @paulo-ferraz-oliveira

Co-authored-by: Paulo F. Oliveira <paulo.ferraz.oliveira@gmail.com>
Signed-off-by: Paul Guyot <pguyot@kallisys.net>

---------

Signed-off-by: Paul Guyot <pguyot@kallisys.net>
Co-authored-by: Paulo F. Oliveira <paulo.ferraz.oliveira@gmail.com>
This commit is contained in:
Paul Guyot
2023-05-04 08:27:05 +02:00
committed by GitHub
parent 9641cb96c1
commit cf692c3264
13 changed files with 362 additions and 99 deletions
+58
View File
@@ -0,0 +1,58 @@
---
name: hexpm-mirrors
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
test-failing-first-mirror:
name: Test option hexpm-mirrors with a dummy first mirror
runs-on: ${{matrix.os}}
strategy:
fail-fast: false
matrix:
os: ['ubuntu-22.04', 'windows-2022']
otp-version: ['24']
elixir-version: ['v1.14', '']
install-rebar: [true, false]
install-hex: [true, false]
steps:
- uses: actions/checkout@v3
- name: Use erlef/setup-beam
id: setup-beam
uses: ./
with:
otp-version: ${{matrix.otp-version}}
elixir-version: ${{matrix.elixir-version}}
install-rebar: ${{matrix.install-rebar}}
install-hex: ${{matrix.install-hex}}
hexpm-mirrors: |
https://mirror.invalid
https://cdn.jsdelivr.net/hex
https://builds.hex.pm
test-invalid-mirror:
name: Test errors with mirror
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- name: Use erlef/setup-beam
id: failing-setup-beam
uses: ./
continue-on-error: true
with:
otp-version: '24.3.4.6'
elixir-version: 'v1.13.4'
install-rebar: true
install-hex: true
hexpm-mirrors: https://mirror.invalid
- name: Report unexpected success
if: ${{ steps.failing-setup-beam.outcome == 'success' }}
run: |
echo "Action is expected to fail"
exit 1
+41
View File
@@ -216,6 +216,47 @@ jobs:
**Note**: the `otp-version: false` input is only applicable when installing Gleam.
## Alternative hex.pm mirrors
It is possible to use alternative hex.pm mirror(s), in their declared order, with
option `hexpm-mirrors`. By default, the action will use `builds.hex.pm`.
To use other alternative mirrors, add one per line, as shown below.
```yaml
# create this in .github/workflows/ci.yml
on: push
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: erlef/setup-beam@v1
with:
otp-version: '25'
# Use `cdn.jsdelivr.net/hex` as an alternative to `builds.hex.pm`
hexpm-mirrors: https://cdn.jsdelivr.net/hex
```
Alternatively, you may try `cdn.jsdelivr.net/hex` if `builds.hex.pm` fails:
```yaml
# create this in .github/workflows/ci.yml
on: push
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: erlef/setup-beam@v1
with:
otp-version: '25'
hexpm-mirrors: |
https://builds.hex.pm
https://cdn.jsdelivr.net/hex
```
## Environment variables
Base installation folders (useful for e.g. fetching headers for NIFs) are available in the following
+19 -17
View File
@@ -102,48 +102,49 @@ async function testOTPVersions() {
let expected
let spec
let osVersion
const hexMirrors = ['https://repo.hex.pm', 'https://cdn.jsdelivr.net/hex']
if (process.platform === 'linux') {
spec = '19.3.x'
osVersion = 'ubuntu-16.04'
expected = 'OTP-19.3.6.13'
got = await setupBeam.getOTPVersion(spec, osVersion)
got = await setupBeam.getOTPVersion(spec, osVersion, hexMirrors)
assert.deepStrictEqual(got, expected)
spec = '^19.3.6'
osVersion = 'ubuntu-16.04'
expected = 'OTP-19.3.6.13'
got = await setupBeam.getOTPVersion(spec, osVersion)
got = await setupBeam.getOTPVersion(spec, osVersion, hexMirrors)
assert.deepStrictEqual(got, expected)
spec = '^19.3'
osVersion = 'ubuntu-18.04'
expected = 'OTP-19.3.6.13'
got = await setupBeam.getOTPVersion(spec, osVersion)
got = await setupBeam.getOTPVersion(spec, osVersion, hexMirrors)
assert.deepStrictEqual(got, expected)
spec = '20'
osVersion = 'ubuntu-20.04'
expected = 'OTP-20.3.8.26'
got = await setupBeam.getOTPVersion(spec, osVersion)
got = await setupBeam.getOTPVersion(spec, osVersion, hexMirrors)
assert.deepStrictEqual(got, expected)
spec = '20.x'
osVersion = 'ubuntu-20.04'
expected = 'OTP-20.3.8.26'
got = await setupBeam.getOTPVersion(spec, osVersion)
got = await setupBeam.getOTPVersion(spec, osVersion, hexMirrors)
assert.deepStrictEqual(got, expected)
spec = '20.0'
osVersion = 'ubuntu-20.04'
expected = 'OTP-20.0.5'
got = await setupBeam.getOTPVersion(spec, osVersion)
got = await setupBeam.getOTPVersion(spec, osVersion, hexMirrors)
assert.deepStrictEqual(got, expected)
spec = '20.0.x'
osVersion = 'ubuntu-20.04'
expected = 'OTP-20.0.5'
got = await setupBeam.getOTPVersion(spec, osVersion)
got = await setupBeam.getOTPVersion(spec, osVersion, hexMirrors)
assert.deepStrictEqual(got, expected)
}
@@ -151,19 +152,19 @@ async function testOTPVersions() {
spec = '24.0.1'
osVersion = 'windows-latest'
expected = '24.0.1'
got = await setupBeam.getOTPVersion(spec, osVersion)
got = await setupBeam.getOTPVersion(spec, osVersion, hexMirrors)
assert.deepStrictEqual(got, expected)
spec = '23.2.x'
osVersion = 'windows-2016'
expected = '23.2.7'
got = await setupBeam.getOTPVersion(spec, osVersion)
got = await setupBeam.getOTPVersion(spec, osVersion, hexMirrors)
assert.deepStrictEqual(got, expected)
spec = '23.0'
osVersion = 'windows-2019'
expected = '23.0.4'
got = await setupBeam.getOTPVersion(spec, osVersion)
got = await setupBeam.getOTPVersion(spec, osVersion, hexMirrors)
assert.deepStrictEqual(got, expected)
}
}
@@ -173,30 +174,31 @@ async function testElixirVersions() {
let expected
let spec
let otpVersion
const hexMirrors = ['https://repo.hex.pm']
spec = '1.1.x'
otpVersion = 'OTP-17'
expected = 'v1.1.1-otp-17'
got = await setupBeam.getElixirVersion(spec, otpVersion)
got = await setupBeam.getElixirVersion(spec, otpVersion, hexMirrors)
assert.deepStrictEqual(got, expected)
spec = '1.10.4'
otpVersion = 'OTP-23'
expected = 'v1.10.4-otp-23'
got = await setupBeam.getElixirVersion(spec, otpVersion)
got = await setupBeam.getElixirVersion(spec, otpVersion, hexMirrors)
assert.deepStrictEqual(got, expected)
spec = '1.12.1'
otpVersion = 'OTP-24.0.2'
expected = 'v1.12.1-otp-24'
got = await setupBeam.getElixirVersion(spec, otpVersion)
got = await setupBeam.getElixirVersion(spec, otpVersion, hexMirrors)
assert.deepStrictEqual(got, expected)
simulateInput('version-type', 'strict')
spec = '1.14.0'
otpVersion = 'master'
expected = 'v1.14.0'
got = await setupBeam.getElixirVersion(spec, otpVersion)
got = await setupBeam.getElixirVersion(spec, otpVersion, hexMirrors)
assert.deepStrictEqual(got, expected)
simulateInput('version-type', 'loose')
@@ -204,7 +206,7 @@ async function testElixirVersions() {
spec = 'v1.11.0-rc.0'
otpVersion = 'OTP-23'
expected = 'v1.11.0-rc.0-otp-23'
got = await setupBeam.getElixirVersion(spec, otpVersion)
got = await setupBeam.getElixirVersion(spec, otpVersion, hexMirrors)
assert.deepStrictEqual(got, expected)
simulateInput('version-type', 'loose')
@@ -212,7 +214,7 @@ async function testElixirVersions() {
spec = 'v1.11.0'
otpVersion = '22.3.4.2'
expected = 'v1.11.0-otp-22'
got = await setupBeam.getElixirVersion(spec, otpVersion)
got = await setupBeam.getElixirVersion(spec, otpVersion, hexMirrors)
assert.deepStrictEqual(got, expected)
simulateInput('version-type', 'loose')
@@ -220,7 +222,7 @@ async function testElixirVersions() {
spec = 'main'
otpVersion = '23.1'
expected = 'main-otp-23'
got = await setupBeam.getElixirVersion(spec, otpVersion)
got = await setupBeam.getElixirVersion(spec, otpVersion, hexMirrors)
assert.deepStrictEqual(got, expected)
simulateInput('version-type', 'loose')
}
+4
View File
@@ -45,6 +45,10 @@ inputs:
version-file:
description: a versions file (e.g. as used by `asdf`), which defines inputs
default: ''
hexpm-mirrors:
description: mirror(s) for hex.pm, one per line
default: |
https://builds.hex.pm
outputs:
elixir-version:
description: Exact version of Elixir that was installed
+114 -37
View File
@@ -7120,6 +7120,7 @@ try {
/***/ 2127:
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
const core = __nccwpck_require__(2186)
const { exec } = __nccwpck_require__(1514)
const path = __nccwpck_require__(1017)
@@ -7128,11 +7129,28 @@ const path = __nccwpck_require__(1017)
*
* @param {string} osVersion
* @param {string} otpVersion
* @param {string[]} hexMirrors
*/
async function installOTP(osVersion, otpVersion) {
async function installOTP(osVersion, otpVersion, hexMirrors) {
const OS = process.platform
if (OS === 'linux') {
await exec(__nccwpck_require__.ab + "install-otp.sh", [osVersion, otpVersion])
if (hexMirrors.length === 0) {
throw new Error(
`Could not install Erlang/OTP ${otpVersion} from any hex.pm mirror`,
)
}
const [hexMirror, ...hexMirrorsT] = hexMirrors
try {
await exec(__nccwpck_require__.ab + "install-otp.sh", [
osVersion,
otpVersion,
hexMirror,
])
return
} catch (err) {
core.info(`install-otp.sh failed for mirror ${hexMirror}`)
}
await installOTP(osVersion, otpVersion, hexMirrorsT)
} else if (OS === 'win32') {
const script = __nccwpck_require__.ab + "install-otp.ps1"
await exec(`pwsh.exe ${script} -VSN:${otpVersion}`)
@@ -7143,15 +7161,34 @@ async function installOTP(osVersion, otpVersion) {
* Install Elixir.
*
* @param {string} elixirVersion
* @param {string[]} hexMirrors
*/
async function installElixir(elixirVersion) {
const OS = process.platform
if (OS === 'linux') {
await exec(__nccwpck_require__.ab + "install-elixir.sh", [elixirVersion])
} else if (OS === 'win32') {
const script = __nccwpck_require__.ab + "install-elixir.ps1"
await exec(`pwsh.exe ${script} -VSN:${elixirVersion}`)
async function installElixir(elixirVersion, hexMirrors) {
if (hexMirrors.length === 0) {
throw new Error(
`Could not install Elixir ${elixirVersion} from any hex.pm mirror`,
)
}
const [hexMirror, ...hexMirrorsT] = hexMirrors
const OS = process.platform
let script
try {
if (OS === 'linux') {
script = __nccwpck_require__.ab + "install-elixir.sh"
await exec(__nccwpck_require__.ab + "install-elixir.sh", [elixirVersion, hexMirror])
return
}
if (OS === 'win32') {
script = __nccwpck_require__.ab + "install-elixir.ps1"
await exec(
`pwsh.exe ${script} -VSN:${elixirVersion} -HEX_MIRROR:${hexMirror}`,
)
return
}
} catch (err) {
core.info(`${script} failed for mirror ${hexMirror}`)
}
await installElixir(elixirVersion, hexMirrorsT)
}
/**
@@ -7238,16 +7275,23 @@ async function main() {
const elixirSpec = getInput('elixir-version', false, 'elixir', versions)
const gleamSpec = getInput('gleam-version', false, 'gleam', versions)
const rebar3Spec = getInput('rebar3-version', false, 'rebar', versions)
const hexMirrors = core.getMultilineInput('hexpm-mirrors', {
required: false,
})
if (otpSpec !== 'false') {
await installOTP(otpSpec, osVersion)
const elixirInstalled = await maybeInstallElixir(elixirSpec, otpSpec)
await installOTP(otpSpec, osVersion, hexMirrors)
const elixirInstalled = await maybeInstallElixir(
elixirSpec,
otpSpec,
hexMirrors,
)
if (elixirInstalled === true) {
const shouldMixRebar = getInput('install-rebar', false)
await mix(shouldMixRebar, 'rebar')
await mix(shouldMixRebar, 'rebar', hexMirrors)
const shouldMixHex = getInput('install-hex', false)
await mix(shouldMixHex, 'hex')
await mix(shouldMixHex, 'hex', hexMirrors)
}
} else if (!gleamSpec) {
throw new Error('otp-version=false is only available when installing Gleam')
@@ -7257,12 +7301,12 @@ async function main() {
await maybeInstallRebar3(rebar3Spec)
}
async function installOTP(otpSpec, osVersion) {
const otpVersion = await getOTPVersion(otpSpec, osVersion)
async function installOTP(otpSpec, osVersion, hexMirrors) {
const otpVersion = await getOTPVersion(otpSpec, osVersion, hexMirrors)
console.log(
`##[group]Installing Erlang/OTP ${otpVersion} - built on ${osVersion}`,
)
await installer.installOTP(osVersion, otpVersion)
await installer.installOTP(osVersion, otpVersion, hexMirrors)
core.setOutput('otp-version', otpVersion)
core.addPath(`${process.env.RUNNER_TEMP}/.setup-beam/otp/bin`)
console.log('##[endgroup]')
@@ -7270,13 +7314,17 @@ async function installOTP(otpSpec, osVersion) {
return otpVersion
}
async function maybeInstallElixir(elixirSpec, otpVersion) {
async function maybeInstallElixir(elixirSpec, otpSpec, hexMirrors) {
let installed = false
if (elixirSpec) {
const elixirVersion = await getElixirVersion(elixirSpec, otpVersion)
const elixirVersion = await getElixirVersion(
elixirSpec,
otpSpec,
hexMirrors,
)
console.log(`##[group]Installing Elixir ${elixirVersion}`)
await installer.installElixir(elixirVersion)
await installer.installElixir(elixirVersion, hexMirrors)
core.setOutput('elixir-version', elixirVersion)
const disableProblemMatchers = getInput('disable_problem_matchers', false)
if (disableProblemMatchers === 'false') {
@@ -7295,12 +7343,28 @@ async function maybeInstallElixir(elixirSpec, otpVersion) {
return installed
}
async function mix(shouldMix, what) {
async function mixWithMirrors(cmd, args, hexMirrors) {
if (hexMirrors.length === 0) {
throw new Error('mix failed with every mirror')
}
const [hexMirror, ...hexMirrorsT] = hexMirrors
process.env.HEX_MIRROR = hexMirror
try {
return await exec(cmd, args)
} catch (err) {
core.info(
`mix failed with mirror ${process.env.HEX_MIRROR} with message ${err.message})`,
)
}
return mixWithMirrors(cmd, args, hexMirrorsT)
}
async function mix(shouldMix, what, hexMirrors) {
if (shouldMix === 'true') {
const cmd = 'mix'
const args = [`local.${what}`, '--force']
console.log(`##[group]Running ${cmd} ${args}`)
await exec(cmd, args)
await mixWithMirrors(cmd, args, hexMirrors)
console.log('##[endgroup]')
}
}
@@ -7344,8 +7408,8 @@ async function maybeInstallRebar3(rebar3Spec) {
return installed
}
async function getOTPVersion(otpSpec0, osVersion) {
const otpVersions = await getOTPVersions(osVersion)
async function getOTPVersion(otpSpec0, osVersion, hexMirrors) {
const otpVersions = await getOTPVersions(osVersion, hexMirrors)
let otpSpec = otpSpec0 // might be a branch (?)
const otpVersion = getVersionFromSpec(
otpSpec,
@@ -7364,10 +7428,10 @@ async function getOTPVersion(otpSpec0, osVersion) {
return otpVersions.get(otpVersion) // from the reference, for download
}
async function getElixirVersion(exSpec0, otpVersion0) {
async function getElixirVersion(exSpec0, otpVersion0, hexMirrors) {
const otpVersion = otpVersion0.match(/^([^-]+-)?(.+)$/)[2]
const otpVersionMajor = otpVersion.match(/^([^.]+).*$/)[1]
const elixirVersions = await getElixirVersions()
const elixirVersions = await getElixirVersions(hexMirrors)
const semverVersions = Array.from(elixirVersions.keys()).sort()
const exSpec = exSpec0.replace(/-otp-.*$/, '')
const elixirVersionFromSpec = getVersionFromSpec(exSpec, semverVersions, true)
@@ -7427,19 +7491,19 @@ async function getRebar3Version(r3Spec) {
return rebar3Version
}
async function getOTPVersions(osVersion) {
let originListing
let pageIdxs
async function getOTPVersions(osVersion, hexMirrors) {
let otpVersionsListings
if (process.platform === 'linux') {
originListing = `https://builds.hex.pm/builds/otp/${osVersion}/builds.txt`
pageIdxs = [null]
otpVersionsListings = await getWithMirrors(
`/builds/otp/${osVersion}/builds.txt`,
hexMirrors,
)
} else if (process.platform === 'win32') {
originListing =
const originListing =
'https://api.github.com/repos/erlang/otp/releases?per_page=100'
pageIdxs = [1, 2, 3]
otpVersionsListings = await get(originListing, [1, 2, 3])
}
const otpVersionsListings = await get(originListing, pageIdxs)
const otpVersions = new Map()
if (process.platform === 'linux') {
@@ -7469,10 +7533,10 @@ async function getOTPVersions(osVersion) {
return otpVersions
}
async function getElixirVersions() {
const elixirVersionsListings = await get(
'https://builds.hex.pm/builds/elixir/builds.txt',
[null],
async function getElixirVersions(hexMirrors) {
const elixirVersionsListings = await getWithMirrors(
'/builds/elixir/builds.txt',
hexMirrors,
)
const otpVersionsForElixirMap = new Map()
@@ -7656,6 +7720,19 @@ async function get(url0, pageIdxs) {
return Promise.all(pageIdxs.map(getPage))
}
async function getWithMirrors(resourcePath, hexMirrors) {
if (hexMirrors.length === 0) {
throw new Error(`Could not fetch ${resourcePath} from any hex.pm mirror`)
}
const [hexMirror, ...hexMirrorsT] = hexMirrors
try {
return await get(`${hexMirror}${resourcePath}`, [null])
} catch (err) {
core.info(`get failed for URL ${hexMirror}${resourcePath}`)
}
return getWithMirrors(resourcePath, hexMirrorsT)
}
function maybePrependWithV(v) {
if (isVersion(v)) {
return `v${v.replace('v', '')}`
+2 -2
View File
@@ -1,4 +1,4 @@
param([Parameter(Mandatory=$true)][string]${VSN})
param([Parameter(Mandatory=$true)][string]${VSN}, [Parameter(Mandatory=$true)][string]${HEX_MIRROR})
$ErrorActionPreference="Stop"
@@ -9,7 +9,7 @@ $FILE_OUTPUT="elixir.zip"
$DIR_FOR_BIN=".setup-beam/elixir"
$ProgressPreference="SilentlyContinue"
Invoke-WebRequest "https://builds.hex.pm/builds/elixir/${FILE_INPUT}" -OutFile "${FILE_OUTPUT}"
Invoke-WebRequest "${HEX_MIRROR}/builds/elixir/${FILE_INPUT}" -OutFile "${FILE_OUTPUT}"
$ProgressPreference="Continue"
New-Item "${DIR_FOR_BIN}" -ItemType Directory | Out-Null
$ProgressPreference="SilentlyContinue"
+2 -1
View File
@@ -5,11 +5,12 @@ set -eo pipefail
cd "${RUNNER_TEMP}"
VSN=${1}
HEX_MIRROR=${2}
FILE_INPUT="${VSN}.zip"
FILE_OUTPUT=elixir.zip
DIR_FOR_BIN=.setup-beam/elixir
wget -q -O "${FILE_OUTPUT}" "https://builds.hex.pm/builds/elixir/${FILE_INPUT}"
wget -q -O "${FILE_OUTPUT}" "${HEX_MIRROR}/builds/elixir/${FILE_INPUT}"
mkdir -p "${DIR_FOR_BIN}"
unzip -q -o -d "${DIR_FOR_BIN}" "${FILE_OUTPUT}"
echo "Installed Elixir version follows"
+2 -1
View File
@@ -6,11 +6,12 @@ cd "${RUNNER_TEMP}"
OS=${1}
VSN=${2}
HEX_MIRROR=${3}
FILE_INPUT="${VSN}.tar.gz"
FILE_OUTPUT=otp.tar.gz
DIR_FOR_BIN=.setup-beam/otp
wget -q -O "${FILE_OUTPUT}" "https://builds.hex.pm/builds/otp/${OS}/${FILE_INPUT}"
wget -q -O "${FILE_OUTPUT}" "${HEX_MIRROR}/builds/otp/${OS}/${FILE_INPUT}"
mkdir -p "${DIR_FOR_BIN}"
tar zxf "${FILE_OUTPUT}" -C "${DIR_FOR_BIN}" --strip-components=1
"${DIR_FOR_BIN}/Install" -minimal "$(pwd)/${DIR_FOR_BIN}"
+2 -2
View File
@@ -1,4 +1,4 @@
param([Parameter(Mandatory=$true)][string]${VSN})
param([Parameter(Mandatory=$true)][string]${VSN}, [Parameter(Mandatory=$true)][string]${HEX_MIRROR})
$ErrorActionPreference="Stop"
@@ -9,7 +9,7 @@ $FILE_OUTPUT="elixir.zip"
$DIR_FOR_BIN=".setup-beam/elixir"
$ProgressPreference="SilentlyContinue"
Invoke-WebRequest "https://builds.hex.pm/builds/elixir/${FILE_INPUT}" -OutFile "${FILE_OUTPUT}"
Invoke-WebRequest "${HEX_MIRROR}/builds/elixir/${FILE_INPUT}" -OutFile "${FILE_OUTPUT}"
$ProgressPreference="Continue"
New-Item "${DIR_FOR_BIN}" -ItemType Directory | Out-Null
$ProgressPreference="SilentlyContinue"
+2 -1
View File
@@ -5,11 +5,12 @@ set -eo pipefail
cd "${RUNNER_TEMP}"
VSN=${1}
HEX_MIRROR=${2}
FILE_INPUT="${VSN}.zip"
FILE_OUTPUT=elixir.zip
DIR_FOR_BIN=.setup-beam/elixir
wget -q -O "${FILE_OUTPUT}" "https://builds.hex.pm/builds/elixir/${FILE_INPUT}"
wget -q -O "${FILE_OUTPUT}" "${HEX_MIRROR}/builds/elixir/${FILE_INPUT}"
mkdir -p "${DIR_FOR_BIN}"
unzip -q -o -d "${DIR_FOR_BIN}" "${FILE_OUTPUT}"
echo "Installed Elixir version follows"
+2 -1
View File
@@ -6,11 +6,12 @@ cd "${RUNNER_TEMP}"
OS=${1}
VSN=${2}
HEX_MIRROR=${3}
FILE_INPUT="${VSN}.tar.gz"
FILE_OUTPUT=otp.tar.gz
DIR_FOR_BIN=.setup-beam/otp
wget -q -O "${FILE_OUTPUT}" "https://builds.hex.pm/builds/otp/${OS}/${FILE_INPUT}"
wget -q -O "${FILE_OUTPUT}" "${HEX_MIRROR}/builds/otp/${OS}/${FILE_INPUT}"
mkdir -p "${DIR_FOR_BIN}"
tar zxf "${FILE_OUTPUT}" -C "${DIR_FOR_BIN}" --strip-components=1
"${DIR_FOR_BIN}/Install" -minimal "$(pwd)/${DIR_FOR_BIN}"
+46 -9
View File
@@ -1,3 +1,4 @@
const core = require('@actions/core')
const { exec } = require('@actions/exec')
const path = require('path')
@@ -6,11 +7,28 @@ const path = require('path')
*
* @param {string} osVersion
* @param {string} otpVersion
* @param {string[]} hexMirrors
*/
async function installOTP(osVersion, otpVersion) {
async function installOTP(osVersion, otpVersion, hexMirrors) {
const OS = process.platform
if (OS === 'linux') {
await exec(path.join(__dirname, 'install-otp.sh'), [osVersion, otpVersion])
if (hexMirrors.length === 0) {
throw new Error(
`Could not install Erlang/OTP ${otpVersion} from any hex.pm mirror`,
)
}
const [hexMirror, ...hexMirrorsT] = hexMirrors
try {
await exec(path.join(__dirname, 'install-otp.sh'), [
osVersion,
otpVersion,
hexMirror,
])
return
} catch (err) {
core.info(`install-otp.sh failed for mirror ${hexMirror}`)
}
await installOTP(osVersion, otpVersion, hexMirrorsT)
} else if (OS === 'win32') {
const script = path.join(__dirname, 'install-otp.ps1')
await exec(`pwsh.exe ${script} -VSN:${otpVersion}`)
@@ -21,15 +39,34 @@ async function installOTP(osVersion, otpVersion) {
* Install Elixir.
*
* @param {string} elixirVersion
* @param {string[]} hexMirrors
*/
async function installElixir(elixirVersion) {
const OS = process.platform
if (OS === 'linux') {
await exec(path.join(__dirname, 'install-elixir.sh'), [elixirVersion])
} else if (OS === 'win32') {
const script = path.join(__dirname, 'install-elixir.ps1')
await exec(`pwsh.exe ${script} -VSN:${elixirVersion}`)
async function installElixir(elixirVersion, hexMirrors) {
if (hexMirrors.length === 0) {
throw new Error(
`Could not install Elixir ${elixirVersion} from any hex.pm mirror`,
)
}
const [hexMirror, ...hexMirrorsT] = hexMirrors
const OS = process.platform
let script
try {
if (OS === 'linux') {
script = path.join(__dirname, 'install-elixir.sh')
await exec(script, [elixirVersion, hexMirror])
return
}
if (OS === 'win32') {
script = path.join(__dirname, 'install-elixir.ps1')
await exec(
`pwsh.exe ${script} -VSN:${elixirVersion} -HEX_MIRROR:${hexMirror}`,
)
return
}
} catch (err) {
core.info(`${script} failed for mirror ${hexMirror}`)
}
await installElixir(elixirVersion, hexMirrorsT)
}
/**
+68 -28
View File
@@ -30,16 +30,23 @@ async function main() {
const elixirSpec = getInput('elixir-version', false, 'elixir', versions)
const gleamSpec = getInput('gleam-version', false, 'gleam', versions)
const rebar3Spec = getInput('rebar3-version', false, 'rebar', versions)
const hexMirrors = core.getMultilineInput('hexpm-mirrors', {
required: false,
})
if (otpSpec !== 'false') {
await installOTP(otpSpec, osVersion)
const elixirInstalled = await maybeInstallElixir(elixirSpec, otpSpec)
await installOTP(otpSpec, osVersion, hexMirrors)
const elixirInstalled = await maybeInstallElixir(
elixirSpec,
otpSpec,
hexMirrors,
)
if (elixirInstalled === true) {
const shouldMixRebar = getInput('install-rebar', false)
await mix(shouldMixRebar, 'rebar')
await mix(shouldMixRebar, 'rebar', hexMirrors)
const shouldMixHex = getInput('install-hex', false)
await mix(shouldMixHex, 'hex')
await mix(shouldMixHex, 'hex', hexMirrors)
}
} else if (!gleamSpec) {
throw new Error('otp-version=false is only available when installing Gleam')
@@ -49,12 +56,12 @@ async function main() {
await maybeInstallRebar3(rebar3Spec)
}
async function installOTP(otpSpec, osVersion) {
const otpVersion = await getOTPVersion(otpSpec, osVersion)
async function installOTP(otpSpec, osVersion, hexMirrors) {
const otpVersion = await getOTPVersion(otpSpec, osVersion, hexMirrors)
console.log(
`##[group]Installing Erlang/OTP ${otpVersion} - built on ${osVersion}`,
)
await installer.installOTP(osVersion, otpVersion)
await installer.installOTP(osVersion, otpVersion, hexMirrors)
core.setOutput('otp-version', otpVersion)
core.addPath(`${process.env.RUNNER_TEMP}/.setup-beam/otp/bin`)
console.log('##[endgroup]')
@@ -62,13 +69,17 @@ async function installOTP(otpSpec, osVersion) {
return otpVersion
}
async function maybeInstallElixir(elixirSpec, otpVersion) {
async function maybeInstallElixir(elixirSpec, otpSpec, hexMirrors) {
let installed = false
if (elixirSpec) {
const elixirVersion = await getElixirVersion(elixirSpec, otpVersion)
const elixirVersion = await getElixirVersion(
elixirSpec,
otpSpec,
hexMirrors,
)
console.log(`##[group]Installing Elixir ${elixirVersion}`)
await installer.installElixir(elixirVersion)
await installer.installElixir(elixirVersion, hexMirrors)
core.setOutput('elixir-version', elixirVersion)
const disableProblemMatchers = getInput('disable_problem_matchers', false)
if (disableProblemMatchers === 'false') {
@@ -87,12 +98,28 @@ async function maybeInstallElixir(elixirSpec, otpVersion) {
return installed
}
async function mix(shouldMix, what) {
async function mixWithMirrors(cmd, args, hexMirrors) {
if (hexMirrors.length === 0) {
throw new Error('mix failed with every mirror')
}
const [hexMirror, ...hexMirrorsT] = hexMirrors
process.env.HEX_MIRROR = hexMirror
try {
return await exec(cmd, args)
} catch (err) {
core.info(
`mix failed with mirror ${process.env.HEX_MIRROR} with message ${err.message})`,
)
}
return mixWithMirrors(cmd, args, hexMirrorsT)
}
async function mix(shouldMix, what, hexMirrors) {
if (shouldMix === 'true') {
const cmd = 'mix'
const args = [`local.${what}`, '--force']
console.log(`##[group]Running ${cmd} ${args}`)
await exec(cmd, args)
await mixWithMirrors(cmd, args, hexMirrors)
console.log('##[endgroup]')
}
}
@@ -136,8 +163,8 @@ async function maybeInstallRebar3(rebar3Spec) {
return installed
}
async function getOTPVersion(otpSpec0, osVersion) {
const otpVersions = await getOTPVersions(osVersion)
async function getOTPVersion(otpSpec0, osVersion, hexMirrors) {
const otpVersions = await getOTPVersions(osVersion, hexMirrors)
let otpSpec = otpSpec0 // might be a branch (?)
const otpVersion = getVersionFromSpec(
otpSpec,
@@ -156,10 +183,10 @@ async function getOTPVersion(otpSpec0, osVersion) {
return otpVersions.get(otpVersion) // from the reference, for download
}
async function getElixirVersion(exSpec0, otpVersion0) {
async function getElixirVersion(exSpec0, otpVersion0, hexMirrors) {
const otpVersion = otpVersion0.match(/^([^-]+-)?(.+)$/)[2]
const otpVersionMajor = otpVersion.match(/^([^.]+).*$/)[1]
const elixirVersions = await getElixirVersions()
const elixirVersions = await getElixirVersions(hexMirrors)
const semverVersions = Array.from(elixirVersions.keys()).sort()
const exSpec = exSpec0.replace(/-otp-.*$/, '')
const elixirVersionFromSpec = getVersionFromSpec(exSpec, semverVersions, true)
@@ -219,19 +246,19 @@ async function getRebar3Version(r3Spec) {
return rebar3Version
}
async function getOTPVersions(osVersion) {
let originListing
let pageIdxs
async function getOTPVersions(osVersion, hexMirrors) {
let otpVersionsListings
if (process.platform === 'linux') {
originListing = `https://builds.hex.pm/builds/otp/${osVersion}/builds.txt`
pageIdxs = [null]
otpVersionsListings = await getWithMirrors(
`/builds/otp/${osVersion}/builds.txt`,
hexMirrors,
)
} else if (process.platform === 'win32') {
originListing =
const originListing =
'https://api.github.com/repos/erlang/otp/releases?per_page=100'
pageIdxs = [1, 2, 3]
otpVersionsListings = await get(originListing, [1, 2, 3])
}
const otpVersionsListings = await get(originListing, pageIdxs)
const otpVersions = new Map()
if (process.platform === 'linux') {
@@ -261,10 +288,10 @@ async function getOTPVersions(osVersion) {
return otpVersions
}
async function getElixirVersions() {
const elixirVersionsListings = await get(
'https://builds.hex.pm/builds/elixir/builds.txt',
[null],
async function getElixirVersions(hexMirrors) {
const elixirVersionsListings = await getWithMirrors(
'/builds/elixir/builds.txt',
hexMirrors,
)
const otpVersionsForElixirMap = new Map()
@@ -448,6 +475,19 @@ async function get(url0, pageIdxs) {
return Promise.all(pageIdxs.map(getPage))
}
async function getWithMirrors(resourcePath, hexMirrors) {
if (hexMirrors.length === 0) {
throw new Error(`Could not fetch ${resourcePath} from any hex.pm mirror`)
}
const [hexMirror, ...hexMirrorsT] = hexMirrors
try {
return await get(`${hexMirror}${resourcePath}`, [null])
} catch (err) {
core.info(`get failed for URL ${hexMirror}${resourcePath}`)
}
return getWithMirrors(resourcePath, hexMirrorsT)
}
function maybePrependWithV(v) {
if (isVersion(v)) {
return `v${v.replace('v', '')}`