oclif
Version:
oclif: create your own CLI
164 lines (163 loc) • 7.83 kB
JavaScript
;
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;