UNPKG

vtex

Version:

The platform for e-commerce apps

201 lines (200 loc) 8.79 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ReleaseUtils = void 0; const tslib_1 = require("tslib"); const chalk_1 = tslib_1.__importDefault(require("chalk")); const child_process_es6_promise_1 = require("child-process-es6-promise"); const fs_extra_1 = require("fs-extra"); const path_1 = require("path"); const ramda_1 = require("ramda"); const semver_1 = tslib_1.__importDefault(require("semver")); const logger_1 = tslib_1.__importDefault(require("../../api/logger")); const ManifestUtil_1 = require("../../api/manifest/ManifestUtil"); const prompts_1 = require("../../api/modules/prompts"); const unreleased = '## [Unreleased]'; class ReleaseUtils { constructor() { this.readVersionFile = () => { try { return fs_extra_1.readJsonSync(this.versionFile); } catch (e) { if (e.code === 'ENOENT') { logger_1.default.error(`Version file not found: ${this.versionFile}.`); } throw e; } }; this.writeVersionFile = (newManifest) => { fs_extra_1.writeJsonSync(this.versionFile, newManifest, { spaces: 2 }); }; this.readVersion = () => { const version = semver_1.default.valid(this.readVersionFile().version, true); if (!version) { throw new Error(`Invalid app version: ${version}`); } return version; }; this.incrementVersion = (rawOldVersion, releaseType, tagName) => { const oldVersion = semver_1.default.valid(rawOldVersion, true); if (tagName !== 'stable' && releaseType !== 'prerelease') { return semver_1.default.inc(oldVersion, `pre${releaseType}`, false, tagName); } return semver_1.default.inc(oldVersion, releaseType); }; this.commit = (tagName) => { const commitMessage = `Release ${tagName}`; let successMessage = `File(s) ${this.versionFile} commited`; if (fs_extra_1.existsSync(this.changelogPath)) { successMessage = `Files ${this.versionFile} ${this.changelogPath} commited`; } return this.runCommand(`git commit -m "${commitMessage}"`, successMessage, true); }; this.tag = (tagName) => { const tagMessage = `Release ${tagName}`; return this.runCommand(`git tag ${tagName} -m "${tagMessage}"`, `Tag created: ${tagName}`, true); }; this.push = (tagName) => { return this.runCommand(`git push && git push origin ${tagName}`, 'Pushed commit and tags', true, 2); }; this.gitStatus = () => { return this.runCommand('git status --porcelain', '', true); }; this.checkNothingToCommit = () => { const response = this.gitStatus().toString(); return !response; }; this.checkIfGitPushWorks = () => { try { this.runCommand('git push', '', true, 2, true); } catch (e) { logger_1.default.error(`Failed pushing to remote.`); throw e; } }; this.preRelease = () => { const msg = 'Pre release'; if (!this.checkNothingToCommit()) { throw new Error('Please commit your changes before proceeding.'); } this.checkIfGitPushWorks(); const key = 'prereleasy'; this.runScript(key, msg); if (!this.checkNothingToCommit()) { const commitMessage = `Pre release commit\n\n ${this.getScript(key)}`; return this.commit(commitMessage); } }; this.confirmRelease = async () => { const answer = await prompts_1.promptConfirm(chalk_1.default.green('Are you sure?')); if (!answer) { logger_1.default.info('Cancelled by user'); return false; } return true; }; this.checkGit = () => { try { child_process_es6_promise_1.execSync('git --version'); } catch (e) { logger_1.default.error(`${chalk_1.default.bold(`git`)} is not available in your system. \ Please install it if you wish to use ${chalk_1.default.bold(`vtex release`)}`); throw e; } }; this.checkIfInGitRepo = () => { try { child_process_es6_promise_1.execSync('git rev-parse --git-dir'); } catch (e) { logger_1.default.error(`The current working directory is not in a git repo. \ Please run ${chalk_1.default.bold(`vtex release`)} from inside a git repo.`); throw e; } }; this.postRelease = () => { const msg = 'Post release'; if (this.getScript('postrelease')) { return this.runScript('postrelease', msg); } if (this.getScript('postreleasy')) { return this.runScript('postreleasy', msg); } }; this.add = () => { let gitAddCommand = `git add "${this.versionFile}"`; let successMessage = `File ${this.versionFile} added`; if (fs_extra_1.existsSync(this.changelogPath)) { gitAddCommand += ` "${this.changelogPath}"`; successMessage = `Files ${this.versionFile} ${this.changelogPath} added`; } return this.runCommand(gitAddCommand, successMessage, true); }; this.updateChangelog = (changelogVersion) => { if (fs_extra_1.existsSync(this.changelogPath)) { let data; try { data = fs_extra_1.readFileSync(this.changelogPath).toString(); } catch (e) { throw new Error(`Error reading file: ${e}`); } if (data.indexOf(unreleased) < 0) { logger_1.default.info(chalk_1.default.red.bold(`I can't update your CHANGELOG. :( \n Make your CHANGELOG great again and follow the CHANGELOG format http://keepachangelog.com/en/1.0.0/`)); } else { const position = data.indexOf(unreleased) + unreleased.length; const bufferedText = Buffer.from(`${changelogVersion}${data.substring(position)}`); const file = fs_extra_1.openSync(this.changelogPath, 'r+'); try { fs_extra_1.writeSync(file, bufferedText, 0, bufferedText.length, position); fs_extra_1.close(file); logger_1.default.info(`updated CHANGELOG`); } catch (e) { throw new Error(`Error writing file: ${e}`); } } } }; this.bump = (newVersion) => { const manifest = this.readVersionFile(); manifest.version = newVersion; this.writeVersionFile(manifest); logger_1.default.info(`Version bumped to ${chalk_1.default.bold.green(newVersion)}`); }; this.getScript = (key) => { return ramda_1.path(['scripts', key], this.readVersionFile()); }; this.runCommand = (cmd, successMessage, hideOutput = false, retries = 0, hideSuccessMessage = false) => { let output; try { output = child_process_es6_promise_1.execSync(cmd, { stdio: hideOutput ? 'pipe' : 'inherit', cwd: this.root }); if (!hideSuccessMessage) { logger_1.default.info(successMessage + chalk_1.default.blue(` > ${cmd}`)); } return output; } catch (e) { logger_1.default.error(`Command '${cmd}' exited with error code: ${e.status}`); if (retries <= 0) { throw e; } logger_1.default.info(`Retrying...`); return this.runCommand(cmd, successMessage, hideOutput, retries - 1, hideSuccessMessage); } }; this.runScript = (key, msg) => { const cmd = this.getScript(key); return cmd ? this.runCommand(cmd, msg, false) : undefined; }; this.root = ManifestUtil_1.getAppRoot(); this.versionFile = path_1.resolve(this.root, 'manifest.json'); this.changelogPath = path_1.resolve(this.root, 'CHANGELOG.md'); } } exports.ReleaseUtils = ReleaseUtils;