├── .node-version ├── .gitignore ├── src ├── ora.js ├── logger.js ├── tag.js ├── exec.js ├── commit.js ├── bumpVersion.js ├── mainLifeCycle.js ├── changelog.js └── utils.js ├── .vscode └── settings.json ├── .npmignore ├── conventional-changelog-picgo ├── templates │ ├── footer.hbs │ ├── template.hbs │ ├── header.hbs │ └── commit.hbs ├── parser-opts.js ├── conventional-changelog.js ├── index.js ├── conventional-recommended-bump.js ├── LICENSE.md └── writer-opts.js ├── commitlint-picgo ├── types.js └── index.js ├── eslint.config.js ├── .github └── workflows │ └── publish.yml ├── License ├── package.json ├── CHANGELOG.md ├── .cz-config.js ├── bin └── bump-version └── README.md /.node-version: -------------------------------------------------------------------------------- 1 | 22 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | yarn-error.log 3 | .serena/ 4 | .vscode/ 5 | -------------------------------------------------------------------------------- /src/ora.js: -------------------------------------------------------------------------------- 1 | const Ora = require('ora') 2 | module.exports = new Ora({ 3 | text: '' 4 | }) 5 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.codeActionsOnSave": { 3 | "source.fixAll.eslint": "explicit" 4 | } 5 | } -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | yarn-error.log 3 | package-lock.json 4 | tsconfig.json 5 | tslint.json 6 | .vscode/ 7 | .travis.yml 8 | .serena/ 9 | pnpm-lock.yaml 10 | -------------------------------------------------------------------------------- /conventional-changelog-picgo/templates/footer.hbs: -------------------------------------------------------------------------------- 1 | {{#if noteGroups}} 2 | {{#each noteGroups}} 3 | 4 | ### {{title}} 5 | 6 | {{#each notes}} 7 | * {{#if commit.scope}}**{{commit.scope}}:** {{/if}}{{text}} 8 | {{/each}} 9 | {{/each}} 10 | 11 | {{/if}} 12 | -------------------------------------------------------------------------------- /conventional-changelog-picgo/templates/template.hbs: -------------------------------------------------------------------------------- 1 | {{> header}} 2 | 3 | {{#each commitGroups}} 4 | 5 | {{#if title}} 6 | ### {{title}} 7 | 8 | {{/if}} 9 | {{#each commits}} 10 | {{> commit root=@root}} 11 | {{/each}} 12 | 13 | {{/each}} 14 | {{> footer}} 15 | 16 | 17 | -------------------------------------------------------------------------------- /conventional-changelog-picgo/parser-opts.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | module.exports = { 4 | headerPattern: /^(:.*: \w*)(?:\((.*)\))?: (.*)$/, 5 | headerCorrespondence: [ 6 | `type`, 7 | `scope`, 8 | `subject` 9 | ], 10 | noteKeywords: [`BREAKING CHANGE`] 11 | } 12 | -------------------------------------------------------------------------------- /conventional-changelog-picgo/templates/header.hbs: -------------------------------------------------------------------------------- 1 | {{#if isPatch~}} 2 | ## 3 | {{~else~}} 4 | # 5 | {{~/if}} {{#if @root.linkCompare~}} 6 | :tada: {{version}} 7 | {{~else}} 8 | :tada: {{version}} 9 | {{~/if}} 10 | {{~#if title}} "{{title}}" 11 | {{~/if}} 12 | {{~#if date}} ({{date}}) 13 | {{/if}} 14 | -------------------------------------------------------------------------------- /conventional-changelog-picgo/conventional-changelog.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const Q = require(`q`) 4 | const parserOpts = require(`./parser-opts`) 5 | const writerOpts = require(`./writer-opts`) 6 | 7 | module.exports = Q.all([parserOpts, writerOpts]) 8 | .spread((parserOpts, writerOpts) => { 9 | return { parserOpts, writerOpts } 10 | }) 11 | -------------------------------------------------------------------------------- /src/logger.js: -------------------------------------------------------------------------------- 1 | const ora = require('./ora') 2 | const chalk = require('chalk') 3 | const level = { 4 | success: 'green', 5 | info: 'blue', 6 | warn: 'yellow', 7 | error: 'red' 8 | } 9 | module.exports = (msg, type) => { 10 | let log = chalk[level[type]](`[Bump ${type.toUpperCase()}]: `) 11 | log += msg 12 | ora.clear() 13 | ora.frame() 14 | console.log(log) 15 | } 16 | -------------------------------------------------------------------------------- /commitlint-picgo/types.js: -------------------------------------------------------------------------------- 1 | const types = [ 2 | ':sparkles: Feature', 3 | ':bug: Fix', 4 | ':construction: WIP', 5 | ':hammer: Refactor', 6 | ':package: Chore', 7 | ':art: Style', 8 | ':arrow_up: Upgrade', 9 | ':zap: Perf', 10 | ':pencil: Docs', 11 | ':white_check_mark: Test', 12 | ':back: Revert', 13 | ':tada: Release', 14 | ':pushpin: Init' 15 | ] 16 | 17 | module.exports = types 18 | -------------------------------------------------------------------------------- /src/tag.js: -------------------------------------------------------------------------------- 1 | const exec = require('./exec') 2 | module.exports = (argv, newVersion) => { 3 | if (argv.dry) { 4 | return Promise.resolve() 5 | } 6 | let flow 7 | if (argv.tag === false) { 8 | flow = Promise.resolve() 9 | } else { 10 | flow = exec(argv, `git tag -a v${newVersion} -m v${newVersion}`) 11 | } 12 | return flow.then(async () => { 13 | if (argv.push) { 14 | await exec(`git push --follow-tags origin master`) 15 | } 16 | return null 17 | }) 18 | } 19 | -------------------------------------------------------------------------------- /conventional-changelog-picgo/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const Q = require(`q`) 3 | const conventionalChangelog = require(`./conventional-changelog`) 4 | const parserOpts = require(`./parser-opts`) 5 | const recommendedBumpOpts = require(`./conventional-recommended-bump`) 6 | const writerOpts = require(`./writer-opts`) 7 | 8 | module.exports = Q.all([conventionalChangelog, parserOpts, recommendedBumpOpts, writerOpts]) 9 | .spread((conventionalChangelog, parserOpts, recommendedBumpOpts, writerOpts) => { 10 | return { conventionalChangelog, parserOpts, recommendedBumpOpts, writerOpts } 11 | }) 12 | -------------------------------------------------------------------------------- /src/exec.js: -------------------------------------------------------------------------------- 1 | const exec = require('child_process').exec 2 | const logger = require('./logger') 3 | 4 | module.exports = (argv, cmd) => { 5 | return new Promise((resolve, reject) => { 6 | // Exec given cmd and handle possible errors 7 | exec(cmd, { cwd: argv.path }, function (err, stdout, stderr) { 8 | // If exec returns content in stderr, but no error, print it as a warning 9 | // If exec returns an error, print it and exit with return code 1 10 | if (err) { 11 | logger(stderr || err.message, 'error') 12 | return reject(err) 13 | } else if (stderr) { 14 | logger(stderr, 'warn') 15 | } 16 | return resolve(stdout) 17 | }) 18 | }) 19 | } 20 | -------------------------------------------------------------------------------- /src/commit.js: -------------------------------------------------------------------------------- 1 | const utils = require('./utils') 2 | const exec = require('./exec') 3 | let changedFiles = [ 4 | 'package.json', 5 | 'package-lock.json' 6 | ] 7 | module.exports = (argv, newVersion) => { 8 | if (argv.changelog !== false) { 9 | changedFiles.push(argv.file) 10 | } 11 | const releaseMsg = `:tada: Release: v${newVersion}` 12 | if (argv.skipCommit) return Promise.resolve() 13 | changedFiles = utils.checkFileAndGetPath(argv, changedFiles).join(' ') 14 | if (changedFiles === '' || argv.dry) { 15 | return Promise.resolve() 16 | } 17 | return exec(argv, `git add ${changedFiles}`) 18 | .then(() => { 19 | return exec(argv, `git commit ${changedFiles} -m "${releaseMsg}"`) 20 | }) 21 | } 22 | -------------------------------------------------------------------------------- /commitlint-picgo/index.js: -------------------------------------------------------------------------------- 1 | const typeEnum = require('./types') 2 | 3 | module.exports = { 4 | parserPreset: '../conventional-changelog-picgo/parser-opts', 5 | rules: { 6 | 'body-leading-blank': [1, 'always'], 7 | 'footer-leading-blank': [1, 'always'], 8 | 'header-max-length': [2, 'always', 100], 9 | 'scope-case': [ 10 | 2, 11 | 'always', 12 | ['lower-case', 'kebab-case'] 13 | ], 14 | 'subject-case': [ 15 | 2, 16 | 'never', 17 | ['sentence-case'] 18 | ], 19 | 'subject-empty': [2, 'never'], 20 | 'subject-full-stop': [2, 'never', '.'], 21 | 'type-case': [0, 'always', 'lower-case'], 22 | 'type-empty': [2, 'never'], 23 | 'type-enum': [2, 'always', typeEnum] 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /eslint.config.js: -------------------------------------------------------------------------------- 1 | const { FlatCompat } = require('@eslint/eslintrc') 2 | const js = require('@eslint/js') 3 | 4 | const compat = new FlatCompat({ 5 | baseDirectory: __dirname, 6 | recommendedConfig: js.configs.recommended, 7 | allConfig: js.configs.all 8 | }) 9 | 10 | module.exports = [ 11 | { 12 | ignores: ['node_modules', 'dist'] 13 | }, 14 | ...compat.extends( 15 | 'eslint:recommended', 16 | 'plugin:import/recommended', 17 | 'plugin:n/recommended', 18 | 'plugin:promise/recommended' 19 | ), 20 | { 21 | languageOptions: { 22 | ecmaVersion: 2022, 23 | sourceType: 'script' 24 | } 25 | }, 26 | { 27 | files: ['eslint.config.js'], 28 | rules: { 29 | 'n/no-unpublished-require': 'off' 30 | } 31 | } 32 | ] 33 | -------------------------------------------------------------------------------- /conventional-changelog-picgo/conventional-recommended-bump.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const parserOpts = require(`./parser-opts`) 4 | 5 | module.exports = { 6 | parserOpts, 7 | 8 | whatBump: (commits) => { 9 | let level = 2 10 | let breakings = 0 11 | let features = 0 12 | 13 | commits.forEach(commit => { 14 | if (commit.notes.length > 0) { 15 | breakings += commit.notes.length 16 | level = 0 17 | } else if (commit.type === `feat`) { 18 | features += 1 19 | if (level === 2) { 20 | level = 1 21 | } 22 | } 23 | }) 24 | 25 | return { 26 | level: level, 27 | reason: breakings === 1 28 | ? `There is ${breakings} BREAKING CHANGE and ${features} features` 29 | : `There are ${breakings} BREAKING CHANGES and ${features} features` 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/bumpVersion.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs') 2 | const checkFileAndGetPath = require('./utils').checkFileAndGetPath 3 | let versionFiles = ['package.json', 'package-lock.json'] 4 | module.exports = (argv, version) => { 5 | if (argv.dry === false) { 6 | return Promise.resolve() 7 | } 8 | versionFiles = checkFileAndGetPath(argv, versionFiles) 9 | 10 | for (let file of versionFiles) { 11 | let content = fs.readFileSync(file, 'utf8') 12 | try { 13 | content = JSON.parse(content) 14 | content.version = version 15 | content = JSON.stringify(content, null, 2) + '\n' 16 | if (argv.dry) { 17 | console.log('bump version to:', version) 18 | } else { 19 | fs.writeFileSync(file, content, 'utf8') 20 | } 21 | } catch (e) { 22 | return Promise.reject(e) 23 | } 24 | } 25 | return Promise.resolve() 26 | } 27 | -------------------------------------------------------------------------------- /conventional-changelog-picgo/LICENSE.md: -------------------------------------------------------------------------------- 1 | ### ISC License 2 | 3 | Copyright © [conventional-changelog team](https://github.com/conventional-changelog) 4 | 5 | Permission to use, copy, modify, and/or distribute this software for any 6 | purpose with or without fee is hereby granted, provided that the above 7 | copyright notice and this permission notice appear in all copies. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 10 | REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 11 | FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 12 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13 | LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 14 | OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15 | PERFORMANCE OF THIS SOFTWARE. 16 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: publish 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | workflow_dispatch: 8 | 9 | jobs: 10 | publish: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Checkout 14 | uses: actions/checkout@v4 15 | 16 | - name: Setup pnpm 17 | uses: pnpm/action-setup@v4 18 | with: 19 | version: 10 20 | 21 | - name: Setup Node.js 22 | uses: actions/setup-node@v4 23 | with: 24 | node-version: 20 25 | registry-url: https://registry.npmjs.org 26 | cache: pnpm 27 | 28 | - name: Install dependencies 29 | run: pnpm install --frozen-lockfile 30 | 31 | - name: Lint 32 | run: pnpm run lint 33 | 34 | - name: Publish 35 | run: pnpm publish --access public --no-git-checks 36 | env: 37 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 38 | -------------------------------------------------------------------------------- /src/mainLifeCycle.js: -------------------------------------------------------------------------------- 1 | const bumpVersion = require('./bumpVersion') 2 | const commit = require('./commit') 3 | const changeLog = require('./changelog') 4 | const tag = require('./tag') 5 | const spinner = require('./ora') 6 | module.exports = (argv, currentVersion, newVersion) => { 7 | spinner.start() 8 | return Promise.resolve() 9 | .then(() => { 10 | spinner.text = 'Bumping version...' 11 | return bumpVersion(argv, newVersion) 12 | }) 13 | .then(() => { 14 | spinner.text = 'Generating changelog...' 15 | return changeLog(argv, newVersion) 16 | }) 17 | .then(() => { 18 | spinner.text = 'Commiting changes...' 19 | return commit(argv, newVersion) 20 | }) 21 | .then(() => { 22 | spinner.text = 'Creating tag...' 23 | return tag(argv, newVersion) 24 | }) 25 | .then(() => { 26 | return spinner.succeed('Done!') 27 | }) 28 | .catch(err => { 29 | spinner.fail('Failed!') 30 | throw err 31 | }) 32 | } 33 | -------------------------------------------------------------------------------- /License: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 PicGo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, 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, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/changelog.js: -------------------------------------------------------------------------------- 1 | const cc = require('conventional-changelog') 2 | const config = require('../conventional-changelog-picgo') 3 | const fs = require('fs') 4 | 5 | module.exports = (argv, newVersion) => { 6 | if (argv.changelog === false) { 7 | return Promise.resolve() 8 | } 9 | return new Promise((resolve, reject) => { 10 | let content = '' 11 | let oldContent = '' 12 | try { 13 | oldContent = fs.readFileSync(argv.file, 'utf8') 14 | } catch { 15 | oldContent = '' 16 | } 17 | let context = '' 18 | if (argv.dry) { 19 | context = { 20 | version: newVersion 21 | } 22 | } 23 | let changeLogStream = cc({ 24 | config 25 | }, context, { merges: null, path: argv.path }).on('error', (err) => { 26 | return reject(err) 27 | }) 28 | changeLogStream.on('data', (buffer) => { 29 | content += buffer.toString() 30 | }) 31 | changeLogStream.on('end', () => { 32 | if (argv.dry) { 33 | console.log('Changelog is:') 34 | console.log(content + oldContent) 35 | } else { 36 | fs.writeFileSync(argv.file, content + oldContent) 37 | } 38 | return resolve() 39 | }) 40 | }) 41 | } 42 | -------------------------------------------------------------------------------- /conventional-changelog-picgo/templates/commit.hbs: -------------------------------------------------------------------------------- 1 | *{{#if scope}} **{{scope}}:** 2 | {{~/if}} {{#if subject}} 3 | {{~subject}} 4 | {{~else}} 5 | {{~header}} 6 | {{~/if}} 7 | 8 | {{~!-- commit link --}} {{#if @root.linkReferences~}} 9 | ([{{hash}}]( 10 | {{~#if @root.repository}} 11 | {{~#if @root.host}} 12 | {{~@root.host}}/ 13 | {{~/if}} 14 | {{~#if @root.owner}} 15 | {{~@root.owner}}/ 16 | {{~/if}} 17 | {{~@root.repository}} 18 | {{~else}} 19 | {{~@root.repoUrl}} 20 | {{~/if}}/ 21 | {{~@root.commit}}/{{hash}})) 22 | {{~else}} 23 | {{~hash}} 24 | {{~/if}} 25 | 26 | {{~!-- commit references --}} 27 | {{~#if references~}} 28 | , closes 29 | {{~#each references}} {{#if @root.linkReferences~}} 30 | [ 31 | {{~#if this.owner}} 32 | {{~this.owner}}/ 33 | {{~/if}} 34 | {{~this.repository}}#{{this.issue}}]( 35 | {{~#if @root.repository}} 36 | {{~#if @root.host}} 37 | {{~@root.host}}/ 38 | {{~/if}} 39 | {{~#if this.repository}} 40 | {{~#if this.owner}} 41 | {{~this.owner}}/ 42 | {{~/if}} 43 | {{~this.repository}} 44 | {{~else}} 45 | {{~#if @root.owner}} 46 | {{~@root.owner}}/ 47 | {{~/if}} 48 | {{~@root.repository}} 49 | {{~/if}} 50 | {{~else}} 51 | {{~@root.repoUrl}} 52 | {{~/if}}/ 53 | {{~@root.issue}}/{{this.issue}}) 54 | {{~else}} 55 | {{~#if this.owner}} 56 | {{~this.owner}}/ 57 | {{~/if}} 58 | {{~this.repository}}#{{this.issue}} 59 | {{~/if}}{{/each}} 60 | {{~/if}} 61 | 62 | -------------------------------------------------------------------------------- /src/utils.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const fs = require('fs') 3 | const checkFileAndGetPath = (argv, files) => { 4 | return files.map(item => { 5 | if (path.isAbsolute(item)) { 6 | return item 7 | } 8 | return path.join(argv.path, item) 9 | }).filter(item => { 10 | return fs.existsSync(item) 11 | }) 12 | } 13 | const helperMsg = ` 14 | BumpVersion -- By PicGo Group 15 | 16 | Usage 17 | bump-version 18 | 19 | Example 20 | bump-version -t major 21 | 22 | Options 23 | -a, --preid-alpha Prerelease id: alpha. Exp. 1.0.0.alpha-0 24 | 25 | -b, --preid-beta Prerelease id: beta. Exp. 1.0.0.beta-0 26 | 27 | -d, --dry Run bump version without change anything & output the log in console 28 | 29 | -f, --file Read and write the CHANGELOG file, relative to package.json's path 30 | Default: CHANGELOG.md 31 | 32 | -p, --path A filepath of where your package.json is located 33 | Default: ./ 34 | 35 | -h, --help Display help message 36 | 37 | -t, --type Release type. [major, minor, patch, premajor, preminor, prepatch, prerelease] 38 | Default: patch 39 | 40 | --push Auto push commits to origin master 41 | Default: false 42 | 43 | --no-tag Tag won't be created 44 | Default: tag will be created 45 | 46 | --no-changelog Changelog won't be created 47 | Default: changelog will be created 48 | ` 49 | 50 | module.exports = { 51 | checkFileAndGetPath, 52 | helperMsg 53 | } 54 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@picgo/bump-version", 3 | "version": "2.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "bin": { 7 | "bump-version": "./bin/bump-version" 8 | }, 9 | "publishConfig": { 10 | "access": "public" 11 | }, 12 | "scripts": { 13 | "test": "echo \"Error: no test specified\"", 14 | "cz": "git-cz", 15 | "release": "node ./bin/bump-version", 16 | "lint": "eslint --ext .js .", 17 | "lint:fix": "eslint --ext .js --fix ." 18 | }, 19 | "husky": { 20 | "hooks": { 21 | "pre-commit": "npm run lint", 22 | "commit-msg": "commitlint -E HUSKY_GIT_PARAMS" 23 | } 24 | }, 25 | "repository": { 26 | "type": "git", 27 | "url": "git+https://github.com/PicGo/bump-version.git" 28 | }, 29 | "author": "Molunerfinn", 30 | "license": "MIT", 31 | "bugs": { 32 | "url": "https://github.com/PicGo/bump-version/issues" 33 | }, 34 | "homepage": "https://github.com/PicGo/bump-version#readme", 35 | "devDependencies": { 36 | "@eslint/eslintrc": "^3.3.3", 37 | "@eslint/js": "^9.39.1", 38 | "eslint": "^9.39.1", 39 | "eslint-plugin-import": "^2.32.0", 40 | "eslint-plugin-n": "^17.23.1", 41 | "eslint-plugin-promise": "^7.2.1" 42 | }, 43 | "config": { 44 | "commitizen": { 45 | "path": "node_modules/cz-customizable" 46 | }, 47 | "cz-customizable": { 48 | "config": ".cz-config.js" 49 | } 50 | }, 51 | "commitlint": { 52 | "extends": [ 53 | "./commitlint-picgo" 54 | ] 55 | }, 56 | "dependencies": { 57 | "@commitlint/cli": "^7.5.2", 58 | "chalk": "^4.1.2", 59 | "commitizen": "^4.2.3", 60 | "compare-func": "^2.0.0", 61 | "conventional-changelog": "^3.0.6", 62 | "cz-customizable": "^7.5.1", 63 | "husky": "^1.3.1", 64 | "inquirer": "^13.0.2", 65 | "minimist": "^1.2.8", 66 | "ora": "^3.4.0", 67 | "q": "^1.5.1", 68 | "semver": "^7.7.3" 69 | }, 70 | "engines": { 71 | "node": ">=20.0.0" 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # :tada: 2.0.0 (2025-12-10) 2 | 3 | 4 | ### :bug: Bug Fixes 5 | 6 | * some deps not installed ([f2a4f74](https://github.com/PicGo/bump-version/commit/f2a4f74)) 7 | 8 | 9 | ### :package: Chore 10 | 11 | * add pnpm-lock to npmignore ([6de1b65](https://github.com/PicGo/bump-version/commit/6de1b65)) 12 | * update deps \&\& add node 20 limit ([d2d96e9](https://github.com/PicGo/bump-version/commit/d2d96e9)) 13 | 14 | 15 | 16 | ## :tada: 1.1.2 (2021-09-16) 17 | 18 | 19 | ### :package: Chore 20 | 21 | * change travis-ci -> github actions ([d3c896f](https://github.com/PicGo/bump-version/commit/d3c896f)) 22 | 23 | 24 | 25 | ## :tada: 1.1.1 (2021-04-10) 26 | 27 | 28 | 29 | # :tada: 1.1.0 (2020-04-30) 30 | 31 | 32 | ### :sparkles: Features 33 | 34 | * change some dev deps to deps ([12bd7b0](https://github.com/PicGo/bump-version/commit/12bd7b0)) 35 | 36 | 37 | 38 | ## :tada: 1.0.3 (2019-05-11) 39 | 40 | 41 | ### :sparkles: Features 42 | 43 | * **header:** add header-max-length from 72 to 100 ([7a5ec79](https://github.com/PicGo/bump-version/commit/7a5ec79)) 44 | 45 | 46 | ### :bug: Bug Fixes 47 | 48 | * **lint:** subject case can't be sentence-case ([860a327](https://github.com/PicGo/bump-version/commit/860a327)) 49 | 50 | 51 | ### :pencil: Documentation 52 | 53 | * refine readme ([#1](https://github.com/PicGo/bump-version/issues/1)) ([1984de2](https://github.com/PicGo/bump-version/commit/1984de2)) 54 | * remove a comma ([f484287](https://github.com/PicGo/bump-version/commit/f484287)) 55 | 56 | 57 | 58 | ## :tada: 1.0.2 (2019-04-10) 59 | 60 | 61 | ### :bug: Bug Fixes 62 | 63 | * preid command from 'pa' to 'a' && eslint error ([cf989fa](https://github.com/PicGo/bump-version/commit/cf989fa)) 64 | 65 | 66 | ### :pencil: Documentation 67 | 68 | * fix word error && change version badge ([0cbeb79](https://github.com/PicGo/bump-version/commit/0cbeb79)) 69 | 70 | 71 | 72 | ## :tada: 1.0.1 (2019-04-09) 73 | 74 | 75 | ### :bug: Bug Fixes 76 | 77 | * npm test command missed ([0c5301f](https://github.com/PicGo/bump-version/commit/0c5301f)) 78 | * symbolic links bug ([1a95111](https://github.com/PicGo/bump-version/commit/1a95111)) 79 | * travis yarn test bug ([77e97d4](https://github.com/PicGo/bump-version/commit/77e97d4)) 80 | 81 | 82 | 83 | # :tada: 1.0.0 (2019-04-09) 84 | 85 | 86 | ### :pushpin: Init 87 | 88 | * picgo bump-version init commit ([b04432f](https://github.com/PicGo/bump-version/commit/b04432f)) 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /.cz-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // types, 3 | types: [ 4 | { 5 | value: ":sparkles: Feature", 6 | name: "Feature: when adding new features" 7 | }, 8 | { 9 | value: ":bug: Fix", 10 | name: "Fix: when fixing bugs" 11 | }, 12 | { 13 | value: ":construction: WIP", 14 | name: "WIP: when working in progress" 15 | }, 16 | { 17 | value: ":hammer: Refactor", 18 | name: "Refactor: when changing the code without adding features or fixing bugs" 19 | }, 20 | { 21 | value: ":package: Chore", 22 | name: "Chore: when changing the build process or auxiliary tools and libraries such as documentation generation" 23 | }, 24 | { 25 | value: ":art: Style", 26 | name: "Style: when improving the format/structure of the code" 27 | }, 28 | { 29 | value: ":arrow_up: Upgrade", 30 | name: "Upgrade: when upgrading dependencies" 31 | }, 32 | { 33 | value: ":zap: Perf", 34 | name: "Perf: when improving performance" 35 | }, 36 | { 37 | value: ":pencil: Docs", 38 | name: "Docs: when wrting docs" 39 | }, 40 | { 41 | value: ":white_check_mark: Test", 42 | name: "Test: when adding or updating tests" 43 | }, 44 | { 45 | value: ":back: Revert", 46 | name: "Revert: when reverting some commits" 47 | }, 48 | { 49 | value: ":tada: Release", 50 | name: "Release: when releasing a new version" 51 | }, 52 | { 53 | value: ":pushpin: Init", 54 | name: "Init: when initializing a project" 55 | } 56 | ], 57 | 58 | // override the messages, defaults are as follows 59 | messages: { 60 | type: "Select the type of change that you're committing:", 61 | scope: "\nDenote the SCOPE of this change (optional):", 62 | // used if allowCustomScopes is true 63 | customScope: "Denote the SCOPE of this change:", 64 | subject: "[subject] Write a SHORT, IMPERATIVE tense description of the change:\n", 65 | body: 66 | '[body] Provide a LONGER description of the change (optional). Use "|" to break new line:\n', 67 | breaking: "List any BREAKING CHANGES (optional):\n", 68 | footer: 69 | "[footer] List any ISSUES CLOSED by this change (optional). E.g.: #31, #34:\n", 70 | confirmCommit: "Are you sure you want to proceed with the commit above?" 71 | }, 72 | 73 | allowCustomScopes: false, 74 | allowBreakingChanges: [":sparkles: Feature", ":bug: Fix"] 75 | }; 76 | -------------------------------------------------------------------------------- /bin/bump-version: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | const minimist = require('minimist') 3 | const semver = require('semver') 4 | const path = require('path') 5 | const inquirer = require('inquirer').default 6 | const logger = require('../src/logger') 7 | const mainLifeCycle = require('../src/mainLifeCycle') 8 | const utils = require('../src/utils') 9 | 10 | let pkg 11 | try { 12 | pkg = require(path.join(process.cwd(), 'package.json')) 13 | } catch (e) { 14 | logger('package.json not found!', 'error') 15 | process.exit(0) 16 | } 17 | let argv = minimist(process.argv.slice(2), { 18 | alias: { 19 | 'preid-alpha': 'a', // alpha 20 | 'preid-beta': 'b', // beta 21 | 'dry': 'd', // dry run mode 22 | 'file': 'f', // changelog file, 23 | 'path': 'p', // package.json's path 24 | 'help': 'h', // help message 25 | 'type': 't' // bump type 26 | } 27 | }) 28 | 29 | if (argv.h) { 30 | console.log(utils.helperMsg) 31 | process.exit(0) 32 | } 33 | 34 | let releaseType = typeof argv.t === 'string' ? argv.t : 'patch' 35 | let currentVersion = pkg.version 36 | if (currentVersion === undefined) { 37 | logger('Version field is not found in package.json!', 'error') 38 | process.exit(0) 39 | } 40 | let preid = argv.a ? 'alpha' : argv.b ? 'beta' : '' 41 | let nextVersion = semver.inc(currentVersion, releaseType, preid) 42 | let releaseTypes = ['major', 'minor', 'patch', 'premajor', 'preminor', 'prepatch', 'prerelease'] 43 | 44 | function generateReleaseTypes (types) { 45 | return types.map(item => { 46 | let version = semver.inc(currentVersion, item, (preid || 'alpha')) 47 | return { 48 | name: `${item} - ${version}`, 49 | value: version 50 | } 51 | }) 52 | } 53 | 54 | let defaultObj = { 55 | path: process.cwd(), 56 | file: 'CHANGELOG.md' 57 | } 58 | 59 | argv = Object.assign({}, defaultObj, argv) 60 | 61 | let promptList = [ 62 | { 63 | type: 'confirm', 64 | name: 'confirmVersion', 65 | message: `The next version is ${nextVersion}, is it right?` 66 | } 67 | ] 68 | console.log( 69 | ` 70 | BumpVersion -- By PicGo Group 71 | ` 72 | ); 73 | (async () => { 74 | let answer = await inquirer.prompt(promptList) 75 | if (answer.confirmVersion) { 76 | await mainLifeCycle(argv, currentVersion, nextVersion) 77 | } else { 78 | promptList = [ 79 | { 80 | type: 'select', 81 | name: 'version', 82 | message: `The current version is ${currentVersion}\n Which version would you like to bump it?`, 83 | choices: [ 84 | ...generateReleaseTypes(releaseTypes), 85 | new inquirer.Separator(), 86 | 'custom version', 87 | 'never mind~' 88 | ], 89 | pageSize: 10 90 | } 91 | ] 92 | let answer = await inquirer.prompt(promptList) 93 | if (answer.version === 'never mind~') { 94 | return console.log('Bye~') 95 | } else if (answer.version === 'custom version') { 96 | promptList = [ 97 | { 98 | type: 'input', 99 | name: 'version', 100 | message: 'Write down your custom version:' 101 | } 102 | ] 103 | let result = await inquirer.prompt(promptList) 104 | if (semver.valid(result.version) && semver.gte(result.version, currentVersion)) { 105 | await mainLifeCycle(argv, currentVersion, result.version) 106 | } else { 107 | return logger('Invalid version!', 'error') 108 | } 109 | } else { 110 | await mainLifeCycle(argv, currentVersion, answer.version) 111 | } 112 | } 113 | })() 114 | -------------------------------------------------------------------------------- /conventional-changelog-picgo/writer-opts.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const compareFunc = require(`compare-func`) 4 | const Q = require(`q`) 5 | const readFile = Q.denodeify(require(`fs`).readFile) 6 | const resolve = require(`path`).resolve 7 | const headerPattern = /^(:.*: (.*))$/ 8 | 9 | const compareTitleFunc = (a, b) => { 10 | let sortMap = { 11 | 'Features': 10, 12 | 'Bug Fixes': 9, 13 | 'BREAKING CHANGES': 8 14 | } 15 | let typeA = a.title.match(headerPattern)[2] 16 | let typeB = b.title.match(headerPattern)[2] 17 | 18 | return (sortMap[typeB] || 0) - (sortMap[typeA] || 0) 19 | } 20 | 21 | module.exports = Q.all([ 22 | readFile(resolve(__dirname, `./templates/template.hbs`), `utf-8`), 23 | readFile(resolve(__dirname, `./templates/header.hbs`), `utf-8`), 24 | readFile(resolve(__dirname, `./templates/commit.hbs`), `utf-8`), 25 | readFile(resolve(__dirname, `./templates/footer.hbs`), `utf-8`) 26 | ]) 27 | .spread((template, header, commit, footer) => { 28 | const writerOpts = getWriterOpts() 29 | 30 | writerOpts.mainTemplate = template 31 | writerOpts.headerPartial = header 32 | writerOpts.commitPartial = commit 33 | writerOpts.footerPartial = footer 34 | 35 | return writerOpts 36 | }) 37 | 38 | function getWriterOpts () { 39 | return { 40 | transform: (commit, context) => { 41 | let discard = true 42 | const issues = [] 43 | 44 | commit.notes.forEach(note => { 45 | note.title = `BREAKING CHANGES` 46 | discard = false 47 | }) 48 | 49 | if (commit.type === `:sparkles: Feature`) { 50 | commit.type = `:sparkles: Features` 51 | } else if (commit.type === `:bug: Fix`) { 52 | commit.type = `:bug: Bug Fixes` 53 | } else if (commit.type === `:zap: Perf`) { 54 | commit.type = `:zap: Performance Improvements` 55 | } else if (commit.type === `:back: Revert`) { 56 | commit.type = `:back: Revert` 57 | } else if (commit.type === `:pencil: Docs`) { 58 | commit.type = `:pencil: Documentation` 59 | } else if (commit.type === `:package: Chore`) { 60 | commit.type = `:package: Chore` 61 | } else if (commit.type === `:pushpin: Init`) { 62 | commit.type = `:pushpin: Init` 63 | } else if (discard) { 64 | return 65 | } else if (commit.type === `:arrow_up: Upgrade`) { 66 | commit.type = `:arrow_up: Dependencies Upgrade` 67 | } else if (commit.type === `:art: Style`) { 68 | commit.type = `:art: Styles` 69 | } else if (commit.type === `:hammer: Refactor`) { 70 | commit.type = `:hammer: Code Refactoring` 71 | } else if (commit.type === `:white_check_mark: Test`) { 72 | commit.type = `:white_check_mark: Tests` 73 | } else if (commit.type === `:construction: WIP` || commit.type === ':tada: Release') { 74 | return 75 | } 76 | 77 | if (commit.scope === `*`) { 78 | commit.scope = `` 79 | } 80 | 81 | if (typeof commit.hash === `string`) { 82 | commit.hash = commit.hash.substring(0, 7) 83 | } 84 | 85 | if (typeof commit.subject === `string`) { 86 | let url = context.repository 87 | ? `${context.host}/${context.owner}/${context.repository}` 88 | : context.repoUrl 89 | if (url) { 90 | url = `${url}/issues/` 91 | // Issue URLs. 92 | commit.subject = commit.subject.replace(/#([0-9]+)/g, (_, issue) => { 93 | issues.push(issue) 94 | return `[#${issue}](${url}${issue})` 95 | }) 96 | } 97 | if (context.host) { 98 | // User URLs. 99 | commit.subject = commit.subject.replace(/\B@([a-z0-9](?:-?[a-z0-9/]){0,38})/g, (_, username) => { 100 | if (username.includes('/')) { 101 | return `@${username}` 102 | } 103 | 104 | return `[@${username}](${context.host}/${username})` 105 | }) 106 | } 107 | } 108 | 109 | // remove references that already appear in the subject 110 | commit.references = commit.references.filter(reference => { 111 | if (issues.indexOf(reference.issue) === -1) { 112 | return true 113 | } 114 | 115 | return false 116 | }) 117 | 118 | return commit 119 | }, 120 | groupBy: `type`, 121 | commitGroupsSort: compareTitleFunc, 122 | commitsSort: [`scope`, `subject`], 123 | noteGroupsSort: `title`, 124 | notesSort: compareFunc 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PicGo BumpVersion 2 | 3 | A full `git commit` -> `changelog` -> `release` workflow & convention. 4 | 5 | It's now only available for Node.js projects. Thanks [standard-version](https://github.com/conventional-changelog/standard-version) for the inspiration. 6 | 7 | > Starting from v1.2.0, bump-version requires Node.js 20 or higher. 8 | 9 |

10 | 11 |

12 |

13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 |

23 | 24 | ## Installation 25 | 26 | ```bash 27 | npm install -D @picgo/bump-version commitizen 28 | 29 | #or 30 | 31 | yarn add -D @picgo/bump-version commitizen 32 | 33 | #or 34 | 35 | pnpm add -D @picgo/bump-version commitizen 36 | ``` 37 | 38 | Also, add the following data at the top level in your `package.json` to properly config `bump-version` (replace old `config` if you have already configured `commitizen` or `cz-customizable` before): 39 | 40 | ```json 41 | "husky": { 42 | "hooks": { 43 | "commit-msg": "commitlint -E HUSKY_GIT_PARAMS" 44 | } 45 | }, 46 | "config": { 47 | "commitizen": { 48 | "path": "./node_modules/cz-customizable" 49 | }, 50 | "cz-customizable": { 51 | "config": "./node_modules/@picgo/bump-version/.cz-config.js" 52 | } 53 | }, 54 | "commitlint": { 55 | "extends": ["./node_modules/@picgo/bump-version/commitlint-picgo"] 56 | } 57 | ``` 58 | 59 | And then add the following (inside the braces) to the `scripts` field of your package.json: 60 | 61 | ```json 62 | "scripts": { 63 | "cz": "git-cz", 64 | "release": "bump-version" 65 | } 66 | ``` 67 | 68 | Then you can use `npm run cz` for committing standard message and use `npm run release` to bump version & auto generate changelog in your project! 69 | 70 | If you are using [yarn](https://yarnpkg.com/), then it will be more simple just like: 71 | 72 | ```bash 73 | # to commit 74 | yarn cz 75 | 76 | # to bump version 77 | yarn release 78 | ``` 79 | 80 | So the workflow is the following: 81 | 82 | 1. `git add` something changed 83 | 2. `npm run cz` to commit 84 | 3. `npm run release` to release or deploy 85 | 86 | ## Usage 87 | 88 | > If you installed bump-version in a project, then you can just write down the `bump-version` command in your `package.json`'s `scripts` field. Then just `npm run you-command`. 89 | 90 | ### Commit 91 | 92 | ```bash 93 | npm run cz 94 | 95 | # or 96 | 97 | yarn cz 98 | ``` 99 | 100 | This leads to an interactive submit message interface: 101 | 102 | ``` 103 | ? Select the type of change that you're committing: (Use arrow keys) 104 | ❯ Feature: when adding new features 105 | Fix: when fixing bugs 106 | WIP: when working in progress 107 | Refactor: when changing the code without adding features or fixing bugs 108 | Chore: when changing the build process or auxiliary tools and libraries such as documentation generation 109 | Style: when improving the format/structure of the code 110 | Upgrade: when upgrading dependencies 111 | ``` 112 | 113 | You can use this interface to quickly generate commit information that is compliant with the PicGo convention. 114 | 115 | ### Bump version 116 | 117 | ```bash 118 | npm run release 119 | 120 | # or 121 | 122 | yarn run cz 123 | ``` 124 | 125 | ```txt 126 | Usage 127 | bump-version 128 | 129 | Example 130 | bump-version -t major 131 | 132 | Options 133 | -a, --preid-alpha Prerelease id: alpha. Exp. 1.0.0.alpha-0 134 | 135 | -b, --preid-beta Prerelease id: beta. Exp. 1.0.0.beta-0 136 | 137 | -d, --dry Run bump version without change anything & output the log in console 138 | 139 | -f, --file Read and write the CHANGELOG file, relative to package.json's path 140 | Default: CHANGELOG.md 141 | 142 | -p, --path A filepath of where your package.json is located 143 | Default: ./ 144 | 145 | -h, --help Display help message 146 | 147 | -t, --type Release type. [major, minor, patch, premajor, preminor, prepatch, prerelease] 148 | Default: patch 149 | 150 | --push Auto push commits to origin master 151 | Default: false 152 | 153 | --no-tag Tag won't be created 154 | Default: tag will be created 155 | 156 | --no-changelog Changelog won't be created 157 | Default: changelog will be created 158 | ``` 159 | 160 | Don't know which version should be the next? Never mind: 161 | 162 | If you reject the default next version, then you can choose which version you want or customize one. 163 | 164 | ![screenshot](https://raw.githubusercontent.com/Molunerfinn/test/master/test/20190409205839.png) 165 | 166 | if you just want to see what the changelog will be created and nothing will be changed: 167 | 168 | ```bash 169 | npm run release --dry 170 | ``` 171 | 172 | ## Badges 173 | 174 | Let more people know that you are using PicGo bump-version for elegant workflow! 175 | 176 | ```md 177 | [![PicGo Convention](https://img.shields.io/badge/picgo-convention-blue.svg?style=flat-square)](https://github.com/PicGo/bump-version) 178 | ``` 179 | 180 | ## PicGo Convention 181 | 182 | PicGo's commit message guidelines. 183 | 184 | ### Git Commit Message 185 | 186 | - Use the present tense ("add feature" not "added feature") 187 | - Use the imperative mood ("move cursor to..." not "moves cursor to...") 188 | - Do not repeat the word in type ("Fix: xxx bugs when..." not "Fix: fix xxx bugs when...") 189 | - Limit the first line to 72 characters or less 190 | - Start the commit message with an applicable `emoji` & `type`: 191 | 192 | - :sparkles: Feature `:sparkles: Feature` when adding new features 193 | - :bug: Fix `:bug: Fix` when fixing bugs 194 | - :construction: WIP `:construction: WIP` when working in progress 195 | - :hammer: Refactor `:hammer: Refactor` when changing the code without adding features or fixing bugs 196 | - :package: Chore `:package: Chore` when changing the build process or auxiliary tools and libraries such as documentation generation 197 | - :art: Style `:art: Style` when improving the format/structure of the code 198 | - :arrow_up: Upgrade `:arrow_up: Upgrade` when upgrading dependencies 199 | - :zap: Perf `:zap: Perf` when improving performance 200 | - :pencil: Docs `:pencil: Docs` when wrting docs 201 | - :white_check_mark: Test `:white_check_mark: Test` when adding or updating tests 202 | - :back: Revert `:back: Revert` when reverting some commits 203 | - :pushpin: Init `:pushpin: Init` when initializing a project 204 | - :tada: Release `:tada: Release` when releasing (**will be automatically committed by `bump-version`**) 205 | 206 | #### Commit Message Format 207 | 208 | A commit message consists of a **header**, **body**(optional) and **footer**(optional). The header has a **emoji**, **type**, **scope**(optional) and **subject**: 209 | 210 | ```txt 211 | ([scope]): 212 | 213 | [body] 214 | 215 | [footer] 216 | ``` 217 | 218 | #### Examples 219 | 220 | ##### 1. Normal 221 | 222 | :sparkles: Feature(core): add error notification 223 | 224 | :bug: Fix(core): xxx error should be thrown 225 | 226 | ```txt 227 | :sparkles: Feature(core): add error notification 228 | 229 | :bug: Fix(core): xxx error should be thrown 230 | ``` 231 | 232 | and they will be rendered into the following changelog: 233 | 234 | ```markdown 235 | # x.x.0 (20xx-xx-xx) 236 | 237 | ## :sparkles: Features 238 | 239 | - add error notification 240 | 241 | ## :bug: Bug Fixes 242 | 243 | - xxx error should be thrown 244 | ``` 245 | 246 | ##### 2. BREAKING CHANGE 247 | 248 | **Note: BREAKING CHANGE can only be in the type of `Feature` or `Fix`.** 249 | 250 | :sparkles: Feature(core): add error notification 251 | 252 | BREAKING CHANGE: change api for error notification 253 | 254 | ```md 255 | :sparkles: Feature(core): add error notification 256 | 257 | BREAKING CHANGE: change api for error notification 258 | ``` 259 | 260 | and they will be rendered into the following changelog: 261 | 262 | ```markdown 263 | # x.x.0 (20xx-xx-xx) 264 | 265 | ## :sparkles: Features 266 | 267 | - add error notification 268 | 269 | ## BREAKING CHANGES 270 | 271 | - change api for error notification 272 | ``` 273 | 274 | ### Git Branch Management 275 | 276 | **Important**: Always use `rebase` or `squash` or `cherry-pick` instead of `merge` 277 | 278 | Available branches: 279 | 280 | - `master` for the release 281 | - `dev` for the development 282 | - `docs` or `gh-pages` for the documentation **[optional]** 283 | - `pr` for the pull request **[optional]** 284 | - `hot-fix` for fixing the bug in master **[optional]** 285 | - `feat-*` for developing a new feature 286 | - `fix-*` for fixing a bug in dev branch 287 | 288 | ## License 289 | 290 | [MIT](http://opensource.org/licenses/MIT) 291 | 292 | Copyright (c) 2019 Molunerfinn 293 | --------------------------------------------------------------------------------