logo
0
0
WeChat Login

cnbexec - CNB 工作流本地执行器

基于 llms-full.txt.cnb.yml / CNB 流水线规则实现的 Go 本地执行器。用于在本地环境中模拟和调试 CNB CI/CD 流水线,无需依赖 CNB 平台即可验证流水线配置的正确性。

核心能力

配置解析

  • 完整支持 .cnb.yml 配置格式
  • include 指令:支持字符串、对象、config 内联形式,智能合并策略
    • 数组 + 数组 → 追加
    • 对象 + 对象 → 递归合并
    • 对象 + 数组 / 数组 + 对象 → 数组优先
  • !reference 跨文件引用,最多递归 10 层
  • 兼容 YAML 锚点、别名、对象合并 <<

触发与选择

  • 分支匹配:普通分支、glob 模式、$ fallback
  • 事件匹配:从分支下选择对应事件的流水线
  • 同一事件下多条 pipeline 并行执行

Pipeline / Stage / Job 语义

  • stages 串行执行
  • Stage 内 jobs
    • 数组格式 → 串行执行
    • 对象格式 → 并行执行
  • 支持脚本任务、插件任务、内置任务
  • 支持 retry 重试机制
  • 支持 allowFailure 允许失败
  • 支持 lock 本进程内锁控制
  • 支持 failStages / endStages 流程控制
  • 支持 exit 78 中断流水线

环境变量管理

  • env / imports 环境变量注入
  • imports 支持 YAML / JSON / key=value / 证书文件
  • 深层属性自动平铺
  • $VAR / ${VAR} 变量替换
  • exports 导出后续 Job 可见的环境变量
  • 解析 ##[set-output key=value] 输出

Docker 运行环境

  • pipeline.docker.image 全局镜像配置
  • pipeline.docker.build Docker 构建支持
    • 根据 Dockerfile + versionBy + buildArgs 计算本地缓存 tag
    • by 控制 build context 可见文件
  • stage.image / job.image 层级镜像覆盖
  • 插件任务自动将 settings 转为 PLUGIN_* 环境变量
  • 支持 docker.volumes 基础映射与 copy-on-write 模式

内置任务

  • cnb:await - 等待异步任务完成
  • cnb:resolve - 解析异步任务结果
  • cnb:read-file - 读取文件内容
  • cnb:destroy-token - 销毁认证令牌(本地近似实现)
  • cnb:apply - 同仓本地递归触发
  • cnb:trigger - 触发其他流水线(当前仓本地近似实现)
  • docker:cache - Docker 缓存管理(noop 占位)

项目结构

cnbexec/ ├── cnbexec.go # 公共 API 入口 ├── cmd/cnbexec/ # CLI 命令行工具 ├── internal/ │ ├── config/ # 配置加载与解析 │ ├── engine/ # 核心执行引擎 │ ├── model/ # 数据模型定义 │ └── util/ # 工具函数 ├── templates/ # 测试模板集 └── llms-full.txt # CNB 规范文档

使用方式

作为 Go 模块调用

package main import ( "context" "fmt" "cnbexec" ) func main() { // 创建执行器 exec, err := cnbexec.New("/path/to/repo") if err != nil { panic(err) } // 执行流水线 result, err := exec.Execute(context.Background(), cnbexec.ExecRequest{ ConfigPath: ".cnb.yml", Branch: "main", Event: "push", }) if err != nil { panic(err) } fmt.Printf("Build status: %s\n", result.Status) }

配置选项

// 设置默认 Docker 镜像 exec, err := cnbexec.New(workspace, cnbexec.WithDefaultImage("alpine:3.20"), ) // 自定义 HTTP 客户端(用于远程 include) exec, err := cnbexec.New(workspace, cnbexec.WithHTTPClient(httpClient), )

直接使用配置对象

// 如果配置已加载到内存,可直接执行 cfg, _ := loader.Load(" .cnb.yml") result, err := exec.ExecuteConfig(ctx, cfg, req)

命令行执行

# 基础执行 go run ./cmd/cnbexec \ --config .cnb.yml \ --workspace . \ --branch main \ --event push # 指定变更文件(用于 ifModify 判断) go run ./cmd/cnbexec \ --config .cnb.yml \ --branch feature/new-api \ --event merge_request \ --changed package.json \ --changed src/main.go # 注入额外环境变量 go run ./cmd/cnbexec \ --config .cnb.yml \ --branch main \ --event push \ -e FOO=bar \ -e BAZ=qux # 设置默认镜像(当 pipeline/job 未声明 image 时使用) CNB_EXEC_DEFAULT_IMAGE=alpine:3.20 go run ./cmd/cnbexec \ --config .cnb.yml

CLI 参数说明

参数默认值说明
--config.cnb.ymlCI 配置文件路径
--workspace.工作区根目录
--branchmain触发分支
--eventpush触发事件
--default-branchmain默认分支(用于新分支判断)
--new-branchfalse标记为新分支事件
--commit-提交 SHA
--before-前一提交 SHA
--changed-变更文件列表(可重复)
--default-imageCNB_EXEC_DEFAULT_IMAGE 环境变量默认 Docker 镜像
-e-额外环境变量 KEY=VALUE(可重复)

执行结果

命令行执行会输出 JSON 格式的执行结果:

{ "Status": "success", "Pipelines": [ { "Name": "Build and Test", "Key": "build-and-test", "Status": "success", "AllowFailure": false, "FailedStage": "", "LastJobExports": { "VERSION": "1.2.3" } } ] }

状态码:

  • success - 所有流水线执行成功
  • error - 有流水线执行失败(且不允许失败)
  • cancel - 流水线被取消
  • skipped - 无匹配的流水线

测试模板

项目提供了完整的测试模板集,位于 templates/ 目录:

模板用途覆盖功能
templates/minimal最小可运行示例docker.imageenvscriptexports
templates/builtin内置任务回归cnb:awaitcnb:resolvecnb:read-filecnb:applycnb:trigger
templates/control-flow流程控制ififModifyifNewBranchretryallowFailurefailStagesendStageslocktimeout
templates/full-supported完整能力展示include、reference、docker.build、插件任务、内置任务、流程控制组合

运行模板测试

# 运行所有回归测试 go test ./... # 运行特定模板测试 go test ./internal/engine -run TestTemplate

推荐验证顺序

  1. 先跑 minimal,验证最基本执行链路
  2. 再跑 builtin,验证内置任务回归
  3. 再跑 control-flow,验证条件与失败控制
  4. 最后跑 full-supported,验证完整能力组合

限制与后续计划

当前实现为本地执行器原型,以下 CNB 平台特性尚未完全复刻或为近似实现:

平台级特性

  • 权限模型CNB_TOKEN、可信/不可信事件隔离、密钥仓库 allow 校验
  • SCM 集成:PR 预合并 checkout、tag/web/api/cron 的真实取代码逻辑
  • 服务注入service:docker / service:vscode 的完整平台注入行为

执行语义差异

  • await/resolve:死锁检测仅做了基础等待,未实现完整拓扑检测
  • ifModify 检测breakIfModify / skipIfModify 还没有接真实 SCM 源分支更新检测
  • Docker 生命周期:目前以每个 job 独立 docker run 近似,不是平台内同一长生命周期容器
  • devcontainer:仅保留配置位,未完整展开

内置任务覆盖

  • 官方内置任务未全部覆盖(当前已实现 7 个核心任务)

开发要求

  • Go 1.26.2+
  • 依赖:
    • golang.org/x/sync - 并发控制
    • gopkg.in/yaml.v3 - YAML 解析

注意:本项目是根据 llms-full.txt 规范文档实现的本地执行器,主要用于本地开发和测试。生产环境请使用 CNB 官方平台。

About

这是一个基于自定义工作流自动创建的临时仓库

Language
Go99.8%
Dockerfile0.2%