const { utils } = require('umi'); const { join, relative, resolve, sep } = require('path'); const exec = require('./utils/exec'); const getPackages = require('./utils/getPackages'); const isNextVersion = require('./utils/isNextVersion'); const { yParser, execa, chalk } = utils; const cwd = process.cwd(); const args = yParser(process.argv); const lernaCli = require.resolve('lerna/cli'); function printErrorAndExit(message) { console.error(chalk.red(message)); process.exit(1); } function logStep(name) { console.log(`${chalk.gray('>> Release:')} ${chalk.magenta.bold(name)}`); } function packageExists({ name, version }) { const { stdout } = execa.sync('npm', ['info', `${name}@${version}`]); return stdout.length > 0; } async function release() { let pkgList = execa.sync(lernaCli, ['list', '--json']).stdout; pkgList = JSON.parse(pkgList); const locMap = {}; pkgList.forEach((item) => { const location = item.location.split(sep); const componentName = item.name.split('/')[1]; locMap[componentName] = `${location[location.length - 2]}/${location[location.length - 1]}`; }); // Check git status if (!args.skipGitStatusCheck) { const gitStatus = execa.sync('git', ['status', '--porcelain']).stdout; if (gitStatus.length) { printErrorAndExit(`Your git status is not clean. Aborting.`); } } else { logStep('git status check is skipped, since --skip-git-status-check is supplied'); } // Check npm registry logStep('check npm registry'); const userRegistry = execa.sync('npm', ['config', 'get', 'registry']).stdout; if (userRegistry.includes('https://registry.yarnpkg.com/')) { printErrorAndExit(`Release failed, please use ${chalk.blue('npm run release')}.`); } // https://g.civnet.cn:4873 // if (!userRegistry.includes('https://registry.npmjs.org/')) { // const registry = chalk.blue('https://registry.npmjs.org/'); // printErrorAndExit(`Release failed, npm registry must be ${registry}.`); // } if (!userRegistry.includes('https://g.civnet.cn:4873/')) { const registry = chalk.blue('https://g.civnet.cn:4873/'); printErrorAndExit(`Release failed, npm registry must be ${registry}.`); } let updated = null; if (!args.publishOnly) { // Get updated packages logStep('check updated packages'); const updatedStdout = execa.sync(lernaCli, ['changed']).stdout; console.log('updatedStdout', updatedStdout); updated = updatedStdout .split('\n') .map((pkg) => { return pkg.split('/')[1]; }) .filter(Boolean); if (!updated.length) { printErrorAndExit('Release failed, no updated package is updated.'); } // Clean logStep('clean'); // Build if (!args.skipBuild) { logStep('build'); try { await exec('npm', ['run', 'build']); } catch (error) { console.log(error); } } else { logStep('build is skipped, since args.skipBuild is supplied'); } // Bump version // Commit // Git Tag // Push logStep('bump version with lerna version'); const conventionalGraduate = args.conventionalGraduate ? ['--conventional-graduate'].concat( Array.isArray(args.conventionalGraduate) ? args.conventionalGraduate.join(',') : [], ) : []; const conventionalPrerelease = args.conventionalPrerelease ? ['--conventional-prerelease'].concat( Array.isArray(args.conventionalPrerelease) ? args.conventionalPrerelease.join(',') : [], ) : []; await exec( lernaCli, [ 'version', '--exact', // '--no-commit-hooks', // '--no-git-tag-version', // '--no-push', '--message', 'π¨ chore(release): Publish', '--conventional-commits', ] .concat(conventionalGraduate) .concat(conventionalPrerelease), ); } // Publish // Umi must be the latest. const pkgs = args.publishOnly ? getPackages() : updated; logStep(`publish packages: ${chalk.blue(pkgs.join(', '))}`); // eslint-disable-next-line consistent-return,array-callback-return const publishList = pkgs.map((pkg, index) => { const pkgMap = locMap[pkg]; const [p, shortName] = pkgMap.split('/'); const pkgPath = join(cwd, 'packages', p, shortName.replace('pro-', '')); // eslint-disable-next-line global-require,import/no-dynamic-require const { name, version } = require(join(pkgPath, 'package.json')); if (name === 'parseform') return false; const isNext = isNextVersion(version); let isPackageExist = null; if (args.publishOnly) { isPackageExist = packageExists({ name, version }); if (isPackageExist) { console.log(`package ${name}@${version} is already exists on npm, skip.`); } } if (!args.publishOnly || !isPackageExist) { console.log( `[${index + 1}/${pkgs.length}] Publish package ${name} ${isNext ? 'with next tag' : ''}`, ); const cliArgs = isNext ? ['publish', '--tag', 'next'] : ['publish', '--tag', 'beta']; return execa('npm', cliArgs, { cwd: pkgPath, }); } }); console.log(`εεΈδΈ${pkgs.join('/')}`); await Promise.all(publishList); console.log('εεΈζε! '); await exec('npm', ['run', 'prettier']); logStep('done'); } release().catch((err) => { console.error(err); process.exit(1); });