Chainlink 本地 CRE E2E 实战指南:环境生命周期、冒烟/回归测试与自定义拓扑
2026/9/16 13:25:11 网站建设 项目流程

Chainlink 本地 CRE E2E 实战指南:环境生命周期、冒烟/回归测试与自定义拓扑

【免费下载链接】chainlinknode of the decentralized oracle network, bridging on and off-chain computation项目地址: https://gitcode.com/GitHub_Trending/ch/chainlink

本文面向需要在chainlink仓库中本地开发、调试 CRE(Chainlink Runtime Environment,链上/链下工作流运行时)的开发者和测试工程师,系统讲解如何在本地拉起完整的 CRE 环境、运行 CRE 冒烟/回归端到端测试,以及通过自定义拓扑覆盖 limits、feature flags、capability 配置与user_config_overrides的完整方法。读完本文,你将掌握从env stopenv start的完整环境生命周期操作、默认拓扑下的测试执行套路,以及基于CTF_CONFIGS+ 拓扑 TOML 灵活定制测试场景的实战技能。

本文的核心依据是仓库内 Agent Skill 文档 docs/local-cre/agent-skills/local-cre-e2e/SKILL.md,并辅以 Local CRE 环境 CLI 与 CRE 冒烟测试套件 的源码佐证。

适用范围与基本假设

这个 Skill 解决什么问题

local-cre-e2e是一个面向 Agent 与开发者的操作技能说明,适用于以下场景:

  • 启动、停止或重启本地 CRE 环境;
  • 在默认拓扑上运行 CRE 冒烟(smoke)或回归(regression)端到端测试;
  • 针对特定拓扑运行测试;
  • 创建自定义拓扑,以覆盖 limits、flags、capability 配置或user_config_overrides

需要特别注意的是,它面向的是Local CRE 系统级测试工作流,不适用于普通单元测试。

运行前提假设

根据 SKILL.md,使用该工作流需满足四个前提:

  • 仓库根目录是chainlink的检出目录(即当前仓库根);
  • 本地 CRE 命令统一在core/scripts/cre/environment目录下执行;
  • CRE E2E 测试命令统一在system-tests/tests目录下执行;
  • 除非明确知道 harness 支持隔离,否则同一时间只应有一个活动的本地 CRE 环境——这是避免状态串扰的关键纪律。

从源码看,CLI 入口位于 core/scripts/cre/environment/main.go,它把envtopologyexamplesbsobs五组子命令挂到根命令root.RootCmd上,因此所有环境操作都通过go run . <command> [subcommand]的统一形态调用。

默认工作流:从清理到启动一次本地 CRE

第一步:停止可能存在的旧环境

每次开始前,先彻底停止可能残留的本地 CRE 环境,避免新环境与旧状态的端口、容器、状态文件冲突:

cd core/scripts/cre/environment go run . env stop -a

-a--all)会连同所有额外服务一起停止。对应源码见 environment.go 中stop子命令的定义,其提示信息明确写道:"All extra services: stop withgo run . env stop --all"。

第二步:一次性准备环境

如果环境尚未准备过(或需要重新拉取/构建依赖镜像),先执行一次设置:

cd core/scripts/cre/environment go run . env setup

env setupconfigs/setup.toml驱动,负责确保 Job Distributor、Chip Router、Chip Ingress、Chip Config 等托管镜像就绪。它也可以显式指定配置并跳过交互提示:

go run . env setup --config configs/setup.toml --no-prompt

如果需要重建或重新拉取全部前置依赖,env setup支持--purge;需要计费(billing)资产时可加--with-billing(详见 docs/local-cre/getting-started/index.md)。

提示:env setup并非每次都要跑。镜像已经就位、只改拓扑 TOML 的情况下,直接env start即可。SKILL.md 强调它是"环境尚未准备时的一次性步骤"。

第三步:启动默认拓扑

cd core/scripts/cre/environment go run . env start

env start默认读取CTF_CONFIGS指向的拓扑 TOML;未设置时使用默认拓扑workflow-gateway-capabilities-don.toml。对应源码见 environment.go,其中还包含对 Job Distributor 镜像的存在性检查(environment.go),若镜像缺失会提示先执行go run . env setup

快速上手时也可以一步到位使用--auto-setup

go run . env start --auto-setup

第四步(可选):启动可观测性组件

go run . obs up

当你需要日志、追踪或面板来调试工作流事件时,用obs up拉起 observability 辅助栈。SKILL.md 特别指出:

  • 当测试依赖真实 ChIP Ingress 栈,或你想用Red Panda Console调试工作流事件时,在env start上加--with-chip-ingress-stack
  • --with-beholder已废弃(deprecated),等价行为请改用--with-chip-ingress-stack

为什么默认冒烟流程不建议开--with-chip-ingress-stack?docs/local-cre/system-tests/running-tests.md 给出了实现层面的原因:大多数 CRE 冒烟测试会在默认 gRPC 端口50051上启动 ChIP 测试 sink(test sink),而 Chip Ingress 栈的 ChIP ingress 也绑定同一端口。两者抢同一端口会导致测试 sink 启动失败。因此仅在以下情况才启用该栈:

  • 你在跑 Chip Ingress 栈专属的覆盖场景;
  • 你需要用它做调试;
  • 你通过--grpc-port给它换一个端口,把默认50051留给测试 sink。

Chip 相关组件的默认端口布局(来自 docs/local-cre/environment/index.md):

  • 50050:Chip Router admin API;
  • 50051:Chip Router ingress gRPC;
  • 50052:chip-config;
  • 50053:真实 ChIP / Chip Ingress 栈 gRPC。

补充:本地源码构建模式

在默认拓扑基础上,如果你正在开发 node 或某个 capability,docs/local-cre/environment/index.md 还提供了两个高频扩展 flag:

# 节点 + 全部 capability 都用本地工作树构建(含 observability) go run . env start --with-observability --local-node --local-capabilities all # 节点用固定镜像,仅 cron + evm 用本地构建覆盖 go run . env start --local-capabilities cron,evm
  • --local-node:在宿主机交叉编译本地 checkout 的 Chainlink 节点并烘焙进最小镜像,覆盖拓扑中的docker_ctx/image
  • --local-capabilities <names|all>:从本地源码构建指定 CRE capability 并注入节点,未列出的 capability 保留镜像内版本;
  • --capabilities-path <dir>:本地 capabilities 仓库位置(默认$CRE_CAPABILITIES_PATH,否则为~/go/src/github.com/smartcontractkit/capabilities);
  • --local-build-platform <os/arch>:本地构建目标平台(默认linux/<宿主机架构>);
  • --local-node-image <tag>:本地构建节点的镜像标签(默认cre-node:local)。

在默认拓扑上运行 E2E 测试

环境起来后,切到测试目录执行测试。测试命令必须在system-tests/tests下运行(这一目录本身是一个独立的 Go module,见 system-tests/tests/go.mod)。

常规 CRE 冒烟套件

cd system-tests/tests go test ./smoke/cre -timeout 20m -run '^Test_CRE_'

仅 V2 冒烟套件

cd system-tests/tests go test ./smoke/cre -timeout 15m -run '^Test_CRE_V2'

回归测试

cd system-tests/tests go test ./regression/cre -timeout 20m -run '^Test_CRE_'

smoke 与 regression 的划分规则

SKILL.md 给出的经验法则与源码注释完全一致:

  • smoke面向 happy path 与 sanity 覆盖;
  • regression面向边界条件与负向场景。

这一点在测试入口文件 cre_suite_test.go 的注释中写得很明确:

//////////// SMOKE TESTS ///////////// // target happy path and sanity checks // all other tests (e.g. edge cases, negative conditions) // should go to a `regression` package /////////////////////////////////////

测试与环境的衔接机制

你可能好奇:为什么先启动 Local CRE 再跑测试就能对上?这依赖system-tests/tests/test-helpers/before_suite.go中的 helper 逻辑(before_suite.go):

  1. 如果CTF_CONFIGS为空,helper 会把它设置为请求的配置;
  2. 如果本地 CRE 状态文件(Local CRE state file)不存在,helper 会自动执行go run . env start把环境拉起来;
  3. 环境创建完成后,CTF_CONFIGS会被切换为指向本地 CRE 状态文件,而不是原始拓扑 TOML,从而让测试使用已部署的环境。

因此两种工作方式都成立:手动先起环境再跑测试,或直接让 helper 帮你引导环境。

运行特定测试或桶

用窄正则调试单个场景

当你在排查单个场景或某个桶时,使用收窄的正则表达式,并配合-count=1防止测试缓存带来的假结果:

cd system-tests/tests go test ./smoke/cre -timeout 20m -run '^Test_CRE_V2_Suite_Bucket_B$' -count=1 -v

按场景子路径过滤

V2 套件内部按场景组织子测试,可以用/继续下钻:

cd system-tests/tests go test ./smoke/cre -timeout 20m -run 'Test_CRE_V2_Suite_Bucket_B/.*/Vault' -count=1 -v
cd system-tests/tests go test ./regression/cre -timeout 20m -run '^Test_CRE_V2_Consensus_Regression$' -count=1 -v

SKILL.md 强调:重跑易 flaky 或带状态(stateful)的 CRE 场景时,务必加-count=1,跳过 Go 测试缓存,确保从头执行。

桶(Bucket)结构与场景分配

较大的 CRE 冒烟套件按运行时均衡拆分为多个桶,而不是一个巨型测试入口。旧的 V2 套件拆分为:

  • Test_CRE_V2_Suite_Bucket_A
  • Test_CRE_V2_Suite_Bucket_B
  • Test_CRE_V2_Suite_Bucket_C

入口定义在 cre_suite_test.go,每个入口都会先校验桶注册表再执行场景。桶到场景的分配定义在 system-tests/tests/smoke/cre/config/bucketing.go:

包含场景
suite-bucket-aProofOfReserve、HTTPTriggerAction、DONTime、Consensus
suite-bucket-bVaultDON
suite-bucket-cCronChipIngressStack、HTTPActionCRUD、HTTPActionMultiGateway(除非TOPOLOGY_NAMEmulti-gateway,否则跳过)

suiteBucketRegistry是旧 V2 套件场景分配桶的唯一登记处,新增场景时应在此添加,并通过 CI 实测时间重新均衡各桶运行时(bucketing.go 的注释给出了这一维护流程)。

EVM 读取套件还有一套独立的桶注册表,位于 system-tests/tests/smoke/cre/evm/evmread/config/bucketing.go,对应入口:

  • Test_CRE_V2_EVM_Read_HeavyCalls
  • Test_CRE_V2_EVM_Read_StateQueries
  • Test_CRE_V2_EVM_Read_TxArtifacts

使用桶化入口的意义在于:更短的本地反馈回路、更稳定的 CI 运行时长,以及在套件增长时可控地再平衡场景运行时。

本地调试的 VS Code 配置

docs/local-cre/system-tests/running-tests.md 提供了一个可直接套用的 VS Code launch 配置模板:

{ "name": "Launch CRE V2 Bucket A", "type": "go", "request": "launch", "mode": "test", "program": "${workspaceFolder}/system-tests/tests/smoke/cre", "args": ["-test.run", "^Test_CRE_V2_Suite_Bucket_A$"] }

配合 debug 日志跑一个窄测试的常见形态是:

CTF_LOG_LEVEL=debug \ go test ./system-tests/tests/smoke/cre -timeout 20m -run '^Test_CRE_V2_Suite_Bucket_A$'

CTF_LOG_LEVEL=debug会让框架在 setup 与测试执行阶段输出更详细的日志,而窄化的-run保证仍走与完整套件相同的拓扑与工作流 setup。

使用特定拓扑

当测试需要特定的 DON 布局、链或功能配置时,使用非默认拓扑。

流程:停旧环境 → 指定拓扑启动 → 跑目标测试

# 1. 停止现有环境 cd core/scripts/cre/environment go run . env stop -a # 2. 用 CTF_CONFIGS 指定拓扑文件启动 cd core/scripts/cre/environment CTF_CONFIGS=./configs/workflow-gateway-capabilities-don.toml go run . env start # 3. 运行目标测试(TOPOLOGY_NAME 可选) cd system-tests/tests TOPOLOGY_NAME=workflow-gateway-capabilities \ go test ./smoke/cre -timeout 20m -run '^Test_CRE_V2_Suite_Bucket_B$' -count=1 -v

TOPOLOGY_NAME的作用

TOPOLOGY_NAME是可选但很有用的环境变量。为什么有用?因为大量 CRE 套件测试会把拓扑名包含进子测试名、桶标签与日志输出,让结果始终与所测拓扑挂钩。实现上,套件入口在 cre_suite_test.go 直接读取该变量:

var ( parallelEnabled = t_helpers.ParallelEnabled() // topology is used in test names topology = os.Getenv("TOPOLOGY_NAME") )

典型例子:多网关 HTTP action 路由场景需要启动configs/workflow-gateway-capabilities-multi-gateway-don.toml,然后执行:

TOPOLOGY_NAME=workflow-gateway-capabilities-multi-gateway \ go test ./system-tests/tests/smoke/cre -timeout 20m -run '^Test_CRE_V2_HTTP_Action_Multi_Gateway$'

测试助手的拓扑衔接细节

docs/local-cre/system-tests/running-tests.md 汇总了冒烟套件使用的核心环境变量:

  • CTF_CONFIGS:启动前指向拓扑 TOML,启动后被 helper 自动切换为生成的 Local CRE 状态文件(本地运行由before_suite.go完成切换);
  • TOPOLOGY_NAME:进入测试名、桶标签与日志输出;
  • CTF_LOG_LEVEL=debug:启用更详细的框架日志;
  • CTF_JD_IMAGE:固定 Job Distributor 镜像,避免默认本地镜像选择;
  • CTF_CHAINLINK_IMAGE:固定 Chainlink 节点镜像,system-tests/lib/cre/environment/dons.go 在选择节点镜像时直接检查该变量。

并行执行(可选)

并行测试是显式开启的,设置环境变量即可:

CRE_TEST_PARALLEL_ENABLED=1

注意冒烟套件并不会盲目地对所有用例开t.Parallel()——runner 在cre_suite_test.go中只对确定可以安全共存的场景启用并行。

创建自定义拓扑

当你想覆盖以下内容时,就需要创建自定义拓扑:

  • limits;
  • feature flags;
  • capability 配置;
  • DON 组成;
  • 额外的数据源;
  • user_config_overrides

工作流

  1. core/scripts/cre/environment/configs/里挑一个最接近现有需求的拓扑;
  2. 复制为同目录下的新文件;
  3. 只改场景需要的字段
  4. CTF_CONFIGS=<新拓扑>启动本地 CRE;
  5. 先只跑相关测试。

示例:

cd core/scripts/cre/environment/configs cp workflow-gateway-capabilities-don.toml workflow-gateway-capabilities-don-my-override.toml

然后启动并测试:

cd ../ CTF_CONFIGS=./configs/workflow-gateway-capabilities-don-my-override.toml go run . env start
cd ../../../system-tests/tests TOPOLOGY_NAME=workflow-gateway-capabilities-my-override \ go test ./smoke/cre -timeout 20m -run '^Test_CRE_V2_Suite_Bucket_B$' -count=1 -v

默认拓扑长什么样

理解默认拓扑是定制的基础。workflow-gateway-capabilities-don.toml(configs/workflow-gateway-capabilities-don.toml)是一个 multi-don 拓扑,包含 3 个 nodeset:

  • workflow:4 个节点,don_types = ["workflow"],capabilities 含cronhttp-actionhttp-triggerconsensusdon-timeevm-1337,同时连接 1337/2337 两条 anvil 链(注释解释:即使不用 2337 上的 capability,bootstrap 节点上仍要创建 capability DON 的 bootstrap job);
  • capabilities:4 个节点,don_types = ["capabilities"]exposes_remote_capabilities = true,capabilities 含vaultevm-2337(连接 1337 是为了用链上节点地址在 gateway 配置中标识节点,这是 vault 与 gateway 型 HTTP capability 的要求);
  • bootstrap-gateway:1 个节点,don_types = ["bootstrap", "gateway"]override_mode = "each",通过custom_ports = ["5002:5002","15002:15002"]暴露 web API capabilities 端口(5002)与 vault 端口(15002)。

其他公共段包括[chip_router]、两条[[blockchains]](anvil 1337/2337)、[jd](Job Distributor 镜像与 CSA 加密密钥)、[fake]/[fake_http](mock 服务端口)、[infra](docker 或 kubernetes)。

仓库现有拓扑的全量清单可参考 core/scripts/cre/environment/docs/TOPOLOGIES.md(该文件由go run . topology generate自动生成),涵盖:

  • workflow-don-solana.toml(multi-don,3 DON)
  • workflow-gateway-capabilities-multi-gateway-don.toml(multi-don,4 DON)
  • workflow-gateway-don-aptos.toml(single-don,2 DON)
  • workflow-gateway-don-cache-test.toml/workflow-gateway-don-cache-soak-test.toml
  • workflow-gateway-don-grpc-source.toml
  • workflow-gateway-don.toml(single-don,2 DON)
  • workflow-gateway-sharded-5-dons.toml(sharded,7 DON)
  • workflow-gateway-sharded-don.toml(sharded,3 DON)

快速查看清单可运行go run . topology list

覆盖指南

制作自定义拓扑时的纪律(SKILL.md 原文要点):

  • 保持 diff 小而目的明确;
  • 优先复制最近似的拓扑,而不是从零新建;
  • 使用能表明改动内容的描述性文件名;
  • 除非测试需要,不要改动无关的镜像、链或 capability;
  • 如果拓扑只用于一次性本地检查,保留在本地,避免加进 CI。

典型的覆盖点包括:

  • nodesets.capability_configs(capability 配置覆盖);
  • nodesets.user_config_overrides(节点用户配置覆盖);
  • CRE feature flags;
  • 额外的 mock 或支持服务端点。

capability_configs 的完整覆盖语义

仓库提供了一个专门讲解覆盖写法的示例拓扑 configs/examples/workflow-don-overrides.toml,其中对capability_configs的关键语义写得很清楚:

覆盖某个 capability 配置时,必须提供该 capability 的全部值——不支持部分覆盖。如果你指定了某个 key,整个CapabilityConfig会原样使用,不会与默认值合并;默认值只对完全没有配置的 capability 生效。

示例(链级 EVM 覆盖,LogTriggerPollInterval以纳秒为单位):

[nodesets.capability_configs.evm-1337.values] LogTriggerPollInterval = 2500000000 # 2.5s in nanoseconds # 其他 capability 同样可覆盖,例如: # [nodesets.capability_configs.http-action] # binary_name = "http_action" # [nodesets.capability_configs.http-action.values] # IncomingGlobalBurst = 20

user_config_overrides 的边界与写法

同一示例还演示了user_config_overrides的用法,并给出一个重要的实现约束:[Telemetry][Billing][Metering]是框架托管的段,会被框架拒绝(validateUserConfigOverrides,位于system-tests/lib),因为框架会自己生成这些配置,把遥测指向 chip-router 以便下游订阅者(如 CI test sink)看到全部事件。要启用 metering,应设置 nodeset 的enable_metering = true

[[nodesets.node_specs]] roles = ["plugin"] # override_mode = "all" 时,DON 内所有节点都是 plugin 角色 [nodesets.node_specs.node] image = "chainlink-tmp:latest" user_config_overrides = """ [Log] Level = 'debug' JSONConsole = true # 删掉这段可以让工作流从远程源下载 [CRE.WorkflowFetcher] URL = "file:///home/chainlink/workflows" """

重启与清理

干净重启

当改动拓扑或底层配置时,优先完整 stop/start,不要假设运行中的环境会自动收敛:

cd core/scripts/cre/environment go run . env stop -a CTF_CONFIGS=./configs/<topology>.toml go run . env start

这也是 SKILL.md 故障排查的第一条:如果测试意外使用了错误的拓扑,停止 Local CRE 并按预期的CTF_CONFIGS重启。

用完后清理

cd core/scripts/cre/environment go run . env stop -a

彻底重置

当保存的状态或缓存产物看起来不一致时,使用 purge:

go run . env state purge

state子命令组定义在 environment.go,包含list(列出环境中所有状态文件)与purge(清空所有状态与缓存文件)。Local CRE 把环境状态持久化到仓库本地的状态文件中,这正是冒烟测试 helper 能检测到已存在环境、避免重复创建的原因(详见 docs/local-cre/environment/index.md)。需要完全重置时,先 purge 状态,再重新 setup/start。

故障排除

SKILL.md 的四条速查

  • 测试意外使用了错误拓扑→ 停止 Local CRE,按预期的CTF_CONFIGS重启;
  • 套件似乎在复用陈旧状态→ 用-count=1重跑;
  • 测试依赖日志、追踪或面板→ 执行go run . obs up
  • 拓扑相关的失败看似与测试无关→ 先确认环境确实是以预期拓扑启动的。

测试逻辑尚未执行就失败的清单

docs/local-cre/system-tests/running-tests.md 给出了"测试还没跑到测试逻辑就失败"时的五步检查:

  1. 确认CTF_CONFIGS
  2. 确认 Local CRE 状态文件有效;
  3. 确认所需镜像存在;
  4. 重跑go run . env setup
  5. 用 debug 日志重跑。

环境启动阶段的高频故障

docs/local-cre/environment/index.md 归纳了环境侧最常见的四类失败:

  • Chainlink 节点数据库迁移失败;
  • Docker 镜像找不到;
  • Docker 无法下载所需公共镜像;
  • gh缺失或未认证(构建需要私有插件访问的镜像时必需)。

对应的处理顺序:重跑go run . env setup→ 确认镜像访问与认证 → 状态陈旧则 purge 状态 → 需要更多信号则带 observability 或 Chip Ingress 栈重启。

超时经验

实践中的超时经验(来自 docs/local-cre/system-tests/running-tests.md):

  • 从源码构建镜像时,给约20 分钟的预算;
  • 使用预构建镜像时运行时长会短得多。

深入参考

本文基于的 SKILL 文档还推荐了以下仓库内资料,供深入阅读:

  • docs/local-cre/index.md:Local CRE 文档总览与导航;
  • docs/local-cre/system-tests/index.md:CRE 系统测试的结构、smoke/regression 划分与 helper 衔接机制;
  • docs/local-cre/system-tests/running-tests.md:本地、Kubernetes 与 CI 视角下的运行细节、环境变量与桶化选择;
  • docs/local-cre/getting-started/index.md:从干净 checkout 到跑起第一个环境的最短路径;
  • docs/local-cre/environment/index.md:环境生命周期命令、env start全部 flag 与 Chip 端口布局;
  • core/scripts/cre/environment:环境 CLI 源码(main.go命令注册、environment/生命周期实现、configs/拓扑目录);
  • system-tests/tests/smoke/cre:冒烟套件源码(cre_suite_test.go桶入口、config/bucketing.go桶注册表)。

【免费下载链接】chainlinknode of the decentralized oracle network, bridging on and off-chain computation项目地址: https://gitcode.com/GitHub_Trending/ch/chainlink

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询