Chapter 08

CI/CD 集成

biome ci 是专为流水线设计的严格模式——任何格式化差异也算失败、输出 GitHub 原生注释、与 PR diff 结合做到"不过 lint 就不给合"。

8.1 biome ci:为什么不是 biome check

两者主要差异:

biome checkbiome ci
意图本地开发CI 流水线
支持 --write❌(CI 不该改代码)
格式化差异报告即可直接算 error
reporter 默认人类可读GitHub Actions 格式
并发自动--max-diagnostics 防日志爆炸

简言之:CI 里就是 biome ci .,别用 check

8.2 GitHub Actions 范例

# .github/workflows/lint.yml
name: Lint

on:
  push:
    branches: [main]
  pull_request:

jobs:
  biome:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with: { fetch-depth: 0 }   # --changed 需要历史

      - uses: biomejs/setup-biome@v2
        with:
          version: latest

      - run: biome ci .
        # PR 里 biome 会用 GitHub annotation 格式,
        # 每个错误都显示在 PR 的 Files changed 标签页对应行
setup-biome 也有 npm 替代

如果已有 @biomejs/biome devDep,直接 pnpm install --frozen-lockfile && pnpm biome ci . 即可——省掉额外 action,版本与代码完全一致。

8.3 只 lint 改动文件(超大 monorepo)

- name: Lint changed only
  run: biome ci --changed --since=origin/main .

百万行仓库可以把 lint 时间从 8s 压到 0.6s。注意 fetch-depth: 0 必须,否则 git 找不到 origin/main

8.4 Reporter 格式

biome ci --reporter=github    # GitHub Actions annotation
biome ci --reporter=gitlab    # GitLab CI
biome ci --reporter=junit     # JUnit XML,Jenkins/CircleCI
biome ci --reporter=json      # 机器处理
biome ci --reporter=summary   # 人类简报

--reporter=junit 的输出保存成 artifact 并上传,可在 Jenkins、CircleCI 里看到每个违规项作为"测试失败"展示。

8.5 GitLab CI 范例

# .gitlab-ci.yml
lint:
  image: node:20-alpine
  script:
    - corepack enable
    - pnpm install --frozen-lockfile
    - pnpm biome ci --reporter=gitlab .
  artifacts:
    reports:
      codequality: gl-code-quality-report.json

8.6 缓存加速

Biome 内置基于文件哈希的缓存,位置 ./node_modules/.cache/biome/。在 GitHub Actions 里:

- uses: actions/cache@v4
  with:
    path: node_modules/.cache/biome
    key: biome-${{ hashFiles('biome.json') }}-${{ hashFiles('**/*.ts','**/*.tsx') }}
    restore-keys: |
      biome-${{ hashFiles('biome.json') }}-

第二次同一分支跑 CI 时,未变更文件直接读缓存;体感差别:6s → 0.4s。

8.7 pre-commit / husky

# .husky/pre-commit
#!/usr/bin/env sh
npx biome check --staged --write --no-errors-on-unmatched \
  && git update-index --again

git update-index --again:Biome 改过的文件自动加回 index,避免"改完却没提交"。

8.8 pre-push:最后一道栅栏

# .husky/pre-push
npx biome ci .

CI 以外再本地挡一次:推到远端前如果有任何 diagnostic,直接拦下——省下一轮 CI 时间。

8.9 自动 PR 注释:Danger/custom bot

如果你希望 PR 评论里看到 lint 摘要,可用 Danger JS + biome 的 JSON reporter:

// dangerfile.ts
import { execSync } from 'node:child_process';
const out = execSync('biome ci --reporter=json . || true').toString();
const { summary, diagnostics } = JSON.parse(out);
if (diagnostics.length > 0) {
  markdown(`### Biome 报告 (${summary.errors} errors)\n...`);
}

8.10 常见 CI 陷阱

小结

CI 里只要 biome ci . 一行;加 --changed --since=origin/main 应对大仓库;用缓存 action 把重复运行拉到亚秒级;客户端用 husky 提前挡一层。配完这条流水线,团队就告别了"合了才发现 lint 挂"的尴尬。下一章进入 monorepo 专题。