Skip to content

semantic-release 是什么?

semantic-release 是一个自动化版本管理和包发布的工具, 它允许开发者根据语义化版本控制 (Semantic Versioning, SemVer)规范来自动发布软件包, 通过集成到持续集成/持续部署(CI/CD)管道中 semantic-release 可以在每次代码提交时检查是否满足发布新版本的条件, 并且如果满足, 则会自动确定新的版本号、生成变更日志、发布到注册表或仓库

semantic-release 能做什么?

1.准备项目

sh
# 1. 创建一个空的 npm 项目
mkdir semantic-release-demo
cd semantic-release-demo
pnpm init
sh
# 2. 安装 typescript 和 semantic-release 及需要的插件
pnpm i -D semantic-release
pnpm i -D @semantic-release/changelog
pnpm i -D @semantic-release/git

# 安装 typescript, 因为现在大多项目都需要编译, 为了还原真实
# 的开发环境, 且尽量减少配置, 这里使用 typescript 编译
pnpm i -D typescript
jsonc
// 3. 修改 package.json(json文件不能有注释, 我这里添加了注释是为了做笔记)
{
  "name": "semantic-release-demo-a1b2c3", // 注意包名必须是唯一的,不能有重复的
  "version": "0.0.1",
  "main": "dist/index.js",
  "type": "module",
  "scripts": {
    "build": "tsc",
    "release": "semantic-release --debug"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/liaohui5/for-write-note-demo.git" // 填写自己的仓库地址
  },
  "keywords": [],
  "author": "",
  "license": "MIT",
  "description": "",
  "devDependencies": {
    "@semantic-release/changelog": "^6.0.3",
    "@semantic-release/git": "^10.0.1",
    "semantic-release": "^24.2.1",
    "typescript": "^5.7.3"
  }
}
jsonc
// 4. 插件 tsconfig.json 配置文件
{
  "include": ["./src/**/*.ts"],
  "compilerOptions": {
    "target": "es2016",
    "module": "ES2015",
    "rootDirs": ["."],
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "outDir": "./dist",
    "strict": true,
    "skipLibCheck": true
  }
}
js
// 创建 src/index.ts, 代码无所谓, 主要是为了测试 ci/cd
export function for_test_release_ci_cd_func() {
  console.log("1");
}
sh
# 编译并测试
npm run build
sh
# 如果前面都没有问题, 目录应该是这样的
.
├── dist               # 编译后的文件
│   └── index.js
├── package-lock.json
├── package.json
├── src
│   └── index.ts       # 源文件
└── tsconfig.json

2.准备 GitHub 仓库

做这些步骤之前, 请先自行注册并登录 github 账号

1.获取 Github Token 用于 Github Actions

获取 GitHub Token 传送门

get-github-token1get-github-token2get-github-token3

2.创建一个空的 GitHub 仓库, 并配置 GitHub Actions Secrets

set-secrets1set-secrets2

3.准备 npmjs.com 的账号的 token

请先自行注册并登录 npmjs.com

1.获取 npmjs.com Token 用于 Github Actions

123

2.将获取到的 npmjs.com Token 配置到 GitHub Actions Secrets

4

4.配置 semantic-release

在项目目录中创建 release.config.js 文件, 内容如下:

代码没有多少, 主要都是注释...😄😄😄

js
/**
 * @type {import('semantic-release').GlobalConfig}
 */
export default {
  branches: ["main", "next"], // 哪些 git 分支需要触发 semantic-release
  plugins: [
    // 1.安装(pnpm i -D semantic-release) 后, 默认会有这4个插件
    // commit-analyzer/release-notes-generator/npm/github
    [
      // 分析提交记录的 conventional-changelog, 用于生成变更日志
      // https://github.com/semantic-release/commit-analyzer
      "@semantic-release/commit-analyzer",
      {
        // 会根据提交记录的  分析出修改的版本
        // 用于控制修改版本规则 major.minor.patch
        // 推荐阅读: https://www.conventionalcommits.org/zh-hans/v1.0.0/
        // 如果需要修改 major 版本, 只需要在 commit 类型后添加 ! 即可, 如: feat!: xxx
        // 并且在 git 提交消息体中增加: BREAKING CHANGE: xxx, 如:
        // feat!: 增加了xxx功能,优化了xxx性能
        //                                 (注意按照规范, 这里必须有个空行)
        // BREAKING CHANGE: xxx
        releaseRules: [
          { type: "fix", release: "patch" }, // 如果 push 代码时有 fix 类型的提交信息, 则修改版本号为 patch
          { type: "refactor", release: "patch" },
          { type: "perf", release: "patch" },
          { type: "chore", release: "patch" },
          { type: "feat", release: "minor" }, // 如果 push 代码时有 feat 类型的提交信息, 则修改版本号为 minor
        ],
      },
    ],

    // 2.如果需要给插件传入参数, 可以使用数组形式, 数组第一个元素是插件名称,
    // 后面是插件参数, 不需要传参可以用字符串的形式
    // 这个插件的功能是: 使用 conventional-changelog 生成变更日志内容
    // https://github.com/semantic-release/npm
    // https://github.com/semantic-release/release-notes-generator
    "@semantic-release/release-notes-generator",

    // 3.每个发布步骤都是通过可配置的插件实现的, 为了实现更方便的功能, 可以去官网找更多需要的插件:
    // https://semantic-release.gitbook.io/semantic-release/extending/plugins-list
    [
      // 将 Github Actions 生成的提交记录, 写入到 CHANGELOG.md 文件中
      "@semantic-release/changelog",
      {
        changelogFile: "CHANGELOG.md",
      },
    ],

    // 3. 将代码发布到 npmjs.com 仓库
    // https://github.com/semantic-release/npm
    [
      "@semantic-release/npm",
      {
        // npmPublish: 是否发布到 npm 仓库, false: 表示不发布 true:表示发布到 npm 仓库
        // 1.注意需要配置 github secrets
        // 2.会自动修改 package.json 的 version 字段
        // 3.如果开启了 2fa 安全验证码, 需要在生成 npm token 时选择 "Automation" 类型
        npmPublish: true,
      },
    ],

    // 4. 默认情况下 semantic-release 打包发布的版本与 commit 的版本号一致, 但是与 package.json
    // 的版本号不一致, 所以要配置让 github tag 和 package.json 版本号保持一致
    [
      "@semantic-release/git",
      {
        assets: ["dist"],
        message:
          "ci(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}",
      },
    ],

    // 5.这个是发布到 tags 页面的额外资源, 比如一些软件会把构建结果的包放在这里
    // 比如: https://github.com/clash-verge-rev/clash-verge-rev/releases/tag/v2.0.2
    // 除了源码(tar.gz)压缩包之外, 还增加了很多构建好的软件, 如: Clash.Verge_2.0.2_x64-setup.exe
    // 我这里就把这个项目的 typescript 构建好的代码都放在这里
    // https://github.com/semantic-release/git
    [
      "@semantic-release/github",
      {
        assets: ["dist"],
      },
    ],
  ],
};

5. 配置 GitHub Actions workflows

在项目根目录下新建 .github/workflows/release.yml 文件, 内容如下:

yaml
name: Release

on:
  push:
    branches:
      - main
  pull_request:
    types: [closed]

jobs:
  release:
    runs-on: ubuntu-latest
    permissions:
      contents: write # 确保有写入权限
      packages: write # 如果你也在发布包的话
      pull-requests: write # 如果需要处理 PR 相关的事情
    steps:
      - name: download codes
        uses: actions/checkout@v4

      - name: install pnpm
        uses: pnpm/action-setup@v4
        with:
          version: 9

      - name: install node
        uses: actions/setup-node@v4
        with:
          node-version: 20

      - name: install dependencies
        run: pnpm install

      # - name: run unit tests
      #   run: pnpm test

      - name: build
        run: pnpm build

      - name: run semantic-release
        env:
          GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
          NPM_TOKEN: ${{ secrets.NPM_TOKEN }} # 注意这2个变量,要和github screts中配置的一致
        run: pnpm run release

TIP

如果这些步骤都没有问题, 目录结构应该是这样的

txt
.
├── .github
│   └── workflows
│       └── release.yaml
├── dist
│   └── index.js
├── node_modules
├── package-lock.json
├── package.json
├── pnpm-lock.yaml
├── release.config.js
├── src
│   └── index.ts
└── tsconfig.json

6.提交代码

  1. 注意分支必须是 main
  2. 注意提交代码时, 提交信息必须符合规范(才能保证正确生成 changelog)
  3. 提交之后查看 github runners, 会自动发布到 npmjs.com 仓库和 github releases 页面

preview-runner

可以看到没有问题, 已经操作成功了

github-successnpm-success

7. 修改代码再次提交测试

这次不要在 main 分支修改代码, 而是新建一个 next 分支, 修改代码后在提交测试

next-preview

提交之后, 会提示有 pull-request 需要合并到 main 分支, 点击 Compare & pull request 合并

pull-request

合并请求后,会自动触发 release workflow, 然后重新打 tag, 生成 changelog, 上传 assets, 发布到 npm

扩展

一般企业内部非开源的代码不会放到 github 和 npm 上去

如何搭建 npm 私服并且将包发布到私服, 而不是 npmjs.com?

  1. 搭建 npm 私服
  2. 获取 npm 私服的 token, 登录私服后会存在 ~/.npmrc 文件中

verdaccio token

  1. 在 package.json 中添加 publishConfig 字段
json
"repository": {
  "type": "git",
  "url": "git+https://github.com/liaohui5/single-utils-demo"
}
  1. 将 github 配置的 secrets 中的 NPM_TOKEN 修改为 verdaccio 私服的 token

如何使用 gitea/gitlab 完成这些操作?

  1. 只要安装对应代码托管凭他的插件

  2. release.config.js 中的 @semantic-release/github 修改即可

  3. .github/workflows/release.yml 修改为对应平台的 cicd 工作流即可

Released under the MIT License.