diff --git a/package.json b/package.json index 76576ffdf..bf69b25c5 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "stylelint": "stylelint '**/*.{css,scss,sass}'", "prettier": "prettier --ignore-unknown .", "pretty-quick": "pretty-quick", - "release": "standard-version", + "release": "zx ./scripts/release.mjs", "precommit": "pretty-quick --staged && npm run check-types", "docs": "typedoc --entryPoints src/index.ts --out docs/api --name 'Molecule API'", "web": "webpack serve --env prod --config ./build/web.js" @@ -108,7 +108,8 @@ "typescript": "^4.0.5", "webpack-cli": "^4.0.0", "webpack-dev-server": "^3.11.0", - "webpack-merge": "^5.2.0" + "webpack-merge": "^5.2.0", + "zx": "^7.0.4" }, "husky": { "hooks": { diff --git a/scripts/release.mjs b/scripts/release.mjs new file mode 100644 index 000000000..064077988 --- /dev/null +++ b/scripts/release.mjs @@ -0,0 +1,87 @@ +import fs from 'fs'; +import path from 'path'; +import { chalk, $, question } from 'zx'; + +const errorLog = (str) => console.log(chalk.redBright(str)); +const infoLog = (str) => console.log(chalk.whiteBright(str)); + +const succeeDoneLog = () => console.log(chalk.greenBright('✔ DONE!')); + +const assert = (validation, str) => { + if (!validation) { + errorLog(str); + process.exit(1); + } +}; +$.verbose = false; + +const pkgPath = path.join(__dirname, '..', 'package.json'); +const pkg = require(pkgPath); + +(async () => { + infoLog('1. Check the npm login.'); + const isLogin = (await $`npm whoami`).stdout.trim().includes('ENEEDAUTH'); + assert( + !isLogin, + 'Please ensure your account is logining at https://registry.npmjs.org/' + ); + succeeDoneLog(); + + infoLog('1. Check the staged.'); + const isGitClean = (await $`git status --porcelain`).stdout.trim().length; + assert(!isGitClean, 'You should empty the staged before release.'); + succeeDoneLog(); + + infoLog('2. Check the branch.'); + const currentBranch = ( + await $`git rev-parse --abbrev-ref HEAD` + ).stdout.trim(); + assert(currentBranch === 'main', `can't release on ${currentBranch}`); + succeeDoneLog(); + + infoLog('3. Check the remote up to date.'); + const gitStatus = (await $`git status --short --branch`).stdout.trim(); + assert(!gitStatus.includes('behind'), `git status is behind remote`); + succeeDoneLog(); + + // check npm registry + infoLog('4. Check the npm registry.'); + const isNPMRegistry = + pkg.publishConfig.registry === 'https://registry.npmjs.org/'; + assert(isNPMRegistry, 'npm registry is not https://registry.npmjs.org/'); + succeeDoneLog(); + + infoLog('5. Bump version.'); + const lastVersion = require('../package.json').version; + const nextVersion = await question( + `Input the next version(current version is ${lastVersion}): ` + ); + + infoLog(`6. Generate Changelog`); + $.verbose = true; + await $`npx standard-version --release-as ${nextVersion}`; + $.verbose = false; + succeeDoneLog(); + + infoLog('7. Execute build...'); + await $`npm run build`; + succeeDoneLog(); + + infoLog(`8. Publish`); + await $`npm pack --dry-run`; + const publishCheck = await question( + 'Are these files you want to publish? (Y/n)' + ); + if (publishCheck.toLocaleLowerCase() === 'n') { + process.exit(1); + } + // use npm pack --dry-run to check publish pack + await $`npm publish`; + succeeDoneLog(); + + infoLog(`9. git push`); + $.verbose = true; + await $`git push --follow-tags origin main`; + $.verbose = false; + succeeDoneLog(); +})();