UNPKG

oclif

Version:

oclif: create your own CLI

164 lines (163 loc) 7.83 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.build = void 0; const findYarnWorkspaceRoot = require("find-yarn-workspace-root"); const log_1 = require("../log"); const path = require("path"); const fs = require("fs-extra"); const bin_1 = require("./bin"); const node_1 = require("./node"); const upload_util_1 = require("../upload-util"); const util_1 = require("../util"); const child_process_1 = require("child_process"); const node_util_1 = require("node:util"); const exec = (0, node_util_1.promisify)(child_process_1.exec); const pack = async (from, to) => { const cwd = path.dirname(from); await fs.promises.mkdir(path.dirname(to), { recursive: true }); (0, log_1.log)(`packing tarball from ${(0, util_1.prettifyPaths)(path.dirname(from))} to ${(0, util_1.prettifyPaths)(to)}`); (to.endsWith('gz') ? await exec(`tar czf ${to} ${(path.basename(from))}`, { cwd }) : await exec(`tar cfJ ${to} ${(path.basename(from))}`, { cwd })); }; async function build(c, options = {}) { const { xz, config } = c; const packCLI = async () => { const { stdout } = await exec('npm pack --unsafe-perm', { cwd: c.root }); return path.join(c.root, stdout.trim().split('\n').pop()); }; const extractCLI = async (tarball) => { await fs.emptyDir(c.workspace()); const tarballNewLocation = path.join(c.workspace(), path.basename(tarball)); await fs.move(tarball, tarballNewLocation); await exec(`tar -xzf "${tarballNewLocation}"`, { cwd: c.workspace() }); await Promise.all((await fs.promises.readdir(path.join(c.workspace(), 'package'), { withFileTypes: true })) .map(i => fs.move(path.join(c.workspace(), 'package', i.name), path.join(c.workspace(), i.name)))); await Promise.all([ fs.promises.rm(path.join(c.workspace(), 'package'), { recursive: true }), fs.promises.rm(path.join(c.workspace(), path.basename(tarball)), { recursive: true }), fs.remove(path.join(c.workspace(), 'bin', 'run.cmd')), ]); }; const updatePJSON = async () => { const pjsonPath = path.join(c.workspace(), 'package.json'); const pjson = await fs.readJSON(pjsonPath); pjson.version = config.version; pjson.oclif.update = pjson.oclif.update || {}; pjson.oclif.update.s3 = pjson.oclif.update.s3 || {}; pjson.oclif.update.s3.bucket = c.s3Config.bucket; await fs.writeJSON(pjsonPath, pjson, { spaces: 2 }); }; const addDependencies = async () => { const yarnRoot = findYarnWorkspaceRoot(c.root) || c.root; if (fs.existsSync(path.join(yarnRoot, 'yarn.lock'))) { await fs.copy(path.join(yarnRoot, 'yarn.lock'), path.join(c.workspace(), 'yarn.lock')); await exec('yarn --no-progress --production --non-interactive', { cwd: c.workspace() }); } else { const lockpath = fs.existsSync(path.join(c.root, 'package-lock.json')) ? path.join(c.root, 'package-lock.json') : path.join(c.root, 'npm-shrinkwrap.json'); await fs.copy(lockpath, path.join(c.workspace(), path.basename(lockpath))); await exec('npm install --production', { cwd: c.workspace() }); } }; const pretarball = async () => { const pjson = await fs.readJSON(path.join(c.workspace(), 'package.json')); const yarnRoot = findYarnWorkspaceRoot(c.root) || c.root; const yarn = fs.existsSync(path.join(yarnRoot, 'yarn.lock')); if (pjson.scripts.pretarball) { yarn ? await exec('yarn run pretarball', { cwd: c.workspace() }) : await exec('npm run pretarball', { cwd: c.workspace() }); } }; const buildTarget = async (target) => { const workspace = c.workspace(target); const gzLocalKey = (0, upload_util_1.templateShortKey)('versioned', '.tar.gz', { arch: target.arch, bin: c.config.bin, platform: target.platform, sha: c.gitSha, version: config.version, }); const xzLocalKey = (0, upload_util_1.templateShortKey)('versioned', '.tar.xz', { arch: target.arch, bin: c.config.bin, platform: target.platform, sha: c.gitSha, version: config.version, }); const base = path.basename(gzLocalKey); (0, log_1.log)(`building target ${base}`); (0, log_1.log)('copying workspace', c.workspace(), workspace); await fs.emptyDir(workspace); await fs.copy(c.workspace(), workspace); await (0, node_1.fetchNodeBinary)({ nodeVersion: c.nodeVersion, output: path.join(workspace, 'bin', 'node'), platform: target.platform, arch: target.arch, tmp: path.join(config.root, 'tmp'), }); if (options.pack === false) return; if (options.parallel) { await Promise.all([pack(workspace, c.dist(gzLocalKey))] .concat(xz ? [pack(workspace, c.dist(xzLocalKey))] : [])); } else { await pack(workspace, c.dist(gzLocalKey)); if (xz) await pack(workspace, c.dist(xzLocalKey)); } if (!c.updateConfig.s3.host) return; const rollout = (typeof c.updateConfig.autoupdate === 'object' && c.updateConfig.autoupdate.rollout); const gzCloudKey = `${(0, upload_util_1.commitAWSDir)(config.version, c.gitSha, c.updateConfig.s3)}/${gzLocalKey}`; const xzCloudKey = `${(0, upload_util_1.commitAWSDir)(config.version, c.gitSha, c.updateConfig.s3)}/${xzLocalKey}`; const [sha256gz, sha256xz] = await Promise.all([(0, util_1.hash)('sha256', c.dist(gzLocalKey))].concat(xz ? [(0, util_1.hash)('sha256', c.dist(xzLocalKey))] : [])); const manifest = { rollout: rollout === false ? undefined : rollout, version: config.version, sha: c.gitSha, baseDir: (0, upload_util_1.templateShortKey)('baseDir', target, { bin: c.config.bin }), gz: config.s3Url(gzCloudKey), xz: xz ? config.s3Url(xzCloudKey) : undefined, sha256gz, sha256xz, node: { compatible: config.pjson.engines.node, recommended: c.nodeVersion, }, }; const manifestFilepath = c.dist((0, upload_util_1.templateShortKey)('manifest', { arch: target.arch, bin: c.config.bin, platform: target.platform, sha: c.gitSha, version: config.version, })); await fs.writeJSON(manifestFilepath, manifest, { spaces: 2 }); }; (0, log_1.log)(`gathering workspace for ${config.bin} to ${c.workspace()}`); await extractCLI(options.tarball ? options.tarball : await packCLI()); await updatePJSON(); await addDependencies(); await (0, bin_1.writeBinScripts)({ config, baseWorkspace: c.workspace(), nodeVersion: c.nodeVersion }); await pretarball(); const targetsToBuild = c.targets.filter(t => !options.platform || options.platform === t.platform); if (options.parallel) { (0, log_1.log)(`will build ${targetsToBuild.length} targets in parallel`); await Promise.all(targetsToBuild.map(t => buildTarget(t))); } else { (0, log_1.log)(`will build ${targetsToBuild.length} targets sequentially`); for (const target of targetsToBuild) { // eslint-disable-next-line no-await-in-loop await buildTarget(target); } (0, log_1.log)(`finished building ${targetsToBuild.length} targets sequentially`); } } exports.build = build;