chore(release): remove old release scripts and deps (#24599)
This commit is contained in:
parent
353dbc0537
commit
3e2d04dcc6
|
@ -1,26 +0,0 @@
|
|||
# Build Scripts
|
||||
|
||||
## Release
|
||||
|
||||
The deploy scripts at the root, make a new release of all the packages in this monorepo.
|
||||
All packages will be released with the same version.
|
||||
|
||||
In order to make a new release:
|
||||
|
||||
1. `npm run release.prepare`
|
||||
2. Review/update changelog
|
||||
3. Commit updates using the package name and version number as the commit message.
|
||||
4. `npm run release`
|
||||
5. :tada:
|
||||
|
||||
|
||||
## Prerelease
|
||||
|
||||
It's also possible to make prereleases of individual packages (@ionic/core, @ionic/angular).
|
||||
In order to do so, move to the package you want to make a new release and execute:
|
||||
```
|
||||
npm run prerelease
|
||||
```
|
||||
|
||||
It will publish a new prerelease in NPM, but it will not create any new git tag
|
||||
or update the CHANGELOG.
|
|
@ -1,15 +0,0 @@
|
|||
const common = require('./common');
|
||||
const Listr = require('listr');
|
||||
|
||||
|
||||
async function main() {
|
||||
const tasks = [];
|
||||
common.packages.forEach(package => {
|
||||
common.preparePackage(tasks, package, false, false);
|
||||
});
|
||||
|
||||
const listr = new Listr(tasks, { showSubtasks: true });
|
||||
await listr.run();
|
||||
}
|
||||
|
||||
main();
|
|
@ -1,404 +0,0 @@
|
|||
const fs = require('fs-extra');
|
||||
const path = require('path');
|
||||
const execa = require('execa');
|
||||
const inquirer = require('inquirer');
|
||||
const Listr = require('listr');
|
||||
const semver = require('semver');
|
||||
const { bold, cyan, dim } = require('colorette');
|
||||
|
||||
const rootDir = path.join(__dirname, '../');
|
||||
|
||||
const packages = [
|
||||
'core',
|
||||
'docs',
|
||||
'angular',
|
||||
'packages/react',
|
||||
'packages/react-router',
|
||||
'packages/angular-server',
|
||||
'packages/vue',
|
||||
'packages/vue-router'
|
||||
];
|
||||
|
||||
function readPkg(project) {
|
||||
const packageJsonPath = packagePath(project);
|
||||
return JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
|
||||
}
|
||||
|
||||
function writePkg(project, pkg) {
|
||||
const packageJsonPath = packagePath(project);
|
||||
const text = JSON.stringify(pkg, null, 2);
|
||||
return fs.writeFileSync(packageJsonPath, `${text}\n`);
|
||||
}
|
||||
|
||||
function packagePath(project) {
|
||||
return path.join(rootDir, project, 'package.json');
|
||||
}
|
||||
|
||||
function projectPath(project) {
|
||||
return path.join(rootDir, project);
|
||||
}
|
||||
|
||||
async function askNpmTag(version) {
|
||||
const prompts = [
|
||||
{
|
||||
type: 'list',
|
||||
name: 'npmTag',
|
||||
message: 'Select npm tag or specify a new tag',
|
||||
choices: ['latest', 'next', 'v4-lts', 'v5-lts']
|
||||
.concat([
|
||||
new inquirer.Separator(),
|
||||
{
|
||||
name: 'Other (specify)',
|
||||
value: null
|
||||
}
|
||||
])
|
||||
},
|
||||
{
|
||||
type: 'confirm',
|
||||
name: 'confirm',
|
||||
message: answers => {
|
||||
return `Will publish ${cyan(version)} to ${cyan(answers.npmTag)}. Continue?`;
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
const { npmTag, confirm } = await inquirer.prompt(prompts);
|
||||
return { npmTag, confirm };
|
||||
}
|
||||
|
||||
function checkGit(tasks) {
|
||||
tasks.push(
|
||||
{
|
||||
title: 'Check current branch',
|
||||
task: () =>
|
||||
execa.stdout('git', ['symbolic-ref', '--short', 'HEAD']).then(branch => {
|
||||
if (branch.indexOf('release') === -1 && branch.indexOf('hotfix') === -1) {
|
||||
throw new Error(`Must be on a "release" or "hotfix" branch.`);
|
||||
}
|
||||
})
|
||||
},
|
||||
{
|
||||
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.`);
|
||||
}
|
||||
})
|
||||
},
|
||||
{
|
||||
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.`);
|
||||
}
|
||||
})
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function checkTestDist(tasks) {
|
||||
tasks.push({
|
||||
title: 'Check dist folders for required files',
|
||||
task: () =>
|
||||
execa.stdout('node', ['.scripts/test-dist.js']).then(status => {
|
||||
if (status.indexOf('✅ test.dist') === -1) {
|
||||
throw new Error(`Test Dist did not find some required files`);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
const isValidVersion = input => Boolean(semver.valid(input));
|
||||
|
||||
function preparePackage(tasks, package, version, install) {
|
||||
const projectRoot = projectPath(package);
|
||||
const pkg = readPkg(package);
|
||||
|
||||
const projectTasks = [];
|
||||
if (version) {
|
||||
projectTasks.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}\``
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
if (install) {
|
||||
projectTasks.push({
|
||||
title: `${pkg.name}: install npm dependencies`,
|
||||
task: async () => {
|
||||
await fs.remove(path.join(projectRoot, 'node_modules'));
|
||||
await execa('npm', ['i', '--legacy-peer-deps'], { cwd: projectRoot });
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (package !== 'docs') {
|
||||
if (package !== 'core') {
|
||||
projectTasks.push({
|
||||
title: `${pkg.name}: npm link @ionic/core`,
|
||||
task: () => execa('npm', ['link', '@ionic/core', '--legacy-peer-deps'], { cwd: projectRoot })
|
||||
});
|
||||
|
||||
if (package === 'packages/react-router') {
|
||||
projectTasks.push({
|
||||
title: `${pkg.name}: npm link @ionic/react`,
|
||||
task: () => execa('npm', ['link', '@ionic/react', '--legacy-peer-deps'], { cwd: projectRoot })
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Lint, Test, Bump Core dependency
|
||||
if (version) {
|
||||
projectTasks.push({
|
||||
title: `${pkg.name}: lint`,
|
||||
task: () => execa('npm', ['run', 'lint'], { cwd: projectRoot })
|
||||
});
|
||||
// TODO will not work due to https://github.com/ionic-team/ionic/issues/20136
|
||||
// projectTasks.push({
|
||||
// title: `${pkg.name}: test`,
|
||||
// task: async () => await execa('npm', ['test'], { cwd: projectRoot })
|
||||
// });
|
||||
}
|
||||
|
||||
// Build
|
||||
projectTasks.push({
|
||||
title: `${pkg.name}: build`,
|
||||
task: () => execa('npm', ['run', 'build'], { cwd: projectRoot })
|
||||
});
|
||||
|
||||
// Link core or react for sub projects
|
||||
if (package === 'core' || package === 'packages/react') {
|
||||
projectTasks.push({
|
||||
title: `${pkg.name}: npm link`,
|
||||
task: () => execa('npm', ['link'], { cwd: projectRoot })
|
||||
});
|
||||
}
|
||||
|
||||
if (version) {
|
||||
projectTasks.push({
|
||||
title: `${pkg.name}: update ionic/core dep to ${version}`,
|
||||
task: () => {
|
||||
updateDependency(pkg, '@ionic/core', version);
|
||||
writePkg(package, pkg);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Add project tasks
|
||||
tasks.push({
|
||||
title: `Prepare ${bold(pkg.name)}`,
|
||||
task: () => new Listr(projectTasks)
|
||||
});
|
||||
}
|
||||
|
||||
function prepareDevPackage(tasks, package, version) {
|
||||
const projectRoot = projectPath(package);
|
||||
const pkg = readPkg(package);
|
||||
|
||||
const projectTasks = [];
|
||||
|
||||
if (package !== 'docs') {
|
||||
if (package !== 'core') {
|
||||
projectTasks.push({
|
||||
title: `${pkg.name}: npm link @ionic/core`,
|
||||
task: () => execa('npm', ['link', '@ionic/core', '--legacy-peer-deps'], { cwd: projectRoot })
|
||||
});
|
||||
|
||||
if (package === 'packages/react-router') {
|
||||
projectTasks.push({
|
||||
title: `${pkg.name}: npm link @ionic/react`,
|
||||
task: () => execa('npm', ['link', '@ionic/react', '--legacy-peer-deps'], { cwd: projectRoot })
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
projectTasks.push({
|
||||
title: `${pkg.name}: update ionic/core dep to ${version}`,
|
||||
task: () => {
|
||||
updateDependency(pkg, '@ionic/core', version);
|
||||
writePkg(package, pkg);
|
||||
}
|
||||
});
|
||||
|
||||
projectTasks.push({
|
||||
title: `${pkg.name}: build`,
|
||||
task: () => execa('npm', ['run', 'build'], { cwd: projectRoot })
|
||||
});
|
||||
|
||||
if (package === 'core' || package === 'packages/react') {
|
||||
projectTasks.push({
|
||||
title: `${pkg.name}: npm link`,
|
||||
task: () => execa('npm', ['link'], { cwd: projectRoot })
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Add project tasks
|
||||
tasks.push({
|
||||
title: `Prepare dev build: ${bold(pkg.name)}`,
|
||||
task: () => new Listr(projectTasks)
|
||||
});
|
||||
}
|
||||
|
||||
function updatePackageVersions(tasks, packages, version) {
|
||||
packages.forEach(package => {
|
||||
updatePackageVersion(tasks, package, version);
|
||||
|
||||
tasks.push({
|
||||
title: `${package} update @ionic/core dependency, if present ${dim(`(${version})`)}`,
|
||||
task: async () => {
|
||||
if (package !== 'core') {
|
||||
const pkg = readPkg(package);
|
||||
updateDependency(pkg, '@ionic/core', version);
|
||||
writePkg(package, pkg);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// angular & angular-server need to update their dist versions
|
||||
if (package === 'angular' || package === 'packages/angular-server') {
|
||||
const distPackage = path.join(package, 'dist');
|
||||
|
||||
updatePackageVersion(tasks, distPackage, version);
|
||||
|
||||
tasks.push({
|
||||
title: `${package} update @ionic/core dependency, if present ${dim(`(${version})`)}`,
|
||||
task: async () => {
|
||||
const pkg = readPkg(distPackage);
|
||||
updateDependency(pkg, '@ionic/core', version);
|
||||
writePkg(distPackage, pkg);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (package === 'packages/react-router') {
|
||||
tasks.push({
|
||||
title: `${package} update @ionic/react dependency, if present ${dim(`(${version})`)}`,
|
||||
task: async () => {
|
||||
const pkg = readPkg(package);
|
||||
updateDependency(pkg, '@ionic/react', version);
|
||||
writePkg(package, pkg);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function updatePackageVersion(tasks, package, version) {
|
||||
const projectRoot = projectPath(package);
|
||||
|
||||
tasks.push({
|
||||
title: `${package}: update package.json ${dim(`(${version})`)}`,
|
||||
task: async () => {
|
||||
await execa('npm', ['version', version], { cwd: projectRoot });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function copyPackageToDist(tasks, packages) {
|
||||
packages.forEach(package => {
|
||||
const projectRoot = projectPath(package);
|
||||
|
||||
// angular and angular-server are the only packages that publish dist
|
||||
if (package !== 'angular' && package !== 'packages/angular-server') {
|
||||
return;
|
||||
}
|
||||
|
||||
tasks.push({
|
||||
title: `${package}: Copy package.json to dist`,
|
||||
task: () => execa('node', ['copy-package.js', package], { cwd: path.join(rootDir, '.scripts') })
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function publishPackages(tasks, packages, version, npmTag = 'latest') {
|
||||
// first verify version
|
||||
packages.forEach(package => {
|
||||
if (package === 'core') {
|
||||
return;
|
||||
}
|
||||
|
||||
tasks.push({
|
||||
title: `${package}: check version (must match: ${version})`,
|
||||
task: () => {
|
||||
const pkg = readPkg(package);
|
||||
|
||||
if (version !== pkg.version) {
|
||||
throw new Error(`${pkg.name} version ${pkg.version} must match ${version}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Publish
|
||||
packages.forEach(package => {
|
||||
let projectRoot = projectPath(package);
|
||||
|
||||
if (package === 'packages/angular-server' || package === 'angular') {
|
||||
projectRoot = path.join(projectRoot, 'dist')
|
||||
}
|
||||
|
||||
tasks.push({
|
||||
title: `${package}: publish to ${npmTag} tag`,
|
||||
task: async () => {
|
||||
await execa('npm', ['publish', '--tag', npmTag], { cwd: projectRoot });
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function updateDependency(pkg, dependency, version) {
|
||||
if (pkg.dependencies && pkg.dependencies[dependency]) {
|
||||
pkg.dependencies[dependency] = version;
|
||||
}
|
||||
if (pkg.devDependencies && pkg.devDependencies[dependency]) {
|
||||
pkg.devDependencies[dependency] = version;
|
||||
}
|
||||
if (pkg.peerDependencies && pkg.peerDependencies[dependency]) {
|
||||
pkg.peerDependencies[dependency] = version;
|
||||
}
|
||||
}
|
||||
|
||||
function isVersionGreater(oldVersion, newVersion) {
|
||||
if (!isValidVersion(newVersion)) {
|
||||
throw new Error('Version should be a valid semver version.');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function copyCDNLoader(tasks, version) {
|
||||
tasks.push({
|
||||
title: `Copy CDN loader`,
|
||||
task: () => execa('node', ['copy-cdn-loader.js', version], { cwd: path.join(rootDir, 'core', 'scripts') })
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
checkTestDist,
|
||||
checkGit,
|
||||
askNpmTag,
|
||||
isValidVersion,
|
||||
isVersionGreater,
|
||||
copyCDNLoader,
|
||||
copyPackageToDist,
|
||||
packages,
|
||||
packagePath,
|
||||
prepareDevPackage,
|
||||
preparePackage,
|
||||
projectPath,
|
||||
publishPackages,
|
||||
readPkg,
|
||||
rootDir,
|
||||
updateDependency,
|
||||
updatePackageVersion,
|
||||
updatePackageVersions,
|
||||
writePkg
|
||||
};
|
|
@ -1,214 +0,0 @@
|
|||
/**
|
||||
* Deploy script adopted from https://github.com/sindresorhus/np
|
||||
* MIT License (c) Sindre Sorhus (sindresorhus.com)
|
||||
*/
|
||||
const { cyan, dim, red, reset } = require('colorette');
|
||||
const execa = require('execa');
|
||||
const inquirer = require('inquirer');
|
||||
const Listr = require('listr');
|
||||
const semver = require('semver');
|
||||
const common = require('./common');
|
||||
const path = require('path');
|
||||
|
||||
|
||||
async function main() {
|
||||
try {
|
||||
if (!process.env.GH_TOKEN) {
|
||||
throw new Error('env.GH_TOKEN is undefined');
|
||||
}
|
||||
|
||||
const { version, confirm } = await askVersion();
|
||||
const install = process.argv.indexOf('--no-install') < 0;
|
||||
|
||||
if (!confirm) {
|
||||
return;
|
||||
}
|
||||
|
||||
// compile and verify packages
|
||||
await preparePackages(common.packages, version, install);
|
||||
|
||||
console.log(`\nionic ${version} prepared 🤖\n`);
|
||||
console.log(`Next steps:`);
|
||||
console.log(` Verify CHANGELOG.md`);
|
||||
console.log(` git commit -m "${version}"`);
|
||||
console.log(` npm run release\n`);
|
||||
|
||||
} catch(err) {
|
||||
console.log('\n', red(err), '\n');
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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 (!common.isVersionGreater(oldVersion, input)) {
|
||||
return `Version must be greater than ${oldVersion}`;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'confirm',
|
||||
name: 'confirm',
|
||||
message: answers => {
|
||||
return `Will bump from ${cyan(oldVersion)} to ${cyan(answers.version)}. Continue?`;
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
const { version, confirm } = await inquirer.prompt(prompts);
|
||||
return { version, confirm };
|
||||
}
|
||||
|
||||
|
||||
async function preparePackages(packages, version, install) {
|
||||
// execution order matters
|
||||
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 => {
|
||||
common.preparePackage(tasks, package, version, install);
|
||||
});
|
||||
|
||||
// add update package.json of each project
|
||||
common.updatePackageVersions(tasks, packages, version);
|
||||
|
||||
// generate changelog
|
||||
generateChangeLog(tasks);
|
||||
|
||||
// check dist folders
|
||||
common.checkTestDist(tasks);
|
||||
|
||||
// update core readme with version number
|
||||
updateCoreReadme(tasks, version);
|
||||
common.copyCDNLoader(tasks, version);
|
||||
|
||||
const listr = new Listr(tasks, { showSubtasks: true });
|
||||
await listr.run();
|
||||
}
|
||||
|
||||
|
||||
function validateGit(tasks, version) {
|
||||
tasks.push(
|
||||
{
|
||||
title: `Validate git tag ${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 generateChangeLog(tasks) {
|
||||
tasks.push({
|
||||
title: `Generate CHANGELOG.md`,
|
||||
task: () => execa('npm', ['run', 'changelog'], { cwd: common.rootDir }),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function updateCoreReadme(tasks, version) {
|
||||
tasks.push({
|
||||
title: `Update core README.md`,
|
||||
task: () => execa('node', ['update-readme.js', version], { cwd: path.join(common.rootDir, 'core', 'scripts') }),
|
||||
});
|
||||
}
|
||||
|
||||
const SEMVER_INCREMENTS = ['patch', 'minor', 'major'];
|
||||
|
||||
const isValidVersionInput = input => SEMVER_INCREMENTS.indexOf(input) !== -1 || common.isValidVersion(input);
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
|
||||
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(`${dim(cyan(newVersion[i]))}`);
|
||||
firstVersionChange = true;
|
||||
} else if (newVersion[i].indexOf('-') >= 1) {
|
||||
let preVersion = [];
|
||||
preVersion = newVersion[i].split('-');
|
||||
output.push(`${dim(cyan(`${preVersion[0]}-${preVersion[1]}`))}`);
|
||||
} else {
|
||||
output.push(reset(dim(newVersion[i])));
|
||||
}
|
||||
}
|
||||
return output.join(reset(dim('.')));
|
||||
}
|
||||
|
||||
main();
|
|
@ -1,107 +0,0 @@
|
|||
const { cyan, red } = require('colorette');
|
||||
const semver = require('semver');
|
||||
const execa = require('execa');
|
||||
const inquirer = require('inquirer');
|
||||
const Listr = require('listr');
|
||||
const fs = require('fs-extra');
|
||||
|
||||
const common = require('./common');
|
||||
|
||||
const DIST_NPM_TAG = 'dev';
|
||||
const DIST_TAG = 'dev';
|
||||
|
||||
async function main() {
|
||||
const { packages } = common;
|
||||
|
||||
const orgPkg = packages.map(package => {
|
||||
const packageJsonPath = common.packagePath(package);
|
||||
return {
|
||||
filePath: packageJsonPath,
|
||||
packageContent: fs.readFileSync(packageJsonPath, 'utf-8')
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
const originalVersion = common.readPkg('core').version;
|
||||
const devVersion = await getDevVersion(originalVersion);
|
||||
|
||||
const confirm = await askDevVersion(devVersion);
|
||||
if (!confirm) {
|
||||
console.log(``);
|
||||
return;
|
||||
}
|
||||
|
||||
const tasks = [];
|
||||
|
||||
await setPackageVersionChanges(packages, devVersion);
|
||||
|
||||
packages.forEach(package => {
|
||||
common.prepareDevPackage(tasks, package, devVersion);
|
||||
});
|
||||
common.copyCDNLoader(tasks, devVersion);
|
||||
common.publishPackages(tasks, packages, devVersion, DIST_NPM_TAG);
|
||||
|
||||
const listr = new Listr(tasks);
|
||||
await listr.run();
|
||||
|
||||
console.log(`\nionic ${devVersion} published!! 🎉\n`);
|
||||
|
||||
} catch (err) {
|
||||
console.log('\n', red(err), '\n');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
orgPkg.forEach(pkg => {
|
||||
fs.writeFileSync(pkg.filePath, pkg.packageContent);
|
||||
});
|
||||
}
|
||||
|
||||
async function askDevVersion(devVersion) {
|
||||
|
||||
const prompts = [
|
||||
{
|
||||
type: 'confirm',
|
||||
name: 'confirm',
|
||||
value: true,
|
||||
message: () => {
|
||||
return `Publish the dev build ${cyan(devVersion)}?`;
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
const { confirm } = await inquirer.prompt(prompts);
|
||||
return confirm;
|
||||
}
|
||||
|
||||
async function setPackageVersionChanges(packages, version) {
|
||||
await Promise.all(packages.map(async package => {
|
||||
if (package !== 'core') {
|
||||
const pkg = common.readPkg(package);
|
||||
common.updateDependency(pkg, '@ionic/core', version);
|
||||
if(package === 'packages/react-router') {
|
||||
common.updateDependency(pkg, '@ionic/react', version);
|
||||
}
|
||||
common.writePkg(package, pkg);
|
||||
}
|
||||
const projectRoot = common.projectPath(package);
|
||||
await execa('npm', ['version', version], { cwd: projectRoot });
|
||||
}));
|
||||
}
|
||||
|
||||
async function getDevVersion(originalVersion) {
|
||||
const { stdout: sha } = await execa('git', ['log', '-1', '--format=%H']);
|
||||
const shortSha = sha.substring(0, 7);
|
||||
const baseVersion = semver.inc(originalVersion, 'minor');
|
||||
|
||||
const d = new Date();
|
||||
|
||||
let timestamp = d.getUTCFullYear().toString();
|
||||
timestamp += (d.getUTCMonth() + 1).toString().padStart(2, '0');
|
||||
timestamp += d.getUTCDate().toString().padStart(2, '0');
|
||||
timestamp += d.getUTCHours().toString().padStart(2, '0');
|
||||
timestamp += d.getUTCMinutes().toString().padStart(2, '0');
|
||||
|
||||
return `${baseVersion}-${DIST_TAG}.${timestamp}.${shortSha}`;
|
||||
}
|
||||
|
||||
main();
|
|
@ -1,144 +0,0 @@
|
|||
/**
|
||||
* Deploy script adopted from https://github.com/sindresorhus/np
|
||||
* MIT License (c) Sindre Sorhus (sindresorhus.com)
|
||||
*/
|
||||
const { cyan, dim, green, red, yellow } = require('colorette');
|
||||
const execa = require('execa');
|
||||
const Listr = require('listr');
|
||||
const path = require('path');
|
||||
const { Octokit } = require('@octokit/rest');
|
||||
const common = require('./common');
|
||||
const fs = require('fs-extra');
|
||||
|
||||
|
||||
async function main() {
|
||||
try {
|
||||
const dryRun = process.argv.indexOf('--dry-run') > -1;
|
||||
|
||||
if (!process.env.GH_TOKEN) {
|
||||
throw new Error('env.GH_TOKEN is undefined');
|
||||
}
|
||||
|
||||
checkProductionRelease();
|
||||
|
||||
const tasks = [];
|
||||
const { version } = common.readPkg('core');
|
||||
const changelog = findChangelog();
|
||||
|
||||
// repo must be clean
|
||||
common.checkGit(tasks);
|
||||
|
||||
const { npmTag, confirm } = await common.askNpmTag(version);
|
||||
|
||||
if (!confirm) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(!dryRun) {
|
||||
// publish each package in NPM
|
||||
common.publishPackages(tasks, common.packages, version, npmTag);
|
||||
|
||||
// push tag to git remote
|
||||
publishGit(tasks, version, changelog, npmTag);
|
||||
}
|
||||
|
||||
const listr = new Listr(tasks);
|
||||
await listr.run();
|
||||
|
||||
// Dry run doesn't publish to npm or git
|
||||
if (dryRun) {
|
||||
console.log(`
|
||||
\n${yellow('Did not publish. Remove the "--dry-run" flag to publish:')}\n${green(version)} to ${cyan(npmTag)}\n
|
||||
`);
|
||||
} else {
|
||||
console.log(`\nionic ${version} published to ${npmTag}!! 🎉\n`);
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
console.log('\n', red(err), '\n');
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
function checkProductionRelease() {
|
||||
const corePath = common.projectPath('core');
|
||||
const hasEsm = fs.existsSync(path.join(corePath, 'dist', 'esm'));
|
||||
const hasEsmEs5 = fs.existsSync(path.join(corePath, 'dist', 'esm-es5'));
|
||||
const hasCjs = fs.existsSync(path.join(corePath, 'dist', 'cjs'));
|
||||
if (!hasEsm || !hasEsmEs5 || !hasCjs) {
|
||||
throw new Error('core build is not a production build');
|
||||
}
|
||||
}
|
||||
|
||||
function publishGit(tasks, version, changelog, npmTag) {
|
||||
const gitTag = `v${version}`;
|
||||
|
||||
tasks.push(
|
||||
{
|
||||
title: `Tag latest commit ${dim(`(${gitTag})`)}`,
|
||||
task: () => execa('git', ['tag', `${gitTag}`], { cwd: common.rootDir })
|
||||
},
|
||||
{
|
||||
title: 'Push branches to remote',
|
||||
task: () => execa('git', ['push'], { cwd: common.rootDir })
|
||||
},
|
||||
{
|
||||
title: 'Push tags to remove',
|
||||
task: () => execa('git', ['push', '--follow-tags'], { cwd: common.rootDir })
|
||||
},
|
||||
{
|
||||
title: 'Publish Github release',
|
||||
task: () => publishGithub(version, gitTag, changelog, npmTag)
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function findChangelog() {
|
||||
const lines = fs.readFileSync('CHANGELOG.md', 'utf-8').toString().split('\n');
|
||||
let start = -1;
|
||||
let end = -1;
|
||||
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const line = lines[i];
|
||||
if (line.startsWith('## [') || line.startsWith('# [')) {
|
||||
if (start === -1) {
|
||||
start = i + 1;
|
||||
} else {
|
||||
end = i - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(start === -1 || end === -1) {
|
||||
throw new Error('changelog diff was not found');
|
||||
}
|
||||
return lines.slice(start, end).join('\n').trim();
|
||||
}
|
||||
|
||||
async function publishGithub(version, gitTag, changelog, npmTag) {
|
||||
// If the npm tag is next then publish as a prerelease
|
||||
const prerelease = npmTag === 'next' ? true : false;
|
||||
|
||||
const octokit = new Octokit({
|
||||
auth: process.env.GH_TOKEN
|
||||
});
|
||||
|
||||
let branch = await execa.stdout('git', ['symbolic-ref', '--short', 'HEAD']);
|
||||
|
||||
if (!branch) {
|
||||
branch = 'main';
|
||||
}
|
||||
|
||||
await octokit.repos.createRelease({
|
||||
owner: 'ionic-team',
|
||||
repo: 'ionic-framework',
|
||||
target_commitish: branch,
|
||||
tag_name: gitTag,
|
||||
name: version,
|
||||
body: changelog,
|
||||
prerelease: prerelease
|
||||
});
|
||||
}
|
||||
|
||||
main();
|
|
@ -1,113 +0,0 @@
|
|||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
|
||||
// Test dist build:
|
||||
// Double-triple check all the packages
|
||||
// and files are good to go before publishing
|
||||
[
|
||||
// core
|
||||
{
|
||||
files: [
|
||||
'../core/css/core.css',
|
||||
'../core/css/core.css.map',
|
||||
'../core/css/normalize.css',
|
||||
'../core/css/normalize.css.map',
|
||||
'../core/components/index.js',
|
||||
'../core/components/index.d.ts',
|
||||
'../core/components/package.json',
|
||||
'../core/dist/index.js',
|
||||
'../core/dist/ionic/index.esm.js',
|
||||
]
|
||||
},
|
||||
// hydrate
|
||||
{
|
||||
files: [
|
||||
'../core/hydrate/index.js',
|
||||
'../core/hydrate/index.d.ts',
|
||||
'../core/hydrate/package.json'
|
||||
]
|
||||
},
|
||||
// angular
|
||||
{
|
||||
files: [
|
||||
'../angular/dist/schematics/collection.json',
|
||||
'../angular/dist/fesm2015/ionic-angular.js',
|
||||
'../angular/dist/esm2015/ionic-angular.js',
|
||||
'../angular/dist/ionic-angular.d.ts'
|
||||
]
|
||||
},
|
||||
// angular-server
|
||||
{
|
||||
files: [
|
||||
'../packages/angular-server/dist/esm2015/ionic-angular-server.js',
|
||||
'../packages/angular-server/dist/fesm2015/ionic-angular-server.js',
|
||||
'../packages/angular-server/dist/ionic-angular-server.d.ts'
|
||||
]
|
||||
},
|
||||
// react
|
||||
{
|
||||
files: ['../packages/react/dist/index.js']
|
||||
},
|
||||
// react-router
|
||||
{
|
||||
files: ['../packages/react-router/dist/index.js']
|
||||
}
|
||||
].forEach(testPackage);
|
||||
|
||||
function testPackage(testPkg) {
|
||||
if (testPkg.packageJson) {
|
||||
const pkgDir = path.dirname(testPkg.packageJson);
|
||||
const pkgJson = require(testPkg.packageJson);
|
||||
|
||||
if (!pkgJson.name) {
|
||||
throw new Error('missing package.json name: ' + testPkg.packageJson);
|
||||
}
|
||||
|
||||
if (!pkgJson.main) {
|
||||
throw new Error('missing package.json main: ' + testPkg.packageJson);
|
||||
}
|
||||
|
||||
const pkgPath = path.join(pkgDir, pkgJson.main);
|
||||
const pkgImport = require(pkgPath);
|
||||
|
||||
if (testPkg.files) {
|
||||
if (!Array.isArray(pkgJson.files)) {
|
||||
throw new Error(testPkg.packageJson + ' missing "files" property');
|
||||
}
|
||||
testPkg.files.forEach(testPkgFile => {
|
||||
if (!pkgJson.files.includes(testPkgFile)) {
|
||||
throw new Error(testPkg.packageJson + ' missing file ' + testPkgFile);
|
||||
}
|
||||
|
||||
const filePath = path.join(__dirname, pkgDir, testPkgFile);
|
||||
fs.accessSync(filePath);
|
||||
});
|
||||
}
|
||||
|
||||
if (pkgJson.module) {
|
||||
const moduleIndex = path.join(__dirname, pkgDir, pkgJson.module);
|
||||
fs.accessSync(moduleIndex);
|
||||
}
|
||||
|
||||
if (pkgJson.types) {
|
||||
const pkgTypes = path.join(__dirname, pkgDir, pkgJson.types);
|
||||
fs.accessSync(pkgTypes);
|
||||
}
|
||||
|
||||
if (testPkg.exports) {
|
||||
testPkg.exports.forEach(exportName => {
|
||||
const m = pkgImport[exportName];
|
||||
if (!m) {
|
||||
throw new Error('export "' + exportName + '" not found in: ' + testPkg.packageJson);
|
||||
}
|
||||
});
|
||||
}
|
||||
} else if (testPkg.files) {
|
||||
testPkg.files.forEach(file => {
|
||||
const filePath = path.join(__dirname, file);
|
||||
fs.statSync(filePath);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`✅ test.dist`);
|
File diff suppressed because it is too large
Load Diff
11
package.json
11
package.json
|
@ -2,27 +2,16 @@
|
|||
"private": true,
|
||||
"description": "Ionic mono-repo root package.json, used mainly to execute build scripts. This package is not published to npm.",
|
||||
"scripts": {
|
||||
"build": "node .scripts/build.js",
|
||||
"release": "node .scripts/release.js",
|
||||
"changelog": "conventional-changelog -p angular -i ./CHANGELOG.md -k core -s",
|
||||
"commitizenBranches": "git-branch-is -q --not -r \"^(main|next|release-)\""
|
||||
},
|
||||
"devDependencies": {
|
||||
"@commitlint/cli": "^13.1.0",
|
||||
"@commitlint/config-conventional": "^13.1.0",
|
||||
"@octokit/rest": "^17.11.2",
|
||||
"colorette": "^1.2.1",
|
||||
"commitizen": "^4.2.4",
|
||||
"conventional-changelog-cli": "^2.1.1",
|
||||
"cz-conventional-changelog": "^3.3.0",
|
||||
"execa": "^0.10.0",
|
||||
"fs-extra": "^7.0.0",
|
||||
"git-branch-is": "^4.0.0",
|
||||
"husky": "^4.3.8",
|
||||
"inquirer": "^6.0.0",
|
||||
"lerna": "^4.0.0",
|
||||
"listr": "^0.14.0",
|
||||
"rimraf": "^2.6.3",
|
||||
"semver": "^5.5.0"
|
||||
},
|
||||
"engines": {
|
||||
|
|
Loading…
Reference in New Issue