Feature tool-cache for Gleam and rebar3 (#223)

afb8586 · Paulo F. Oliveira · 2023-08-07 09:32

11 files +936 -838
Message
{commit_body(@commit)}

Files changed

modified .eslintrc.yml
+2 −1
@@ -7,11 +7,12 @@ extends:
7 7 parserOptions:
8 8 ecmaVersion: 2022
9 9 rules:
10 indent: [warn, 2]
10 + indent: [warn, 2, {SwitchCase: 1}]
11 11 max-len: [warn, 100]
12 12 no-use-before-define: 0
13 13 operator-linebreak: 0
14 14 semi: 0
15 + implicit-arrow-linebreak: 0
15 16
16 17 settings:
17 18 react:
modified dist/index.js
+398 −297
@@ -9814,225 +9814,6 @@ try {
9814 9814 } catch (er) {}
9815 9815
9816 9816
9817 /***/ }),
9818
9819 /***/ 2127:
9820 /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
9821
9822 const core = __nccwpck_require__(2186)
9823 const { exec } = __nccwpck_require__(1514)
9824 const tc = __nccwpck_require__(7784)
9825 const path = __nccwpck_require__(1017)
9826 const fs = __nccwpck_require__(7147)
9827 const os = __nccwpck_require__(2037)
9828
9829 /**
9830 * Install Erlang/OTP.
9831 *
9832 * @param {string} osVersion
9833 * @param {string} otpVersion
9834 * @param {string[]} hexMirrors
9835 */
9836 async function installOTP(osVersion, otpVersion, hexMirrors) {
9837 let cmd
9838 let args
9839
9840 if (hexMirrors.length === 0) {
9841 throw new Error(
9842 `Could not install Erlang/OTP ${otpVersion} from any hex.pm mirror`,
9843 )
9844 }
9845
9846 const [hexMirror, ...hexMirrorsT] = hexMirrors
9847 const fullVersion = `${osVersion}/${otpVersion}`
9848 let cachedPath = tc.find('otp', fullVersion)
9849 const OS = process.platform
9850
9851 try {
9852 if (OS === 'linux') {
9853 if (!cachedPath) {
9854 const tarPath = await tc.downloadTool(
9855 `https://builds.hex.pm/builds/otp/${fullVersion}.tar.gz`,
9856 )
9857 const extractPath = await tc.extractTar(tarPath, undefined, [
9858 'zx',
9859 '--strip-components=1',
9860 ])
9861 cachedPath = await tc.cacheDir(extractPath, 'otp', fullVersion)
9862 }
9863
9864 cmd = path.join(cachedPath, 'Install')
9865 args = ['-minimal', cachedPath]
9866 await exec(cmd, args)
9867
9868 const otpPath = path.join(cachedPath, 'bin')
9869
9870 core.addPath(otpPath)
9871 core.exportVariable('INSTALL_DIR_FOR_OTP', cachedPath)
9872
9873 core.info('Installed Erlang/OTP version')
9874 cmd = path.join(otpPath, 'erl')
9875 args = ['-version']
9876 await exec(cmd, args)
9877 } else if (OS === 'win32') {
9878 if (!cachedPath) {
9879 const exePath = await tc.downloadTool(
9880 'https://github.com/erlang/otp/releases/download/' +
9881 `OTP-${otpVersion}/otp_win64_${otpVersion}.exe`,
9882 )
9883 cachedPath = await tc.cacheFile(exePath, 'otp.exe', 'otp', fullVersion)
9884 }
9885
9886 const otpDir = path.join(process.env.RUNNER_TEMP, '.setup-beam', 'otp')
9887 const otpPath = path.join(otpDir, 'bin')
9888
9889 await fs.promises.mkdir(otpDir, { recursive: true })
9890
9891 cmd = path.join(cachedPath, 'otp.exe')
9892 args = ['/S', `/D=${otpDir}`]
9893 await exec(cmd, args)
9894
9895 core.addPath(otpPath)
9896 core.exportVariable('INSTALL_DIR_FOR_OTP', otpDir)
9897
9898 core.info('Installed Erlang/OTP version')
9899
9900 cmd = path.join(otpPath, 'erl.exe')
9901 args = ['+V']
9902 await exec(cmd, args)
9903 }
9904 } catch (err) {
9905 core.info(`Install OTP failed for mirror ${hexMirror}`)
9906 core.info(`${err}\n${err.stack}`)
9907 await installOTP(osVersion, otpVersion, hexMirrorsT)
9908 }
9909 }
9910
9911 /**
9912 * Install Elixir.
9913 *
9914 * @param {string} elixirVersion
9915 * @param {string[]} hexMirrors
9916 */
9917 async function installElixir(elixirVersion, hexMirrors) {
9918 let cmd
9919 let args
9920 let options
9921
9922 if (hexMirrors.length === 0) {
9923 throw new Error(
9924 `Could not install Elixir ${elixirVersion} from any hex.pm mirror`,
9925 )
9926 }
9927 const [hexMirror, ...hexMirrorsT] = hexMirrors
9928
9929 try {
9930 let cachedPath = tc.find('elixir', elixirVersion)
9931 const OS = process.platform
9932
9933 if (!cachedPath) {
9934 const zipPath = await tc.downloadTool(
9935 `${hexMirror}/builds/elixir/${elixirVersion}.zip`,
9936 )
9937 const extractPath = await tc.extractZip(zipPath)
9938 cachedPath = await tc.cacheDir(extractPath, 'elixir', elixirVersion)
9939 }
9940
9941 const elixirPath = path.join(cachedPath, 'bin')
9942 const escriptsPath = path.join(os.homedir(), '.mix', 'escripts')
9943
9944 core.addPath(elixirPath)
9945 core.addPath(escriptsPath)
9946 core.exportVariable('INSTALL_DIR_FOR_ELIXIR', cachedPath)
9947
9948 core.info('Installed Elixir version')
9949
9950 if (debugLoggingEnabled()) {
9951 core.exportVariable('ELIXIR_CLI_ECHO', 'true')
9952 }
9953
9954 if (OS === 'linux') {
9955 cmd = path.join(elixirPath, 'elixir')
9956 args = ['-v']
9957 options = {}
9958 } else if (OS === 'win32') {
9959 cmd = path.join(elixirPath, 'elixir.bat')
9960 args = ['-v']
9961 options = { windowsVerbatimArguments: true }
9962 }
9963 await exec(cmd, args, options)
9964
9965 await fs.promises.mkdir(escriptsPath, { recursive: true })
9966 } catch (err) {
9967 core.info(`Elixir install failed for mirror ${hexMirror}`)
9968 core.info(`${err}\n${err.stack}`)
9969 await installElixir(elixirVersion, hexMirrorsT)
9970 }
9971 }
9972
9973 /**
9974 * Install Gleam.
9975 *
9976 * @param {string} gleamVersion
9977 */
9978 async function installGleam(gleamVersion) {
9979 let cmd
9980 let args
9981
9982 const OS = process.platform
9983 if (OS === 'linux') {
9984 cmd = __nccwpck_require__.ab + "install-gleam.sh"
9985 args = [gleamVersion]
9986 await exec(__nccwpck_require__.ab + "install-gleam.sh", args)
9987 } else if (OS === 'win32') {
9988 cmd = `pwsh.exe ${path.join(__dirname, 'install-gleam.ps1')}`
9989 args = [`-VSN:${gleamVersion}`]
9990 await exec(cmd, args)
9991 }
9992 }
9993
9994 /**
9995 * Install rebar3.
9996 *
9997 * @param {string} rebar3Version
9998 */
9999 async function installRebar3(rebar3Version) {
10000 let cmd
10001 let args
10002
10003 const OS = process.platform
10004 if (OS === 'linux') {
10005 cmd = __nccwpck_require__.ab + "install-rebar3.sh"
10006 args = [rebar3Version]
10007 await exec(__nccwpck_require__.ab + "install-rebar3.sh", args)
10008 } else if (OS === 'win32') {
10009 cmd = `pwsh.exe ${path.join(__dirname, 'install-rebar3.ps1')}`
10010 args = [`-VSN:${rebar3Version}`]
10011 await exec(cmd, args)
10012 }
10013 }
10014
10015 function checkPlatform() {
10016 if (process.platform !== 'linux' && process.platform !== 'win32') {
10017 throw new Error(
10018 '@erlef/setup-beam only supports Ubuntu and Windows at this time',
10019 )
10020 }
10021 }
10022
10023 function debugLoggingEnabled() {
10024 return !!process.env.RUNNER_DEBUG
10025 }
10026
10027 module.exports = {
10028 installOTP,
10029 installElixir,
10030 installGleam,
10031 installRebar3,
10032 checkPlatform,
10033 }
10034
10035
10036 9817 /***/ }),
10037 9818
10038 9819 /***/ 7037:
@@ -10040,18 +9821,19 @@ module.exports = {
10040 9821
10041 9822 const core = __nccwpck_require__(2186)
10042 9823 const { exec } = __nccwpck_require__(1514)
9824 +const tc = __nccwpck_require__(7784)
10043 9825 const http = __nccwpck_require__(6255)
10044 9826 const path = __nccwpck_require__(1017)
10045 9827 const semver = __nccwpck_require__(1383)
10046 9828 const fs = __nccwpck_require__(7147)
10047 const installer = __nccwpck_require__(2127)
9829 +const os = __nccwpck_require__(2037)
10048 9830
10049 9831 main().catch((err) => {
10050 9832 core.setFailed(err.message)
10051 9833 })
10052 9834
10053 9835 async function main() {
10054 installer.checkPlatform()
9836 + checkPlatform()
10055 9837
10056 9838 const versionFilePath = getInput('version-file', false)
10057 9839 let versions
@@ -10069,24 +9851,16 @@ async function main() {
10069 9851 const elixirSpec = getInput('elixir-version', false, 'elixir', versions)
10070 9852 const gleamSpec = getInput('gleam-version', false, 'gleam', versions)
10071 9853 const rebar3Spec = getInput('rebar3-version', false, 'rebar', versions)
10072 const hexMirrors = core.getMultilineInput('hexpm-mirrors', {
10073 required: false,
10074 })
10075 9854
10076 9855 if (otpSpec !== 'false') {
10077 await installOTP(otpSpec, osVersion, hexMirrors)
10078
10079 const elixirInstalled = await maybeInstallElixir(
10080 elixirSpec,
10081 otpSpec,
10082 hexMirrors,
10083 )
9856 + await installOTP(otpSpec, osVersion)
9857 + const elixirInstalled = await maybeInstallElixir(elixirSpec, otpSpec)
10084 9858 if (elixirInstalled === true) {
10085 9859 const shouldMixRebar = getInput('install-rebar', false)
10086 await mix(shouldMixRebar, 'rebar', hexMirrors)
9860 + await mix(shouldMixRebar, 'rebar')
10087 9861
10088 9862 const shouldMixHex = getInput('install-hex', false)
10089 await mix(shouldMixHex, 'hex', hexMirrors)
9863 + await mix(shouldMixHex, 'hex')
10090 9864 }
10091 9865 } else if (!gleamSpec) {
10092 9866 throw new Error('otp-version=false is only available when installing Gleam')
@@ -10096,33 +9870,43 @@ async function main() {
10096 9870 await maybeInstallRebar3(rebar3Spec)
10097 9871 }
10098 9872
10099 async function installOTP(otpSpec, osVersion, hexMirrors) {
10100 const otpVersion = await getOTPVersion(otpSpec, osVersion, hexMirrors)
9873 +async function installOTP(otpSpec, osVersion) {
9874 + const otpVersion = await getOTPVersion(otpSpec, osVersion)
10101 9875 core.startGroup(`Installing Erlang/OTP ${otpVersion} - built on ${osVersion}`)
10102 await installer.installOTP(osVersion, otpVersion, hexMirrors)
9876 + await doWithMirrors({
9877 + hexMirrors: hexMirrorsInput(),
9878 + actionTitle: `install Erlang/OTP ${otpVersion}`,
9879 + action: async (hexMirror) => {
9880 + await install('otp', {
9881 + osVersion,
9882 + toolVersion: otpVersion,
9883 + hexMirror,
9884 + })
9885 + },
9886 + })
10103 9887 core.setOutput('otp-version', otpVersion)
10104 9888 core.endGroup()
10105 9889
10106 9890 return otpVersion
10107 9891 }
10108 9892
10109 async function maybeInstallElixir(elixirSpec, otpSpec, hexMirrors) {
9893 +async function maybeInstallElixir(elixirSpec, otpSpec) {
10110 9894 let installed = false
10111 9895 if (elixirSpec) {
10112 const elixirVersion = await getElixirVersion(
10113 elixirSpec,
10114 otpSpec,
10115 hexMirrors,
10116 )
9896 + const elixirVersion = await getElixirVersion(elixirSpec, otpSpec)
10117 9897 core.startGroup(`Installing Elixir ${elixirVersion}`)
10118 await installer.installElixir(elixirVersion, hexMirrors)
9898 + await doWithMirrors({
9899 + hexMirrors: hexMirrorsInput(),
9900 + actionTitle: `install Elixir ${elixirVersion}`,
9901 + action: async (hexMirror) => {
9902 + await install('elixir', {
9903 + toolVersion: elixirVersion,
9904 + hexMirror,
9905 + })
9906 + },
9907 + })
10119 9908 core.setOutput('elixir-version', elixirVersion)
10120
10121 const disableProblemMatchers = getInput('disable_problem_matchers', false)
10122 if (disableProblemMatchers === 'false') {
10123 const elixirMatchers = __nccwpck_require__.ab + "elixir-matchers.json"
10124 core.info(`##[add-matcher]${elixirMatchers}`)
10125 }
9909 + maybeEnableElixirProblemMatchers()
10126 9910 core.endGroup()
10127 9911
10128 9912 installed = true
@@ -10131,30 +9915,27 @@ async function maybeInstallElixir(elixirSpec, otpSpec, hexMirrors) {
10131 9915 return installed
10132 9916 }
10133 9917
10134 async function mixWithMirrors(cmd, args, hexMirrors) {
10135 if (hexMirrors.length === 0) {
10136 throw new Error('mix failed with every mirror')
9918 +function maybeEnableElixirProblemMatchers() {
9919 + const disableProblemMatchers = getInput('disable_problem_matchers', false)
9920 + if (disableProblemMatchers === 'false') {
9921 + const elixirMatchers = __nccwpck_require__.ab + "elixir-matchers.json"
9922 + core.info(`##[add-matcher]${elixirMatchers}`)
10137 9923 }
10138
10139 const [hexMirror, ...hexMirrorsT] = hexMirrors
10140 process.env.HEX_MIRROR = hexMirror
10141 try {
10142 return await exec(cmd, args)
10143 } catch (err) {
10144 core.info(
10145 `mix failed with mirror ${process.env.HEX_MIRROR} with message ${err.message})`,
10146 )
10147 }
10148
10149 return mixWithMirrors(cmd, args, hexMirrorsT)
10150 9924 }
10151 9925
10152 async function mix(shouldMix, what, hexMirrors) {
9926 +async function mix(shouldMix, what) {
10153 9927 if (shouldMix === 'true') {
10154 9928 const cmd = 'mix'
10155 9929 const args = [`local.${what}`, '--force']
10156 9930 core.startGroup(`Running ${cmd} ${args}`)
10157 await mixWithMirrors(cmd, args, hexMirrors)
9931 + await doWithMirrors({
9932 + hexMirrors: hexMirrorsInput(),
9933 + actionTitle: `mix ${what}`,
9934 + action: async (hexMirror) => {
9935 + process.env.HEX_MIRROR = hexMirror
9936 + await exec(cmd, args)
9937 + },
9938 + })
10158 9939 core.endGroup()
10159 9940 }
10160 9941 }
@@ -10164,7 +9945,7 @@ async function maybeInstallGleam(gleamSpec) {
10164 9945 if (gleamSpec) {
10165 9946 const gleamVersion = await getGleamVersion(gleamSpec)
10166 9947 core.startGroup(`Installing Gleam ${gleamVersion}`)
10167 await installer.installGleam(gleamVersion)
9948 + await install('gleam', { toolVersion: gleamVersion })
10168 9949 core.setOutput('gleam-version', gleamVersion)
10169 9950 core.addPath(`${process.env.RUNNER_TEMP}/.setup-beam/gleam/bin`)
10170 9951 core.endGroup()
@@ -10185,7 +9966,7 @@ async function maybeInstallRebar3(rebar3Spec) {
10185 9966 rebar3Version = await getRebar3Version(rebar3Spec)
10186 9967 }
10187 9968 core.startGroup(`Installing rebar3 ${rebar3Version}`)
10188 await installer.installRebar3(rebar3Version)
9969 + await install('rebar3', { toolVersion: rebar3Version })
10189 9970 core.setOutput('rebar3-version', rebar3Version)
10190 9971 core.addPath(`${process.env.RUNNER_TEMP}/.setup-beam/rebar3/bin`)
10191 9972 core.endGroup()
@@ -10196,9 +9977,9 @@ async function maybeInstallRebar3(rebar3Spec) {
10196 9977 return installed
10197 9978 }
10198 9979
10199 async function getOTPVersion(otpSpec0, osVersion, hexMirrors) {
10200 const otpVersions = await getOTPVersions(osVersion, hexMirrors)
10201 const spec = otpSpec0.replace(/^OTP-/, '')
9980 +async function getOTPVersion(otpSpec0, osVersion) {
9981 + const otpVersions = await getOTPVersions(osVersion)
9982 + let spec = otpSpec0.replace(/^OTP-/, '')
10202 9983 const versions = otpVersions
10203 9984 const otpVersion = getVersionFromSpec(spec, versions)
10204 9985 if (otpVersion === null) {
@@ -10211,15 +9992,15 @@ async function getOTPVersion(otpSpec0, osVersion, hexMirrors) {
10211 9992 return otpVersion // from the reference, for download
10212 9993 }
10213 9994
10214 async function getElixirVersion(exSpec0, otpVersion0, hexMirrors) {
9995 +async function getElixirVersion(exSpec0, otpVersion0) {
10215 9996 const otpVersion = otpVersion0.match(/^([^-]+-)?(.+)$/)[2]
10216 9997 const otpVersionMajor = otpVersion.match(/^([^.]+).*$/)[1]
10217 const [otpVersionsForElixirMap, elixirVersions] = await getElixirVersions(
10218 hexMirrors,
10219 )
9998 +
9999 + const [otpVersionsForElixirMap, elixirVersions] = await getElixirVersions()
10220 10000 const spec = exSpec0.replace(/-otp-.*$/, '')
10221 10001 const versions = elixirVersions
10222 10002 const elixirVersionFromSpec = getVersionFromSpec(spec, versions)
10003 +
10223 10004 if (elixirVersionFromSpec === null) {
10224 10005 throw new Error(
10225 10006 `Requested Elixir version (${exSpec0}) not found in version list ` +
@@ -10283,12 +10064,19 @@ async function getRebar3Version(r3Spec) {
10283 10064 return rebar3Version
10284 10065 }
10285 10066
10286 async function getOTPVersions(osVersion, hexMirrors) {
10067 +async function getOTPVersions(osVersion) {
10287 10068 let otpVersionsListings
10288 10069 let originListing
10289 10070 if (process.platform === 'linux') {
10290 10071 originListing = `/builds/otp/${osVersion}/builds.txt`
10291 otpVersionsListings = await getWithMirrors(originListing, hexMirrors)
10072 + otpVersionsListings = await doWithMirrors({
10073 + hexMirrors: hexMirrorsInput(),
10074 + actionTitle: `fetch ${originListing}`,
10075 + action: async (hexMirror) => {
10076 + const l = await get(`${hexMirror}${originListing}`, [null])
10077 + return l
10078 + },
10079 + })
10292 10080 } else if (process.platform === 'win32') {
10293 10081 originListing =
10294 10082 'https://api.github.com/repos/erlang/otp/releases?per_page=100'
@@ -10331,11 +10119,16 @@ async function getOTPVersions(osVersion, hexMirrors) {
10331 10119 return otpVersions
10332 10120 }
10333 10121
10334 async function getElixirVersions(hexMirrors) {
10335 const elixirVersionsListings = await getWithMirrors(
10336 '/builds/elixir/builds.txt',
10337 hexMirrors,
10338 )
10122 +async function getElixirVersions() {
10123 + const originListing = '/builds/elixir/builds.txt'
10124 + const elixirVersionsListings = await doWithMirrors({
10125 + hexMirrors: hexMirrorsInput(),
10126 + actionTitle: `fetch ${originListing}`,
10127 + action: async (hexMirror) => {
10128 + const l = await get(`${hexMirror}${originListing}`, [null])
10129 + return l
10130 + },
10131 + })
10339 10132 const otpVersionsForElixirMap = {}
10340 10133 const elixirVersions = {}
10341 10134
@@ -10463,6 +10256,7 @@ function maybeCoerced(v) {
10463 10256 }
10464 10257 } catch {
10465 10258 // some stuff can't be coerced, like 'main'
10259 + core.debug(`Was not able to coerce ${v} with semver`)
10466 10260 ret = v
10467 10261 }
10468 10262
@@ -10552,21 +10346,6 @@ async function get(url0, pageIdxs) {
10552 10346 return Promise.all(pageIdxs.map(getPage))
10553 10347 }
10554 10348
10555 async function getWithMirrors(resourcePath, hexMirrors) {
10556 if (hexMirrors.length === 0) {
10557 throw new Error(`Could not fetch ${resourcePath} from any hex.pm mirror`)
10558 }
10559
10560 const [hexMirror, ...hexMirrorsT] = hexMirrors
10561 try {
10562 return await get(`${hexMirror}${resourcePath}`, [null])
10563 } catch (err) {
10564 core.info(`get failed for URL ${hexMirror}${resourcePath}`)
10565 }
10566
10567 return getWithMirrors(resourcePath, hexMirrorsT)
10568 }
10569
10570 10349 function maybePrependWithV(v) {
10571 10350 if (isVersion(v)) {
10572 10351 return `v${v.replace('v', '')}`
@@ -10687,12 +10466,334 @@ function debugLog(groupName, message) {
10687 10466 )
10688 10467 }
10689 10468
10469 +function hexMirrorsInput() {
10470 + return core.getMultilineInput('hexpm-mirrors', {
10471 + required: false,
10472 + })
10473 +}
10474 +
10475 +async function doWithMirrors(opts) {
10476 + const { hexMirrors, actionTitle, action } = opts
10477 + let actionRes
10478 +
10479 + if (hexMirrors.length === 0) {
10480 + throw new Error(`Could not ${actionTitle} from any hex.pm mirror`)
10481 + }
10482 +
10483 + const [hexMirror, ...hexMirrorsT] = hexMirrors
10484 + try {
10485 + actionRes = await action(hexMirror)
10486 + } catch (err) {
10487 + core.info(
10488 + `Action ${actionTitle} failed for mirror ${hexMirror}, with ${err}`,
10489 + )
10490 + core.debug(`Stacktrace: ${err.stack}`)
10491 + actionRes = await doWithMirrors({
10492 + hexMirrors: hexMirrorsT,
10493 + actionTitle,
10494 + action,
10495 + })
10496 + }
10497 +
10498 + return actionRes
10499 +}
10500 +
10501 +async function install(toolName, opts) {
10502 + const { osVersion, toolVersion, hexMirror } = opts
10503 + const versionSpec =
10504 + osVersion !== undefined ? `${osVersion}/${toolVersion}` : toolVersion
10505 + let installOpts
10506 +
10507 + // The installOpts object is composed of supported processPlatform keys
10508 + // (e.g. 'linux', 'win32', or 'all' - in case there's no distinction between platforms)
10509 + // In each of these keys there's an object with keys:
10510 + // * downloadToolURL
10511 + // - where to fetch the downloadable from
10512 + // * extract
10513 + // - if the downloadable is compressed: how to extract it
10514 + // - return ['dir', targetDir]
10515 + // - if the downloadable is not compressed: a filename.ext you want to cache it under
10516 + // - return ['file', filenameWithExt]
10517 + // * postExtract
10518 + // - stuff to execute outside the cache scope (just after it's created)
10519 + // * reportVersion
10520 + /// - configuration elements on how to output the tool version, post-install
10521 +
10522 + switch (toolName) {
10523 + case 'otp':
10524 + installOpts = {
10525 + tool: 'Erlang/OTP',
10526 + linux: {
10527 + downloadToolURL: () =>
10528 + `${hexMirror}/builds/otp/${versionSpec}.tar.gz`,
10529 + extract: async (file) => {
10530 + const dest = undefined
10531 + const flags = ['zx', '--strip-components=1']
10532 + const targetDir = await tc.extractTar(file, dest, flags)
10533 +
10534 + return ['dir', targetDir]
10535 + },
10536 + postExtract: async (cachePath) => {
10537 + const cmd = path.join(cachePath, 'Install')
10538 + const args = ['-minimal', cachePath]
10539 + await exec(cmd, args)
10540 + },
10541 + reportVersion: () => {
10542 + const cmd = 'erl'
10543 + const args = ['-version']
10544 +
10545 + return [cmd, args]
10546 + },
10547 + },
10548 + win32: {
10549 + downloadToolURL: () =>
10550 + 'https://github.com/erlang/otp/releases/download/' +
10551 + `OTP-${toolVersion}/otp_win64_${toolVersion}.exe`,
10552 + extract: async () => ['file', 'otp.exe'],
10553 + postExtract: async (cachePath) => {
10554 + const cmd = path.join(cachePath, 'otp.exe')
10555 + const args = ['/S', `/D=${cachePath}`]
10556 + await exec(cmd, args)
10557 + },
10558 + reportVersion: () => {
10559 + const cmd = 'erl.exe'
10560 + const args = ['+V']
10561 +
10562 + return [cmd, args]
10563 + },
10564 + },
10565 + }
10566 + break
10567 + case 'elixir':
10568 + installOpts = {
10569 + tool: 'Elixir',
10570 + all: {
10571 + downloadToolURL: () =>
10572 + `${hexMirror}/builds/elixir/${versionSpec}.zip`,
10573 + extract: async (file) => {
10574 + const targetDir = await tc.extractZip(file)
10575 +
10576 + return ['dir', targetDir]
10577 + },
10578 + postExtract: async () => {
10579 + const escriptsPath = path.join(os.homedir(), '.mix', 'escripts')
10580 + fs.mkdirSync(escriptsPath, { recursive: true })
10581 + core.addPath(escriptsPath)
10582 +
10583 + if (debugLoggingEnabled()) {
10584 + core.exportVariable('ELIXIR_CLI_ECHO', 'true')
10585 + }
10586 + },
10587 + reportVersion: () => {
10588 + const cmd = 'elixir'
10589 + const args = ['-v']
10590 +
10591 + return [cmd, args]
10592 + },
10593 + },
10594 + }
10595 + break
10596 + case 'gleam':
10597 + installOpts = {
10598 + tool: 'Gleam',
10599 + linux: {
10600 + downloadToolURL: () => {
10601 + let gz
10602 + if (
10603 + versionSpec === 'nightly' ||
10604 + semver.gt(versionSpec, 'v0.22.1')
10605 + ) {
10606 + gz = `gleam-${versionSpec}-x86_64-unknown-linux-musl.tar.gz`
10607 + } else {
10608 + gz = `gleam-${versionSpec}-linux-amd64.tar.gz`
10609 + }
10610 +
10611 + return `https://github.com/gleam-lang/gleam/releases/download/${versionSpec}/${gz}`
10612 + },
10613 + extract: async (file) => {
10614 + const dest = undefined
10615 + const flags = ['zx']
10616 + const targetDir = await tc.extractTar(file, dest, flags)
10617 +
10618 + return ['dir', targetDir]
10619 + },
10620 + postExtract: async (cachePath) => {
10621 + const bindir = path.join(cachePath, 'bin')
10622 + const oldPath = path.join(cachePath, 'gleam')
10623 + const newPath = path.join(bindir, 'gleam')
10624 + fs.mkdirSync(bindir)
10625 + fs.renameSync(oldPath, newPath)
10626 + },
10627 + reportVersion: () => {
10628 + const cmd = 'gleam'
10629 + const args = ['--version']
10630 +
10631 + return [cmd, args]
10632 + },
10633 + },
10634 + win32: {
10635 + downloadToolURL: () => {
10636 + let zip
10637 + if (
10638 + versionSpec === 'nightly' ||
10639 + semver.gt(versionSpec, 'v0.22.1')
10640 + ) {
10641 + zip = `gleam-${versionSpec}-x86_64-pc-windows-msvc.zip`
10642 + } else {
10643 + zip = `gleam-${versionSpec}-windows-64bit.zip`
10644 + }
10645 +
10646 + return `https://github.com/gleam-lang/gleam/releases/download/${versionSpec}/${zip}`
10647 + },
10648 + extract: async (file) => {
10649 + const targetDir = await tc.extractZip(file)
10650 +
10651 + return ['dir', targetDir]
10652 + },
10653 + postExtract: async (cachePath) => {
10654 + const bindir = path.join(cachePath, 'bin')
10655 + const oldPath = path.join(cachePath, 'gleam.exe')
10656 + const newPath = path.join(bindir, 'gleam.exe')
10657 + fs.mkdirSync(bindir)
10658 + fs.renameSync(oldPath, newPath)
10659 + },
10660 + reportVersion: () => {
10661 + const cmd = 'gleam.exe'
10662 + const args = ['--version']
10663 +
10664 + return [cmd, args]
10665 + },
10666 + },
10667 + }
10668 + break
10669 + case 'rebar3':
10670 + installOpts = {
10671 + tool: 'Rebar3',
10672 + linux: {
10673 + downloadToolURL: () => {
10674 + let url
10675 + if (versionSpec === 'nightly') {
10676 + url = 'https://s3.amazonaws.com/rebar3-nightly/rebar3'
10677 + } else {
10678 + url = `https://github.com/erlang/rebar3/releases/download/${versionSpec}/rebar3`
10679 + }
10680 +
10681 + return url
10682 + },
10683 + extract: async () => ['file', 'rebar3'],
10684 + postExtract: async (cachePath) => {
10685 + const bindir = path.join(cachePath, 'bin')
10686 + const oldPath = path.join(cachePath, 'rebar3')
10687 + const newPath = path.join(bindir, 'rebar3')
10688 + fs.mkdirSync(bindir)
10689 + fs.renameSync(oldPath, newPath)
10690 + fs.chmodSync(newPath, 0o755)
10691 + },
10692 + reportVersion: () => {
10693 + const cmd = 'rebar3'
10694 + const args = ['version']
10695 +
10696 + return [cmd, args]
10697 + },
10698 + },
10699 + win32: {
10700 + downloadToolURL: () => {
10701 + let url
10702 + if (versionSpec === 'nightly') {
10703 + url = 'https://s3.amazonaws.com/rebar3-nightly/rebar3'
10704 + } else {
10705 + url = `https://github.com/erlang/rebar3/releases/download/${versionSpec}/rebar3`
10706 + }
10707 +
10708 + return url
10709 + },
10710 + extract: async () => ['file', 'rebar3'],
10711 + postExtract: async (cachePath) => {
10712 + const bindir = path.join(cachePath, 'bin')
10713 + const oldPath = path.join(cachePath, 'rebar3')
10714 + fs.mkdirSync(bindir)
10715 + fs.chmodSync(oldPath, 0o755)
10716 +
10717 + const ps1Filename = path.join(bindir, 'rebar3.ps1')
10718 + fs.writeFileSync(ps1Filename, `& escript.exe ${oldPath} \${args}`)
10719 +
10720 + const cmdFilename = path.join(bindir, 'rebar3.cmd')
10721 + fs.writeFileSync(
10722 + cmdFilename,
10723 + `@echo off\r\nescript.exe ${oldPath} %*`,
10724 + )
10725 + },
10726 + reportVersion: () => {
10727 + const cmd = 'rebar3.cmd'
10728 + const args = ['version']
10729 +
10730 + return [cmd, args]
10731 + },
10732 + },
10733 + }
10734 + break
10735 + default:
10736 + throw new Error(`no installer for ${toolName}`)
10737 + }
10738 +
10739 + await installTool({ toolName, versionSpec, installOpts })
10740 +}
10741 +
10742 +async function installTool(opts) {
10743 + const { toolName, versionSpec, installOpts } = opts
10744 + const platformOpts = installOpts[process.platform] || installOpts.all
10745 + let cachePath = tc.find(toolName, versionSpec)
10746 +
10747 + core.debug(`Checking if ${installOpts.tool} is already cached...`)
10748 + if (cachePath === '') {
10749 + core.debug(" ... it isn't!")
10750 + const downloadToolURL = platformOpts.downloadToolURL()
10751 + const file = await tc.downloadTool(downloadToolURL)
10752 + const [targetElemType, targetElem] = await platformOpts.extract(file)
10753 +
10754 + if (targetElemType === 'dir') {
10755 + cachePath = await tc.cacheDir(targetElem, toolName, versionSpec)
10756 + } else if (targetElemType === 'file') {
10757 + cachePath = await tc.cacheFile(file, targetElem, toolName, versionSpec)
10758 + }
10759 + } else {
10760 + core.debug(` ... it is, at ${cachePath}`)
10761 + }
10762 +
10763 + core.debug('Performing post extract operations...')
10764 + await platformOpts.postExtract(cachePath)
10765 +
10766 + core.debug(`Adding ${cachePath}'s bin to system path`)
10767 + core.addPath(path.join(cachePath, 'bin'))
10768 +
10769 + const installDirForVarName = `INSTALL_DIR_FOR_${toolName}`.toUpperCase()
10770 + core.debug(`Exporting ${installDirForVarName} as ${cachePath}`)
10771 + core.exportVariable(installDirForVarName, cachePath)
10772 +
10773 + core.info(`Installed ${installOpts.tool} version`)
10774 + const [cmd, args] = platformOpts.reportVersion()
10775 + await exec(cmd, args)
10776 +}
10777 +
10778 +function checkPlatform() {
10779 + if (process.platform !== 'linux' && process.platform !== 'win32') {
10780 + throw new Error(
10781 + '@erlef/setup-beam only supports Ubuntu and Windows at this time',
10782 + )
10783 + }
10784 +}
10785 +
10786 +function debugLoggingEnabled() {
10787 + return !!process.env.RUNNER_DEBUG
10788 +}
10789 +
10690 10790 module.exports = {
10691 10791 getOTPVersion,
10692 10792 getElixirVersion,
10693 10793 getGleamVersion,
10694 10794 getRebar3Version,
10695 10795 getVersionFromSpec,
10796 + install,
10696 10797 parseVersionFile,
10697 10798 }
10698 10799
modified package.json
+2 −2
@@ -8,8 +8,8 @@
8 8 "jslint": "eslint src/**/*.js && eslint test/**/*.js",
9 9 "licenses": "yarn licenses generate-disclaimer > 3RD_PARTY_LICENSES",
10 10 "markdownlint": "markdownlint *.md ./github/**/*.md",
11 "shellcheck": "shellcheck src/install-*.sh .github/workflows/*.sh",
12 "test": "node test/setup-beam.test.js && node ./test/problem-matchers.test.js",
11 + "shellcheck": "shellcheck .github/workflows/*.sh",
12 + "test": "node test/setup-beam.test.js",
13 13 "yamllint": "yamllint .github/workflows/**.yml && yamllint .*.yml && yamllint *.yml",
14 14 "build-dist": "npm install && npm run build && npm run format && npm run markdownlint && npm run shellcheck && npm run yamllint && npm run jslint"
15 15 },
deleted src/install-gleam.ps1
+0 −37
@@ -1,37 +0,0 @@
1 param([Parameter(Mandatory=$true)][string]${VSN})
2
3 $ErrorActionPreference="Stop"
4
5 Set-Location ${Env:RUNNER_TEMP}
6
7 $FILE_OUTPUT="gleam.zip"
8 $DIR_FOR_BIN=".setup-beam/gleam"
9
10 function Version-Greater-Than([string]${THIS_ONE}, [string]${REFERENCE}) {
11 $THIS_ONE=$THIS_ONE.replace('v', '')
12 $THIS_ONE=$THIS_ONE.replace('rc', '')
13 $THIS_ONE=$THIS_ONE.replace('-', '')
14 return [version]${THIS_ONE} -gt [version]${REFERENCE}
15 }
16
17 function Uses-LLVM-Triplets([string]${THIS_VSN}) {
18 return "${THIS_VSN}" -eq "nightly" -or (Version-Greater-Than "${THIS_VSN}" "0.22.1")
19 }
20
21 if (Uses-LLVM-Triplets "$VSN") {
22 $FILE_INPUT="gleam-${VSN}-x86_64-pc-windows-msvc.zip"
23 } else {
24 $FILE_INPUT="gleam-${VSN}-windows-64bit.zip"
25 }
26
27 $ProgressPreference="SilentlyContinue"
28 Invoke-WebRequest "https://github.com/gleam-lang/gleam/releases/download/${VSN}/${FILE_INPUT}" -OutFile "${FILE_OUTPUT}"
29 $ProgressPreference="Continue"
30 New-Item "${DIR_FOR_BIN}/bin" -ItemType Directory | Out-Null
31 $ProgressPreference="SilentlyContinue"
32 Expand-Archive -DestinationPath "${DIR_FOR_BIN}/bin" -Path "${FILE_OUTPUT}"
33 $ProgressPreference="Continue"
34 Write-Output "Installed Gleam version follows"
35 & "${DIR_FOR_BIN}/bin/gleam" "--version" | Write-Output
36
37 "INSTALL_DIR_FOR_GLEAM=${Env:RUNNER_TEMP}/${DIR_FOR_BIN}" | Out-File -FilePath ${Env:GITHUB_ENV} -Encoding utf8 -Append
deleted src/install-gleam.sh
+0 −35
@@ -1,35 +0,0 @@
1 #!/bin/bash
2
3 set -eo pipefail
4
5 cd "${RUNNER_TEMP}"
6
7 VSN="$1"
8 FILE_OUTPUT=gleam.tar.gz
9 DIR_FOR_BIN=.setup-beam/gleam
10
11 version_gt() {
12 REFERENCE=$1
13 test "$(printf '%s\n' "$@" | sort -V | head -n 1)" != "$REFERENCE"
14 }
15
16 uses_llvm_triplets() {
17 local VERSION="$1"
18 test "${VERSION}" = "nightly" || version_gt "${VERSION}" "v0.22.1"
19 }
20
21 if uses_llvm_triplets "$VSN"
22 then
23 FILE_INPUT="gleam-${VSN}-x86_64-unknown-linux-musl.tar.gz"
24 else
25 FILE_INPUT="gleam-${VSN}-linux-amd64.tar.gz"
26 fi
27
28 wget -q -O "${FILE_OUTPUT}" "https://github.com/gleam-lang/gleam/releases/download/${VSN}/${FILE_INPUT}"
29 mkdir -p "${DIR_FOR_BIN}/bin"
30 tar zxf "${FILE_OUTPUT}" -C "${DIR_FOR_BIN}/bin"
31
32 echo "Installed Gleam version follows"
33 ${DIR_FOR_BIN}/bin/gleam --version
34
35 echo "INSTALL_DIR_FOR_GLEAM=${RUNNER_TEMP}/${DIR_FOR_BIN}" >> "${GITHUB_ENV}"
deleted src/install-rebar3.ps1
+0 −32

Click to load diff…

deleted src/install-rebar3.sh
+0 −25

Click to load diff…

deleted src/installer.js
+0 −212

Click to load diff…

modified src/setup-beam.js
+402 −82

Click to load diff…

deleted test/problem-matchers.test.js
+0 −82

Click to load diff…

modified test/setup-beam.test.js
+132 −33

Click to load diff…

Parents: 3ba5b86