Skip to content

Commit 8fc1380

Browse files
Fix calculating -otp- major for Elixir (#351)
* Set expectations * Ease testing without having to install via `require` * Code a solution for the tests * Avoid errors on unit tests rebar3 is saying something about SSL, most likely because our tests are installing a bunch of OTPs which makes for unpredictable behavior * Avoid errors on integration tests
1 parent 3c915dd commit 8fc1380

File tree

6 files changed

+192
-123
lines changed

6 files changed

+192
-123
lines changed

.github/workflows/action.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ jobs:
7676
uses: ./
7777
with:
7878
install-rebar: false
79+
install-hex: false
7980
version-file: test/.tool-versions
8081
version-type: strict
8182

.github/workflows/ubuntu.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,15 @@ jobs:
2525
fail-fast: false
2626
matrix:
2727
combo:
28+
- otp-version: '<26'
29+
elixir-version: '<1.17'
30+
os: 'ubuntu-22.04'
31+
- otp-version: 'master'
32+
elixir-version: '> 0'
33+
os: 'ubuntu-24.04'
34+
- otp-version: 'master'
35+
elixir-version: 'main'
36+
os: 'ubuntu-24.04'
2837
- otp-version: '27'
2938
elixir-version: 'v1.17.0'
3039
rebar3-version: '3.23'

.github/workflows/windows.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@ jobs:
2525
fail-fast: false
2626
matrix:
2727
combo:
28+
- otp-version: '<26'
29+
elixir-version: '<1.17'
30+
os: 'ubuntu-22.04'
31+
- otp-version: 'master'
32+
elixir-version: '> 0'
33+
os: 'ubuntu-24.04'
2834
- otp-version: '27'
2935
elixir-version: 'v1.17.0'
3036
rebar3-version: '3.23'

dist/index.js

Lines changed: 59 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -25890,9 +25890,11 @@ const _ = __nccwpck_require__(2356)
2589025890

2589125891
const MAX_HTTP_RETRIES = 3
2589225892

25893-
main().catch((err) => {
25894-
core.setFailed(err.message)
25895-
})
25893+
if (process.env.NODE_ENV !== 'test') {
25894+
main().catch((err) => {
25895+
core.setFailed(err.message)
25896+
})
25897+
}
2589625898

2589725899
async function main() {
2589825900
checkOtpArchitecture()
@@ -25908,15 +25910,14 @@ async function main() {
2590825910
versions = parseVersionFile(versionFilePath)
2590925911
}
2591025912

25911-
const osVersion = getRunnerOSVersion()
2591225913
const otpSpec = getInput('otp-version', true, 'erlang', versions)
2591325914
const elixirSpec = getInput('elixir-version', false, 'elixir', versions)
2591425915
const gleamSpec = getInput('gleam-version', false, 'gleam', versions)
2591525916
const rebar3Spec = getInput('rebar3-version', false, 'rebar', versions)
2591625917

2591725918
if (otpSpec !== 'false') {
25918-
await installOTP(otpSpec, osVersion)
25919-
const elixirInstalled = await maybeInstallElixir(elixirSpec, otpSpec)
25919+
await installOTP(otpSpec)
25920+
const elixirInstalled = await maybeInstallElixir(elixirSpec)
2592025921
if (elixirInstalled === true) {
2592125922
const shouldMixRebar = getInput('install-rebar', false)
2592225923
await mix(shouldMixRebar, 'rebar')
@@ -25936,7 +25937,8 @@ async function main() {
2593625937
core.setOutput('setup-beam-version', setupBeamVersion)
2593725938
}
2593825939

25939-
async function installOTP(otpSpec, osVersion) {
25940+
async function installOTP(otpSpec) {
25941+
const osVersion = getRunnerOSVersion()
2594025942
const otpVersion = await getOTPVersion(otpSpec, osVersion)
2594125943
core.startGroup(
2594225944
`Installing Erlang/OTP ${otpVersion} - built on ${getRunnerOSArchitecture()}/${osVersion}`,
@@ -25958,10 +25960,10 @@ async function installOTP(otpSpec, osVersion) {
2595825960
return otpVersion
2595925961
}
2596025962

25961-
async function maybeInstallElixir(elixirSpec, otpSpec) {
25963+
async function maybeInstallElixir(elixirSpec) {
2596225964
let installed = false
2596325965
if (elixirSpec) {
25964-
const elixirVersion = await getElixirVersion(elixirSpec, otpSpec)
25966+
const elixirVersion = await getElixirVersion(elixirSpec)
2596525967
core.startGroup(`Installing Elixir ${elixirVersion}`)
2596625968
await doWithMirrors({
2596725969
hexMirrors: hexMirrorsInput(),
@@ -26070,16 +26072,30 @@ function requestedVersionFor(tool, version, originListing, mirrors) {
2607026072
const knownBranches = ['main', 'master', 'maint']
2607126073
const nonSpecificVersions = ['nightly', 'latest']
2607226074

26073-
async function getElixirVersion(exSpec0, otpVersion0) {
26074-
const otpVersion = otpVersion0.match(/^(?:OTP-)?(.+)$/)[1]
26075-
const regex = `^(\\d{1,3}|${knownBranches.join('|')}|${nonSpecificVersions.join('|')})?.*$`
26076-
let otpVersionMajor = otpVersion.match(new RegExp(regex))[1]
26077-
26075+
async function getElixirVersion(exSpec0) {
2607826076
const otpSuffix = /-otp-(\d+)/
2607926077
const userSuppliedOtp = exSpec0.match(otpSuffix)?.[1] ?? null
26078+
let otpVersionMajor = ''
2608026079

2608126080
if (userSuppliedOtp && isVersion(userSuppliedOtp)) {
2608226081
otpVersionMajor = userSuppliedOtp
26082+
} else {
26083+
let cmd = 'erl'
26084+
if (process.platform === 'win32') {
26085+
cmd = 'erl.exe'
26086+
}
26087+
const args = [
26088+
'-noshell',
26089+
'-eval',
26090+
'io:format(erlang:system_info(otp_release)), halt().',
26091+
]
26092+
await exec(cmd, args, {
26093+
listeners: {
26094+
stdout: (data) => {
26095+
otpVersionMajor = data.toString()
26096+
},
26097+
},
26098+
})
2608326099
}
2608426100

2608526101
const [otpVersionsForElixirMap, elixirVersions, originListing, hexMirrors] =
@@ -26094,17 +26110,29 @@ async function getElixirVersion(exSpec0, otpVersion0) {
2609426110
)
2609526111
}
2609626112

26097-
const elixirVersionComp = otpVersionsForElixirMap[elixirVersionFromSpec]
26098-
if (
26099-
(elixirVersionComp && elixirVersionComp.includes(otpVersionMajor)) ||
26100-
!isVersion(otpVersionMajor)
26101-
) {
26102-
core.info(
26103-
`Using Elixir ${elixirVersionFromSpec} (built for Erlang/OTP ${otpVersionMajor})`,
26104-
)
26105-
} else {
26113+
let foundCombo = false
26114+
let otpVersionMajorIter = parseInt(otpVersionMajor)
26115+
let otpVersionsMajor = []
26116+
while (otpVersionMajorIter > otpVersionMajor - 3) {
26117+
otpVersionMajorIter += ''
26118+
otpVersionsMajor.push(otpVersionMajorIter)
26119+
const elixirVersionComp = otpVersionsForElixirMap[elixirVersionFromSpec]
26120+
if (
26121+
(elixirVersionComp && elixirVersionComp.includes(otpVersionMajorIter)) ||
26122+
!isVersion(otpVersionMajorIter)
26123+
) {
26124+
core.info(
26125+
`Using Elixir ${elixirVersionFromSpec} (built for Erlang/OTP ${otpVersionMajorIter})`,
26126+
)
26127+
foundCombo = true
26128+
break
26129+
}
26130+
otpVersionMajorIter = parseInt(otpVersionMajorIter) - 1
26131+
}
26132+
26133+
if (!foundCombo) {
2610626134
throw new Error(
26107-
`Requested Elixir / Erlang/OTP version (${exSpec0} / ${otpVersion0}) not ` +
26135+
`Requested Elixir / Erlang/OTP version (${exSpec0} / tried ${otpVersionsMajor}) not ` +
2610826136
'found in version list (did you check Compatibility between Elixir and Erlang/OTP?).' +
2610926137
'Elixir and Erlang/OTP compatibility can be found at: ' +
2611026138
'https://hexdocs.pm/elixir/compatibility-and-deprecations.html',
@@ -26113,8 +26141,8 @@ async function getElixirVersion(exSpec0, otpVersion0) {
2611326141

2611426142
let elixirVersionForDownload = elixirVersionFromSpec
2611526143

26116-
if (isVersion(otpVersionMajor)) {
26117-
elixirVersionForDownload = `${elixirVersionFromSpec}-otp-${otpVersionMajor}`
26144+
if (isVersion(otpVersionMajorIter)) {
26145+
elixirVersionForDownload = `${elixirVersionFromSpec}-otp-${otpVersionMajorIter}`
2611826146
}
2611926147

2612026148
return maybePrependWithV(elixirVersionForDownload)
@@ -27073,14 +27101,18 @@ function debugLoggingEnabled() {
2707327101

2707427102
module.exports = {
2707527103
get,
27076-
getOTPVersion,
2707727104
getElixirVersion,
2707827105
getGleamVersion,
27106+
getOTPVersion,
2707927107
getRebar3Version,
2708027108
getVersionFromSpec,
2708127109
githubAMDRunnerArchs,
2708227110
githubARMRunnerArchs,
2708327111
install,
27112+
installOTP,
27113+
maybeInstallElixir,
27114+
maybeInstallGleam,
27115+
maybeInstallRebar3,
2708427116
parseVersionFile,
2708527117
}
2708627118

src/setup-beam.js

Lines changed: 59 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@ const _ = require('lodash')
1010

1111
const MAX_HTTP_RETRIES = 3
1212

13-
main().catch((err) => {
14-
core.setFailed(err.message)
15-
})
13+
if (process.env.NODE_ENV !== 'test') {
14+
main().catch((err) => {
15+
core.setFailed(err.message)
16+
})
17+
}
1618

1719
async function main() {
1820
checkOtpArchitecture()
@@ -28,15 +30,14 @@ async function main() {
2830
versions = parseVersionFile(versionFilePath)
2931
}
3032

31-
const osVersion = getRunnerOSVersion()
3233
const otpSpec = getInput('otp-version', true, 'erlang', versions)
3334
const elixirSpec = getInput('elixir-version', false, 'elixir', versions)
3435
const gleamSpec = getInput('gleam-version', false, 'gleam', versions)
3536
const rebar3Spec = getInput('rebar3-version', false, 'rebar', versions)
3637

3738
if (otpSpec !== 'false') {
38-
await installOTP(otpSpec, osVersion)
39-
const elixirInstalled = await maybeInstallElixir(elixirSpec, otpSpec)
39+
await installOTP(otpSpec)
40+
const elixirInstalled = await maybeInstallElixir(elixirSpec)
4041
if (elixirInstalled === true) {
4142
const shouldMixRebar = getInput('install-rebar', false)
4243
await mix(shouldMixRebar, 'rebar')
@@ -56,7 +57,8 @@ async function main() {
5657
core.setOutput('setup-beam-version', setupBeamVersion)
5758
}
5859

59-
async function installOTP(otpSpec, osVersion) {
60+
async function installOTP(otpSpec) {
61+
const osVersion = getRunnerOSVersion()
6062
const otpVersion = await getOTPVersion(otpSpec, osVersion)
6163
core.startGroup(
6264
`Installing Erlang/OTP ${otpVersion} - built on ${getRunnerOSArchitecture()}/${osVersion}`,
@@ -78,10 +80,10 @@ async function installOTP(otpSpec, osVersion) {
7880
return otpVersion
7981
}
8082

81-
async function maybeInstallElixir(elixirSpec, otpSpec) {
83+
async function maybeInstallElixir(elixirSpec) {
8284
let installed = false
8385
if (elixirSpec) {
84-
const elixirVersion = await getElixirVersion(elixirSpec, otpSpec)
86+
const elixirVersion = await getElixirVersion(elixirSpec)
8587
core.startGroup(`Installing Elixir ${elixirVersion}`)
8688
await doWithMirrors({
8789
hexMirrors: hexMirrorsInput(),
@@ -195,16 +197,30 @@ function requestedVersionFor(tool, version, originListing, mirrors) {
195197
const knownBranches = ['main', 'master', 'maint']
196198
const nonSpecificVersions = ['nightly', 'latest']
197199

198-
async function getElixirVersion(exSpec0, otpVersion0) {
199-
const otpVersion = otpVersion0.match(/^(?:OTP-)?(.+)$/)[1]
200-
const regex = `^(\\d{1,3}|${knownBranches.join('|')}|${nonSpecificVersions.join('|')})?.*$`
201-
let otpVersionMajor = otpVersion.match(new RegExp(regex))[1]
202-
200+
async function getElixirVersion(exSpec0) {
203201
const otpSuffix = /-otp-(\d+)/
204202
const userSuppliedOtp = exSpec0.match(otpSuffix)?.[1] ?? null
203+
let otpVersionMajor = ''
205204

206205
if (userSuppliedOtp && isVersion(userSuppliedOtp)) {
207206
otpVersionMajor = userSuppliedOtp
207+
} else {
208+
let cmd = 'erl'
209+
if (process.platform === 'win32') {
210+
cmd = 'erl.exe'
211+
}
212+
const args = [
213+
'-noshell',
214+
'-eval',
215+
'io:format(erlang:system_info(otp_release)), halt().',
216+
]
217+
await exec(cmd, args, {
218+
listeners: {
219+
stdout: (data) => {
220+
otpVersionMajor = data.toString()
221+
},
222+
},
223+
})
208224
}
209225

210226
const [otpVersionsForElixirMap, elixirVersions, originListing, hexMirrors] =
@@ -219,17 +235,29 @@ async function getElixirVersion(exSpec0, otpVersion0) {
219235
)
220236
}
221237

222-
const elixirVersionComp = otpVersionsForElixirMap[elixirVersionFromSpec]
223-
if (
224-
(elixirVersionComp && elixirVersionComp.includes(otpVersionMajor)) ||
225-
!isVersion(otpVersionMajor)
226-
) {
227-
core.info(
228-
`Using Elixir ${elixirVersionFromSpec} (built for Erlang/OTP ${otpVersionMajor})`,
229-
)
230-
} else {
238+
let foundCombo = false
239+
let otpVersionMajorIter = parseInt(otpVersionMajor)
240+
let otpVersionsMajor = []
241+
while (otpVersionMajorIter > otpVersionMajor - 3) {
242+
otpVersionMajorIter += ''
243+
otpVersionsMajor.push(otpVersionMajorIter)
244+
const elixirVersionComp = otpVersionsForElixirMap[elixirVersionFromSpec]
245+
if (
246+
(elixirVersionComp && elixirVersionComp.includes(otpVersionMajorIter)) ||
247+
!isVersion(otpVersionMajorIter)
248+
) {
249+
core.info(
250+
`Using Elixir ${elixirVersionFromSpec} (built for Erlang/OTP ${otpVersionMajorIter})`,
251+
)
252+
foundCombo = true
253+
break
254+
}
255+
otpVersionMajorIter = parseInt(otpVersionMajorIter) - 1
256+
}
257+
258+
if (!foundCombo) {
231259
throw new Error(
232-
`Requested Elixir / Erlang/OTP version (${exSpec0} / ${otpVersion0}) not ` +
260+
`Requested Elixir / Erlang/OTP version (${exSpec0} / tried ${otpVersionsMajor}) not ` +
233261
'found in version list (did you check Compatibility between Elixir and Erlang/OTP?).' +
234262
'Elixir and Erlang/OTP compatibility can be found at: ' +
235263
'https://hexdocs.pm/elixir/compatibility-and-deprecations.html',
@@ -238,8 +266,8 @@ async function getElixirVersion(exSpec0, otpVersion0) {
238266

239267
let elixirVersionForDownload = elixirVersionFromSpec
240268

241-
if (isVersion(otpVersionMajor)) {
242-
elixirVersionForDownload = `${elixirVersionFromSpec}-otp-${otpVersionMajor}`
269+
if (isVersion(otpVersionMajorIter)) {
270+
elixirVersionForDownload = `${elixirVersionFromSpec}-otp-${otpVersionMajorIter}`
243271
}
244272

245273
return maybePrependWithV(elixirVersionForDownload)
@@ -1198,13 +1226,17 @@ function debugLoggingEnabled() {
11981226

11991227
module.exports = {
12001228
get,
1201-
getOTPVersion,
12021229
getElixirVersion,
12031230
getGleamVersion,
1231+
getOTPVersion,
12041232
getRebar3Version,
12051233
getVersionFromSpec,
12061234
githubAMDRunnerArchs,
12071235
githubARMRunnerArchs,
12081236
install,
1237+
installOTP,
1238+
maybeInstallElixir,
1239+
maybeInstallGleam,
1240+
maybeInstallRebar3,
12091241
parseVersionFile,
12101242
}

0 commit comments

Comments
 (0)