跳到主要内容

12. 工程化:测试、边界、CI 与发布

12.1 测试不是一层

n8n 的测试按风险面分层:

层次关注点例子
单元测试函数、解析器、图算法、错误分类packages/core/src/**/__tests__
节点测试description、execute、版本兼容packages/nodes-base/nodes/*/test
集成测试DB、Redis、credential、runnerpackages/cli/src/** integration tests
E2E编辑器、Webhook、浏览器和真实容器packages/testing/playwright
评估/基准AI agent、MCP、性能、mutation health@n8n/instance-ai@n8n/benchmark

读一个新模块时,测试目录经常比实现更快说明它的边界:输入格式、错误语义、并发策略和外部依赖都在测试名里暴露出来。

12.2 边界检查

根脚本包含 boundaries:checkcheck:workspace-private-depscheck:zod-peer-deps 和 skill link 检查。它们解决的是“代码能编译,但架构已经漂移”的问题:

  • 包不应偷偷依赖不允许的内部模块。
  • private workspace package 不应被错误发布。
  • peer dependency 和版本 catalog 要保持一致。
  • agent/skill 的同步链接不应断裂。

这说明 n8n 把 monorepo 的结构约束视为产品可靠性的一部分。

12.3 CI 工作流的分层

.github/workflows 按前缀分成 ci-*test-*build-*release-*sec-*util-*。主 PR 工作流先做路径过滤,再复用 unit/typecheck/lint/e2e/security 工作流;release workflow 负责 npm、Docker、GitHub Release、SBOM、Sentry 等下游发布。

.github/WORKFLOWS.md 本身是一份架构文档,适合在源码阅读后对照“哪些变更会触发哪些验证”。

12.4 构建产物和 Docker

源码包构建和最终 n8n 可运行包不是同一个动作:Turbo 先构建 workspace,scripts/build-n8n.mjs 再聚合运行时需要的包、节点、前端静态资源和 CLI 入口;Docker 脚本把它们装进镜像并执行 smoke test。

这条链解释了为什么修改某个 package 后只运行 package unit test 还不够:若改变 exports、节点打包、前端静态资源或 Docker 路径,最终应用构建可能暴露问题。

12.5 版本和兼容性

n8n 需要同时兼容:

  • 历史 workflow JSON 和 node version。
  • 数据库迁移和已存在的 execution。
  • 社区节点与 npm 生态。
  • queue worker 与 main 的协议。
  • 前后端 API 与旧浏览器状态。

因此 release 不是简单 bump version,而是数据库、节点、Docker、npm、SBOM、telemetry 和文档/变更日志的联合发布。

12.6 设计取舍

路径过滤 CI降低大 monorepo 的反馈时间;代价是过滤规则本身也必须测试,否则会出现“改了核心却没有跑关键检查”。

可复用 workflow减少复制粘贴,代价是调用方参数、secret、artifact 和权限边界更难追踪。

多层测试覆盖不同故障模式,代价是本地完整验证昂贵,所以 test:affected、Turbo cache 和 agent setup 负责把验证成本压缩到可接受范围。