@zhupengji/release-kit
v0.1.5
Published
Zero-dependency release & changelog toolkit: sync versions, group commits, run hooks, tag and push.
Downloads
344
Maintainers
Readme
release-kit
零依赖的发布与变更日志工具包。一条命令即可:跨文件同步版本号、按 Conventional Commits 生成变更日志、执行生命周期钩子、提交、打标签,可选推送。运行时无需任何 npm 包(Node ≥ 18,ESM)。
特性
- 零运行时依赖 — 只使用
node:fs、node:path、node:child_process。 - 版本文件适配器 — 支持
package.json、Cargo.toml、pyproject.toml、tauri.conf.json、通用.json,或完全自定义的读写函数。 - 可配置的变更日志 — Conventional Commits 分组(Features / Bug Fixes / Other)、 忽略规则、自定义章节、全量重建或增量追加。
- 生命周期钩子 — 围绕每个步骤执行 shell 命令或异步 JS 函数。
- CI 友好 —
--no-input/--yes、dry-run 预览、脏工作树守卫。 - 安全设计 — 任何写入前先在内存中暂存版本文件;git 命令不经过 shell 执行 (无引号/注入隐患)。
安装
npm install --save-dev @zhupengji/release-kit快速上手
release-kit patch # 升到 0.1.1,更新 CHANGELOG.md,提交并打附注标签 v0.1.1
release-kit minor --dry-run # 预览一次 minor 发布会做什么
release-kit changelog # 重新生成/追加 CHANGELOG.md假设 package.json 当前为 0.1.0,且自上一个标签以来的提交为:
feat: add the thing
fix: correct the bug
docs: add guide
chore: cleanup执行 release-kit patch 将:
- 从
versionFiles读取当前版本(0.1.0), - 计算出
0.1.1(交互模式下也可提示手动覆盖), - 将分组为
Features/Bug Fixes/Other的## 0.1.1 (2026-09-02)写入CHANGELOG.md(chore: cleanup会被过滤掉), - 在每个配置的文件中提升
version字段, - 创建提交
chore: release v0.1.1和附注标签v0.1.1。
CLI
release-kit <major|minor|patch> [options] Run a full release
release-kit changelog [--preview] [--full] Generate or rewrite CHANGELOG.md
release-kit --help | -h Show help| 选项 | 含义 |
| --- | --- |
| --version <x.y.z> | 发布指定版本(跳过计算与提示) |
| --dry-run | 只打印将要执行的操作,不修改任何内容 |
| --yes, -y | 所有提示均接受默认值 |
| --no-input | 永不提示(CI 安全;使用默认值,脏树时中止) |
| --push | 将提交与附注标签推送到远程仓库 |
| --build | 执行配置的构建命令 |
| --timeout <duration> | 覆盖 shell/构建超时(默认 10m;如 30m、90s、2h) |
| --config <path> | 使用指定的配置文件 |
| --tag-prefix <v> | 覆盖 git.tagPrefix(默认 v) |
| --no-changelog | 本次发布跳过变更日志生成 |
| --quiet | 隐藏非错误输出 |
changelog 选项:--preview 只打印不写入;--full 从所有标签全量重建。
默认为 auto:变更日志文件不存在时全量重建,否则增量追加。
配置
配置查找顺序(首个命中即用;CLI 参数覆盖最终结果):
--config <path>./release.config.mjs/./release.config.jspackage.json中的"releaseKit"字段- 内置默认值(零配置即可用)
默认配置(零配置即用)
「零配置」仍遵循一套确定的规则——查找顺序的最后一级就是以下内置默认值
(与 src/config.js 的 DEFAULTS 保持一致;修改代码默认值时请同步本文档):
export default {
versionFiles: ['package.json'],
changelog: {
file: 'CHANGELOG.md',
full: 'auto', // 'auto' | true | false
header: '# Changelog',
ignore: [/^chore(\(.+\))?!?:/, /^release:/],
sections: [
{ title: 'Features', pattern: /^feat(\(.+\))?!?:/, strip: /^feat(\(.+\))?!?:\s*/ },
{ title: 'Bug Fixes', pattern: /^fix(\(.+\))?!?:/, strip: /^fix(\(.+\))?!?:\s*/ },
{ title: 'Other', pattern: /.*/ }, // 兜底分组,须放最后;无 strip → 保留整行
],
},
git: {
tagPrefix: 'v',
commitMessage: 'chore: release ${tag}',
branch: '', // 空 = 不限制分支
remote: 'origin',
requireClean: 'ask', // 'ask' | true | false
addFiles: [],
push: false,
sign: false,
},
timeout: 10 * 60 * 1000, // 10 分钟;shell 钩子与构建命令
build: { command: '', run: false },
hooks: { prerelease: [], prebump: [], postbump: [], precommit: [], postcommit: [], pretag: [], posttag: [], prepush: [], postpush: [], postrelease: [] },
}由此默认出发,仅一条 release-kit patch 即可完成发布:bump package.json 的
version、生成/追加 CHANGELOG.md、提交 chore: release vX.Y.Z 并打 vX.Y.Z
附注标签(不推送、不构建、不执行任何钩子)。
下面的示例演示如何在这些默认值之上接入常见扩展点;标有 // 演示: 的字段是
示例所需、并非默认值:
示例 release.config.mjs:
import { defineConfig } from '@zhupengji/release-kit'
export default defineConfig({
versionFiles: [ // 演示:默认仅为 ['package.json']
'package.json',
'src-tauri/Cargo.toml',
{ path: 'custom.json', read: (raw) => JSON.parse(raw).appVer, write: (raw, v) => JSON.stringify({ ...JSON.parse(raw), appVer: v }, null, 2) + '\n' },
],
changelog: {
file: 'CHANGELOG.md',
header: '# Changelog',
ignore: [/^chore(\(.+\))?!?:/, /^release:/],
sections: [
{ title: 'Features', pattern: /^feat(\(.+\))?!?:/, strip: /^feat(\(.+\))?!?:\s*/ },
{ title: 'Bug Fixes', pattern: /^fix(\(.+\))?!?:/, strip: /^fix(\(.+\))?!?:\s*/ },
{ title: 'Other', pattern: /.*/ },
],
},
git: {
tagPrefix: 'v',
commitMessage: 'chore: release ${tag}',
branch: 'main', // 演示:默认 ''(不限制分支)
remote: 'origin',
requireClean: 'ask', // 'ask' | true | false
addFiles: ['package-lock.json'], // 演示:默认 []
push: false,
sign: false,
},
timeout: '30m', // 演示:默认 10 分钟
build: { command: 'pnpm tauri build', run: false, timeout: '45m' }, // 演示:默认 command ''(不构建)
hooks: {
prerelease: [], // string | fn(ctx) | { run, cwd?, onError?, timeout? }
postbump: ['echo released ${RELEASE_KIT_VERSION}'], // 演示:默认全部为 []
postrelease: [],
},
})changelog.full
'auto'(默认)— 文件缺失时全量重建,否则增量追加。true— 始终从所有标签全量重建文件。false— 只生成/追加增量章节。
git.requireClean
'ask'(默认)— 工作树脏时提示(非交互运行则中止)。true— 工作树脏时直接失败。false— 不询问直接继续。
钩子(Hooks)
每个已命名的生命周期事件(见下方列表)都会按声明顺序执行钩子。每个条目可以是:
- shell 命令字符串 — 通过系统 shell 在项目目录下执行,或
- 异步函数
(ctx) => Promise<void>— 在进程内执行,或 - 对象
{ run: 'cmd', cwd?: 'sub/dir', onError?: 'fail'|'warn', timeout?: '30m' }。
Shell 钩子可获取环境变量 RELEASE_KIT_VERSION、RELEASE_KIT_PREVIOUS_VERSION、
RELEASE_KIT_TAG 和 RELEASE_KIT_DRY_RUN。函数钩子可获取完整上下文(version、
previousVersion、tag、changelog、config、dryRun、cwd)。
事件(执行顺序):prerelease → prebump → postbump → precommit →
postcommit → pretag → posttag → [prepush → postpush](仅在推送时执行)→
postrelease。
命令超时
Shell 钩子和 build.command 默认 10 分钟后会被终止。冷编译这类长命令(例如
pnpm tauri build)可以加长:
timeout— 所有 shell 钩子和构建命令的项目默认值(30m、90s、2h,或毫秒数)。build.timeout— 只作用于构建命令。- 钩子对象上的
timeout— 只作用于这一条钩子。 --timeout <duration>— 覆盖本次运行的timeout。单条命令自己的超时仍然优先。
构建步骤以及 posttag / postrelease 钩子在标签创建之后才执行。如果希望超时发生在
打标签之前,把长命令放到 pretag。
编程 API
import { release, generateChangelog, loadConfig, defineConfig } from '@zhupengji/release-kit'
const result = await release({ level: 'patch', cwd: '/path/to/repo' })
// { version: '0.1.1', previousVersion: '0.1.0', tag: 'v0.1.1', dryRun: false }发布本包
release-kit patch --no-input # 内部使用;保持 dogfooding 简单许可证
MIT
