UNPKG

oclif

Version:

oclif: create your own CLI

115 lines (114 loc) 5.78 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const core_1 = require("@oclif/core"); const fs = require("fs-extra"); const _ = require("lodash"); const path = require("path"); const Tarballs = require("../../tarballs"); const upload_util_1 = require("../../upload-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 scripts = { /* eslint-disable no-useless-escape */ bin: (config) => `#!/usr/bin/env bash set -e echoerr() { echo "$@" 1>&2; } get_script_dir () { SOURCE="\${BASH_SOURCE[0]}" # While \$SOURCE is a symlink, resolve it while [ -h "\$SOURCE" ]; do DIR="\$( cd -P "\$( dirname "\$SOURCE" )" && pwd )" SOURCE="\$( readlink "\$SOURCE" )" # If \$SOURCE was a relative symlink (so no "/" as prefix, need to resolve it relative to the symlink base directory [[ \$SOURCE != /* ]] && SOURCE="\$DIR/\$SOURCE" done DIR="\$( cd -P "\$( dirname "\$SOURCE" )" && pwd )" echo "\$DIR" } DIR=\$(get_script_dir) export ${config.scopedEnvVarKey('UPDATE_INSTRUCTIONS')}="update with \\"sudo apt update && sudo apt install ${config.bin}\\"" \$DIR/node \$DIR/run "\$@" `, /* eslint-enable no-useless-escape */ control: (config, arch) => `Package: ${config.config.bin} Version: ${(0, upload_util_1.debVersion)(config)} Section: main Priority: standard Architecture: ${arch} Maintainer: ${config.config.scopedEnvVar('AUTHOR') || config.config.pjson.author} Description: ${config.config.pjson.description} `, ftparchive: (config) => ` APT::FTPArchive::Release { Origin "${config.scopedEnvVar('AUTHOR') || config.pjson.author}"; Suite "stable"; `, }; class PackDeb extends core_1.Command { async run() { if (process.platform !== 'linux') throw new Error('debian packing must be run on linux'); const { flags } = await this.parse(PackDeb); const buildConfig = await Tarballs.buildConfig(flags.root); const { config } = buildConfig; await Tarballs.build(buildConfig, { platform: 'linux', pack: false, tarball: flags.tarball, parallel: true }); const dist = buildConfig.dist('deb'); await fs.emptyDir(dist); const build = async (arch) => { this.log(`building debian / ${arch}`); const target = { platform: 'linux', arch }; const versionedDebBase = (0, upload_util_1.templateShortKey)('deb', { bin: config.bin, versionShaRevision: (0, upload_util_1.debVersion)(buildConfig), arch: (0, upload_util_1.debArch)(arch) }); const workspace = path.join(buildConfig.tmp, 'apt', versionedDebBase.replace('.deb', '.apt')); await fs.remove(workspace); await Promise.all([ fs.promises.mkdir(path.join(workspace, 'DEBIAN'), { recursive: true }), fs.promises.mkdir(path.join(workspace, 'usr', 'bin'), { recursive: true }), ]); await fs.copy(buildConfig.workspace(target), path.join(workspace, 'usr', 'lib', config.dirname)); await Promise.all([ // usr/lib/oclif/bin/oclif (the executable) fs.promises.writeFile(path.join(workspace, 'usr', 'lib', config.dirname, 'bin', config.bin), scripts.bin(config), { mode: 0o755 }), fs.promises.writeFile(path.join(workspace, 'DEBIAN', 'control'), scripts.control(buildConfig, (0, upload_util_1.debArch)(arch))), ]); // symlink usr/bin/oclif points to usr/lib/oclif/bin/oclif await exec(`ln -s "${path.join('..', 'lib', config.dirname, 'bin', config.bin)}" "${config.bin}"`, { cwd: path.join(workspace, 'usr', 'bin') }); await exec(`sudo chown -R root "${workspace}"`); await exec(`sudo chgrp -R root "${workspace}"`); await exec(`dpkg --build "${workspace}" "${path.join(dist, versionedDebBase)}"`); this.log(`finished building debian / ${arch}`); }; const arches = _.uniq(buildConfig.targets .filter(t => t.platform === 'linux') .map(t => t.arch)); await Promise.all(arches.map(a => build(a))); await exec('apt-ftparchive packages . > Packages', { cwd: dist }); this.log('debian packages created'); await Promise.all([ exec('gzip -c Packages > Packages.gz', { cwd: dist }), exec('bzip2 -k Packages', { cwd: dist }), exec('xz -k Packages', { cwd: dist }), packForFTP(buildConfig, config, dist), ]); this.log('debian packages archived'); const gpgKey = config.scopedEnvVar('DEB_KEY'); if (gpgKey) { this.log('adding gpg signatures to Release'); await exec(`gpg --digest-algo SHA512 --clearsign -u ${gpgKey} -o InRelease Release`, { cwd: dist }); await exec(`gpg --digest-algo SHA512 -abs -u ${gpgKey} -o Release.gpg Release`, { cwd: dist }); } this.log('debian packing complete'); } } exports.default = PackDeb; PackDeb.description = 'pack CLI into debian package'; PackDeb.flags = { root: core_1.Flags.string({ char: 'r', description: 'path to oclif CLI root', default: '.', required: true }), tarball: core_1.Flags.string({ char: 't', description: 'optionally specify a path to a tarball already generated by NPM', required: false }), }; async function packForFTP(buildConfig, config, dist) { const ftparchive = path.join(buildConfig.tmp, 'apt', 'apt-ftparchive.conf'); await fs.promises.mkdir(path.basename(ftparchive), { recursive: true }); await fs.writeFile(ftparchive, scripts.ftparchive(config)); await exec(`apt-ftparchive -c "${ftparchive}" release . > Release`, { cwd: dist }); }