@picgo/bump-version 2.0.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,64 @@
1
+ # :tada: 3.0.0 (2026-08-22)
2
+
3
+
4
+ ### :sparkles: Features
5
+
6
+ * convert the CLI to ESM and upgrade its dependencies ([9165570](https://github.com/PicGo/bump-version/commit/9165570))
7
+
8
+
9
+ ### :bug: Bug Fixes
10
+
11
+ * stop dropping Upgrade, Style, Refactor and Test from changelogs ([cd252e2](https://github.com/PicGo/bump-version/commit/cd252e2))
12
+
13
+
14
+ ### :arrow_up: Dependencies Upgrade
15
+
16
+ * clear the remaining dev vulnerabilities ([bdd1fb2](https://github.com/PicGo/bump-version/commit/bdd1fb2))
17
+ * move contributor tooling out of dependencies ([08093ca](https://github.com/PicGo/bump-version/commit/08093ca))
18
+
19
+
20
+ ### :package: Chore
21
+
22
+ * update actions and run tests before publishing ([3317c25](https://github.com/PicGo/bump-version/commit/3317c25))
23
+
24
+
25
+ ### :white_check_mark: Tests
26
+
27
+ * cover version resolution and the version write ([4b98e2a](https://github.com/PicGo/bump-version/commit/4b98e2a))
28
+
29
+
30
+ ### BREAKING CHANGES
31
+
32
+ * note — otherwise it was silently discarded. Four of the
33
+ PicGo convention's own types never appeared in a changelog.
34
+
35
+ Moved the discard branch below them, where it now only catches genuinely
36
+ unrecognised types, and kept WIP and Release excluded explicitly.
37
+
38
+
39
+
40
+ # :tada: 2.1.0 (2026-08-22)
41
+
42
+
43
+ ### :sparkles: Features
44
+
45
+ * add non-interactive mode and an explicit --version ([278d034](https://github.com/PicGo/bump-version/commit/278d034))
46
+
47
+
48
+ ### :bug: Bug Fixes
49
+
50
+ * fix deps bug ([caba420](https://github.com/PicGo/bump-version/commit/caba420))
51
+ * github actions error ([03c0733](https://github.com/PicGo/bump-version/commit/03c0733))
52
+ * write the version when --no-dry is passed ([1c042cd](https://github.com/PicGo/bump-version/commit/1c042cd))
53
+
54
+
55
+ ### :package: Chore
56
+
57
+ * update actions ([4b0c924](https://github.com/PicGo/bump-version/commit/4b0c924))
58
+ * update readme ([1819726](https://github.com/PicGo/bump-version/commit/1819726))
59
+
60
+
61
+
1
62
  # :tada: 2.0.0 (2025-12-10)
2
63
 
3
64
 
package/README.md CHANGED
@@ -4,7 +4,7 @@ A full `git commit` -> `changelog` -> `release` workflow & convention.
4
4
 
5
5
  It's now only available for Node.js projects. Thanks [standard-version](https://github.com/conventional-changelog/standard-version) for the inspiration.
6
6
 
7
- > Starting from v1.2.0, bump-version requires Node.js 20 or higher.
7
+ > Starting from v3.0.0, bump-version is an ESM package and requires Node.js 22 or higher. The configs it ships for `commitlint` and `cz-customizable` remain CommonJS, so those tools keep loading them as before.
8
8
 
9
9
  <p align="center">
10
10
  <img src="https://raw.githubusercontent.com/Molunerfinn/test/master/picgo/New%20LOGO-150.png" alt="">
@@ -24,17 +24,19 @@ It's now only available for Node.js projects. Thanks [standard-version](https://
24
24
  ## Installation
25
25
 
26
26
  ```bash
27
- npm install -D @picgo/bump-version commitizen
27
+ npm install -D @picgo/bump-version commitizen cz-customizable @commitlint/cli husky
28
28
 
29
29
  #or
30
30
 
31
- yarn add -D @picgo/bump-version commitizen
31
+ yarn add -D @picgo/bump-version commitizen cz-customizable @commitlint/cli husky
32
32
 
33
33
  #or
34
34
 
35
- pnpm add -D @picgo/bump-version commitizen
35
+ pnpm add -D @picgo/bump-version commitizen cz-customizable @commitlint/cli husky
36
36
  ```
37
37
 
38
+ > `commitizen`, `cz-customizable`, `@commitlint/cli` and `husky` are the tools that provide the `git-cz` and `commitlint` commands and the git hooks. They are peer tooling rather than dependencies of `bump-version` itself, so install the ones you actually use — if you only want `bump-version` to bump versions and write changelogs, `@picgo/bump-version` alone is enough.
39
+
38
40
  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
41
 
40
42
  ```json
@@ -48,11 +50,11 @@ Also, add the following data at the top level in your `package.json` to properly
48
50
  "path": "./node_modules/cz-customizable"
49
51
  },
50
52
  "cz-customizable": {
51
- "config": "./node_modules/@picgo/bump-version/.cz-config.js"
53
+ "config": "./node_modules/@picgo/bump-version/.cz-config.cjs"
52
54
  }
53
55
  },
54
56
  "commitlint": {
55
- "extends": ["./node_modules/@picgo/bump-version/commitlint-picgo"]
57
+ "extends": ["./node_modules/@picgo/bump-version/commitlint-picgo/index.cjs"]
56
58
  }
57
59
  ```
58
60
 
@@ -127,7 +129,10 @@ Usage
127
129
  bump-version
128
130
 
129
131
  Example
130
- bump-version -t major
132
+ bump-version -t major Interactive, confirms before running
133
+ bump-version -t minor -y Non-interactive, no TTY needed
134
+ bump-version --version 1.0.0 -y Bump to an exact version
135
+ bump-version -t minor -y -d Preview without changing anything
131
136
 
132
137
  Options
133
138
  -a, --preid-alpha Prerelease id: alpha. Exp. 1.0.0.alpha-0
@@ -147,6 +152,13 @@ Options
147
152
  -t, --type Release type. [major, minor, patch, premajor, preminor, prepatch, prerelease]
148
153
  Default: patch
149
154
 
155
+ -y, --yes Skip all prompts and run immediately. Needs no TTY,
156
+ so it works in CI and in scripts
157
+ Default: false
158
+
159
+ --version Bump to this exact version instead of deriving one
160
+ from --type. A leading "v" is accepted. Exp. 1.0.0
161
+
150
162
  --push Auto push commits to origin master
151
163
  Default: false
152
164
 
@@ -157,6 +169,24 @@ Options
157
169
  Default: changelog will be created
158
170
  ```
159
171
 
172
+ #### Non-interactive use
173
+
174
+ Without `-y` the tool always asks for confirmation, which needs a TTY and therefore fails in CI, in `npm run` chains and in agent sessions. `-y` skips every prompt:
175
+
176
+ ```bash
177
+ bump-version -t minor -y # 0.1.0 -> 0.2.0
178
+ bump-version --version 1.0.0 -y # bump to exactly 1.0.0
179
+ bump-version --version v1.0.0 -y # same; a leading "v" is accepted
180
+ ```
181
+
182
+ `--version` takes precedence over `--type`, and is rejected when it is not valid semver or is not greater than the current version. Invalid input exits with code `1`, so a CI step fails rather than tagging the wrong version.
183
+
184
+ Pair it with `-d` to see exactly what a release would do — the new version, the generated changelog — without writing, committing or tagging anything:
185
+
186
+ ```bash
187
+ bump-version -t minor -y -d
188
+ ```
189
+
160
190
  Don't know which version should be the next? Never mind:
161
191
 
162
192
  If you reject the default next version, then you can choose which version you want or customize one.
package/bin/bump-version CHANGED
@@ -1,15 +1,18 @@
1
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')
2
+ import minimist from 'minimist'
3
+ import semver from 'semver'
4
+ import path from 'node:path'
5
+ import fs from 'node:fs'
6
+ import { Separator } from '@inquirer/prompts'
7
+ import inquirer from 'inquirer'
8
+ import logger from '../src/logger.js'
9
+ import mainLifeCycle from '../src/mainLifeCycle.js'
10
+ import resolveVersion, { releaseTypes } from '../src/resolveVersion.js'
11
+ import * as utils from '../src/utils.js'
9
12
 
10
13
  let pkg
11
14
  try {
12
- pkg = require(path.join(process.cwd(), 'package.json'))
15
+ pkg = JSON.parse(fs.readFileSync(path.join(process.cwd(), 'package.json'), 'utf8'))
13
16
  } catch (e) {
14
17
  logger('package.json not found!', 'error')
15
18
  process.exit(0)
@@ -22,8 +25,12 @@ let argv = minimist(process.argv.slice(2), {
22
25
  'file': 'f', // changelog file,
23
26
  'path': 'p', // package.json's path
24
27
  'help': 'h', // help message
25
- 'type': 't' // bump type
26
- }
28
+ 'type': 't', // bump type
29
+ 'yes': 'y' // skip prompts
30
+ },
31
+ // Without this, `--version 1.0.0-beta.1` is parsed as a number and loses
32
+ // everything after the first dot.
33
+ string: ['version', 'type', 'file', 'path']
27
34
  })
28
35
 
29
36
  if (argv.h) {
@@ -31,15 +38,19 @@ if (argv.h) {
31
38
  process.exit(0)
32
39
  }
33
40
 
34
- let releaseType = typeof argv.t === 'string' ? argv.t : 'patch'
35
41
  let currentVersion = pkg.version
36
42
  if (currentVersion === undefined) {
37
43
  logger('Version field is not found in package.json!', 'error')
38
44
  process.exit(0)
39
45
  }
40
46
  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']
47
+
48
+ let resolved = resolveVersion(argv, currentVersion)
49
+ if (resolved.error) {
50
+ logger(resolved.error, 'error')
51
+ process.exit(1)
52
+ }
53
+ let nextVersion = resolved.version
43
54
 
44
55
  function generateReleaseTypes (types) {
45
56
  return types.map(item => {
@@ -71,6 +82,14 @@ BumpVersion -- By PicGo Group
71
82
  `
72
83
  );
73
84
  (async () => {
85
+ // Non-interactive path: no prompt is written at all, so this works with no
86
+ // TTY attached (CI, `pnpm release` from a script, an agent session).
87
+ if (argv.yes) {
88
+ console.log(`Bumping ${currentVersion} -> ${nextVersion}${argv.dry ? ' (dry run)' : ''}`)
89
+ await mainLifeCycle(argv, currentVersion, nextVersion)
90
+ return
91
+ }
92
+
74
93
  let answer = await inquirer.prompt(promptList)
75
94
  if (answer.confirmVersion) {
76
95
  await mainLifeCycle(argv, currentVersion, nextVersion)
@@ -82,7 +101,7 @@ BumpVersion -- By PicGo Group
82
101
  message: `The current version is ${currentVersion}\n Which version would you like to bump it?`,
83
102
  choices: [
84
103
  ...generateReleaseTypes(releaseTypes),
85
- new inquirer.Separator(),
104
+ new Separator(),
86
105
  'custom version',
87
106
  'never mind~'
88
107
  ],
@@ -101,11 +120,13 @@ BumpVersion -- By PicGo Group
101
120
  }
102
121
  ]
103
122
  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')
123
+ // Same validator as --version, so a typed version and a flagged one are
124
+ // held to one rule.
125
+ let custom = resolveVersion({ version: result.version }, currentVersion)
126
+ if (custom.error) {
127
+ return logger(custom.error, 'error')
108
128
  }
129
+ await mainLifeCycle(argv, currentVersion, custom.version)
109
130
  } else {
110
131
  await mainLifeCycle(argv, currentVersion, answer.version)
111
132
  }
@@ -1,7 +1,7 @@
1
- const typeEnum = require('./types')
1
+ const typeEnum = require('./types.cjs')
2
2
 
3
3
  module.exports = {
4
- parserPreset: '../conventional-changelog-picgo/parser-opts',
4
+ parserPreset: '../conventional-changelog-picgo/parser-opts.cjs',
5
5
  rules: {
6
6
  'body-leading-blank': [1, 'always'],
7
7
  'footer-leading-blank': [1, 'always'],
@@ -0,0 +1,9 @@
1
+ 'use strict'
2
+
3
+ const parserOpts = require(`./parser-opts.cjs`)
4
+ const writerOpts = require(`./writer-opts.cjs`)
5
+
6
+ module.exports = Promise.all([parserOpts, writerOpts])
7
+ .then(([parserOpts, writerOpts]) => {
8
+ return { parserOpts, writerOpts }
9
+ })
@@ -1,6 +1,6 @@
1
1
  'use strict'
2
2
 
3
- const parserOpts = require(`./parser-opts`)
3
+ const parserOpts = require(`./parser-opts.cjs`)
4
4
 
5
5
  module.exports = {
6
6
  parserOpts,
@@ -0,0 +1,10 @@
1
+ 'use strict'
2
+ const conventionalChangelog = require(`./conventional-changelog.cjs`)
3
+ const parserOpts = require(`./parser-opts.cjs`)
4
+ const recommendedBumpOpts = require(`./conventional-recommended-bump.cjs`)
5
+ const writerOpts = require(`./writer-opts.cjs`)
6
+
7
+ module.exports = Promise.all([conventionalChangelog, parserOpts, recommendedBumpOpts, writerOpts])
8
+ .then(([conventionalChangelog, parserOpts, recommendedBumpOpts, writerOpts]) => {
9
+ return { conventionalChangelog, parserOpts, recommendedBumpOpts, writerOpts }
10
+ })
@@ -1,8 +1,7 @@
1
1
  'use strict'
2
2
 
3
3
  const compareFunc = require(`compare-func`)
4
- const Q = require(`q`)
5
- const readFile = Q.denodeify(require(`fs`).readFile)
4
+ const readFile = require(`fs`).promises.readFile
6
5
  const resolve = require(`path`).resolve
7
6
  const headerPattern = /^(:.*: (.*))$/
8
7
 
@@ -18,13 +17,13 @@ const compareTitleFunc = (a, b) => {
18
17
  return (sortMap[typeB] || 0) - (sortMap[typeA] || 0)
19
18
  }
20
19
 
21
- module.exports = Q.all([
20
+ module.exports = Promise.all([
22
21
  readFile(resolve(__dirname, `./templates/template.hbs`), `utf-8`),
23
22
  readFile(resolve(__dirname, `./templates/header.hbs`), `utf-8`),
24
23
  readFile(resolve(__dirname, `./templates/commit.hbs`), `utf-8`),
25
24
  readFile(resolve(__dirname, `./templates/footer.hbs`), `utf-8`)
26
25
  ])
27
- .spread((template, header, commit, footer) => {
26
+ .then(([template, header, commit, footer]) => {
28
27
  const writerOpts = getWriterOpts()
29
28
 
30
29
  writerOpts.mainTemplate = template
@@ -60,8 +59,6 @@ function getWriterOpts () {
60
59
  commit.type = `:package: Chore`
61
60
  } else if (commit.type === `:pushpin: Init`) {
62
61
  commit.type = `:pushpin: Init`
63
- } else if (discard) {
64
- return
65
62
  } else if (commit.type === `:arrow_up: Upgrade`) {
66
63
  commit.type = `:arrow_up: Dependencies Upgrade`
67
64
  } else if (commit.type === `:art: Style`) {
@@ -71,6 +68,10 @@ function getWriterOpts () {
71
68
  } else if (commit.type === `:white_check_mark: Test`) {
72
69
  commit.type = `:white_check_mark: Tests`
73
70
  } else if (commit.type === `:construction: WIP` || commit.type === ':tada: Release') {
71
+ // WIP is noise and Release is this tool's own commit.
72
+ return
73
+ } else if (discard) {
74
+ // Anything unrecognised, unless it carries a BREAKING CHANGE note.
74
75
  return
75
76
  }
76
77
 
package/eslint.config.js CHANGED
@@ -1,5 +1,9 @@
1
- const { FlatCompat } = require('@eslint/eslintrc')
2
- const js = require('@eslint/js')
1
+ import { FlatCompat } from '@eslint/eslintrc'
2
+ import js from '@eslint/js'
3
+ import path from 'node:path'
4
+ import { fileURLToPath } from 'node:url'
5
+
6
+ const __dirname = path.dirname(fileURLToPath(import.meta.url))
3
7
 
4
8
  const compat = new FlatCompat({
5
9
  baseDirectory: __dirname,
@@ -7,7 +11,7 @@ const compat = new FlatCompat({
7
11
  allConfig: js.configs.all
8
12
  })
9
13
 
10
- module.exports = [
14
+ export default [
11
15
  {
12
16
  ignores: ['node_modules', 'dist']
13
17
  },
@@ -18,15 +22,38 @@ module.exports = [
18
22
  'plugin:promise/recommended'
19
23
  ),
20
24
  {
25
+ // The CLI and its src/ modules are ESM, as is this config.
21
26
  languageOptions: {
22
27
  ecmaVersion: 2022,
23
- sourceType: 'script'
28
+ sourceType: 'module'
29
+ },
30
+ rules: {
31
+ // Resolution of bare ESM specifiers is handled by Node, not the plugin.
32
+ 'import/no-unresolved': 'off'
33
+ }
34
+ },
35
+ {
36
+ // Configs consumed by other tools' CommonJS loaders stay CJS.
37
+ files: ['**/*.cjs'],
38
+ languageOptions: {
39
+ sourceType: 'commonjs',
40
+ globals: {
41
+ module: 'writable',
42
+ require: 'readonly',
43
+ __dirname: 'readonly'
44
+ }
24
45
  }
25
46
  },
26
47
  {
27
48
  files: ['eslint.config.js'],
28
49
  rules: {
29
- 'n/no-unpublished-require': 'off'
50
+ 'n/no-unpublished-import': 'off'
51
+ }
52
+ },
53
+ {
54
+ files: ['test/**/*.js'],
55
+ rules: {
56
+ 'n/no-unpublished-import': 'off'
30
57
  }
31
58
  }
32
59
  ]
package/package.json CHANGED
@@ -1,23 +1,25 @@
1
1
  {
2
2
  "name": "@picgo/bump-version",
3
- "version": "2.0.0",
3
+ "version": "3.0.0",
4
4
  "description": "",
5
- "main": "index.js",
6
5
  "bin": {
7
6
  "bump-version": "./bin/bump-version"
8
7
  },
9
8
  "publishConfig": {
10
9
  "access": "public"
11
10
  },
12
- "husky": {
13
- "hooks": {
14
- "pre-commit": "npm run lint",
15
- "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
16
- }
11
+ "scripts": {
12
+ "test": "vitest run",
13
+ "cz": "git-cz",
14
+ "release": "node ./bin/bump-version",
15
+ "lint": "eslint --ext .js .",
16
+ "lint:fix": "eslint --ext .js --fix .",
17
+ "test:watch": "vitest",
18
+ "prepare": "husky || true"
17
19
  },
18
20
  "repository": {
19
21
  "type": "git",
20
- "url": "git+https://github.com/PicGo/bump-version.git"
22
+ "url": "https://github.com/PicGo/bump-version"
21
23
  },
22
24
  "author": "Molunerfinn",
23
25
  "license": "MIT",
@@ -26,48 +28,48 @@
26
28
  },
27
29
  "homepage": "https://github.com/PicGo/bump-version#readme",
28
30
  "devDependencies": {
31
+ "@commitlint/cli": "^21.2.2",
29
32
  "@eslint/eslintrc": "^3.3.3",
30
33
  "@eslint/js": "^9.39.1",
34
+ "commitizen": "^4.3.2",
35
+ "cz-customizable": "^7.5.4",
31
36
  "eslint": "^9.39.1",
32
37
  "eslint-plugin-import": "^2.32.0",
33
38
  "eslint-plugin-n": "^17.23.1",
34
- "eslint-plugin-promise": "^7.2.1"
39
+ "eslint-plugin-promise": "^7.2.1",
40
+ "husky": "^9.1.7",
41
+ "vitest": "^4.1.11"
35
42
  },
36
43
  "config": {
37
44
  "commitizen": {
38
45
  "path": "node_modules/cz-customizable"
39
46
  },
40
47
  "cz-customizable": {
41
- "config": ".cz-config.js"
48
+ "config": ".cz-config.cjs"
42
49
  }
43
50
  },
44
51
  "commitlint": {
45
52
  "extends": [
46
- "./commitlint-picgo"
53
+ "./commitlint-picgo/index.cjs"
47
54
  ]
48
55
  },
49
56
  "dependencies": {
50
- "@commitlint/cli": "^7.5.2",
51
- "chalk": "^4.1.2",
52
- "commitizen": "^4.2.3",
57
+ "@inquirer/prompts": "^8.6.0",
58
+ "chalk": "^6.0.0",
53
59
  "compare-func": "^2.0.0",
54
60
  "conventional-changelog": "^3.0.6",
55
- "cz-customizable": "^7.5.1",
56
- "husky": "^1.3.1",
57
- "inquirer": "^13.0.2",
61
+ "inquirer": "^14.1.0",
58
62
  "minimist": "^1.2.8",
59
- "ora": "^3.4.0",
60
- "q": "^1.5.1",
63
+ "ora": "^6.3.1",
61
64
  "semver": "^7.7.3"
62
65
  },
63
66
  "engines": {
64
- "node": ">=20.0.0"
67
+ "node": ">=22.0.0"
65
68
  },
66
- "scripts": {
67
- "test": "echo \"Error: no test specified\"",
68
- "cz": "git-cz",
69
- "release": "node ./bin/bump-version",
70
- "lint": "eslint --ext .js .",
71
- "lint:fix": "eslint --ext .js --fix ."
69
+ "type": "module",
70
+ "pnpm": {
71
+ "overrides": {
72
+ "tmp": "^0.2.5"
73
+ }
72
74
  }
73
- }
75
+ }
@@ -1,13 +1,18 @@
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)
1
+ import fs from 'node:fs'
2
+ import { checkFileAndGetPath } from './utils.js'
3
+
4
+ // Resolved per call rather than cached at module scope: the resolved list is
5
+ // absolute and tied to one `argv.path`, so reusing it across calls would
6
+ // silently target the previous directory.
7
+ const VERSION_FILES = ['package.json', 'package-lock.json']
8
+
9
+ export default (argv, version) => {
10
+ // No early return for `dry` here: the write itself is guarded below, so
11
+ // bailing out would also skip it for `--no-dry`, leaving commit and tag to
12
+ // run against an unchanged version.
13
+ const versionFiles = checkFileAndGetPath(argv, VERSION_FILES)
9
14
 
10
- for (let file of versionFiles) {
15
+ for (const file of versionFiles) {
11
16
  let content = fs.readFileSync(file, 'utf8')
12
17
  try {
13
18
  content = JSON.parse(content)
package/src/changelog.js CHANGED
@@ -1,8 +1,8 @@
1
- const cc = require('conventional-changelog')
2
- const config = require('../conventional-changelog-picgo')
3
- const fs = require('fs')
1
+ import cc from 'conventional-changelog'
2
+ import fs from 'node:fs'
3
+ import config from '../conventional-changelog-picgo/index.cjs'
4
4
 
5
- module.exports = (argv, newVersion) => {
5
+ export default (argv, newVersion) => {
6
6
  if (argv.changelog === false) {
7
7
  return Promise.resolve()
8
8
  }
package/src/commit.js CHANGED
@@ -1,16 +1,16 @@
1
- const utils = require('./utils')
2
- const exec = require('./exec')
3
- let changedFiles = [
1
+ import { checkFileAndGetPath } from './utils.js'
2
+ import exec from './exec.js'
3
+ const VERSION_FILES = [
4
4
  'package.json',
5
5
  'package-lock.json'
6
6
  ]
7
- module.exports = (argv, newVersion) => {
8
- if (argv.changelog !== false) {
9
- changedFiles.push(argv.file)
10
- }
7
+ export default (argv, newVersion) => {
8
+ // Built per call: reassigning a module-level array leaks the previous
9
+ // run's resolved paths into the next one.
10
+ const files = argv.changelog !== false ? [...VERSION_FILES, argv.file] : [...VERSION_FILES]
11
11
  const releaseMsg = `:tada: Release: v${newVersion}`
12
12
  if (argv.skipCommit) return Promise.resolve()
13
- changedFiles = utils.checkFileAndGetPath(argv, changedFiles).join(' ')
13
+ const changedFiles = checkFileAndGetPath(argv, files).join(' ')
14
14
  if (changedFiles === '' || argv.dry) {
15
15
  return Promise.resolve()
16
16
  }
package/src/exec.js CHANGED
@@ -1,7 +1,7 @@
1
- const exec = require('child_process').exec
2
- const logger = require('./logger')
1
+ import { exec } from 'node:child_process'
2
+ import logger from './logger.js'
3
3
 
4
- module.exports = (argv, cmd) => {
4
+ export default (argv, cmd) => {
5
5
  return new Promise((resolve, reject) => {
6
6
  // Exec given cmd and handle possible errors
7
7
  exec(cmd, { cwd: argv.path }, function (err, stdout, stderr) {
package/src/logger.js CHANGED
@@ -1,12 +1,14 @@
1
- const ora = require('./ora')
2
- const chalk = require('chalk')
1
+ import chalk from 'chalk'
2
+ import ora from './ora.js'
3
+
3
4
  const level = {
4
5
  success: 'green',
5
6
  info: 'blue',
6
7
  warn: 'yellow',
7
8
  error: 'red'
8
9
  }
9
- module.exports = (msg, type) => {
10
+
11
+ export default (msg, type) => {
10
12
  let log = chalk[level[type]](`[Bump ${type.toUpperCase()}]: `)
11
13
  log += msg
12
14
  ora.clear()
@@ -1,9 +1,9 @@
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) => {
1
+ import bumpVersion from './bumpVersion.js'
2
+ import commit from './commit.js'
3
+ import changeLog from './changelog.js'
4
+ import tag from './tag.js'
5
+ import spinner from './ora.js'
6
+ export default (argv, currentVersion, newVersion) => {
7
7
  spinner.start()
8
8
  return Promise.resolve()
9
9
  .then(() => {
package/src/ora.js CHANGED
@@ -1,4 +1,11 @@
1
- const Ora = require('ora')
2
- module.exports = new Ora({
1
+ import Ora from 'ora'
2
+
3
+ // Pinned to ora 6.x in package.json on purpose. From ora 7 onwards the spinner
4
+ // kills the process when it is started after an inquirer prompt has restored
5
+ // the TTY: the confirm is answered, the spinner draws one frame, and the
6
+ // process exits before the release finishes — leaving a bumped package.json
7
+ // with no commit and no tag. Verified against ora 3/4/5/6 (fine) and 7/8/9
8
+ // (broken), with inquirer 13 and 14 alike.
9
+ export default new Ora({
3
10
  text: ''
4
11
  })
@@ -0,0 +1,48 @@
1
+ import semver from 'semver'
2
+
3
+ const RELEASE_TYPES = ['major', 'minor', 'patch', 'premajor', 'preminor', 'prepatch', 'prerelease']
4
+
5
+ export const releaseTypes = RELEASE_TYPES
6
+
7
+ /**
8
+ * Work out which version to bump to.
9
+ *
10
+ * Pure on purpose: the CLI turns the result into either an error exit or a
11
+ * lifecycle run, and keeping the decision separate is what makes it testable
12
+ * without spawning a process or touching a git repo.
13
+ *
14
+ * @param {object} argv parsed arguments; reads `version`, `t`/`type`, `a`, `b`
15
+ * @param {string} currentVersion the version currently in package.json
16
+ * @returns {{ version: string } | { error: string }}
17
+ */
18
+ export default (argv, currentVersion) => {
19
+ // An explicit --version wins over --type: naming a version is unambiguous,
20
+ // so silently deriving a different one from the type would be surprising.
21
+ const explicit = typeof argv.version === 'string' ? argv.version.trim() : ''
22
+
23
+ if (explicit !== '') {
24
+ // Accept a leading `v` because that is how the tag is written and how
25
+ // people say it out loud.
26
+ const version = semver.valid(explicit.replace(/^v/, ''))
27
+ if (version === null) {
28
+ return { error: `Invalid version: ${explicit}` }
29
+ }
30
+ if (semver.lte(version, currentVersion)) {
31
+ return { error: `Version ${version} is not greater than the current ${currentVersion}!` }
32
+ }
33
+ return { version }
34
+ }
35
+
36
+ const releaseType = typeof argv.t === 'string' ? argv.t : 'patch'
37
+ if (!RELEASE_TYPES.includes(releaseType)) {
38
+ return { error: `Invalid release type: ${releaseType}. Expected one of ${RELEASE_TYPES.join(', ')}` }
39
+ }
40
+
41
+ const preid = argv.a ? 'alpha' : argv.b ? 'beta' : ''
42
+ const version = semver.inc(currentVersion, releaseType, preid)
43
+ if (version === null) {
44
+ return { error: `Cannot bump ${currentVersion} with release type ${releaseType}` }
45
+ }
46
+ return { version }
47
+ }
48
+
package/src/tag.js CHANGED
@@ -1,5 +1,5 @@
1
- const exec = require('./exec')
2
- module.exports = (argv, newVersion) => {
1
+ import exec from './exec.js'
2
+ export default (argv, newVersion) => {
3
3
  if (argv.dry) {
4
4
  return Promise.resolve()
5
5
  }
@@ -11,7 +11,7 @@ module.exports = (argv, newVersion) => {
11
11
  }
12
12
  return flow.then(async () => {
13
13
  if (argv.push) {
14
- await exec(`git push --follow-tags origin master`)
14
+ await exec(argv, `git push --follow-tags origin master`)
15
15
  }
16
16
  return null
17
17
  })
package/src/utils.js CHANGED
@@ -1,6 +1,6 @@
1
- const path = require('path')
2
- const fs = require('fs')
3
- const checkFileAndGetPath = (argv, files) => {
1
+ import path from 'node:path'
2
+ import fs from 'node:fs'
3
+ export const checkFileAndGetPath = (argv, files) => {
4
4
  return files.map(item => {
5
5
  if (path.isAbsolute(item)) {
6
6
  return item
@@ -10,14 +10,17 @@ const checkFileAndGetPath = (argv, files) => {
10
10
  return fs.existsSync(item)
11
11
  })
12
12
  }
13
- const helperMsg = `
13
+ export const helperMsg = `
14
14
  BumpVersion -- By PicGo Group
15
15
 
16
16
  Usage
17
17
  bump-version
18
18
 
19
19
  Example
20
- bump-version -t major
20
+ bump-version -t major Interactive, confirms before running
21
+ bump-version -t minor -y Non-interactive, no TTY needed
22
+ bump-version --version 1.0.0 -y Bump to an exact version
23
+ bump-version -t minor -y -d Preview without changing anything
21
24
 
22
25
  Options
23
26
  -a, --preid-alpha Prerelease id: alpha. Exp. 1.0.0.alpha-0
@@ -37,6 +40,13 @@ Options
37
40
  -t, --type Release type. [major, minor, patch, premajor, preminor, prepatch, prerelease]
38
41
  Default: patch
39
42
 
43
+ -y, --yes Skip all prompts and run immediately. Needs no TTY,
44
+ so it works in CI and in scripts
45
+ Default: false
46
+
47
+ --version Bump to this exact version instead of deriving one
48
+ from --type. A leading "v" is accepted. Exp. 1.0.0
49
+
40
50
  --push Auto push commits to origin master
41
51
  Default: false
42
52
 
@@ -47,7 +57,3 @@ Options
47
57
  Default: changelog will be created
48
58
  `
49
59
 
50
- module.exports = {
51
- checkFileAndGetPath,
52
- helperMsg
53
- }
@@ -1,37 +0,0 @@
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 }}
@@ -1,10 +0,0 @@
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
- })
@@ -1,11 +0,0 @@
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
- })
File without changes
File without changes