Files
2018-03-22 14:45:41 +01:00

258 lines
7.4 KiB
JavaScript

/**
* Deploy script adopted from https://github.com/sindresorhus/np
* MIT License (c) Sindre Sorhus (sindresorhus.com)
*/
const chalk = require('chalk');
const execa = require('execa');
const inquirer = require('inquirer');
const Listr = require('listr');
const fs = require('fs-extra');
const semver = require('semver');
const common = require('./common');
const path = require('path');
async function main() {
try {
await common.checkGit();
const version = await askVersion();
await checkTagVersion(version);
// compiler and verify projects (read-only)
await prepareProject('core', version);
await prepareProject('angular', version, ['@ionic/core']);
// writes start here
// update package.json of each project
await updateVersion('core', version);
await updateVersion('angular', version);
// generate changelog
await generateChangeLog(version);
process.exit(0);
} catch(err) {
console.log('\n', chalk.red(err), '\n');
process.exit(1);
}
}
async function checkTagVersion(version) {
const listr = new Listr([
{
title: 'Check git tag existence',
task: () => execa('git', ['fetch'])
.then(() => {
return execa.stdout('npm', ['config', 'get', 'tag-version-prefix']);
})
.then(
output => {
tagPrefix = output;
},
() => {}
)
.then(() => execa.stdout('git', ['rev-parse', '--quiet', '--verify', `refs/tags/${tagPrefix}${version}`]))
.then(
output => {
if (output) {
throw new Error(`Git tag \`${tagPrefix}${version}\` already exists.`);
}
},
err => {
// Command fails with code 1 and no output if the tag does not exist, even though `--quiet` is provided
// https://github.com/sindresorhus/np/pull/73#discussion_r72385685
if (err.stdout !== '' || err.stderr !== '') {
throw err;
}
}
)
},
]);
await listr.run();
}
async function askVersion() {
const pkg = common.readPkg('core');
const oldVersion = pkg.version;
const prompts = [
{
type: 'list',
name: 'version',
message: 'Select semver increment or specify new version',
pageSize: SEMVER_INCREMENTS.length + 2,
choices: SEMVER_INCREMENTS
.map(inc => ({
name: `${inc} ${prettyVersionDiff(oldVersion, inc)}`,
value: inc
}))
.concat([
new inquirer.Separator(),
{
name: 'Other (specify)',
value: null
}
]),
filter: input => isValidVersionInput(input) ? getNewVersion(oldVersion, input) : input
},
{
type: 'input',
name: 'version',
message: 'Version',
when: answers => !answers.version,
filter: input => isValidVersionInput(input) ? getNewVersion(pkg.version, input) : input,
validate: input => {
if (!isValidVersionInput(input)) {
return 'Please specify a valid semver, for example, `1.2.3`. See http://semver.org';
} else if (!isVersionGreater(oldVersion, input)) {
return `Version must be greater than ${oldVersion}`;
}
return true;
}
},
{
type: 'confirm',
name: 'confirm',
message: answers => {
return `Will bump from ${chalk.cyan(oldVersion)} to ${chalk.cyan(answers.version)}. Continue?`;
}
}
];
const {version} = await inquirer.prompt(prompts);
return version;
}
async function prepareProject(project, version, dependencies) {
const projectRoot = common.projectPath(project);
const pkg = common.readPkg(project);
const oldVersion = pkg.version;
console.log(`\nPrepare to publish a new version of ${chalk.bold.magenta(pkg.name)} ${chalk.dim(`(${oldVersion}) => (${version})`)}\n`);
const tasks = [
{
title: 'Validate version',
task: () => {
if (!isVersionGreater(pkg.version, version)) {
throw new Error(`New version \`${newVersion}\` should be higher than current version \`${pkg.version}\``);
}
}
},
{
title: 'Cleanup',
task: () => fs.remove(path.join(projectRoot, 'node_modules'))
},
{
title: 'Install npm dependencies',
task: () => execa('npm', ['install'], { cwd: projectRoot }),
}];
if (dependencies && dependencies.length > 0) {
tasks.push(
{
title: 'Linking local dependencies',
task: () => {
return new Listr(dependencies.map(dep => ({
title: dep,
task: () => execa('npm', ['link', dep], { cwd: projectRoot }),
})));
}
}
);
}
tasks.push(
{
title: 'Run lint',
task: () => execa('npm', ['run', 'lint'], { cwd: projectRoot })
},
{
title: 'Build ' + pkg.name,
task: () => execa('npm', ['run', 'build'], { cwd: projectRoot })
},
{
title: 'Run tests',
task: () => execa('npm', ['test'], { cwd: projectRoot })
},
{
title: 'Linking',
task: () => execa('npm', ['link'], { cwd: projectRoot })
}
);
const listr = new Listr(tasks, { showSubtasks: false });
await listr.run();
}
async function updateVersion(project, version) {
const projectRoot = common.projectPath(project);
const listr = new Listr([{
title: `Updating ${project}/package.json version ${chalk.dim(`(${version})`)}`,
task: () => execa('npm', ['version', version], { cwd: projectRoot }),
}]);
await listr.run();
}
async function generateChangeLog() {
const rootDir = common.rootPath();
const listr = new Listr([{
title: 'Generate CHANGELOG',
task: () => execa('npm', ['run', 'changelog'], { cwd: rootDir }),
}]);
await listr.run();
}
const SEMVER_INCREMENTS = ['patch', 'minor', 'major', 'prepatch', 'preminor', 'premajor', 'prerelease'];
const PRERELEASE_VERSIONS = ['prepatch', 'preminor', 'premajor', 'prerelease'];
const isValidVersion = input => Boolean(semver.valid(input));
const isValidVersionInput = input => SEMVER_INCREMENTS.indexOf(input) !== -1 || common.isValidVersion(input);
const isPrereleaseVersion = version => PRERELEASE_VERSIONS.indexOf(version) !== -1 || Boolean(semver.prerelease(version));
function getNewVersion(oldVersion, input) {
if (!isValidVersionInput(input)) {
throw new Error(`Version should be either ${SEMVER_INCREMENTS.join(', ')} or a valid semver version.`);
}
return SEMVER_INCREMENTS.indexOf(input) === -1 ? input : semver.inc(oldVersion, input);
};
const isVersionGreater = (oldVersion, newVersion) => {
if (!common.isValidVersion(newVersion)) {
throw new Error('Version should be a valid semver version.');
}
return semver.gt(newVersion, oldVersion);
};
function prettyVersionDiff(oldVersion, inc) {
const newVersion = getNewVersion(oldVersion, inc).split('.');
oldVersion = oldVersion.split('.');
let firstVersionChange = false;
const output = [];
for (let i = 0; i < newVersion.length; i++) {
if ((newVersion[i] !== oldVersion[i] && !firstVersionChange)) {
output.push(`${chalk.dim.cyan(newVersion[i])}`);
firstVersionChange = true;
} else if (newVersion[i].indexOf('-') >= 1) {
let preVersion = [];
preVersion = newVersion[i].split('-');
output.push(`${chalk.dim.cyan(`${preVersion[0]}-${preVersion[1]}`)}`);
} else {
output.push(chalk.reset.dim(newVersion[i]));
}
}
return output.join(chalk.reset.dim('.'));
}
main();