使用 Semantic Release 实现 NPM 全自动发版 monorepo 和 单仓库 项目

1.前言

作为项目维护者,你是否也遇到过这样的痛点:

  • 每次发版都要手动修改 package.json 版本号
  • 手写 CHANGELOG.md 既费时又容易遗漏
  • 在 GitHub 创建 Release、打 Tag、发布 NPM 包,一套流程下来十几分钟
  • 重复性工作多,容易出错,影响开发效率

如果你也有这些困扰,那么今天介绍的 Semantic Release 工作链路 将彻底解放你的双手!

并且会讲到我在公司里工程化的实践,包含 gitlab, github, 私有化npm, 单仓库, monorepo 仓库下怎么实现发版。并且在github会提供一个相关联

2.什么是 Semantic Release?

Semantic Release 是一个全自动的版本管理和发布工具。它通过分析你的 Git 提交信息,自动完成以下所有工作:

  • 🎯 自动确定版本号:根据提交类型决定是 patch、minor 还是 major 版本
  • 📝 自动生成 CHANGELOG:基于提交信息生成美观的变更日志
  • 🏷️ 自动打 Git Tag:无需手动管理版本标签
  • 📦 自动发布 NPM 包:一键发布到 npm registry
  • 🚀 自动创建 GitHub Release:生成详细的发布说明

3. 单仓库 配置 (github)

模版地址: github.com/electroluxc...

3.1 安装依赖

shell 复制代码
# 安装 semantic-release 核心包
npm install --save-dev semantic-release

# 安装常用插件
npm install --save-dev @semantic-release/commit-analyzer
npm install --save-dev @semantic-release/release-notes-generator
npm install --save-dev @semantic-release/changelog
npm install --save-dev @semantic-release/npm
npm install --save-dev @semantic-release/git

3.2 Semantic 配置文件 - releaserc.json

创建 .releaserc.json 文件:

javascript 复制代码
{
  "repositoryUrl": "git@github.com:electroluxcode/semantic-release-bolierplate.git",
  "branches": [
    "master"
  ],
  "plugins": [
    "@semantic-release/commit-analyzer",
    "@semantic-release/release-notes-generator",
    [
      "@semantic-release/changelog",
      {
        "changelogFile": "CHANGELOG.md"
      }
    ],
    "@semantic-release/npm",
    [
      "@semantic-release/git",
      {
        "assets": [
          "CHANGELOG.md", "package.json"
        ],
        "message": "chore(release): v${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
      }
    ]
  ]
}

其中各个参数说明如下

js 复制代码
{
  // 仓库地址
  repositoryUrl: '',
  branches: ["master"], // 指定在哪个分支下要执行发布操作
  plugins: [
    // 1. 解析 commit 信息,默认就是 Angular 规范
    "@semantic-release/commit-analyzer",
    // 2. 生成发布信息
    "@semantic-release/release-notes-generator",
    // 3. 把发布日志写入该文件
    [
      "@semantic-release/changelog",
      {
        changelogFile: "CHANGELOG.md", 
      },
    ],
    // 4. 发布 NPM
    "@semantic-release/npm", 
    // 5. changelog 和 vesion,需要重新写入 package.json
    [
      "@semantic-release/git",
      {
        assets: ["CHANGELOG.md", "package.json"],
      },
    ],
  ],
};

3.3 配置 GitHub Actions

创建 .github/workflows/release.yml

yaml 复制代码
name: Release

on:
  push:
    ## 触发的分支
    branches: [master]

# 重要:配置必要权限
permissions:
  contents: write
  issues: write
  pull-requests: write
  packages: write
  id-token: write

jobs:
  release:
    runs-on: ubuntu-latest
    
    steps:
      - name: 检出代码
        uses: actions/checkout@v3
        with:
          fetch-depth: 0
          persist-credentials: false

      - name: 设置 Node.js
        uses: actions/setup-node@v3
        with:
          node-version: "18"
          cache: 'npm'

      - name: 安装依赖
        run: npm ci

      - name: 运行测试(可选)
        run: npm test || echo "No tests found"

      - name: 构建项目(可选)
        run: npm run build || echo "No build script found"

      - name: 语义化发版
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
        run: npx semantic-release

3.4 配置 Token

3.4.1. 获取 NPM Token

  1. 登录 npmjs.com
  2. 点击头像 → Access Tokens
  3. 点击 "Generate New Token"
  4. 选择 "Automation" 类型
  5. 复制生成的 token

example: npm_Easwh8OQHMbxxxxxxxxx

3.4.2. 获取 GitHub Token

  1. 创建 Github 个人访问令牌
  2. 点击 Generate new token
  3. 根据你的需求选择 Repository access
  4. 生成具有以下权限的新令牌:
    • Actions - read and write
    • Commit statuses - read and write
    • Contents - read and write
    • Deployments - read and write

example: github_pat_xxxxxxxxxxx

3.4.3 在仓库中配置 Secrets

  1. 进入你的 GitHub 仓库
  2. Settings → Secrets and variables → Actions
  3. 点击 "Repository secrets"
  4. 添加 NPM_TOKEN,值为3.4.1获取的 NPM token
  5. 添加 GH_TOKEN,值为3.4.2获取的 GH token

4. 单仓库 配置 (gitlab)

在上面的基础上, 安装一个 gitlab 插件然后指向一下地址就好了

shell 复制代码
npm install --save-dev @semantic-release/gitlab

.release

js 复制代码
{
  "branches": ["master"],
  "plugins": [
    "@semantic-release/commit-analyzer",
    "@semantic-release/release-notes-generator",
    [
      "@semantic-release/gitlab",
      {
        "gitlabUrl": "your url"
      }
    ],
    "@semantic-release/changelog",
    [
      "@semantic-release/npm"
    ],
    [
      "@semantic-release/git",
      {
        "assets": ["package.json", "CHANGELOG.md"],
        "message": "chore(release): v${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
      }
    ]
  ],
  "debug": true
}

5. monorepo 仓库配置 (github)

模版地址: github.com/electroluxc...

token配置我们都可以复用上面的配置,有一些专属于monorepo的插件和细节需要我们配置一下

5.1 安装依赖

shell 复制代码
# 安装 semantic-release 核心包
npm install --save-dev semantic-release

# 安装常用插件
npm install --save-dev @semantic-release/commit-analyzer
npm install --save-dev @semantic-release/release-notes-generator
npm install --save-dev @semantic-release/changelog
npm install --save-dev @semantic-release/npm
npm install --save-dev @semantic-release/git

# monorepo 专属插件
npm install --save-dev semantic-release-monorepo
npm install --save-dev semantic-release-monorepo-npm-plugin

5.2 Semantic 配置文件 - releaserc.json

我们在子仓库的根路径配置 下面的 .releaserc.json 文件即可, 参数不做解释了,基本跟单仓库的差不多

js 复制代码
{
  "repositoryUrl": "git@github.com:electroluxcode/semantic-release-monorepo-bolierplate.git",
  "branches": [
   "master"
  ],
  "plugins": [
    "@semantic-release/commit-analyzer",
    ["semantic-release-monorepo-npm-plugin", {
      "isReplaceWorkspace": true
    }],
    "@semantic-release/release-notes-generator",
    [
      "@semantic-release/changelog",
      {
        "changelogFile": "CHANGELOG.md"
      }
    ],
    [
      "@semantic-release/git",
      {
        "assets": [
          "CHANGELOG.md", "package.json"
        ],
        "message": "chore(release): v${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
      }
    ]
  ],
  "extends": "semantic-release-monorepo"
}

5.3 配置 Token

跟上面的一样,略

5.4 配置 GitHub Actions

yaml 复制代码
name: Release

# 当 master 分支被 push,就会触发
on:
  push:
    branches: [master]
# 权限
permissions:
  contents: write
  issues: write
  pull-requests: write
  packages: write
  id-token: write

jobs:
  release:
    runs-on: ubuntu-latest

    steps:
      - name: 签出代码
        uses: actions/checkout@v3
        with:
          fetch-depth: 0
          persist-credentials: false

      - name: 安装 nodejs
        uses: actions/setup-node@v2.5.2
        with:
          node-version: "20.8.1" # node 版本

      - name: 构建 dist # 构建,根据自己的仓库构建命令来
        run: |
          npm -v
          node -v
          npm install -g pnpm@latest-8
          pnpm config set registry https://registry.npmmirror.com
          pnpm install

      - name: 发布 npm 包
        env:
          GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
        run: |
          pnpm config set registry https://registry.npmjs.org
          pnpm -r --workspace-concurrency=1 exec -- npx --no-install semantic-release -e semantic-release-monorepo

6. monorepo 仓库配置 (gitlab)

同样在上面的基础上

安装一个 gitlab 插件然后指向一下地址就好了

shell 复制代码
npm install --save-dev @semantic-release/gitlab

Senantic 配置文件示例如下

json 复制代码
{
  "branches": ["master"],
  "plugins": [
    "@semantic-release/commit-analyzer",
    "@semantic-release/release-notes-generator",
    ["semantic-release-monorepo-npm-plugin", {
      "isReplaceWorkspace": true
    }],
    [
      "@semantic-release/gitlab",
      {
        "gitlabUrl": "your url"
      }
    ],
    "@semantic-release/changelog",
    [
      "@semantic-release/git",
      {
        "assets": ["package.json", "CHANGELOG.md"],
        "message": "chore(release): v${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
      }
    ]
  ],
  "extends": "semantic-release-monorepo", 
  "debug": true
}

7. 其他

7.1 私有仓库怎么配置

在发版的流程script中加入如下的代码就可以了

bash 复制代码
CI_JOB_TOKEN=${CI_JOB_TOKEN:-"your_default_token"}

{
    echo "//registry.npmmirror.com/:_authToken=${CI_JOB_TOKEN}"
    echo "registry=https://registry.npmmirror.com/"
} | tee .npmrc

7.2 如果我想要跨版本发布怎么办

场景: 仓库的版本是 1.0.0,想要直接升级到 1.4.0 的版本。

这个时候 需要在仓库那里 打一个 tag, 例如 1.3.0,然后commit 一个 feat 的type就可以了

因为 semantic-release 的 逻辑是 会用仓库中 最近的 tag 做基准, 然后进行发布仓库的仓库

总结

使用 Semantic Release 后,你的发版流程将变得极其简单:

  1. 开发功能 → 按规范提交代码
  2. 推送到 master → 自动触发发版流程
  3. 自动完成 → 版本升级、打标签、发布包、创建 Release

如果这篇文章对你有帮助,别忘了给项目点个 ⭐ Star!有问题欢迎在评论区讨论。

相关推荐
讨厌吃蛋黄酥3 分钟前
利用Mock实现前后端联调的解决方案
前端·javascript·后端
zzywxc78725 分钟前
在处理大数据列表渲染时,React 虚拟列表是提升性能的关键技术,但在实际实现中常遇到渲染抖动和滚动定位偏移等问题。
前端·javascript·人工智能·深度学习·react.js·重构·ecmascript
Hello.Reader1 小时前
Rust → WebAssembly 的性能剖析全指南
前端·rust·wasm
前端小巷子1 小时前
Vue 2 Diff 算法
前端·vue.js·面试
奕辰杰5 小时前
关于npm前端项目编译时栈溢出 Maximum call stack size exceeded的处理方案
前端·npm·node.js
JiaLin_Denny7 小时前
如何在NPM上发布自己的React组件(包)
前端·react.js·npm·npm包·npm发布组件·npm发布包
路光.8 小时前
触发事件,按钮loading状态,封装hooks
前端·typescript·vue3hooks
我爱996!8 小时前
SpringMVC——响应
java·服务器·前端
咔咔一顿操作9 小时前
Vue 3 入门教程7 - 状态管理工具 Pinia
前端·javascript·vue.js·vue3
kk爱闹9 小时前
用el-table实现的可编辑的动态表格组件
前端·vue.js