Skip to content

插件系统

🚀 通用的 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]:

partvalue
prefixbefore or after
pluginversion, git, npm, github, gitlab
hookinit, 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')
  1. before:init
  2. before:plugin:init
  3. plugin:init
  4. after:plugin:init
  5. 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)
  }
}