mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
chore(deploy): update deploy scripts
This commit is contained in:
@@ -6,37 +6,27 @@ const semver = require('semver');
|
||||
|
||||
const rootDir = path.join(__dirname, '../');
|
||||
|
||||
const packages = [
|
||||
'core',
|
||||
'angular'
|
||||
];
|
||||
|
||||
function readPkg(project) {
|
||||
const packageJsonPath = path.join(rootDir, project, 'package.json');
|
||||
function readPkg(package) {
|
||||
const packageJsonPath = path.join(rootDir, package, 'package.json');
|
||||
return JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
|
||||
}
|
||||
|
||||
function rootPath() {
|
||||
return rootDir;
|
||||
}
|
||||
|
||||
function projectPath(project) {
|
||||
return path.join(rootDir, project);
|
||||
}
|
||||
|
||||
async function checkGit() {
|
||||
const listr = new Listr([
|
||||
{
|
||||
title: 'Check npm version',
|
||||
skip: () => isVersionLower('6.0.0', process.version),
|
||||
task: () => execa.stdout('npm', ['version', '--json']).then(json => {
|
||||
const versions = JSON.parse(json);
|
||||
if (!satisfies(versions.npm, '>=2.15.8 <3.0.0 || >=3.10.1')) {
|
||||
throw new Error(`npm@${versions.npm} has known issues publishing when running Node.js 6. Please upgrade npm or downgrade Node and publish again. https://github.com/npm/npm/issues/5082`);
|
||||
}
|
||||
})
|
||||
},
|
||||
function checkGit(tasks) {
|
||||
tasks.push(
|
||||
{
|
||||
title: 'Check current branch',
|
||||
task: () => execa.stdout('git', ['symbolic-ref', '--short', 'HEAD']).then(branch => {
|
||||
if (branch !== 'master' && branch !== 'core') {
|
||||
throw new Error('Not on `master` or `core` branch');
|
||||
if (branch !== 'master') {
|
||||
throw new Error(`Not on "master" branch`);
|
||||
}
|
||||
})
|
||||
},
|
||||
@@ -44,7 +34,7 @@ async function checkGit() {
|
||||
title: 'Check local working tree',
|
||||
task: () => execa.stdout('git', ['status', '--porcelain']).then(status => {
|
||||
if (status !== '') {
|
||||
throw new Error('Unclean working tree. Commit or stash changes first.');
|
||||
throw new Error(`Unclean working tree. Commit or stash changes first.`);
|
||||
}
|
||||
})
|
||||
},
|
||||
@@ -52,31 +42,21 @@ async function checkGit() {
|
||||
title: 'Check remote history',
|
||||
task: () => execa.stdout('git', ['rev-list', '--count', '--left-only', '@{u}...HEAD']).then(result => {
|
||||
if (result !== '0') {
|
||||
throw new Error('Remote history differs. Please pull changes.');
|
||||
throw new Error(`Remote history differs. Please pull changes.`);
|
||||
}
|
||||
})
|
||||
}
|
||||
]);
|
||||
await listr.run();
|
||||
);
|
||||
}
|
||||
|
||||
const satisfies = (version, range) => semver.satisfies(version, range);
|
||||
|
||||
const isValidVersion = input => Boolean(semver.valid(input));
|
||||
|
||||
const isVersionLower = (oldVersion, newVersion) => {
|
||||
if (!isValidVersion(newVersion)) {
|
||||
throw new Error('Version should be a valid semver version.');
|
||||
}
|
||||
|
||||
return semver.lt(newVersion, oldVersion);
|
||||
};
|
||||
|
||||
|
||||
module.exports = {
|
||||
isValidVersion,
|
||||
readPkg,
|
||||
rootPath,
|
||||
rootDir,
|
||||
projectPath,
|
||||
checkGit,
|
||||
packages
|
||||
};
|
||||
|
||||
@@ -14,64 +14,24 @@ 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']);
|
||||
// compile and verify packages
|
||||
await preparePackages(common.packages, version);
|
||||
|
||||
// writes start here
|
||||
// update package.json of each project
|
||||
await updateVersion('core', version);
|
||||
await updateVersion('angular', version);
|
||||
console.log(`\nionic ${version} prepared 🤖\n`);
|
||||
console.log(`Next steps:`);
|
||||
console.log(` Verify CHANGELOG.md`);
|
||||
console.log(` git commit -m "${version}"`);
|
||||
console.log(` git push`);
|
||||
console.log(` npm run deploy\n`);
|
||||
|
||||
// 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');
|
||||
@@ -126,84 +86,155 @@ async function askVersion() {
|
||||
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`);
|
||||
async function preparePackages(packages, version) {
|
||||
// execution order matters
|
||||
const tasks = [];
|
||||
|
||||
const tasks = [
|
||||
// check git is nice and clean local and remote
|
||||
common.checkGit(tasks);
|
||||
|
||||
// test we're good with git
|
||||
validateGit(tasks, version);
|
||||
|
||||
// add all the prepare scripts
|
||||
// run all these tasks before updating package.json version
|
||||
packages.forEach(package => {
|
||||
preparePackage(tasks, package, version);
|
||||
});
|
||||
|
||||
// add update package.json of each project
|
||||
packages.forEach(package => {
|
||||
updatePackageVersion(tasks, package, version);
|
||||
});
|
||||
|
||||
// generate changelog
|
||||
generateChangeLog(tasks);
|
||||
|
||||
const listr = new Listr(tasks, { showSubtasks: false });
|
||||
await listr.run();
|
||||
}
|
||||
|
||||
|
||||
function validateGit(tasks, version) {
|
||||
tasks.push(
|
||||
{
|
||||
title: 'Validate version',
|
||||
title: `Validate git tag ${chalk.dim(`(v${version})`)}`,
|
||||
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;
|
||||
}
|
||||
}
|
||||
)
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
function preparePackage(tasks, package, version) {
|
||||
const projectRoot = common.projectPath(package);
|
||||
const pkg = common.readPkg(package);
|
||||
|
||||
tasks.push(
|
||||
{
|
||||
title: `${pkg.name}: validate new version`,
|
||||
task: () => {
|
||||
if (!isVersionGreater(pkg.version, version)) {
|
||||
throw new Error(`New version \`${newVersion}\` should be higher than current version \`${pkg.version}\``);
|
||||
throw new Error(`New version \`${version}\` 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 }),
|
||||
}];
|
||||
title: `${pkg.name}: install npm dependencies`,
|
||||
task: async () => {
|
||||
await fs.remove(path.join(projectRoot, 'node_modules'))
|
||||
await execa('npm', ['install'], { cwd: projectRoot });
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
if (dependencies && dependencies.length > 0) {
|
||||
if (package !== 'core') {
|
||||
tasks.push(
|
||||
{
|
||||
title: 'Linking local dependencies',
|
||||
task: () => {
|
||||
return new Listr(dependencies.map(dep => ({
|
||||
title: dep,
|
||||
task: () => execa('npm', ['link', dep], { cwd: projectRoot }),
|
||||
})));
|
||||
}
|
||||
title: `${pkg.name}: npm link @ionic/core`,
|
||||
task: () => execa('npm', ['link', '@ionic/core'], { cwd: projectRoot })
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
tasks.push(
|
||||
{
|
||||
title: 'Run lint',
|
||||
title: `${pkg.name}: lint`,
|
||||
task: () => execa('npm', ['run', 'lint'], { cwd: projectRoot })
|
||||
},
|
||||
{
|
||||
title: 'Build ' + pkg.name,
|
||||
title: `${pkg.name}: build`,
|
||||
task: () => execa('npm', ['run', 'build'], { cwd: projectRoot })
|
||||
},
|
||||
{
|
||||
title: 'Run tests',
|
||||
title: `${pkg.name}: test`,
|
||||
task: () => execa('npm', ['test'], { cwd: projectRoot })
|
||||
},
|
||||
{
|
||||
title: 'Linking',
|
||||
task: () => execa('npm', ['link'], { cwd: projectRoot })
|
||||
}
|
||||
);
|
||||
|
||||
const listr = new Listr(tasks, { showSubtasks: false });
|
||||
await listr.run();
|
||||
if (package === 'core') {
|
||||
tasks.push(
|
||||
{
|
||||
title: `${pkg.name}: npm link`,
|
||||
task: () => execa('npm', ['link'], { cwd: projectRoot })
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
function updatePackageVersion(tasks, package, version) {
|
||||
const projectRoot = common.projectPath(package);
|
||||
const pkg = common.readPkg(package);
|
||||
|
||||
tasks.push(
|
||||
{
|
||||
title: `${pkg.name}: update package.json ${chalk.dim(`(${version})`)}`,
|
||||
task: async () => {
|
||||
await execa('npm', ['version', version], { cwd: projectRoot });
|
||||
|
||||
const pkgLock = path.join(projectRoot, 'package-lock.json');
|
||||
const pkgLockData = JSON.parse(fs.readFileSync(pkgLock, 'utf-8'));
|
||||
pkgLockData.version = version;
|
||||
|
||||
fs.writeFileSync(pkgLock, JSON.stringify(pkgLockData));
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
async function generateChangeLog() {
|
||||
const rootDir = common.rootPath();
|
||||
const listr = new Listr([{
|
||||
title: 'Generate CHANGELOG',
|
||||
task: () => execa('npm', ['run', 'changelog'], { cwd: rootDir }),
|
||||
}]);
|
||||
await listr.run();
|
||||
|
||||
async function generateChangeLog(tasks) {
|
||||
tasks.push(
|
||||
{
|
||||
title: `Generate CHANGELOG.md`,
|
||||
task: () => execa('npm', ['run', 'changelog'], { cwd: common.rootDir }),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -12,17 +12,10 @@ async function main() {
|
||||
try {
|
||||
const {version} = common.readPkg('core');
|
||||
|
||||
// repo must be clean
|
||||
await common.checkGit();
|
||||
// publish each package in NPM
|
||||
await publishPackages(common.packages, version);
|
||||
|
||||
// publish each project in NPM
|
||||
await publishProjects(['core', 'angular'], version);
|
||||
|
||||
// push commits and tags to git remote
|
||||
await publishGit(version);
|
||||
|
||||
console.log(`\n${version} published!! 🎉\n`);
|
||||
process.exit(0);
|
||||
console.log(`\nionic ${version} published!! 🎉\n`);
|
||||
|
||||
} catch (err) {
|
||||
console.log('\n', chalk.red(err), '\n');
|
||||
@@ -30,42 +23,63 @@ async function main() {
|
||||
}
|
||||
}
|
||||
|
||||
async function publishProjects(projects, newVersion) {
|
||||
|
||||
async function publishPackages(packages, version) {
|
||||
const tasks = [];
|
||||
projects.forEach((project) => {
|
||||
const {name, version} = common.readPkg(project);
|
||||
tasks.push({
|
||||
title: `Checking version of name (must match: ${version})`,
|
||||
task: () => {
|
||||
if(newVersion !== version) {
|
||||
throw new Error('version does not match');
|
||||
|
||||
// repo must be clean
|
||||
common.checkGit(tasks);
|
||||
|
||||
// first verify version
|
||||
packages.forEach(package => {
|
||||
if (package === 'core') return;
|
||||
|
||||
const pkg = common.readPkg(package);
|
||||
|
||||
tasks.push(
|
||||
{
|
||||
title: `${pkg.name}: check version (must match: ${version})`,
|
||||
task: () => {
|
||||
if (version !== pkg.version) {
|
||||
throw new Error(`${pkg.name} version ${pkg.version} must match ${version}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
);
|
||||
});
|
||||
|
||||
projects.forEach((project) => {
|
||||
const projectRoot = common.projectPath(project);
|
||||
tasks.push({
|
||||
title: `Publish (latest) ${project} (v${newVersion})`,
|
||||
task: () => execa('npm', ['publish', '--tag', 'latest'], { cwd: projectRoot })
|
||||
});
|
||||
// next publish
|
||||
packages.forEach(package => {
|
||||
const pkg = common.readPkg(package);
|
||||
|
||||
tasks.push(
|
||||
{
|
||||
title: `${pkg.name}: publish ${pkg.version}`,
|
||||
task: () =>execa('npm', ['publish', '--tag', 'latest'], { cwd: projectRoot })
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
// push commits and tags to git remote
|
||||
publishGit(version);
|
||||
|
||||
const listr = new Listr(tasks);
|
||||
await listr.run();
|
||||
}
|
||||
|
||||
async function publishGit(version) {
|
||||
const rootDir = common.rootPath();
|
||||
const listr = new Listr([{
|
||||
title: 'Tagging the latest commit',
|
||||
task: () => execa('git', ['tag', `v${version}`], { cwd: rootDir })
|
||||
},
|
||||
{
|
||||
title: 'Pushing to Github',
|
||||
task: () => execa('git', ['push', '--follow-tags'], { cwd: rootDir })
|
||||
}]);
|
||||
await listr.run();
|
||||
|
||||
function publishGit(tasks, version) {
|
||||
tasks.push(
|
||||
{
|
||||
title: 'Tagging the latest commit',
|
||||
task: () => execa('git', ['tag', `v${version}`], { cwd: common.rootDir })
|
||||
},
|
||||
{
|
||||
title: 'Pushing to Github',
|
||||
task: () => execa('git', ['push', '--follow-tags'], { cwd: common.rootDir })
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
main();
|
||||
|
||||
Reference in New Issue
Block a user