UNPKG

oclif

Version:

oclif: create your own CLI

152 lines (151 loc) 10.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const path = require("path"); const _ = require("lodash"); const core_1 = require("@oclif/core"); const aws_1 = require("../aws"); const Tarballs = require("../tarballs"); const upload_util_1 = require("../upload-util"); const version_indexes_1 = require("../version-indexes"); class Promote extends core_1.Command { async run() { var _a, _b; const { flags } = await this.parse(Promote); const buildConfig = await Tarballs.buildConfig(flags.root, { targets: (_a = flags === null || flags === void 0 ? void 0 : flags.targets) === null || _a === void 0 ? void 0 : _a.split(',') }); const { s3Config, config } = buildConfig; const indexDefaults = { version: flags.version, s3Config, maxAge: `max-age=${flags['max-age']}`, }; if (!s3Config.bucket) this.error('Cannot determine S3 bucket for promotion'); const awsDefaults = { Bucket: s3Config.bucket, ACL: (_b = s3Config.acl) !== null && _b !== void 0 ? _b : 'public-read', MetadataDirective: 'REPLACE', CacheControl: indexDefaults.maxAge, }; const cloudBucketCommitKey = (shortKey) => path.join(s3Config.bucket, (0, upload_util_1.commitAWSDir)(flags.version, flags.sha, s3Config), shortKey); const cloudChannelKey = (shortKey) => path.join((0, upload_util_1.channelAWSDir)(flags.channel, s3Config), shortKey); // copy tarballs manifests if (buildConfig.targets.length > 0) this.log(`Promoting buildmanifests & unversioned tarballs to ${flags.channel}`); const promoteManifest = async (target) => { const manifest = (0, upload_util_1.templateShortKey)('manifest', { arch: target.arch, bin: config.bin, platform: target.platform, sha: flags.sha, version: flags.version, }); // strip version & sha so update/scripts can point to a static channel manifest const unversionedManifest = manifest.replace(`-v${flags.version}-${flags.sha}`, ''); await aws_1.default.s3.copyObject(Object.assign(Object.assign({}, awsDefaults), { CopySource: cloudBucketCommitKey(manifest), Key: cloudChannelKey(unversionedManifest) })); }; const promoteGzTarballs = async (target) => { const versionedTarGzName = (0, upload_util_1.templateShortKey)('versioned', '.tar.gz', { arch: target.arch, bin: config.bin, platform: target.platform, sha: flags.sha, version: flags.version, }); const versionedTarGzKey = cloudBucketCommitKey(versionedTarGzName); // strip version & sha so update/scripts can point to a static channel tarball const unversionedTarGzName = versionedTarGzName.replace(`-v${flags.version}-${flags.sha}`, ''); const unversionedTarGzKey = cloudChannelKey(unversionedTarGzName); await Promise.all([aws_1.default.s3.copyObject(Object.assign(Object.assign({}, awsDefaults), { CopySource: versionedTarGzKey, Key: unversionedTarGzKey }))].concat(flags.indexes ? [(0, version_indexes_1.appendToIndex)(Object.assign(Object.assign({}, indexDefaults), { originalUrl: versionedTarGzKey, filename: unversionedTarGzName }))] : [])); }; const promoteXzTarballs = async (target) => { const versionedTarXzName = (0, upload_util_1.templateShortKey)('versioned', '.tar.xz', { arch: target.arch, bin: config.bin, platform: target.platform, sha: flags.sha, version: flags.version, }); const versionedTarXzKey = cloudBucketCommitKey(versionedTarXzName); // strip version & sha so update/scripts can point to a static channel tarball const unversionedTarXzName = versionedTarXzName.replace(`-v${flags.version}-${flags.sha}`, ''); const unversionedTarXzKey = cloudChannelKey(unversionedTarXzName); await Promise.all([aws_1.default.s3.copyObject(Object.assign(Object.assign({}, awsDefaults), { CopySource: versionedTarXzKey, Key: unversionedTarXzKey }))].concat(flags.indexes ? [(0, version_indexes_1.appendToIndex)(Object.assign(Object.assign({}, indexDefaults), { originalUrl: versionedTarXzKey, filename: unversionedTarXzName }))] : [])); }; const promoteMacInstallers = async () => { this.log(`Promoting macos pkgs to ${flags.channel}`); const arches = _.uniq(buildConfig.targets.filter(t => t.platform === 'darwin').map(t => t.arch)); await Promise.all(arches.map(async (arch) => { const darwinPkg = (0, upload_util_1.templateShortKey)('macos', { bin: config.bin, version: flags.version, sha: flags.sha, arch }); const darwinCopySource = cloudBucketCommitKey(darwinPkg); // strip version & sha so scripts can point to a static channel pkg const unversionedPkg = darwinPkg.replace(`-v${flags.version}-${flags.sha}`, ''); await Promise.all([aws_1.default.s3.copyObject(Object.assign(Object.assign({}, awsDefaults), { CopySource: darwinCopySource, Key: cloudChannelKey(unversionedPkg) }))].concat(flags.indexes ? [(0, version_indexes_1.appendToIndex)(Object.assign(Object.assign({}, indexDefaults), { originalUrl: darwinCopySource, filename: unversionedPkg }))] : [])); })); }; const promoteWindowsInstallers = async () => { // copy win exe this.log(`Promoting windows exe to ${flags.channel}`); const arches = buildConfig.targets.filter(t => t.platform === 'win32').map(t => t.arch); await Promise.all(arches.map(async (arch) => { const winPkg = (0, upload_util_1.templateShortKey)('win32', { bin: config.bin, version: flags.version, sha: flags.sha, arch }); const winCopySource = cloudBucketCommitKey(winPkg); // strip version & sha so scripts can point to a static channel exe const unversionedExe = winPkg.replace(`-v${flags.version}-${flags.sha}`, ''); await Promise.all([aws_1.default.s3.copyObject(Object.assign(Object.assign({}, awsDefaults), { CopySource: winCopySource, Key: cloudChannelKey(unversionedExe) }))].concat(flags.indexes ? [(0, version_indexes_1.appendToIndex)(Object.assign(Object.assign({}, indexDefaults), { originalUrl: winCopySource, filename: unversionedExe }))] : [])); core_1.CliUx.ux.action.stop('successfully'); })); }; const promoteDebianAptPackages = async () => { // copy debian artifacts const debArtifacts = [ (0, upload_util_1.templateShortKey)('deb', { bin: config.bin, versionShaRevision: (0, upload_util_1.debVersion)(buildConfig), arch: 'amd64' }), (0, upload_util_1.templateShortKey)('deb', { bin: config.bin, versionShaRevision: (0, upload_util_1.debVersion)(buildConfig), arch: 'i386' }), 'Packages.gz', 'Packages.xz', 'Packages.bz2', 'Release', 'InRelease', 'Release.gpg', ]; this.log(`Promoting debian artifacts to ${flags.channel}`); await Promise.all(debArtifacts.flatMap(artifact => { const debCopySource = cloudBucketCommitKey(`apt/${artifact}`); const debKey = cloudChannelKey(`apt/${artifact}`); // apt expects ../apt/dists/versionName/[artifacts] but oclif wants varsions/sha/apt/[artifacts] // see https://github.com/oclif/oclif/issues/347 for the AWS-redirect that solves this // this workaround puts the code in both places that the redirect was doing // with this, the docs are correct. The copies are all done in parallel so it shouldn't be too costly. const workaroundKey = cloudChannelKey(`apt/./${artifact}`); return [ aws_1.default.s3.copyObject(Object.assign(Object.assign({}, awsDefaults), { CopySource: debCopySource, Key: debKey })), aws_1.default.s3.copyObject(Object.assign(Object.assign({}, awsDefaults), { CopySource: debCopySource, Key: workaroundKey })), ]; })); }; await Promise.all(buildConfig.targets.flatMap(target => [ // always promote the manifest and gz promoteManifest(target), promoteGzTarballs(target), ]) // optionally promote other artifacts depending on the specified flags .concat(flags.xz ? buildConfig.targets.map(target => promoteXzTarballs(target)) : []) .concat(flags.macos ? [promoteMacInstallers()] : []) .concat(flags.win ? [promoteWindowsInstallers()] : []) .concat(flags.deb ? [promoteDebianAptPackages()] : [])); } } exports.default = Promote; Promote.description = 'promote CLI builds to a S3 release channel'; Promote.flags = { root: core_1.Flags.string({ char: 'r', description: 'path to the oclif CLI project root', default: '.', required: true }), version: core_1.Flags.string({ description: 'semantic version of the CLI to promote', required: true }), sha: core_1.Flags.string({ description: '7-digit short git commit SHA of the CLI to promote', required: true }), channel: core_1.Flags.string({ description: 'which channel to promote to', required: true, default: 'stable' }), targets: core_1.Flags.string({ char: 't', description: 'comma-separated targets to promote (e.g.: linux-arm,win32-x64)' }), deb: core_1.Flags.boolean({ char: 'd', description: 'promote debian artifacts' }), macos: core_1.Flags.boolean({ char: 'm', description: 'promote macOS pkg' }), win: core_1.Flags.boolean({ char: 'w', description: 'promote Windows exe' }), 'max-age': core_1.Flags.string({ char: 'a', description: 'cache control max-age in seconds', default: '86400' }), xz: core_1.Flags.boolean({ description: 'also upload xz', allowNo: true }), indexes: core_1.Flags.boolean({ description: 'append the promoted urls into the index files' }), };