Github自动发版机器人semantic-release在monorepo中的配置

之前的文章《Github自动发版机器人semantic-release配置教程》介绍了如何使用 semantic-release 进行代码库的自动发版。今天介绍一下 monorepo 该如何操作。

什么是 monorepo

monorepo 就是多个包在同一个代码库中的情况,例如 vue.js 就是一个 monorepo,它的 package 路径下包含了多个包:

01.png

如果 monorepo 包想要发版,则需要对每个包分别进行处理。由于 git tag 也是整个代码库的,因此对于不同的包需要有所区分。而这一切也可以使用 semantic-release 来完成。

semantic-release-monorepo

想要让 semantic-release 可以处理 monorepo,我们需要使用 semantic-release-monorepo 这个插件。

前面配置 semantic-release 的过程不再重复了,可以看《Github自动发版机器人semantic-release配置教程》来复习。

  1. 直接进行安装:

    1
    npm install -D semantic-release semantic-release-monorepo
  2. 修改配置文件 .releaserc,增加这样一行:

    1
    2
    3
    {
    "extends": "semantic-release-monorepo"
    }

    注意是 extends,不是 plugin。

    此外这里的 .releaserc 也需要每个包的目录下都有一个。

  3. 在流水线中想办法在每个 package 文件夹中执行 semantic-release。

    如果我们同时也使用了 lerna,直接一行命令就可以了:

    1
    lerna exec --concurrency 1 -- npx --no-install semantic-release

经过上面的操作,semantic-release 就增加了对 monorepo 的支持。

下面介绍一下遇到的问题。

一些问题

.releaserc 文件维护

刚才说了 .releaserc 文件需要在每个包目录下都有一个,那么他们的文件内容维护就很重要了,否则每次都要所有配置文件改一遍。

可以在配置文件中使用 extends 字段,可以看到我们也是通过 extedns 来使用 semantic-release-monorepo 的。

extends 的作用是扩展一份配置文件,我们可以在根目录下建立一个共用的配置文件,然后在所有的子包中 extends 这个文件。

version tag 不生效

如果我们之前没用 semantic-release,那么需要让 semantic-release 从某个版本开始发布,否则 semantic-release 默认会从 1.0.0 开始发。

semantic-release 是根据 git tag 来判断当前应该是哪个版本的。当是 monorepo 时,则需要特殊的格式用来区分是哪个包。

semantic-release-monorepo 默认的格式为 ${LERNA_PACKAGE_NAME}-v${version},例如 aaa-v1.2.0

这里有个注意点,就是 tag 对应的 commit 必须要能在发版分支历史中找到,否则会被忽略。

如果你打了个 tag,又执行过 git commit --amend,那么个这个 tag 就不生效了,导致明明有 tag,但是 semantic-release 就是不识别的情况。

commitlint 等校验无法通过,导致 semantic-release 无法提交

如果设置了 commitlint,但是 semantic-release 的提交无法通过,目前没找到好的方法禁止。

可以在流水线中执行 semantic-release 之前,把 git hooks 删掉:

1
rm -rf .git/hooks

如何测试

增加了 semantic-release 之后,如何测试呢?直接提交的话可能会发出我们不想要的版本。

目前没找到好的办法,semantic-release 在执行 cli 工具的时候,有个 debug 选项,但是也只是输出了更多内容,行为是不会变的。

现在的方法是新建了个分支,然后在配置中禁止 npm 发包:

1
2
3
4
5
6
[
"@semantic-release/npm",
{
"npmPublish": false
}
]

这样就可以跳过发包步骤了,提交的 commit 因为是在单独的分支,也比较好处理。但是 tag 还是会被提交上去。