12. 工程化:测试、边界、CI 与发布
12.1 测试不是一层
n8n 的测试按风险面分层:
| 层次 | 关注点 | 例子 |
|---|---|---|
| 单元测试 | 函数、解析器、图算法、错误分类 | packages/core/src/**/__tests__ |
| 节点测试 | description、execute、版本兼容 | packages/nodes-base/nodes/*/test |
| 集成测试 | DB、Redis、credential、runner | packages/cli/src/** integration tests |
| E2E | 编辑器、Webhook、浏览器和真实容器 | packages/testing/playwright |
| 评估/基准 | AI agent、MCP、性能、mutation health | @n8n/instance-ai、@n8n/benchmark |
读一个新模块时,测试目录经常比实现更快说明它的边界:输入格式、错误语义、并发策略和外部依赖都在测试名里暴露出来。
12.2 边界检查
根脚本包含 boundaries:check、check:workspace-private-deps、check: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 负责把验证成本压缩到可接受范围。