diff --git a/action.yml b/action.yml index d0ef387..4b54aed 100644 --- a/action.yml +++ b/action.yml @@ -18,10 +18,27 @@ inputs: manifest: description: JSON or opam file to be used required: false + ocaml-compiler-version: + description: + Version of ocaml compiler (in semver. Eg. 5.1.0 or 4.10.1000) Optional, + but mandatory if prepare-npm-artifacts-mode and bundle-npm-artifacts-mode + is used. This is because, these version strings affect the relocatability + logic while both preparation mode, and while postinstall scripts are + generated during bundling mode. + required: false + ocaml-static-compiler-version: + description: + Version of static ocaml compiler (in semver. Eg. 5.1.0-musl.static.flambda + or 4.10.1000-musl.static.flambda). Optional, but mandatory if + prepare-npm-artifacts-mode and bundle-npm-artifacts-mode is used. This is + because, these version strings affect the relocatability logic while both + preparation mode, and while postinstall scripts are generated during + bundling mode. + required: false prepare-npm-artifacts-mode: description: Runs a steps that prepare artifacts for release the app to NPM. These - artifacts are later used by, `bundle-npm-tarball-mode` + artifacts are later used by, `bundle-npm-tarball-mode`. required: false bundle-npm-artifacts-mode: description: Runs a steps that bundle artifacts for release the app to NPM. diff --git a/dist/index.js b/dist/index.js index 353fa72..e6c1f8e 100644 --- a/dist/index.js +++ b/dist/index.js @@ -143888,6 +143888,8 @@ const sourceCacheKey = core.getInput("source-cache-key"); const manifestKey = core.getInput("manifest"); const prepareNPMArtifactsMode = core.getInput("prepare-npm-artifacts-mode"); const bundleNPMArtifactsMode = core.getInput("bundle-npm-artifacts-mode"); +const compilerVersion = core.getInput("ocaml-compiler-version"); +const staticCompilerVersion = core.getInput("ocaml-static-compiler-version"); const customPostInstallJS = core.getInput("postinstall-js"); const setupEsy = core.getInput("setup-esy") || true; // Default behaviour is to install esy for user and cache it const setupEsyTarball = core.getInput("setup-esy-tarball"); @@ -143905,9 +143907,13 @@ let workingDirectory = core.getInput("working-directory") || process.cwd(); workingDirectory = external_path_.isAbsolute(workingDirectory) ? workingDirectory : external_path_.join(process.cwd(), workingDirectory); +function cli(cmd) { + console.log(`cli: ${cmd}`); + return external_child_process_.execSync(cmd).toString().trim(); +} function getEsyCLIVersion() { const cmd = "esy --version"; - return external_child_process_.execSync(cmd).toString().trim(); + return cli(cmd); } function getEsyStoreVersion() { const esyCLIVersion = getEsyCLIVersion(); @@ -143915,41 +143921,7 @@ function getEsyStoreVersion() { if (!parsedEsyCLIVersion) { throw new Error(`Could not parsed esy CLI version: ${esyCLIVersion}`); } - return semver_default().compare(parsedEsyCLIVersion, "0.9.0") >= 0 ? "4" : "3"; -} -function getCompilerVersion(sandbox) { - // let lockFileFolder; - // if (!sandbox) { - // lockFileFolder = "esy.lock"; - // } else { - // lockFileFolder = `${sandbox}.esy.lock`; - // } - // console.log(`Looking up ${lockFileFolder} for compiler version`); - // const lockFile = JSON.parse( - // fs - // .readFileSync(path.join(process.cwd(), lockFileFolder, "index.json")) - // .toString() - // ); - // const ocamlPackages = Object.keys(lockFile.node).filter((k) => - // k.startsWith("ocaml@") - // ); - // if (ocamlPackages.length === 0) { - // throw new Error( - // "Couldn't figure ocaml compiler version from lock file because no ocaml-like packages were found" - // ); - // } - // const ocamlPackageID = ocamlPackages[0]; - // const ocamlPackageIDParts = ocamlPackageID.split("@"); - // if (ocamlPackageIDParts.length !== 3) { - // throw new Error( - // `Couldn't figure ocaml compiler version from lock file because PackageId wasn't in expected format: ${ocamlPackageID}` - // ); - // } - // return ocamlPackageIDParts[1]; - const ocamlcVersionCmd = sandbox - ? `esy ${sandbox} ocamlc --version` - : "esy ocamlc --version"; - return external_child_process_.execSync(ocamlcVersionCmd).toString(); + return semver_default().compare(parsedEsyCLIVersion, "0.8.0") > 0 ? "4" : "3"; } function run(name, command, args) { return __awaiter(this, void 0, void 0, function* () { @@ -144017,102 +143989,92 @@ function computeChecksum(filePath, algo) { } const index_platform = external_os_.platform(); const arch = external_os_.arch(); -function main() { +function build() { return __awaiter(this, void 0, void 0, function* () { // Otherwise, when we change directories and then back (workingDirectory -> /tmp -> workingDirectory) // chdir() would try to enter a path relative to that path - try { - if (setupEsy) { - let tarballUrl, checksum, esyPackageVersion, esyPackageName; - if (!setupEsyVersion || !setupEsyShaSum || !setupEsyTarball) { - const meta = getEsyDownloadArtifactsMeta(setupEsyNPMPackageName); - tarballUrl = meta.tarballUrl; - checksum = meta.shasum; - esyPackageVersion = meta.version; - esyPackageName = meta.name; + if (setupEsy) { + let tarballUrl, checksum, esyPackageVersion, esyPackageName; + if (!setupEsyVersion || !setupEsyShaSum || !setupEsyTarball) { + const meta = getEsyDownloadArtifactsMeta(setupEsyNPMPackageName); + tarballUrl = meta.tarballUrl; + checksum = meta.shasum; + esyPackageVersion = meta.version; + esyPackageName = meta.name; + } + else { + tarballUrl = setupEsyTarball; + esyPackageVersion = setupEsyVersion; + checksum = setupEsyShaSum; + esyPackageName = setupEsyNPMPackageName; + } + let cachedPath = tool_cache.find(esyPackageName, esyPackageVersion, arch); + if (cachedPath === "") { + console.log("Fetching tarball from", tarballUrl); + const downloadedEsyNPMTarball = yield tool_cache.downloadTool(tarballUrl); + const checksumAlgo = "sha1"; + const computedChecksum = yield computeChecksum(downloadedEsyNPMTarball, checksumAlgo); + if (computedChecksum !== checksum) { + throw new Error(`Downloaded by checksum failed. url: ${setupEsyTarball} downloadPath: ${downloadedEsyNPMTarball} checksum expected: ${checksum} checksum computed: ${computedChecksum} checksum algorithm: ${checksumAlgo}`); } else { - tarballUrl = setupEsyTarball; - esyPackageVersion = setupEsyVersion; - checksum = setupEsyShaSum; - esyPackageName = setupEsyNPMPackageName; - } - let cachedPath = tool_cache.find(esyPackageName, esyPackageVersion, arch); - if (cachedPath === "") { - console.log("Fetching tarball from", tarballUrl); - const downloadedEsyNPMTarball = yield tool_cache.downloadTool(tarballUrl); - const checksumAlgo = "sha1"; - const computedChecksum = yield computeChecksum(downloadedEsyNPMTarball, checksumAlgo); - if (computedChecksum !== checksum) { - throw new Error(`Downloaded by checksum failed. url: ${setupEsyTarball} downloadPath: ${downloadedEsyNPMTarball} checksum expected: ${checksum} checksum computed: ${computedChecksum} checksum algorithm: ${checksumAlgo}`); - } - else { - console.log("Checksum validation succeeded. Downloaded tarball's checksum is:", checksum); - } - const extractedEsyNPM = yield tool_cache.extractTar(downloadedEsyNPMTarball); - core.startGroup("Running postinstall"); - const esyPackagePath = external_path_.join(extractedEsyNPM, "package"); - const postInstall = JSON.parse(external_fs_.readFileSync(external_path_.join(esyPackagePath, "package.json")) - .toString() - .trim()).scripts.postinstall; - process.chdir(esyPackagePath); - yield (0,exec.exec)(postInstall); - core.endGroup(); - process.chdir(workingDirectory); - cachedPath = yield tool_cache.cacheDir(esyPackagePath, esyPackageName, esyPackageVersion, arch); - } - core.addPath(external_path_.join(cachedPath, "bin")); - } - external_fs_.statSync(workingDirectory); - process.chdir(workingDirectory); - const installPath = [`${esyPrefix}/source`]; - const installKey = `source-${index_platform}-${arch}-${sourceCacheKey}`; - core.startGroup("Restoring install cache"); - const installCacheKey = yield cache.restoreCache(installPath, installKey, []); - if (installCacheKey) { - console.log("Restored the install cache"); - } - core.endGroup(); - yield runEsyCommand("Run esy install", ["install"]); - if (installCacheKey != installKey) { - yield cache.saveCache(installPath, installKey); - } - const storeVersion = getEsyStoreVersion(); - const esy3 = external_fs_.readdirSync(esyPrefix) - .filter((name) => name.length > 0 && name[0] === storeVersion) - .sort() - .pop(); - const depsPath = [external_path_.join(esyPrefix, esy3, "i")]; - const buildKey = `build-${index_platform}-${arch}-${cacheKey}`; - core.startGroup("Restoring build cache"); - const buildCacheKey = yield cache.restoreCache(depsPath, buildKey, []); - if (buildCacheKey) { - console.log("Restored the build cache"); - } - core.endGroup(); - if (!buildCacheKey) { - yield runEsyCommand("Run esy build-dependencies", ["build-dependencies"]); - } - yield runEsyCommand("Run esy build", ["build"]); - if (buildCacheKey != buildKey) { - yield cache.saveCache(depsPath, buildKey); - } - // TODO: support cleanup + manifest - // Need to improve how subcommands are called - // --prefix after cleanup subcommand doesn't work - // --prefix prepended doesn't work with any other sub-command - // if (!manifestKey && !buildCacheKey) { - // await runEsyCommand("Run esy cleanup", ["cleanup", "."]); - // } + console.log("Checksum validation succeeded. Downloaded tarball's checksum is:", checksum); + } + const extractedEsyNPM = yield tool_cache.extractTar(downloadedEsyNPMTarball); + core.startGroup("Running postinstall"); + const esyPackagePath = external_path_.join(extractedEsyNPM, "package"); + const postInstall = JSON.parse(external_fs_.readFileSync(external_path_.join(esyPackagePath, "package.json")) + .toString() + .trim()).scripts.postinstall; + process.chdir(esyPackagePath); + yield (0,exec.exec)(postInstall); + core.endGroup(); + process.chdir(workingDirectory); + cachedPath = yield tool_cache.cacheDir(esyPackagePath, esyPackageName, esyPackageVersion, arch); + } + core.addPath(external_path_.join(cachedPath, "bin")); } - catch (error) { - if (error instanceof Error) { - core.setFailed(error.message); - } - else { - core.setFailed(external_util_.inspect(error)); - } + external_fs_.statSync(workingDirectory); + process.chdir(workingDirectory); + const installPath = [`${esyPrefix}/source`]; + const installKey = `source-${index_platform}-${arch}-${sourceCacheKey}`; + core.startGroup("Restoring install cache"); + const installCacheKey = yield cache.restoreCache(installPath, installKey, []); + if (installCacheKey) { + console.log("Restored the install cache"); } + core.endGroup(); + yield runEsyCommand("Run esy install", ["install"]); + if (installCacheKey != installKey) { + yield cache.saveCache(installPath, installKey); + } + const storeVersion = getEsyStoreVersion(); + const esy3 = external_fs_.readdirSync(esyPrefix) + .filter((name) => name.length > 0 && name[0] === storeVersion) + .sort() + .pop(); + const depsPath = [external_path_.join(esyPrefix, esy3, "i")]; + const buildKey = `build-${index_platform}-${arch}-${cacheKey}`; + core.startGroup("Restoring build cache"); + const buildCacheKey = yield cache.restoreCache(depsPath, buildKey, []); + if (buildCacheKey) { + console.log("Restored the build cache"); + } + core.endGroup(); + if (!buildCacheKey) { + yield runEsyCommand("Run esy build-dependencies", ["build-dependencies"]); + } + yield runEsyCommand("Run esy build", ["build"]); + if (buildCacheKey != buildKey) { + yield cache.saveCache(depsPath, buildKey); + } + // TODO: support cleanup + manifest + // Need to improve how subcommands are called + // --prefix after cleanup subcommand doesn't work + // --prefix prepended doesn't work with any other sub-command + // if (!manifestKey && !buildCacheKey) { + // await runEsyCommand("Run esy cleanup", ["cleanup", "."]); + // } }); } function uncompress(dest, tarFile, strip) { @@ -144141,6 +144103,12 @@ function compress(dir, outputFile) { function prepareNPMArtifacts() { return __awaiter(this, void 0, void 0, function* () { var _a, _b, _c; + if (!compilerVersion) { + throw new Error("Prepare bundle-npm-artifacts needs `ocaml-compiler-version` field to be set in github actions"); + } + if (!staticCompilerVersion) { + throw new Error("Prepare bundle-npm-artifacts needs `ocaml-static-compiler-version` field to be set in github actions"); + } const statusCmd = manifestKey ? `esy ${manifestKey} status` : "esy status"; try { const manifestFilePath = JSON.parse(external_child_process_.execSync(statusCmd, { cwd: workingDirectory }).toString()).rootPackageConfigPath; @@ -144148,7 +144116,6 @@ function prepareNPMArtifacts() { if ((_a = manifest.esy) === null || _a === void 0 ? void 0 : _a.release) { const command = ["npm-release"]; if ((_c = (_b = manifest.esy) === null || _b === void 0 ? void 0 : _b.release) === null || _c === void 0 ? void 0 : _c.rewritePrefix) { - const compilerVersion = getCompilerVersion(); command.push("--ocaml-version"); command.push(compilerVersion); } @@ -144187,13 +144154,21 @@ function prepareNPMArtifacts() { } function bundleNPMArtifacts() { return __awaiter(this, void 0, void 0, function* () { + if (!compilerVersion) { + throw new Error("Prepare bundle-npm-artifacts needs `ocaml-compiler-version` field to be set in github actions"); + } + if (!staticCompilerVersion) { + throw new Error("Prepare bundle-npm-artifacts needs `ocaml-static-compiler-version` field to be set in github actions"); + } external_fs_.statSync(workingDirectory); process.chdir(workingDirectory); const releaseFolder = external_path_.join(workingDirectory, "_npm-release"); external_fs_.mkdirSync(releaseFolder); const { artifacts } = yield artifact_default().listArtifacts(); // TODO: filter out artifacts that dont have esy-npm-release-* prefix in their name - const artifactFoldersList = yield Promise.all(artifacts.map((a) => __awaiter(this, void 0, void 0, function* () { + const artifactFoldersList = []; + for (let i = 0; i < artifacts.length; ++i) { + const a = artifacts[i]; const folderName = `platform-${a.name}`; const folderPath = external_path_.join(releaseFolder, folderName); yield artifact_default().downloadArtifact(a.id, { @@ -144202,12 +144177,8 @@ function bundleNPMArtifacts() { const npmTarballPath = external_path_.join(folderPath, "npm-tarball.tgz"); yield uncompress(folderPath, npmTarballPath, 1); external_fs_.rmSync(npmTarballPath); - return folderName; - }))); - const artifactFolders = artifactFoldersList.reduce((acc, folderName) => { - acc.push(folderName); - return acc; - }, []); + artifactFoldersList.push(folderName); + } try { const esyInstallReleaseJS = "esyInstallRelease.js"; external_fs_.cpSync(external_path_.join(releaseFolder, artifactFoldersList[0], esyInstallReleaseJS), external_path_.join(releaseFolder, esyInstallReleaseJS)); @@ -144234,15 +144205,7 @@ function bundleNPMArtifacts() { const rewritePrefix = mainPackageJson.esy && mainPackageJson.esy.release && mainPackageJson.esy.release.rewritePrefix; - function exec(cmd) { - console.log(`exec: ${cmd}`); - return external_child_process_.execSync(cmd).toString().trim(); - } - const version = exec("git describe --tags --always"); - const compilerVersion = getCompilerVersion(); - console.log("Found compiler version", compilerVersion); - const staticCompilerVersion = getCompilerVersion("static.esy"); - console.log("Found static compiler version", staticCompilerVersion); + const version = cli("git describe --tags --always"); const packageJson = JSON.stringify({ name: mainPackageJson.name, version, @@ -144251,8 +144214,8 @@ function bundleNPMArtifacts() { repository: mainPackageJson.repository, scripts: { postinstall: rewritePrefix - ? `node -e \"process.env['OCAML_VERSION'] = process.platform == 'linux' ? '${staticCompilerVersion}-musl.static.flambda': '${compilerVersion}'; process.env['OCAML_PKG_NAME'] = 'ocaml'; process.env['ESY_RELEASE_REWRITE_PREFIX']=true; require('./postinstall.js')\"` - : "require('./postinstall.js')\"", + ? `node -e \"process.env['OCAML_VERSION'] = process.platform == 'linux' ? '${staticCompilerVersion}': '${compilerVersion}'; process.env['OCAML_PKG_NAME'] = 'ocaml'; process.env['ESY_RELEASE_REWRITE_PREFIX']=true; require('./postinstall.js')\"` + : "node ./postinstall.js", }, bin: bins, files: [ @@ -144260,7 +144223,7 @@ function bundleNPMArtifacts() { "bin/", "postinstall.js", "esyInstallRelease.js", - ].concat(artifactFolders), + ].concat(artifactFoldersList), }, null, 2); external_fs_.writeFileSync(external_path_.join(releaseFolder, "package.json"), packageJson, { encoding: "utf8", @@ -144316,15 +144279,27 @@ ECHO You need to have postinstall enabled`; core.endGroup(); }); } -if (prepareNPMArtifactsMode) { - prepareNPMArtifacts(); -} -else if (bundleNPMArtifactsMode) { - bundleNPMArtifacts(); -} -else { - main(); +function main() { + return __awaiter(this, void 0, void 0, function* () { + if (prepareNPMArtifactsMode) { + return prepareNPMArtifacts(); + } + else if (bundleNPMArtifactsMode) { + return bundleNPMArtifacts(); + } + else { + return build(); + } + }); } +main().catch((error) => { + if (error instanceof Error) { + core.setFailed(error.message); + } + else { + core.setFailed(external_util_.inspect(error)); + } +}); })(); diff --git a/index.ts b/index.ts index 0752e63..d516df2 100644 --- a/index.ts +++ b/index.ts @@ -34,6 +34,8 @@ const sourceCacheKey = core.getInput("source-cache-key"); const manifestKey = core.getInput("manifest"); const prepareNPMArtifactsMode = core.getInput("prepare-npm-artifacts-mode"); const bundleNPMArtifactsMode = core.getInput("bundle-npm-artifacts-mode"); +const compilerVersion = core.getInput("ocaml-compiler-version"); +const staticCompilerVersion = core.getInput("ocaml-static-compiler-version"); const customPostInstallJS = core.getInput("postinstall-js"); const setupEsy = core.getInput("setup-esy") || true; // Default behaviour is to install esy for user and cache it const setupEsyTarball = core.getInput("setup-esy-tarball"); @@ -54,9 +56,14 @@ workingDirectory = path.isAbsolute(workingDirectory) ? workingDirectory : path.join(process.cwd(), workingDirectory); +function cli(cmd: string) { + console.log(`cli: ${cmd}`); + return cp.execSync(cmd).toString().trim(); +} + function getEsyCLIVersion() { const cmd = "esy --version"; - return cp.execSync(cmd).toString().trim(); + return cli(cmd); } function getEsyStoreVersion() { @@ -65,48 +72,7 @@ function getEsyStoreVersion() { if (!parsedEsyCLIVersion) { throw new Error(`Could not parsed esy CLI version: ${esyCLIVersion}`); } - return semver.compare(parsedEsyCLIVersion, "0.9.0") >= 0 ? "4" : "3"; -} - -function getCompilerVersion(sandbox?: string) { - // let lockFileFolder; - - // if (!sandbox) { - // lockFileFolder = "esy.lock"; - // } else { - // lockFileFolder = `${sandbox}.esy.lock`; - // } - // console.log(`Looking up ${lockFileFolder} for compiler version`); - // const lockFile = JSON.parse( - // fs - // .readFileSync(path.join(process.cwd(), lockFileFolder, "index.json")) - // .toString() - // ); - // const ocamlPackages = Object.keys(lockFile.node).filter((k) => - // k.startsWith("ocaml@") - // ); - - // if (ocamlPackages.length === 0) { - // throw new Error( - // "Couldn't figure ocaml compiler version from lock file because no ocaml-like packages were found" - // ); - // } - - // const ocamlPackageID = ocamlPackages[0]; - // const ocamlPackageIDParts = ocamlPackageID.split("@"); - - // if (ocamlPackageIDParts.length !== 3) { - // throw new Error( - // `Couldn't figure ocaml compiler version from lock file because PackageId wasn't in expected format: ${ocamlPackageID}` - // ); - // } - - // return ocamlPackageIDParts[1]; - - const ocamlcVersionCmd = sandbox - ? `esy ${sandbox} ocamlc --version` - : "esy ocamlc --version"; - return cp.execSync(ocamlcVersionCmd).toString(); + return semver.compare(parsedEsyCLIVersion, "0.8.0") > 0 ? "4" : "3"; } async function run(name: string, command: string, args: string[]) { @@ -190,132 +156,118 @@ function computeChecksum(filePath: string, algo: string) { const platform = os.platform(); const arch = os.arch(); -async function main() { +async function build() { // Otherwise, when we change directories and then back (workingDirectory -> /tmp -> workingDirectory) // chdir() would try to enter a path relative to that path - try { - if (setupEsy) { - let tarballUrl, checksum, esyPackageVersion, esyPackageName; - if (!setupEsyVersion || !setupEsyShaSum || !setupEsyTarball) { - const meta = getEsyDownloadArtifactsMeta(setupEsyNPMPackageName); - tarballUrl = meta.tarballUrl; - checksum = meta.shasum; - esyPackageVersion = meta.version; - esyPackageName = meta.name; - } else { - tarballUrl = setupEsyTarball; - esyPackageVersion = setupEsyVersion; - checksum = setupEsyShaSum; - esyPackageName = setupEsyNPMPackageName; - } - let cachedPath = toolCache.find(esyPackageName, esyPackageVersion, arch); - if (cachedPath === "") { - console.log("Fetching tarball from", tarballUrl); - const downloadedEsyNPMTarball = await toolCache.downloadTool( - tarballUrl - ); - const checksumAlgo = "sha1"; - const computedChecksum = await computeChecksum( - downloadedEsyNPMTarball, - checksumAlgo - ); - if (computedChecksum !== checksum) { - throw new Error( - `Downloaded by checksum failed. url: ${setupEsyTarball} downloadPath: ${downloadedEsyNPMTarball} checksum expected: ${checksum} checksum computed: ${computedChecksum} checksum algorithm: ${checksumAlgo}` - ); - } else { - console.log( - "Checksum validation succeeded. Downloaded tarball's checksum is:", - checksum - ); - } - - const extractedEsyNPM = await toolCache.extractTar( - downloadedEsyNPMTarball + if (setupEsy) { + let tarballUrl, checksum, esyPackageVersion, esyPackageName; + if (!setupEsyVersion || !setupEsyShaSum || !setupEsyTarball) { + const meta = getEsyDownloadArtifactsMeta(setupEsyNPMPackageName); + tarballUrl = meta.tarballUrl; + checksum = meta.shasum; + esyPackageVersion = meta.version; + esyPackageName = meta.name; + } else { + tarballUrl = setupEsyTarball; + esyPackageVersion = setupEsyVersion; + checksum = setupEsyShaSum; + esyPackageName = setupEsyNPMPackageName; + } + let cachedPath = toolCache.find(esyPackageName, esyPackageVersion, arch); + if (cachedPath === "") { + console.log("Fetching tarball from", tarballUrl); + const downloadedEsyNPMTarball = await toolCache.downloadTool(tarballUrl); + const checksumAlgo = "sha1"; + const computedChecksum = await computeChecksum( + downloadedEsyNPMTarball, + checksumAlgo + ); + if (computedChecksum !== checksum) { + throw new Error( + `Downloaded by checksum failed. url: ${setupEsyTarball} downloadPath: ${downloadedEsyNPMTarball} checksum expected: ${checksum} checksum computed: ${computedChecksum} checksum algorithm: ${checksumAlgo}` ); - core.startGroup("Running postinstall"); - const esyPackagePath = path.join(extractedEsyNPM, "package"); - const postInstall = JSON.parse( - fs - .readFileSync(path.join(esyPackagePath, "package.json")) - .toString() - .trim() - ).scripts.postinstall; - process.chdir(esyPackagePath); - await exec(postInstall); - core.endGroup(); - process.chdir(workingDirectory); - cachedPath = await toolCache.cacheDir( - esyPackagePath, - esyPackageName, - esyPackageVersion, - arch + } else { + console.log( + "Checksum validation succeeded. Downloaded tarball's checksum is:", + checksum ); } - core.addPath(path.join(cachedPath, "bin")); - } - fs.statSync(workingDirectory); - process.chdir(workingDirectory); - const installPath = [`${esyPrefix}/source`]; - const installKey = `source-${platform}-${arch}-${sourceCacheKey}`; - core.startGroup("Restoring install cache"); - const installCacheKey = await cache.restoreCache( - installPath, - installKey, - [] - ); - if (installCacheKey) { - console.log("Restored the install cache"); - } - core.endGroup(); - - await runEsyCommand("Run esy install", ["install"]); - if (installCacheKey != installKey) { - await cache.saveCache(installPath, installKey); + const extractedEsyNPM = await toolCache.extractTar( + downloadedEsyNPMTarball + ); + core.startGroup("Running postinstall"); + const esyPackagePath = path.join(extractedEsyNPM, "package"); + const postInstall = JSON.parse( + fs + .readFileSync(path.join(esyPackagePath, "package.json")) + .toString() + .trim() + ).scripts.postinstall; + process.chdir(esyPackagePath); + await exec(postInstall); + core.endGroup(); + process.chdir(workingDirectory); + cachedPath = await toolCache.cacheDir( + esyPackagePath, + esyPackageName, + esyPackageVersion, + arch + ); } + core.addPath(path.join(cachedPath, "bin")); + } + fs.statSync(workingDirectory); + process.chdir(workingDirectory); + const installPath = [`${esyPrefix}/source`]; + const installKey = `source-${platform}-${arch}-${sourceCacheKey}`; + core.startGroup("Restoring install cache"); + const installCacheKey = await cache.restoreCache(installPath, installKey, []); + if (installCacheKey) { + console.log("Restored the install cache"); + } + core.endGroup(); - const storeVersion = getEsyStoreVersion(); - const esy3 = fs - .readdirSync(esyPrefix) - .filter((name: string) => name.length > 0 && name[0] === storeVersion) - .sort() - .pop(); + await runEsyCommand("Run esy install", ["install"]); - const depsPath = [path.join(esyPrefix, esy3!, "i")]; - const buildKey = `build-${platform}-${arch}-${cacheKey}`; + if (installCacheKey != installKey) { + await cache.saveCache(installPath, installKey); + } - core.startGroup("Restoring build cache"); - const buildCacheKey = await cache.restoreCache(depsPath, buildKey, []); - if (buildCacheKey) { - console.log("Restored the build cache"); - } - core.endGroup(); + const storeVersion = getEsyStoreVersion(); + const esy3 = fs + .readdirSync(esyPrefix) + .filter((name: string) => name.length > 0 && name[0] === storeVersion) + .sort() + .pop(); - if (!buildCacheKey) { - await runEsyCommand("Run esy build-dependencies", ["build-dependencies"]); - } + const depsPath = [path.join(esyPrefix, esy3!, "i")]; + const buildKey = `build-${platform}-${arch}-${cacheKey}`; - await runEsyCommand("Run esy build", ["build"]); + core.startGroup("Restoring build cache"); + const buildCacheKey = await cache.restoreCache(depsPath, buildKey, []); + if (buildCacheKey) { + console.log("Restored the build cache"); + } + core.endGroup(); - if (buildCacheKey != buildKey) { - await cache.saveCache(depsPath, buildKey); - } + if (!buildCacheKey) { + await runEsyCommand("Run esy build-dependencies", ["build-dependencies"]); + } - // TODO: support cleanup + manifest - // Need to improve how subcommands are called - // --prefix after cleanup subcommand doesn't work - // --prefix prepended doesn't work with any other sub-command - // if (!manifestKey && !buildCacheKey) { - // await runEsyCommand("Run esy cleanup", ["cleanup", "."]); - // } - } catch (error) { - if (error instanceof Error) { - core.setFailed(error.message); - } else { - core.setFailed(util.inspect(error)); - } + await runEsyCommand("Run esy build", ["build"]); + + if (buildCacheKey != buildKey) { + await cache.saveCache(depsPath, buildKey); } + + // TODO: support cleanup + manifest + // Need to improve how subcommands are called + // --prefix after cleanup subcommand doesn't work + // --prefix prepended doesn't work with any other sub-command + // if (!manifestKey && !buildCacheKey) { + // await runEsyCommand("Run esy cleanup", ["cleanup", "."]); + // } } async function uncompress( @@ -335,6 +287,7 @@ async function uncompress( .on("error", reject); }); } + async function compress(dir: string, outputFile: string): Promise { return new Promise((resolve, reject) => { tar @@ -344,7 +297,19 @@ async function compress(dir: string, outputFile: string): Promise { .on("error", reject); }); } + async function prepareNPMArtifacts() { + if (!compilerVersion) { + throw new Error( + "Prepare bundle-npm-artifacts needs `ocaml-compiler-version` field to be set in github actions" + ); + } + + if (!staticCompilerVersion) { + throw new Error( + "Prepare bundle-npm-artifacts needs `ocaml-static-compiler-version` field to be set in github actions" + ); + } const statusCmd = manifestKey ? `esy ${manifestKey} status` : "esy status"; try { const manifestFilePath = JSON.parse( @@ -354,7 +319,6 @@ async function prepareNPMArtifacts() { if (manifest.esy?.release) { const command = ["npm-release"]; if (manifest.esy?.release?.rewritePrefix) { - const compilerVersion = getCompilerVersion(); command.push("--ocaml-version"); command.push(compilerVersion); } @@ -398,6 +362,18 @@ async function prepareNPMArtifacts() { } async function bundleNPMArtifacts() { + if (!compilerVersion) { + throw new Error( + "Prepare bundle-npm-artifacts needs `ocaml-compiler-version` field to be set in github actions" + ); + } + + if (!staticCompilerVersion) { + throw new Error( + "Prepare bundle-npm-artifacts needs `ocaml-static-compiler-version` field to be set in github actions" + ); + } + fs.statSync(workingDirectory); process.chdir(workingDirectory); const releaseFolder = path.join(workingDirectory, "_npm-release"); @@ -405,26 +381,19 @@ async function bundleNPMArtifacts() { const { artifacts } = await artifact.listArtifacts(); // TODO: filter out artifacts that dont have esy-npm-release-* prefix in their name - const artifactFoldersList = await Promise.all( - artifacts.map(async (a: Artifact) => { - const folderName = `platform-${a.name}`; - const folderPath = path.join(releaseFolder, folderName); - await artifact.downloadArtifact(a.id, { - path: folderPath, - }); - const npmTarballPath = path.join(folderPath, "npm-tarball.tgz"); - await uncompress(folderPath, npmTarballPath, 1); - fs.rmSync(npmTarballPath); - return folderName; - }) - ); - const artifactFolders = artifactFoldersList.reduce( - (acc: string[], folderName: string) => { - acc.push(folderName); - return acc; - }, - [] - ); + const artifactFoldersList: string[] = []; + for (let i = 0; i < artifacts.length; ++i) { + const a: Artifact = artifacts[i]; + const folderName = `platform-${a.name}`; + const folderPath = path.join(releaseFolder, folderName); + await artifact.downloadArtifact(a.id, { + path: folderPath, + }); + const npmTarballPath = path.join(folderPath, "npm-tarball.tgz"); + await uncompress(folderPath, npmTarballPath, 1); + fs.rmSync(npmTarballPath); + artifactFoldersList.push(folderName); + } try { const esyInstallReleaseJS = "esyInstallRelease.js"; fs.cpSync( @@ -468,16 +437,7 @@ async function bundleNPMArtifacts() { mainPackageJson.esy.release && mainPackageJson.esy.release.rewritePrefix; - function exec(cmd: string) { - console.log(`exec: ${cmd}`); - return cp.execSync(cmd).toString().trim(); - } - const version = exec("git describe --tags --always"); - - const compilerVersion = getCompilerVersion(); - console.log("Found compiler version", compilerVersion); - const staticCompilerVersion = getCompilerVersion("static.esy"); - console.log("Found static compiler version", staticCompilerVersion); + const version = cli("git describe --tags --always"); const packageJson = JSON.stringify( { @@ -488,8 +448,8 @@ async function bundleNPMArtifacts() { repository: mainPackageJson.repository, scripts: { postinstall: rewritePrefix - ? `node -e \"process.env['OCAML_VERSION'] = process.platform == 'linux' ? '${staticCompilerVersion}-musl.static.flambda': '${compilerVersion}'; process.env['OCAML_PKG_NAME'] = 'ocaml'; process.env['ESY_RELEASE_REWRITE_PREFIX']=true; require('./postinstall.js')\"` - : "require('./postinstall.js')\"", + ? `node -e \"process.env['OCAML_VERSION'] = process.platform == 'linux' ? '${staticCompilerVersion}': '${compilerVersion}'; process.env['OCAML_PKG_NAME'] = 'ocaml'; process.env['ESY_RELEASE_REWRITE_PREFIX']=true; require('./postinstall.js')\"` + : "node ./postinstall.js", }, bin: bins, files: [ @@ -497,7 +457,7 @@ async function bundleNPMArtifacts() { "bin/", "postinstall.js", "esyInstallRelease.js", - ].concat(artifactFolders), + ].concat(artifactFoldersList), }, null, 2 @@ -577,10 +537,20 @@ ECHO You need to have postinstall enabled`; core.endGroup(); } -if (prepareNPMArtifactsMode) { - prepareNPMArtifacts(); -} else if (bundleNPMArtifactsMode) { - bundleNPMArtifacts(); -} else { - main(); +async function main() { + if (prepareNPMArtifactsMode) { + return prepareNPMArtifacts(); + } else if (bundleNPMArtifactsMode) { + return bundleNPMArtifacts(); + } else { + return build(); + } } + +main().catch((error) => { + if (error instanceof Error) { + core.setFailed(error.message); + } else { + core.setFailed(util.inspect(error)); + } +});