vtex
Version:
The platform for e-commerce apps
201 lines (200 loc) • 8.79 kB
JavaScript
;
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;