chore(deploy): update deploy scripts

This commit is contained in:
Adam Bradley
2018-03-28 15:35:31 -05:00
parent a5d2a33016
commit f304480dfc
10 changed files with 202 additions and 3488 deletions

View File

@ -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
};

View File

@ -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 = [
{
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 }),
}];
// check git is nice and clean local and remote
common.checkGit(tasks);
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 }),
})));
}
}
);
}
// test we're good with git
validateGit(tasks, version);
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 })
}
);
// 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();
}
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 validateGit(tasks, version) {
tasks.push(
{
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;
}
}
)
},
);
}
async function generateChangeLog() {
const rootDir = common.rootPath();
const listr = new Listr([{
title: 'Generate CHANGELOG',
task: () => execa('npm', ['run', 'changelog'], { cwd: rootDir }),
}]);
await listr.run();
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 \`${version}\` should be higher than current version \`${pkg.version}\``);
}
}
},
{
title: `${pkg.name}: install npm dependencies`,
task: async () => {
await fs.remove(path.join(projectRoot, 'node_modules'))
await execa('npm', ['install'], { cwd: projectRoot });
}
}
);
if (package !== 'core') {
tasks.push(
{
title: `${pkg.name}: npm link @ionic/core`,
task: () => execa('npm', ['link', '@ionic/core'], { cwd: projectRoot })
}
);
}
tasks.push(
{
title: `${pkg.name}: lint`,
task: () => execa('npm', ['run', 'lint'], { cwd: projectRoot })
},
{
title: `${pkg.name}: build`,
task: () => execa('npm', ['run', 'build'], { cwd: projectRoot })
},
{
title: `${pkg.name}: test`,
task: () => execa('npm', ['test'], { cwd: projectRoot })
}
);
if (package === 'core') {
tasks.push(
{
title: `${pkg.name}: npm link`,
task: () => execa('npm', ['link'], { cwd: projectRoot })
}
);
}
}
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(tasks) {
tasks.push(
{
title: `Generate CHANGELOG.md`,
task: () => execa('npm', ['run', 'changelog'], { cwd: common.rootDir }),
}
);
}

View File

@ -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})`,
// 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(newVersion !== version) {
throw new Error('version does not match');
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})`,
// 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([{
function publishGit(tasks, version) {
tasks.push(
{
title: 'Tagging the latest commit',
task: () => execa('git', ['tag', `v${version}`], { cwd: rootDir })
task: () => execa('git', ['tag', `v${version}`], { cwd: common.rootDir })
},
{
title: 'Pushing to Github',
task: () => execa('git', ['push', '--follow-tags'], { cwd: rootDir })
}]);
await listr.run();
task: () => execa('git', ['push', '--follow-tags'], { cwd: common.rootDir })
}
);
}
main();

3300
angular/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{
"name": "@ionic/angular",
"version": "0.1.4",
"version": "0.1.5-4",
"description": "Angular specific wrappers for @ionic/core",
"keywords": [
"ionic",
@ -25,8 +25,10 @@
"clean": "node scripts/clean.js",
"clean-generated": "node ./scripts/clean-generated.js",
"compile": "./node_modules/.bin/ngc",
"ionic-core": "stencil build --dev",
"ionic-core": "node ../core/node_modules/.bin/stencil build",
"ionic-core-dev": "node ../core/node_modules/.bin/stencil build --dev",
"lint": "tslint --project .",
"test": "echo 'angular no tests yet'",
"tsc": "tsc -p ."
},
"main": "./dist/index.js",
@ -45,8 +47,7 @@
"@angular/platform-browser": "latest",
"@angular/platform-browser-dynamic": "latest",
"@angular/router": "latest",
"@ionic/core": "^0.1.4",
"@stencil/core": "^0.7.9",
"@ionic/core": "latest",
"chalk": "^2.3.2",
"execa": "^0.9.0",
"fs-extra": "^5.0.0",

View File

@ -230,14 +230,6 @@
"resolved": "https://registry.npmjs.org/@ionic/angular/-/angular-0.0.2-29.tgz",
"integrity": "sha512-6HkJ+IZAy1o+EKjw1hBn+/CzkhHolCMXnUBxjHBCdNduCkeAiijFVCmok5lYbTjCX0xNI/rBtJmkFKrotBmWLQ=="
},
"@ionic/core": {
"version": "0.1.5-4",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-0.1.5-4.tgz",
"integrity": "sha512-dXaxgiWtiZc8pQzu/ia05OAqyr6QVwZFxOyKVhW/kIlzsTFfvNaxaPLnjG05YHqVYnRAhLd8ll00fgBYf95vWg==",
"requires": {
"ionicons": "4.0.0-18"
}
},
"@ngtools/json-schema": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@ngtools/json-schema/-/json-schema-1.2.0.tgz",
@ -4810,11 +4802,6 @@
"integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=",
"dev": true
},
"ionicons": {
"version": "4.0.0-18",
"resolved": "https://registry.npmjs.org/ionicons/-/ionicons-4.0.0-18.tgz",
"integrity": "sha512-nPijotkyDVy1tX6IBuo9/uLnWLtvwYUxX5YGcJJ0meyx6XwUrc+9irDF/xXkVnnUrw9cHbGoJv2Hs0l65wMWLQ=="
},
"ip": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz",

View File

@ -22,7 +22,6 @@
"@angular/platform-browser-dynamic": "latest",
"@angular/router": "latest",
"@ionic/angular": "next",
"@ionic/core": "next",
"body-parser": "^1.18.2",
"core-js": "^2.4.1",
"express": "^4.16.2",

View File

@ -24,7 +24,7 @@
"ionicons": "4.0.0-18"
},
"devDependencies": {
"@stencil/core": "^0.7.9",
"@stencil/core": "0.7.9",
"@stencil/dev-server": "latest",
"@stencil/postcss": "0.0.2",
"@stencil/sass": "0.0.3",
@ -57,7 +57,8 @@
"devapp": "sd concurrent \"stencil build --dev --watch --docs\" \"stencil-dev-server --broadcast\"",
"e2e": "node ./scripts/e2e",
"e2e-debug": "node --inspect --debug-brk ./scripts/e2e",
"lint": "npm run tslint & npm run sass-lint",
"lint": "npm run tslint && npm run sass-lint",
"prerelease": "npm run validate && np prerelease --yolo --any-branch --tag next",
"sass-lint": "sass-lint -v -q",
"set.version": "node scripts/set-version.js",
"snapshot": "node ./scripts/e2e --snapshot",
@ -67,11 +68,10 @@
"theme-builder": "sd concurrent \"npm run theme-app-build\" \"stencil build --dev --watch\" \"stencil-dev-server\" \"npm run theme-server\" ",
"theme-builder:dev": "sd concurrent \"npm run theme-app-build -- --watch\" \"stencil build --dev --watch\" \"stencil-dev-server\" \"npm run theme-server\" ",
"theme-server": "node scripts/theme-builder/server.js",
"tsc": "./node_modules/.bin/tsc -p .",
"tslint": "tslint --project .",
"tslint-fix": "tslint --project . --fix",
"prerelease": "npm run validate && np prerelease --yolo --any-branch --tag next",
"validate": "npm i && npm run lint && npm run test && npm run build",
"tsc": "./node_modules/.bin/tsc -p ."
"validate": "npm i && npm run lint && npm run test && npm run build"
},
"author": "Ionic Team",
"license": "MIT",

View File

@ -6,7 +6,7 @@
"scripts": {
"prepare.deploy": "node .scripts/prepare.js",
"deploy": "node .scripts/publish.js",
"changelog": "conventional-changelog -p angular -i core/CHANGELOG.md -k core -s"
"changelog": "conventional-changelog -p angular -i ./CHANGELOG.md -k core -s"
},
"devDependencies": {
"chalk": "^2.3.2",