├── .node-version ├── .gitignore ├── bin.js ├── test.js ├── .github └── workflows │ └── build.yml ├── LICENSE ├── package.json ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── README.md └── npmpub.js /.node-version: -------------------------------------------------------------------------------- 1 | 16 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /bin.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | require("./npmpub.js"); 4 | -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | /* 3 | hum sorry, it's not automated yet 4 | 5 | ./bin.js --verbose --debug --skip-status --skip-fetch --skip-compare --skip-cleanup --dry 6 | ./bin.js --verbose --debug --skip-fetch --skip-compare --skip-cleanup --dry 7 | ./bin.js --verbose --debug --skip-compare --skip-cleanup --dry 8 | ./bin.js --verbose --skip-cleanup --dry 9 | ./bin.js --skip-cleanup --dry 10 | ./bin.js --dry 11 | 12 | Then when everything is ready, pray and try 13 | 14 | npm run release 15 | 16 | And now you know. 17 | */ 18 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | tests: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v2 10 | - uses: actions/setup-node@v2 11 | with: 12 | node-version-file: ".node-version" 13 | 14 | - uses: actions/cache@v2 15 | with: 16 | path: ~/.npm 17 | key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} 18 | restore-keys: | 19 | ${{ runner.os }}-node- 20 | 21 | - run: npm ci 22 | 23 | - run: npm test 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) Maxime Thirouin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "npmpub", 3 | "version": "5.1.1", 4 | "description": "`npm publish` on steroid", 5 | "keywords": [ 6 | "cli-app", 7 | "cli", 8 | "npm", 9 | "publish", 10 | "git", 11 | "push", 12 | "version", 13 | "bump", 14 | "commit" 15 | ], 16 | "author": "Maxime Thirouin", 17 | "license": "MIT", 18 | "repository": "https://github.com/MoOx/npmpub.git", 19 | "bin": { 20 | "npmpub": "bin.js" 21 | }, 22 | "files": [ 23 | "bin.js", 24 | "npmpub.js" 25 | ], 26 | "dependencies": { 27 | "chalk": "^1.1.1", 28 | "github-release-from-changelog": "^2.0.0", 29 | "minimist": "^1.2.0", 30 | "shelljs": "^0.8.5", 31 | "trash": "^3.4.1" 32 | }, 33 | "devDependencies": { 34 | "eslint": "^6.4.0", 35 | "husky": "^3.0.5", 36 | "prettier": "^1.18.2", 37 | "pretty-quick": "^1.11.1" 38 | }, 39 | "scripts": { 40 | "pretest": "eslint .", 41 | "test": "echo \"I use myself to publish myself, that's how I test myself.\"", 42 | "release": "./bin.js --verbose --debug" 43 | }, 44 | "engines": { 45 | "node": ">=8.0.0" 46 | }, 47 | "eslintConfig": { 48 | "parserOptions": { 49 | "ecmaVersion": 2017 50 | }, 51 | "env": { 52 | "node": true, 53 | "es6": true 54 | }, 55 | "extends": "eslint:recommended" 56 | }, 57 | "husky": { 58 | "hooks": { 59 | "pre-commit": "pretty-quick --staged" 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # `npmpub` Changelog 2 | 3 | ## 5.1.1 - 2022-04-13 4 | 5 | - Bump shelljs to avoid security issue. 6 | 7 | ## 5.1.0 - 2022-03-07 8 | 9 | - Add support for otp flag for npm publish [#28](https://github.com/MoOx/npmpub/pull/28) by [@mbehzad](https://github.com/mbehzad) 10 | 11 | ## 5.0.0 - 2019-09-20 12 | 13 | - Bump github-release-from-changelog to v2 to support more changelog formats. 14 | 15 | ## 4.1.0 - 2018-07-29 16 | 17 | - Use `npm install` if no lock files found (by @hudochenkov in [#25](https://github.com/MoOx/npmpub/pull/25)). 18 | 19 | ## 4.0.1 - 2018-06-07 20 | 21 | - Fixed: annotated tags won't have "created with npmpub" anymore. 22 | 23 | ## 4.0.0 - 2018-06-07 24 | 25 | - Use `yarn --frozen-lockfile` or `npm ci` for cleanup 26 | - Fixed: tags are now annotated tags. 27 | 28 | ## 3.1.0 - 2016-03-12 29 | 30 | - Added: `--skip-test`, because you might need it for shitty test runner 31 | (eg: `testling` don't like to be ran from another location). 32 | **That's a pretty stupid option, I agree.** 33 | 34 | _Recommended Usage: `npm test && npmpub --skip-test`._ 35 | 36 | ## 3.0.3 - 2016-02-12 37 | 38 | - Fixed: 3.0.2 deactivated auto GitHub release. This is now fixed. 39 | 40 | ## 3.0.2 - 2016-02-12 41 | 42 | - Fixed: `--no-release` flag now works. 43 | 44 | ## 3.0.1 - 2016-01-20 45 | 46 | - Fixed: "npm publish" should actually call "npm publish", not "npmPublish". 47 | 48 | ## 3.0.0 - 2016-01-20 49 | 50 | **Complete rewrite using Node.js instead of sh.** 51 | 52 | - Changed: bin is now "npmpub" 53 | - Added: Does a GitHub release by default from the version number and the 54 | corresponding section in your changelog. 55 | - Added: `--help` to see the help 56 | - Added: `--verbose` to see some informations. 57 | - Added: `--debug` to see all informations about process. 58 | - Added: `--skip-status` to skip git status check 59 | - Added: `--skip-fetch` to skip git fetch to compare remote 60 | - Added: `--skip-compare` to skip git comparison with origin 61 | - Added: `--skip-cleanup` to skip node_modules cleanup 62 | - Added: `--dry` to skip npm publish, just to check that tests are ok. 63 | - Added: `--no-release` to avoid the GitHub release from changelog. 64 | 65 | ## 2.0.0 - 2016-01-11 66 | 67 | - Changed: do not rebase by default, but instead show a warning if relevant. 68 | - Fixed: no more `*-trash` warnings (`trash` replaced by `trash-cli`). 69 | - Added: show a warning if you have unstashed changes or remote is unreadable. 70 | 71 | ## 1.0.0 - 2015-10-04 72 | 73 | ✨ Initial release 74 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, gender identity and expression, level of 9 | experience, nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | - Using welcoming and inclusive language 18 | - Being respectful of differing viewpoints and experiences 19 | - Gracefully accepting constructive criticism 20 | - Focusing on what is best for the community 21 | - Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | - The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | - Trolling, insulting/derogatory comments, and personal or political attacks 28 | - Public or private harassmentthe 29 | - Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | - Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or reject 41 | comments, commits, code, wiki edits, issues, and other contributions that are 42 | not aligned to this Code of Conduct, or to ban temporarily or permanently any 43 | contributor for other behaviors that they deem inappropriate, threatening, 44 | offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting . All complaints will be 59 | reviewed and investigated and will result in a response that is deemed necessary 60 | and appropriate to the circumstances. The project team is obligated to maintain 61 | confidentiality with regard to the reporter of an incident. Further details of 62 | specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 71 | version 1.4, available at 72 | https://www.contributor-covenant.org/version/1/4/code-of-conduct/ 73 | 74 | [homepage]: https://www.contributor-covenant.org 75 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # npmpub 2 | 3 | [![Build Status](https://github.com/MoOx/npmpub/workflows/Build/badge.svg)](https://github.com/MoOx/npmpub/actions) 4 | [![NPM version](https://img.shields.io/npm/v/npmpub.svg?style=flat)](https://www.npmjs.com/package/npmpub) 5 | 6 | > `npm publish` on steroid 7 | 8 | ## What is this? 9 | 10 | The `npm publish` command is nice, but you always have to handle things before 11 | (fresh tests) and after (tag, GitHub release)... So if you want to release 12 | faster, just use this package/command! 13 | 14 | - Pulls in remote git commits to ensure you publish the latest commit. 15 | - Checks that a tag does not exist with the current version. 16 | - Reinstalls dependencies to ensure your project works with a fresh dependency 17 | tree. 18 | - Runs the tests. 19 | - Publishes a new version to npm. 20 | - Creates a git tag. 21 | - Pushes commits and tags to GitHub. 22 | - Edits the tag as a GitHub release based on the new version and corresponding 23 | changelog version 24 | (using [github-release-from-changelog](https://github.com/MoOx/github-release-from-changelog)). 25 | 26 | ## Requirements 27 | 28 | - npm ( 5.7 if you don't use yarn - to use `npm ci`) 29 | - yarn (optional) 30 | 31 | _In order to make use this package and the "GitHub release" feature, you will 32 | need a `$GITHUB_TOKEN` available as an env variable. 33 | If you want to use everything except this feature, just use the `--no-release` 34 | option (see below)._ 35 | 36 | - You can generate a 37 | [token from GitHub interface](https://help.github.com/articles/creating-an-access-token-for-command-line-use/) 38 | - Put it in `~/.github_token` 39 | - In your `.bashrc/zshrc`, export it by adding 40 | `export GITHUB_TOKEN=$(cat $HOME/.github_token)`. 41 | 42 | ## Install 43 | 44 | ``` 45 | $ npm install -D npmpub 46 | # -- or -- 47 | $ yarn add --dev npmpub 48 | ``` 49 | 50 | ## Usage 51 | 52 | Since you are probably 53 | [maintaining a CHANGELOG (or you should)](http://keepachangelog.com/), you 54 | already handle by hand version number (because you care about 55 | [semver](http://semver.org/), don't you?). 56 | 57 | So here is how to use this command: 58 | 59 | - Prepare your `CHANGELOG`. The best (and easy way) to do this is by 60 | preparing your changelog while you commit your features/fixes. 61 | It make the release process more easy. 62 | So when you commit an API change, a feature or a fix, add your commit message 63 | in your CHANGELOG prefixed by _Removed/Changed/Added/Fixed_. 64 | - Update your version number in your `CHANGELOG`. 65 | It's very easy to choose a version number: 66 | - If you have at least a _Removed_ or a _Changed_, it's a **breaking change**, 67 | so increment the first number (X.y.z), 68 | - If you have _Added_ something, it's a **minor change**, 69 | so increment the second number (x.Y.z), 70 | - If you just have _Fixed_ something, it's a **patch**, 71 | so increment the last number (x.y.Z). 72 | - Update your version number in your `package.json` 73 | - Commit 74 | - Run `npmpub` so have a clean release (fresh tests + tag + GitHub release 75 | notes) 76 | 77 | ## How to run `npmpub`? 78 | 79 | There is two way: 80 | 81 | ```console 82 | $ ./node_modules/.bin/npmpub 83 | ``` 84 | 85 | Or you can add a npm scripts in your `package.json` 86 | 87 | ```json 88 | { 89 | "scripts": { 90 | "release": "npmpub" 91 | } 92 | } 93 | ``` 94 | 95 | This way you can run 96 | 97 | ```console 98 | $ npm run release 99 | # -- or -- 100 | $ yarn release 101 | ``` 102 | 103 | ## Options 104 | 105 | ```console 106 | $ ./node_modules/.bin/npmpub --help 107 | 108 | npmpub [options] 109 | 110 | --help Just what you are reading. 111 | --verbose Get some informations. 112 | --debug Get all informations about process. 113 | --skip-status Skip git status check (⚠︎ you might release unversionned stuff). 114 | --skip-fetch Skip git fetch to compare remote (⚠︎ you might not be able to push). 115 | --skip-compare Skip git comparison with origin (⚠︎ you might not be able to push). 116 | --skip-cleanup Skip node_modules cleanup (⚠︎ you might miss some dependencies changes). 117 | --skip-test Skip test (⚠︎ USE THIS VERY CAREFULLY). 118 | --otp Prompt for npm's 2FA one-time-password before publishing 119 | --public Set access to public when publishing @scoped/package 120 | --dry No publish, just check that tests are ok. 121 | --no-release No GitHub release from changelog. 122 | ``` 123 | 124 | --- 125 | 126 | ## CONTRIBUTING 127 | 128 | - ⇄ Pull requests and ★ Stars are always welcome. 129 | - For bugs and feature requests, please create an issue. 130 | 131 | ## [CHANGELOG](CHANGELOG.md) 132 | 133 | ## [LICENSE](LICENSE) 134 | -------------------------------------------------------------------------------- /npmpub.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | const readline = require("readline"); 3 | 4 | const colors = require("chalk"); 5 | const sh = require("shelljs"); 6 | const parseArgs = require("minimist"); 7 | const trash = require("trash"); 8 | 9 | const exec = sh.exec; 10 | const exit = sh.exit; 11 | 12 | const argv = parseArgs(process.argv.slice(2), { 13 | boolean: true, 14 | default: { 15 | release: true 16 | } 17 | }); 18 | 19 | const print = msg => console.log("📦 " + msg); 20 | const notice = msg => print(colors.yellow.bold(msg)); 21 | const log = msg => argv.verbose && print(colors.yellow(msg)); 22 | const debug = msg => argv.debug && print(msg); 23 | const error = msg => print(colors.red.bold(msg)); 24 | 25 | const cmds = { 26 | isYarn: "ls yarn.lock", 27 | isPackageLockPresent: "ls package-lock.json", 28 | install: undefined, // defined after isYarn test 29 | gitStatus: "git status --porcelain", 30 | gitFetch: "git fetch --quiet", 31 | gitCheckRemote: "git rev-list --count --left-only @'{u}'...HEAD" 32 | }; 33 | 34 | if (argv["help"]) { 35 | /* eslint-disable max-len */ 36 | console.log(`npmpub [options] 37 | 38 | --help Just what you are reading. 39 | --verbose Get some informations. 40 | --debug Get all informations about process. 41 | --skip-status Skip git status check (⚠︎ you might release unversionned stuff). 42 | --skip-fetch Skip git fetch to compare remote (⚠︎ you might not be able to push). 43 | --skip-compare Skip git comparison with origin (⚠︎ you might not be able to push). 44 | --skip-cleanup Skip node_modules cleanup (⚠︎ you might miss some dependencies changes). 45 | --skip-test Skip test (⚠︎ USE THIS VERY CAREFULLY). 46 | --otp Prompt for npm's 2FA one-time-password before publishing 47 | --public Set access to public when publishing @scoped/package 48 | --dry No publish, just check that tests are ok. 49 | --no-release No GitHub release from changelog. 50 | `); 51 | /* eslint-enable max-len */ 52 | exit(0); 53 | } 54 | 55 | const execOpts = { silent: !argv.debug }; 56 | 57 | // check if yarn is used 58 | debug(cmds.isYarn); 59 | const isYarn = exec(cmds.isYarn, execOpts).code === 0; 60 | if (isYarn) { 61 | log("Yarn detected."); 62 | } 63 | 64 | // check if package-lock is used 65 | debug(cmds.isPackageLockPresent); 66 | const isPackageLockPresent = 67 | exec(cmds.isPackageLockPresent, execOpts).code === 0; 68 | if (isPackageLockPresent) { 69 | log("package-lock.json detected."); 70 | } 71 | 72 | if (isYarn) { 73 | cmds.install = "yarn --frozen-lockfile"; 74 | } else if (isPackageLockPresent) { 75 | cmds.install = "npm ci"; 76 | } else { 77 | cmds.install = "npm install"; 78 | } 79 | 80 | // check clean status 81 | if (argv["skip-status"]) { 82 | log("Git status check skipped."); 83 | } else { 84 | debug(cmds.gitStatus); 85 | const gitStatus = exec(cmds.gitStatus, execOpts); 86 | if (gitStatus.code !== 0 || gitStatus.stdout !== "") { 87 | error("Unclean working tree. Commit or stash changes first."); 88 | exit(1); 89 | } else { 90 | log("Git working directory clean."); 91 | } 92 | } 93 | 94 | // fetch remote 95 | if (argv["skip-fetch"]) { 96 | log("Git fetch skipped."); 97 | } else { 98 | debug(cmds.gitFetch); 99 | const gitFetch = exec(cmds.gitFetch, execOpts); 100 | if (gitFetch.code !== 0) { 101 | error("There was a problem fetching your branch."); 102 | exit(1); 103 | } else { 104 | log("Git fetch done."); 105 | } 106 | } 107 | 108 | // compare remote 109 | if (argv["skip-compare"]) { 110 | log("Git comparison skipped."); 111 | } else { 112 | debug(cmds.gitCheckRemote); 113 | const gitCheckRemote = exec(cmds.gitCheckRemote, execOpts); 114 | if (gitCheckRemote.stdout !== "0\n") { 115 | error("Remote history differ. Please pull changes."); 116 | exit(1); 117 | } else { 118 | log("Git local copy up to date."); 119 | } 120 | } 121 | 122 | const pkg = path.join(process.cwd(), "package.json"); 123 | log("package.json is '" + pkg + "'."); 124 | const version = require(pkg).version; 125 | notice("Preparing v" + version + "."); 126 | 127 | log("Checking existing tags."); 128 | const gitTags = exec("git tag", { silent: true }); 129 | if (gitTags.code !== 0) { 130 | error("Can't read tags."); 131 | exit(1); 132 | } else if (gitTags.stdout.split("\n").indexOf(version) > -1) { 133 | error("Tag already exist."); 134 | exit(1); 135 | } 136 | 137 | let cleanupPromise; 138 | if (argv["skip-cleanup"]) { 139 | log("Cleanup skipped."); 140 | cleanupPromise = Promise.resolve(); 141 | } else { 142 | log("Cleaning node_modules."); 143 | const nodeModules = path.join(process.cwd(), "node_modules"); 144 | if (argv.verbose) { 145 | debug("Will delete '" + nodeModules + "'."); 146 | } 147 | cleanupPromise = trash([nodeModules]).then(() => { 148 | log("node_modules deleted."); 149 | 150 | notice("Running '" + cmds.install + "'. This can take a while."); 151 | return new Promise(resolve => { 152 | exec(cmds.install, execOpts, (code, stdout, stderr) => { 153 | if (code === 0) { 154 | resolve(); 155 | } else { 156 | console.log(stderr); 157 | error(cmds.install + " failed."); 158 | exit(1); 159 | } 160 | }); 161 | }); 162 | }); 163 | } 164 | 165 | cleanupPromise 166 | .then(async () => { 167 | if (argv["skip-test"]) { 168 | log("Test skipped."); 169 | } else { 170 | notice("Running tests..."); 171 | const npmTest = exec("npm test"); 172 | if (npmTest.code !== 0) { 173 | throw new Error("'npm test' failed."); 174 | } 175 | } 176 | 177 | if (argv.dry) { 178 | notice("Dry run. No publish."); 179 | } else { 180 | const flags = []; 181 | // prompt user to enter npm's two-factor authentication's one-time-password 182 | if (argv["otp"]) { 183 | let otp = await new Promise(resolve => { 184 | const rl = readline.createInterface({ 185 | input: process.stdin, 186 | output: process.stdout 187 | }); 188 | 189 | rl.question("Enter OTP:", answer => { 190 | rl.close(); 191 | resolve(answer); 192 | }); 193 | }); 194 | flags.push(`--otp=${otp}`); 195 | } 196 | 197 | if (argv["public"]) { 198 | // is needed for (public) scoped npm packages 199 | flags.push("--access=public"); 200 | } 201 | 202 | notice("Publishing..."); 203 | const npmPublish = exec(`npm publish ${flags.join(" ")}`); 204 | if (npmPublish.code !== 0) { 205 | error("Publishing failed."); 206 | exit(1); 207 | } 208 | 209 | log("Tagging."); 210 | const gitTag = exec( 211 | 'git tag -m "Release version ' + version + '" -a ' + version 212 | ); 213 | if (gitTag.code !== 0) { 214 | error("Tagging failed."); 215 | exit(1); 216 | } 217 | 218 | log("Git push."); 219 | const gitPush = exec("git push --follow-tags"); 220 | if (gitPush.code !== 0) { 221 | error("pushing failed."); 222 | exit(1); 223 | } 224 | 225 | if (!argv["release"]) { 226 | log("No GitHub release."); 227 | } else { 228 | log("GitHub release."); 229 | const githubRelease = exec( 230 | "./node_modules/.bin/github-release-from-changelog" 231 | ); 232 | if (githubRelease.code !== 0) { 233 | error("GitHub release failed."); 234 | exit(1); 235 | } 236 | } 237 | } 238 | }) 239 | .catch(err => { 240 | if (err) { 241 | setTimeout(() => { 242 | throw err; 243 | }, 1); 244 | } else { 245 | exit(1); 246 | } 247 | }); 248 | --------------------------------------------------------------------------------