插件系统
🚀 通用的 CLI 工具,用于自动化版本控制和软件包发布相关的任务:
- 提升版本号(例如在 package.json 文件中)
- Git 提交、打标签、推送
- 使用钩子执行任何测试或构建命令
- 在 GitHub 或 GitLab 上创建发布
- 生成变更日志
- 发布到 npm
- 管理预发布版本
- 使用插件进行扩展
- 可以在任何 CI/CD 环境中发布
Plugin
json
{
"scripts": {
"release:dry": "release-it --dry-run --no-npm",
"release:info": "release-it --release-version",
"release:beta:no-npm": "release-it --preRelease=beta --no-npm",
"release:beta": "release-it --preRelease=beta",
"release:no-npm": "release-it --no-npm",
"release:changelog:fix": "node ./bin/injectContributorsList.js && git add CHANGELOG.md",
"release": "release-it"
},
"release-it": {
"git": {
"commitMessage": "chore(release): v${version}",
"push": true,
"commit": true,
"tag": true,
"requireCommits": false,
"requireCleanWorkingDir": false
},
"github": {
"release": true,
"draft": true
},
"npm": {
"publish": false,
"ignoreVersion": false
},
"plugins": {
"@release-it/conventional-changelog": {
"preset": "angular",
"infile": "CHANGELOG.md",
"header": "# Changelog"
}
},
"hooks": {
"before:init": "npm test",
"after:bump": "gulp version --bump ${version} && npm run build && npm run test:build:version && git add ./dist && git add ./package-lock.json",
"before:release": "npm run release:changelog:fix",
"after:release": "echo Successfully released ${name} v${version} to ${repo.repository}."
}
}
}json
{
"hooks": {},
"git": {
"changelog": "git log --pretty=format:\"* %s (%h)\" ${from}...${to}",
"requireCleanWorkingDir": true,
"requireBranch": false,
"requireUpstream": true,
"requireCommits": false,
"addUntrackedFiles": false,
"commit": true,
"commitMessage": "Release ${version}",
"commitArgs": [],
"tag": true,
"tagName": null,
"tagMatch": null,
"tagAnnotation": "Release ${version}",
"tagArgs": [],
"push": true,
"pushArgs": ["--follow-tags"],
"pushRepo": ""
},
"npm": {
"publish": true,
"publishPath": ".",
"publishArgs": [],
"tag": null,
"otp": null,
"ignoreVersion": false,
"allowSameVersion": false,
"versionArgs": [],
"skipChecks": false,
"timeout": 10
},
"github": {
"release": false,
"releaseName": "Release ${version}",
"releaseNotes": null,
"autoGenerate": false,
"preRelease": false,
"draft": false,
"tokenRef": "GITHUB_TOKEN",
"assets": null,
"host": null,
"timeout": 0,
"proxy": null,
"skipChecks": false,
"web": false
},
"gitlab": {
"release": false,
"releaseName": "Release ${version}",
"releaseNotes": null,
"milestones": [],
"tokenRef": "GITLAB_TOKEN",
"tokenHeader": "Private-Token",
"certificateAuthorityFile": null,
"assets": null,
"origin": null,
"skipChecks": false
}
}hooks
Use script hooks to run shell commands at any moment during the release process (such as before:init or after:release).
在发包过程中使用钩子来执行命令,格式为 [prefix]:[hook] or [prefix]:[plugin]:[hook]:
| part | value |
|---|---|
| prefix | before or after |
| plugin | version, git, npm, github, gitlab |
| hook | init, bump, release |
json
{
"hooks": {
"before:init": ["npm run lint", "npm test"],
"after:my-plugin:bump": "./bin/my-script.sh",
"after:bump": "npm run build",
"after:git:release": "echo After git push, before github release",
"after:release": "echo Successfully released ${name} v${version} to ${repo.repository}."
}
}执行用户配置的 hooks 脚本
ts
async function runHook(...name) {
const scripts = hooks[name.join(':')]
if (!scripts || !scripts.length)
return
const context = config.getContext()
const external = true
for (const script of _.castArray(scripts)) {
const task = () => shell.exec(script, { external }, context)
await spinner.show({ task, label: script, context, external })
}
}生命周期
执行生命周期钩子函数
ts
async function runLifeCycleHook(plugin, name, ...args) {
// before:[name]
if (plugin === _.first(plugins))
await runHook('before', name)
// before:[plugin]:[name]
await runHook('before', plugin.namespace, name)
// 如果返回 false 则不执行 after:[plugin]:[name]
const willHookRun = (await plugin[name](...args)) !== false
if (willHookRun) {
await runHook('after', plugin.namespace, name)
}
if (plugin === _.last(plugins))
await runHook('after', name)
}
runLifeCycleHook(plugin, 'init')- before:init
- before:plugin:init
- plugin:init
- after:plugin:init
- after:init
ts
// 内置的插件 和 三方插件
const plugins = []
for (const plugin of plugins) {
await runLifeCycleHook(plugin, 'init')
}
for (const hook of ['beforeBump', 'bump', 'beforeRelease']) {
for (const plugin of plugins) {
const args = hook === 'bump' ? [version] : []
await runLifeCycleHook(plugin, hook, ...args)
}
}
for (const hook of ['release', 'afterRelease']) {
for (const plugin of plugins) {
await runLifeCycleHook(plugin, hook)
}
}