UNPKG

@salesforce/plugin-release-management

Version:
205 lines 8.04 kB
"use strict"; /* * Copyright (c) 2020, salesforce.com, inc. * All rights reserved. * Licensed under the BSD 3-Clause license. * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause */ Object.defineProperty(exports, "__esModule", { value: true }); exports.PackageRepo = void 0; const os = require("os"); const ts_types_1 = require("@salesforce/ts-types"); const shelljs_1 = require("shelljs"); const core_1 = require("@salesforce/core"); const kit_1 = require("@salesforce/kit"); const ts_types_2 = require("@salesforce/ts-types"); const chalk = require("chalk"); const package_1 = require("./package"); const registry_1 = require("./registry"); const inspectCommits_1 = require("./inspectCommits"); const packAndSign_1 = require("./codeSigning/packAndSign"); class Repository extends kit_1.AsyncOptionalCreatable { constructor(options) { super(options); this.stepCounter = 1; this.options = options; this.ux = options.ux; this.shouldBePublished = options.shouldBePublished; this.env = new kit_1.Env(); this.registry = new registry_1.Registry(); } install(silent = false) { this.execCommand(`yarn install ${this.registry.getRegistryParameter()}`, silent); } build(silent = false) { this.execCommand('yarn build', silent); } run(script, location, silent = false) { if (location) { this.execCommand(`(cd ${location} && yarn run ${script})`, silent); } else { this.execCommand(`(yarn run ${script})`, silent); } } test() { this.execCommand('yarn test'); } getBranchName() { const branch = this.env.getString('CIRCLE_BRANCH', null) || (0, shelljs_1.exec)('git branch --show-current', { silent: true }).stdout; return (0, ts_types_1.ensureString)(branch); } pushChangesToGit() { const branch = this.getBranchName(); const cmd = `git push --set-upstream --no-verify --follow-tags origin ${branch}`; this.execCommand(cmd, false); } stageChanges() { this.execCommand('git add .', false); } revertUnstagedChanges() { const changedFiles = (0, shelljs_1.exec)('git diff --name-only', { silent: true }) .stdout.split(os.EOL) .filter((f) => !!f); changedFiles.forEach((file) => { (0, shelljs_1.exec)(`git checkout -- ${file}`, { silent: false }); }); } revertAllChanges() { (0, shelljs_1.exec)('git reset --hard HEAD', { silent: true }); } printStage(msg) { this.ux.log(chalk.green.bold(`${os.EOL}${this.stepCounter}) ${msg}`)); this.stepCounter += 1; } async writeNpmToken() { const home = this.env.getString('HOME') ?? os.homedir(); await this.registry.setNpmAuth(home); await this.registry.setNpmRegistry(home); } execCommand(cmd, silent) { if (!silent) this.ux.log(`${chalk.dim(cmd)}${os.EOL}`); const result = (0, shelljs_1.exec)(cmd, { silent }); if (result.code !== 0) { throw new core_1.SfError(result.stderr, 'FailedCommandExecution'); } else { return result; } } async poll(checkFn) { const isNonTTY = this.env.getBoolean('CI') || this.env.getBoolean('CIRCLECI'); let found = false; let attempts = 0; const maxAttempts = 300; const start = isNonTTY ? (msg) => this.ux.log(msg) : (msg) => this.ux.startSpinner(msg); const update = isNonTTY ? (msg) => this.ux.log(msg) : (msg) => this.ux.setSpinnerStatus(msg); const stop = isNonTTY ? (msg) => this.ux.log(msg) : (msg) => this.ux.stopSpinner(msg); start('Polling for new version(s) to become available on npm'); while (attempts < maxAttempts && !found) { attempts += 1; update(`attempt: ${attempts} of ${maxAttempts}`); found = checkFn(); await (0, kit_1.sleep)(1000); } stop(attempts >= maxAttempts ? 'failed' : 'done'); return found; } /** * If the commit type isn't fix (patch bump), feat (minor bump), or breaking (major bump), * then standard-version always defaults to a patch bump. * See https://github.com/conventional-changelog/standard-version/issues/577 * * We, however, don't want to publish a new version for chore, docs, etc. So we analyze * the commits to see if any of them indicate that a new release should be published. */ async isReleasable(pkg) { const commitInspection = await (0, inspectCommits_1.inspectCommits)(pkg); return commitInspection.shouldRelease; } } class PackageRepo extends Repository { constructor(options) { super(options); } validate() { return this.package.validateNextVersion(); } prepare(opts = {}) { const { dryrun } = opts; if (this.package.hasScript('version')) { this.run('version'); this.stageChanges(); } let cmd = 'npx standard-version --commit-all --releaseCommitMessageFormat="chore(release): {{currentTag}} [ci skip]"'; if (dryrun) cmd += ' --dry-run'; cmd += ` --release-as ${this.nextVersion}`; this.execCommand(cmd); } async sign() { packAndSign_1.api.setUx(this.ux); return packAndSign_1.api.packSignVerifyModifyPackageJSON(this.package.location); } async revertChanges() { return packAndSign_1.api.revertPackageJsonIfExists(); } getPkgInfo() { return { name: this.name, nextVersion: this.nextVersion, registryParam: this.registry.getRegistryParameter(), }; } async publish(opts = {}) { const { dryrun, signatures, access, tag } = opts; if (!dryrun) await this.writeNpmToken(); let cmd = 'npm publish'; if (signatures?.[0]?.fileTarPath) cmd += ` ${signatures[0]?.fileTarPath}`; if (tag) cmd += ` --tag ${tag}`; if (dryrun) cmd += ' --dry-run'; cmd += ` ${this.registry.getRegistryParameter()}`; cmd += ` --access ${access || 'public'}`; this.execCommand(cmd); } async waitForAvailability() { return this.poll(() => this.package.nextVersionIsAvailable()); } getSuccessMessage() { return chalk.green.bold(`Successfully released ${this.name}@${this.nextVersion}`); } async init() { this.logger = await core_1.Logger.child(this.constructor.name); this.package = await package_1.Package.create(); this.shouldBePublished = await this.isReleasable(this.package); this.nextVersion = this.determineNextVersion(); this.package.setNextVersion(this.nextVersion); this.name = this.package.npmPackage.name; } determineNextVersion() { if (this.package.nextVersionIsHardcoded()) { this.logger.debug(`${this.package.packageJson.name}@${this.package.packageJson.version} does not exist in the registry. Assuming that it's the version we want published`); return this.package.packageJson.version; } else { this.logger.debug('Using standard-version to determine next version'); let command = 'npx standard-version --dry-run --skip.tag --skip.commit --skip.changelog'; // It can be an empty string if they want if ((0, ts_types_2.isString)(this.options.useprerelease)) { command += ` --prerelease ${this.options.useprerelease}`; } const result = this.execCommand(command, true); const nextVersionRegex = /(?<=to\s)([0-9]{1,}\.|.){2,}/gi; return result.match(nextVersionRegex)[0]; } } } exports.PackageRepo = PackageRepo; //# sourceMappingURL=repository.js.map