探索 monorepo 发布应用的 ci 流程

3,188 阅读3分钟

背景

前些日子,笔者通过 pnpm + workspace 勉强搭建起一个简易版本的 monorepo,但是却在如何发布某一个应用犯了难。假如我这个 monorepo 里面有两个应用 a 和 b , 我对 a 有改动,那我 git push 之后,gitlab ci 咋知道运行 a 的 build 命令?

方案

手动硬编码

最简单的方法就是手动简单指定在哪个应用内运行 build 命令,pnpm 提供 filter 选项供你指定应用, 那我就可以在 monorepo 的根 package.json 里面添加如下 script, 构建 a 应用。

"build": "pnpm --filter a run build"

这样的方式简单,缺点就是不灵活,不同的应用要使用不同的 build 脚本,如果项目比较多,会比较麻烦,所以还是希望能有自动的方案

自动检测项目更改

现在的问题是如何在 gitlab ci 检测到哪个项目更改了 ?

可以参考这边文章: On Monorepos and the Deployment With GitLab CI/CD | by Onno Gabriel | The Startup | Medium

我们可以通过设置 only/change 条件,利用 path 的 正则表达式定位到哪些文件有更改,gitlab ci 设置如下:

build:feature:
  script:
    - pnpm i
    - pnpm --filter a run build:test
  only:
    refs:
      - branches
    changes:
      - 'apps/a/**/*.{vue,js,ts,png,json}'
      - 'apps/a/*'

可以看到当 apps/a 下面的文件有更改时, gitlab ci 就会运行 build:feature 的 script

这种方法勉强可以自动化,但是每多一个应用就要在 gitlab ci 里面添加一段上面检测对应应用更改的代码。并且没有解决如果 monorepo 下 a,b 应用同时修改编译哪个应用的问题,只能同事之间约定好,一次修改只改一个应用。

利用预定义变量

可以参考 基于 Monorepo + 前后端未完全分离的 gitlab CI/CD 实践 - 掘金

gitlab 文档里面有一个 trigger api, 该 api 可以触发 gitlab 的 pipeline , 其可以携带参数 variable

文中作者通过搭建一个构建平台,列出当前环境所有子项目列表,可选构建,点击确定后发送 trigger 请求触发 gitlab 的 pipeline

当然,笔者的团队可能没有这个人力去搭建一个构建平台,但是可以借鉴这个思路,通过注入事先设置预定义的变量,指定运行某个包下的 build 脚本。

因为各个前端团队基建不同,笔者在这里也是举个例子,比如可以在 gitlab ci/cd 界面,选择 Run Pipeline ,在该界面可以注入 Variables , 比如直接注入变量 PKG_NAME="a",对应的 gitlab ci 的 build 脚本如下:

build:feature:
  script:
    - pnpm i
    - pnpm --filter $PKG_NAME run build:test
  only:
    refs:
      - branches

其他

笔者在 monorepo 方面也是个小白,如果引入 Nx , rush, lerna 等 monorepo 管理方案也是担心自己 hold 不住,自己对 monorepo 的理解也不够深刻,如果有更好的方案欢迎在评论区和我交流

本文正在参加「金石计划」