--- url: /W3C/index.md --- > For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /W3C/index.md. # 联盟动态总览 ## NEWS ### [记录大事件](/W3C/news/news.md) ### [Pages.Top 页界之巅 项目正式启动](/W3C/news/pages.md) ### [W3C技术联盟正式成立](/W3C/news/w3c.md) ## 发展历程 ### [发展历程](/W3C/history/1.md) - [整理中...](/W3C/history/1.md#整理中) - [发展历程整理中...](/W3C/history/1.md#发展历程整理中) ### [发展历程](/W3C/history/2.md) - [整理中...](/W3C/history/2.md#整理中) - [发展历程整理中...](/W3C/history/2.md#发展历程整理中) --- url: /W3C/news/news.md --- > For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /W3C/news/news.md. # 记录大事件 暂无内容... --- url: /W3C/news/pages.md --- > For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /W3C/news/pages.md. # 记录大事件 Pages.Top 页界之巅 项目正式启动... [https://pages.top](https://pages.top) --- url: /W3C/news/w3c.md --- > For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /W3C/news/w3c.md. # W3C技术联盟正式成立 W3C技术联盟正式成立 --- url: /W3C/history/1.md --- > For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /W3C/history/1.md. # 发展历程 ## 整理中... ## 发展历程整理中... --- url: /W3C/history/2.md --- > For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /W3C/history/2.md. # 发展历程 ## 整理中... ## 发展历程整理中... --- url: /cnb/index.md --- > For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /cnb/index.md. # CNB文档总览 ## 指南 ### [创建你的第一个仓库](/cnb/guide/first-repo.md) - [1. 创建组织](/cnb/guide/first-repo.md#1-创建组织) - [2. 创建仓库](/cnb/guide/first-repo.md#2-创建仓库) - [3. 初始化仓库](/cnb/guide/first-repo.md#3-初始化仓库) ### [迁移工具](/cnb/guide/migration-tools.md) - [CNB Code Import](/cnb/guide/migration-tools.md#cnb-code-import) - [Git Sync](/cnb/guide/migration-tools.md#git-sync) ### [角色权限](/cnb/guide/role-permissions.md) ### [访问令牌](/cnb/guide/access-token.md) - [访问令牌申请](/cnb/guide/access-token.md#访问令牌申请) - [访问代码仓库](/cnb/guide/access-token.md#访问代码仓库) - [访问制品库](/cnb/guide/access-token.md#访问制品库) - [访问OPENAPI](/cnb/guide/access-token.md#访问openapi) ## 代码托管 ### [产品介绍](/cnb/repo/intro.md) - [核心功能](/cnb/repo/intro.md#核心功能) ### [密钥仓库](/cnb/repo/secret.md) - [创建密钥仓库](/cnb/repo/secret.md#创建密钥仓库) - [密钥仓库核心特点](/cnb/repo/secret.md#密钥仓库核心特点) - [在流水线中引用密钥仓库文件](/cnb/repo/secret.md#在流水线中引用密钥仓库文件) - [最佳实践](/cnb/repo/secret.md#最佳实践) ### [元数据](/cnb/repo/annotations.md) - [什么是元数据?](/cnb/repo/annotations.md#什么是元数据) - [存储形式](/cnb/repo/annotations.md#存储形式) - [如何查看元数据?](/cnb/repo/annotations.md#如何查看元数据) - [如何操作元数据?](/cnb/repo/annotations.md#如何操作元数据) ### [ISSUE 模板](/cnb/repo/issue-template.md) - [使用要求](/cnb/repo/issue-template.md#使用要求) - [模板格式](/cnb/repo/issue-template.md#模板格式) ### [分类标签](/cnb/repo/label.md) - [导入CNB公开仓库的标签](/cnb/repo/label.md#导入cnb公开仓库的标签) ### [UI 定制](/cnb/repo/settings.md) - [配置文件说明](/cnb/repo/settings.md#配置文件说明) - [抄了么按钮](/cnb/repo/settings.md#抄了么按钮) ## 云原生构建 ### [云原生构建介绍](/cnb/build/intro.md) - [高性能](/cnb/build/intro.md#高性能) ### [快速开始](/cnb/build/quick-start.md) - [编写你的第一条流水线](/cnb/build/quick-start.md#编写你的第一条流水线) - [配置说明](/cnb/build/quick-start.md#配置说明) - [语法说明](/cnb/build/quick-start.md#语法说明) - [最佳实践](/cnb/build/quick-start.md#最佳实践) ### [构建触发规则](/cnb/build/trigger-rule.md) - [触发分支](/cnb/build/trigger-rule.md#触发分支) - [触发事件](/cnb/build/trigger-rule.md#trigger-event) - [代码版本选择](/cnb/build/trigger-rule.md#代码版本选择) ### [配置文件](/cnb/build/configuration.md) - [简介](/cnb/build/configuration.md#简介) - [存放位置](/cnb/build/configuration.md#存放位置) - [基本语法结构](/cnb/build/configuration.md#基本语法结构) - [配置文件版本选择](/cnb/build/configuration.md#配置文件版本选择) - [语法检查和自动补全](/cnb/build/configuration.md#语法检查和自动补全) - [配置复用](/cnb/build/configuration.md#配置复用) ### [流水线语法](/cnb/build/grammar.md) - [基本概念](/cnb/build/grammar.md#基本概念) - [Pipeline](/cnb/build/grammar.md#pipeline) - [Stage](/cnb/build/grammar.md#stage) - [Job](/cnb/build/grammar.md#job) ### [构建环境](/cnb/build/build-env.md) - [配置方式](/cnb/build/build-env.md#配置方式) - [使用案例](/cnb/build/build-env.md#使用案例) ### [构建集群](/cnb/build/build-node.md) - [配置方式](/cnb/build/build-node.md#配置方式) ### [环境变量](/cnb/build/env.md) - [声明环境变量](/cnb/build/env.md#声明环境变量) - [导入环境变量](/cnb/build/env.md#导入环境变量) - [变量名限制](/cnb/build/env.md#变量名限制) - [导出环境变量](/cnb/build/env.md#导出环境变量) - [使用环境变量](/cnb/build/env.md#使用环境变量) - [限制](/cnb/build/env.md#限制) ### [默认环境变量](/cnb/build/build-in-env.md) - [基础变量](/cnb/build/build-in-env.md#基础变量) - [提交类变量](/cnb/build/build-in-env.md#提交类变量) - [仓库类变量](/cnb/build/build-in-env.md#仓库类变量) - [构建类变量](/cnb/build/build-in-env.md#构建类变量) - [合并类变量](/cnb/build/build-in-env.md#合并类变量) - [远程开发类变量](/cnb/build/build-in-env.md#远程开发类变量) - [Issue 类变量](/cnb/build/build-in-env.md#issue-类变量) - [评论类变量](/cnb/build/build-in-env.md#评论类变量) ### [超时策略](/cnb/build/timeout.md) - [流水线超时](/cnb/build/timeout.md#流水线超时) - [任务超时](/cnb/build/timeout.md#任务超时) ### [权限说明](/cnb/build/permission.md) ### [常见问题](/cnb/build/faq.md) - [流水线为什么没触发](/cnb/build/faq.md#流水线为什么没触发) - [在本地明明好的,为什么在 CI 上跑失败了](/cnb/build/faq.md#在本地明明好的为什么在-ci-上跑失败了) - [如何登录到流水线容器调试](/cnb/build/faq.md#如何登录到流水线容器调试) - [流水线执行脚本和登陆调试执行脚本结果不一样](/cnb/build/faq.md#流水线执行脚本和登陆调试执行脚本结果不一样) - [超时无输出](/cnb/build/faq.md#超时无输出) - [没改代码为什么流水线就失败了](/cnb/build/faq.md#没改代码为什么流水线就失败了) - [流水线报错 docker not found?](/cnb/build/faq.md#流水线报错-docker-not-found) ### [内置任务](/cnb/build/internal-steps.md) - [Docker](/cnb/build/internal-steps.md#docker) - [cnb](/cnb/build/internal-steps.md#cnb) - [vscode](/cnb/build/internal-steps.md#vscode) - [git](/cnb/build/internal-steps.md#git) - [testing](/cnb/build/internal-steps.md#testing) - [artifact](/cnb/build/internal-steps.md#artifact) ### [插件市场](/cnb/build/plugins.md) ### [插件制作](/cnb/build/create-plugin.md) - [设计插件](/cnb/build/create-plugin.md#设计插件) - [书写脚本](/cnb/build/create-plugin.md#书写脚本) - [构建插件镜像](/cnb/build/create-plugin.md#构建插件镜像) - [测试插件](/cnb/build/create-plugin.md#测试插件) - [导出变量](/cnb/build/create-plugin.md#导出变量) - [发布插件](/cnb/build/create-plugin.md#发布插件) ### [贡献插件](/cnb/build/contribute-plugin.md) ### [简化配置文件](/cnb/build/simplify-configuration.md) - [YAML 高级语法](/cnb/build/simplify-configuration.md#yaml-高级语法) - [文件引用](/cnb/build/simplify-configuration.md#文件引用) - [变量引用](/cnb/build/simplify-configuration.md#变量引用) ### [文件引用](/cnb/build/file-reference.md) - [背景](/cnb/build/file-reference.md#背景) - [引用方式](/cnb/build/file-reference.md#引用方式) - [文件类型](/cnb/build/file-reference.md#文件类型) - [权限检查](/cnb/build/file-reference.md#权限检查) - [示例](/cnb/build/file-reference.md#示例) ### [流水线缓存](/cnb/build/pipeline-cache.md) - [节点缓存](/cnb/build/pipeline-cache.md#节点缓存) - [跨节点缓存](/cnb/build/pipeline-cache.md#跨节点缓存) ### [定时任务](/cnb/build/crontab.md) - [简介](/cnb/build/crontab.md#简介) - [配置解析](/cnb/build/crontab.md#配置解析) ### [跳过流水线](/cnb/build/skip-pipeline.md) - [主动跳过流水线](/cnb/build/skip-pipeline.md#主动跳过流水线) - [事件忽略](/cnb/build/skip-pipeline.md#事件忽略) ### [登录调试](/cnb/build/login-debug.md) - [什么情况需要登录调试?](/cnb/build/login-debug.md#什么情况需要登录调试) - [如何使用?](/cnb/build/login-debug.md#如何使用) - [调试技巧](/cnb/build/login-debug.md#调试技巧) ### [手动触发流水线](/cnb/build/web-trigger.md) - [自定义按钮配置](/cnb/build/web-trigger.md#自定义按钮配置) - [自定义 web_trigger 流水线](/cnb/build/web-trigger.md#自定义-web_trigger-流水线) - [权限说明](/cnb/build/web-trigger.md#权限说明) ### [自定义部署流程](/cnb/build/deploy.md) - [自定义部署环境](/cnb/build/deploy.md#自定义部署环境) - [自定义部署前置条件](/cnb/build/deploy.md#自定义部署前置条件) - [自定义部署流水线](/cnb/build/deploy.md#自定义部署流水线) - [部署权限说明](/cnb/build/deploy.md#部署权限说明) ### [示例介绍](/cnb/build/showcase/docker-build-and-push-to-cnb-artifact.md) ## 云原生开发 ### [云原生开发介绍](/cnb/workspaces/intro.md) - [使用方式](/cnb/workspaces/intro.md#使用方式) ### [默认开发环境](/cnb/workspaces/default-dev-env.md) - [云原生开发默认的环境镜像为 `cnbcool/default-dev-env:latest`](/cnb/workspaces/default-dev-env.md#云原生开发默认的环境镜像为-cnbcooldefault-dev-envlatest) ### [自定义开发环境](/cnb/workspaces/custom-dev-env.md) - [通过 docker 镜像指定开发环境](/cnb/workspaces/custom-dev-env.md#通过-docker-镜像指定开发环境) - [通过 Dockerfile 自定义开发环境](/cnb/workspaces/custom-dev-env.md#通过-dockerfile-自定义开发环境) - [同时自定义开发环境和启动流程](/cnb/workspaces/custom-dev-env.md#同时自定义开发环境和启动流程) ### [业务端口预览](/cnb/workspaces/business-preview.md) ### [远程开发工作区回收机制](/cnb/workspaces/workspace-recycling.md) ### [代码备份和文件漫游](/cnb/workspaces/file-keeper.md) - [工作区代码备份](/cnb/workspaces/file-keeper.md#工作区代码备份) - [非工作区文件漫游](/cnb/workspaces/file-keeper.md#非工作区文件漫游) ### [云原生开发推荐用法](/cnb/workspaces/working-principle.md) ### [常见问题解答](/cnb/workspaces/question.md) - [如何安装指定版本 code-server](/cnb/workspaces/question.md#如何安装指定版本-code-server) ### [自定义环境创建流程](/cnb/workspaces/custom-dev-pipeline.md) - [自定义资源规格](/cnb/workspaces/custom-dev-pipeline.md#自定义资源规格) - [自定义启动事件](/cnb/workspaces/custom-dev-pipeline.md#自定义启动事件) - [自定义可用时机](/cnb/workspaces/custom-dev-pipeline.md#自定义可用时机) - [自定义环境销毁前任务](/cnb/workspaces/custom-dev-pipeline.md#自定义环境销毁前任务) ### [自定义云原生开发启动按钮](/cnb/workspaces/custom-dev-button.md) ### [单/双容器模式](/cnb/workspaces/double-container.md) - [单容器模式](/cnb/workspaces/double-container.md#单容器模式) - [双容器模式](/cnb/workspaces/double-container.md#双容器模式) - [双容器模式-跨容器终端](/cnb/workspaces/double-container.md#双容器模式-跨容器终端) - [双容器模式-插件能力限制](/cnb/workspaces/double-container.md#双容器模式-插件能力限制) ### [使用技巧](/cnb/workspaces/usage-tips.md) - [快捷键](/cnb/workspaces/usage-tips.md#快捷键) - [VSCode 配置文件漫游](/cnb/workspaces/usage-tips.md#vscode-配置文件漫游) - [如何安装 VSCode 扩展](/cnb/workspaces/usage-tips.md#如何安装-vscode-扩展) ### [VSCode/Cursor 客户端](/cnb/workspaces/vscode-likes.md) ### [Jetbrains 客户端](/cnb/workspaces/jetbrains.md) - [准备工作](/cnb/workspaces/jetbrains.md#准备工作) - [如何访问](/cnb/workspaces/jetbrains.md#如何访问) ### [云原生开发 SSH 密钥指纹验证](/cnb/workspaces/fingerprint.md) - [SSH 密钥指纹](/cnb/workspaces/fingerprint.md#ssh-密钥指纹) - [如何验证 SSH 密钥指纹](/cnb/workspaces/fingerprint.md#如何验证-ssh-密钥指纹) ## 制品库 ### [概述](/cnb/artifact/intro.md) - [身份认证](/cnb/artifact/intro.md#身份认证) - [权限管控](/cnb/artifact/intro.md#权限管控) - [制品类型](/cnb/artifact/intro.md#制品类型) - [容量统计](/cnb/artifact/intro.md#容量统计) ### [Docker 制品库](/cnb/artifact/docker.md) - [登录 CNB Docker 制品库](/cnb/artifact/docker.md#登录-cnb-docker-制品库) - [Docker 制品路径规则](/cnb/artifact/docker.md#docker-制品路径规则) - [推送制品](/cnb/artifact/docker.md#推送制品) - [使用制品](/cnb/artifact/docker.md#使用制品) - [更多用法](/cnb/artifact/docker.md#更多用法) ### [Helm 制品库](/cnb/artifact/helm.md) - [登录 CNB Helm 制品库](/cnb/artifact/helm.md#登录-cnb-helm-制品库) - [Helm 制品路径规则](/cnb/artifact/helm.md#helm-制品路径规则) - [推送制品](/cnb/artifact/helm.md#推送制品) - [使用制品](/cnb/artifact/helm.md#使用制品) - [更多用法](/cnb/artifact/helm.md#更多用法) ## AI助手 ### [AI助手简介](/cnb/ai/intro.md) - [功能介绍](/cnb/ai/intro.md#功能介绍) ### [知识库](/cnb/ai/knowledge-base.md) - [知识准备](/cnb/ai/knowledge-base.md#知识准备) - [具体使用方法](/cnb/ai/knowledge-base.md#具体使用方法) ## 任务集 ### [任务集介绍](/cnb/missions/intro.md) - [创建任务集](/cnb/missions/intro.md#创建任务集) - [任务集视图](/cnb/missions/intro.md#任务集视图) - [任务集设置](/cnb/missions/intro.md#任务集设置) - [任务集权限](/cnb/missions/intro.md#任务集权限) ## 开发者 ### [徽章](/cnb/develops/badge.md) - [云原生构建相关徽章](/cnb/develops/badge.md#云原生构建相关徽章) - [仓库相关徽章](/cnb/develops/badge.md#仓库相关徽章) ### [Open API](/cnb/develops/openapi.md) - [API 服务地址](/cnb/develops/openapi.md#api-服务地址) - [API 文档](/cnb/develops/openapi.md#api-文档) - [调用方式](/cnb/develops/openapi.md#调用方式) ## 更多 ### [定价](/cnb/more/pricing.md) - [概述](/cnb/more/pricing.md#概述) - [计费模式](/cnb/more/pricing.md#计费模式) - [免费额度说明](/cnb/more/pricing.md#免费额度说明) - [非盈利组织特权](/cnb/more/pricing.md#非盈利组织特权) ### [平台赞赏](/cnb/more/sponsor.md) - [上传赞赏码](/cnb/more/sponsor.md#上传赞赏码) - [展示赞赏码](/cnb/more/sponsor.md#展示赞赏码) - [自定义仓库赞赏信息](/cnb/more/sponsor.md#自定义仓库赞赏信息) - [停止接受赞赏](/cnb/more/sponsor.md#停止接受赞赏) ### [云原生构建-企业版](/cnb/more/enterprise.md) - [满足企业合规要求](/cnb/more/enterprise.md#满足企业合规要求) - [企业版计费说明](/cnb/more/enterprise.md#企业版计费说明) - [安装使用](/cnb/more/enterprise.md#安装使用) ### [产品Logo](/cnb/more/logo.md) - [PNG格式](/cnb/more/logo.md#png格式) - [SVG格式](/cnb/more/logo.md#svg格式) - [AI格式](/cnb/more/logo.md#ai格式) ### [集成TAPD](/cnb/more/tapd.md) --- url: /cnb/guide/first-repo.md --- > For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /cnb/guide/first-repo.md. # 创建你的第一个仓库 组织是团队管理成员和资源的命名空间,在创建仓库资源前,需创建组织以管理成员及仓库等资源。 仓库可以用于托管企业的代码资产,管理云原生构建流水线配置。 ## 1. 创建组织 单击右上角的 `+`,选择`创建组织`,填写组织名称及相关描述后,单击`创建`即可完成组织创建。 ![创建组织](https://docs.cnb.cool/images/quick-start/create-group.zh.png) ## 2. 创建仓库 单击右上角的 `+`,选择`创建仓库`,选择仓库的归属组织、填写仓库名称,并按需选择仓库的公开性后,单击`创建`即可完成仓库创建。 ![创建仓库](https://docs.cnb.cool/images/quick-start/create-repo.zh.png) ## 3. 初始化仓库 您可以选择以下任一方式完成仓库的初始化。 ### 3.1 云端快速初始化(推荐) 您可以在云原生开发中执行相关命令迁移仓库,或直接新建文件来完成仓库的初始化。 ![云端快速初始化](https://docs.cnb.cool/images/quick-start/workspace.zh.png) ### 3.2 本地初始化 可以通过裸库迁移、分支迁移、空仓初始化中任一方式来完成初始化。具体命令可在目标仓库查看,界面如下: ![本地初始化](https://docs.cnb.cool/images/quick-start/local-init.zh.png) --- url: /cnb/guide/migration-tools.md --- > For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /cnb/guide/migration-tools.md. # 迁移工具 ## CNB Code Import CNB代码仓库批量迁移工具 支持 `CODING`、`Github`、`Gitlab`、`Gitee`、`阿里云效`以及`通用第三方`代码托管平台的代码仓库批量迁移至CNB 工具地址:[https://cnb.cool/cnb/plugins/cnbcool/code-import](https://cnb.cool/cnb/plugins/cnbcool/code-import) ## Git Sync 一个用于在不同 Git 平台之间同步代码的插件 工具地址:[https://cnb.cool/cnb/plugins/tencentcom/git-sync](https://cnb.cool/cnb/plugins/tencentcom/git-sync) --- url: /cnb/guide/role-permissions.md --- > For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /cnb/guide/role-permissions.md. # 角色权限 `云原生构建` 将成员分为五种角色:`访客`、`助手`、`开发者`、`管理员`、`负责人`。 对于**公开**仓库,非仓库用户和未登录用户也能访问,用户角色为`匿名`。 对于一些资源(PR、Issue、评论等),非仓库成员也可以创建,用户角色为`创建者`。 下表列出了各角色所能访问、操作的资源:
操作单元 操作 场景 负责人 管理员 开发者 助手 访客 匿名 创建者
Group 查看 Group ✔ ✔ ✔ ✔ ✔ ✔
编辑 Group 设置 ✔ ✔
Group 成员管理(邀请成员,删除成员,修改成员权限) ✔ ✔
创建仓库/制品库 ✔ ✔
创建 SubGroup ✔ ✔
删除,转移 ✔
仓库 查看 公开 ✔ ✔ ✔ ✔ ✔ ✔
私有 ✔ ✔ ✔ ✔ ✔
密钥 ✔ ✔
查看仓库设置 公开 ✔ ✔ ✔ ✔ ✔
私有 ✔ ✔ ✔ ✔ ✔
密钥 ✔ ✔
管理仓库设置:分支保护规则,名称/描述,归档等 公开 ✔ ✔
私有 ✔ ✔
密钥 ✔ ✔
管理仓库成员:邀请/移除成员,修改成员权限 公开 ✔ ✔
私有 ✔ ✔
密钥 ✔ ✔
删除,转移、转让 公开 ✔
私有 ✔
密钥 ✔
代码 WEB端查看文件内容 公开 ✔ ✔ ✔ ✔ ✔ ✔
私有 ✔ ✔ ✔ ✔
密钥 ✔ ✔
WEB端修改文件内容 公开 ✔ ✔ ✔
私有 ✔ ✔ ✔
密钥 ✔ ✔
克隆、拉取、下载 公开 ✔ ✔ ✔ ✔ ✔ ✔
私有 ✔ ✔ ✔ ✔
推送 公开 ✔ ✔ ✔
私有 ✔ ✔ ✔
分支 查看 公开 ✔ ✔ ✔ ✔ ✔ ✔
私有 ✔ ✔ ✔ ✔
密钥 ✔ ✔
创建/删除 公开 ✔ ✔ ✔
私有 ✔ ✔ ✔
密钥 ✔ ✔
合并 公开 ✔ ✔ ✔
私有 ✔ ✔ ✔
密钥 ✔ ✔
分支保护设置 ✔ ✔
云原生构建 查看、下载构建日志 公开 ✔ ✔ ✔ ✔ ✔ ✔
私有 ✔ ✔ ✔ ✔
删除构建日志 公开 ✔ ✔ ✔
私有 ✔ ✔ ✔
触发、停止构建 公开 ✔ ✔ ✔
私有 ✔ ✔ ✔
云原生开发 创建云原生开发环境 公开 ✔ ✔ ✔
私有 ✔ ✔ ✔
访问云原生开发环境 公开 ✔
私有 ✔
Issue 查看 公开 ✔ ✔ ✔ ✔ ✔ ✔
私有 ✔ ✔ ✔ ✔ ✔
密钥 ✔ ✔ ✔ ✔ ✔
创建、评论、引用 公开 ✔ ✔ ✔ ✔ ✔
私有 ✔ ✔ ✔ ✔ ✔
密钥 ✔ ✔ ✔ ✔ ✔
编辑标题描述 公开 ✔ ✔ ✔ ✔ ✔
私有 ✔ ✔ ✔ ✔ ✔
密钥 ✔ ✔ ✔
编辑(处理人、标签、优先级) 公开 ✔ ✔ ✔ ✔ ✔
私有 ✔ ✔ ✔ ✔ ✔
密钥 ✔ ✔ ✔ ✔ ✔
关闭/重新打开 公开 ✔ ✔ ✔ ✔ ✔
私有 ✔ ✔ ✔ ✔ ✔
密钥 ✔ ✔ ✔ ✔ ✔
PR 查看 公开 ✔ ✔ ✔ ✔ ✔ ✔
私有 ✔ ✔ ✔ ✔
密钥 ✔ ✔
创建、评论、引用 公开 ✔ ✔ ✔ ✔ ✔
私有 ✔ ✔ ✔
密钥 ✔ ✔
编辑标题描述 公开 ✔ ✔ ✔ ✔ ✔
私有 ✔ ✔ ✔ ✔ ✔
密钥 ✔ ✔ ✔
编辑(处理人、评审者、标签) 公开 ✔ ✔ ✔ ✔ ✔
私有 ✔ ✔ ✔ ✔ ✔
密钥 ✔ ✔ ✔
审核(评论、审查代码、批准、请求修改) 公开 ✔ ✔ ✔
私有 ✔ ✔ ✔
密钥 ✔ ✔
合并/appoved/request change 公开 ✔ ✔ ✔
私有 ✔ ✔ ✔
密钥 ✔ ✔
关闭/重新打开 公开 ✔ ✔ ✔
私有 ✔ ✔ ✔
密钥 ✔ ✔
Issue、PR评论 编辑对话评论 公开 ✔ ✔ ✔ ✔ ✔ ✔
私有 ✔ ✔ ✔ ✔ ✔ ✔
密钥 ✔ ✔ ✔
隐藏对话评论 公开 ✔ ✔ ✔ ✔
私有 ✔ ✔ ✔ ✔
密钥 ✔ ✔
删除对话评论 公开 ✔ ✔ ✔ ✔ ✔
私有 ✔ ✔ ✔ ✔ ✔
密钥 ✔ ✔ ✔
标签 (Label) 查看 公开 ✔ ✔ ✔ ✔ ✔ ✔
私有 ✔ ✔ ✔ ✔ ✔
密钥 ✔ ✔ ✔ ✔ ✔
创建/编辑 ✔ ✔ ✔ ✔
删除 ✔ ✔ ✔ ✔
Tag 查看 公开 ✔ ✔ ✔ ✔ ✔ ✔
私有 ✔ ✔ ✔
密钥 ✔ ✔
创建 公开 ✔ ✔ ✔
私有 ✔ ✔ ✔
密钥 ✔ ✔
下载 公开 ✔ ✔ ✔ ✔ ✔ ✔
私有 ✔ ✔ ✔
密钥 ✔ ✔
删除 公开 ✔ ✔ ✔
私有 ✔ ✔
密钥 ✔ ✔
Release 版本 查看 公开 ✔ ✔ ✔ ✔ ✔ ✔
私有 ✔ ✔ ✔ ✔ ✔
密钥 ✔ ✔
创建 公开 ✔ ✔ ✔
私有 ✔ ✔ ✔
密钥 ✔ ✔
上传附件 公开 ✔ ✔ ✔
私有 ✔ ✔ ✔
密钥 ✔ ✔
编辑 公开 ✔ ✔ ✔
私有 ✔ ✔ ✔
密钥 ✔ ✔
删除 公开 ✔ ✔ ✔
私有 ✔ ✔ ✔
密钥 ✔ ✔
更新版本描述 公开 ✔ ✔ ✔
私有 ✔ ✔ ✔
密钥 ✔ ✔
下载 公开 ✔ ✔ ✔ ✔ ✔ ✔
私有 ✔ ✔ ✔ ✔ ✔
密钥 ✔ ✔
Docker/Helm 制品库 查看/下载 公开 ✔ ✔ ✔ ✔ ✔ ✔
私有 ✔ ✔ ✔ ✔ ✔
创建/上传版本 公开 ✔ ✔ ✔
私有 ✔ ✔ ✔
删除版本 ✔ ✔ ✔
删除制品库 ✔
任务集 创建任务集 ✔ ✔
修改任务集设置(基础设置、高级设置、成员管理) ✔ ✔
创建视图 ✔ ✔
查看视图 公开 ✔ ✔ ✔ ✔ ✔ ✔
私有 ✔ ✔ ✔ ✔ ✔
编辑视图 ✔ ✔ ✔ ✔
复制任务集 ✔ ✔ ✔ ✔ ✔
删除任务集 ✔
--- url: /cnb/guide/access-token.md --- > For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /cnb/guide/access-token.md. # 访问令牌 云原生构建平台的所有资源(包括代码仓库、制品库、OPENAPI等),都需要通过访问令牌进行操作。 ## 访问令牌申请 登录后,进入 `个人设置` - [访问令牌](https://cnb.cool/profile/token) -> `添加访问令牌`。 令牌需要的配置参数如下: - 令牌名: 令牌名称,用于唯一标识令牌。 - 到期时间: 令牌过期时间,过期后令牌不可用。 - 使用范围: 令牌使用范围,用于限制令牌访问的仓库类型。 - 授权范围: 令牌授权范围,授予令牌在账号下的可操作权限。 - 常见场景: 根据常见的使用场景,提供快速初始化令牌授权范围。 完成创建后,即可获取到令牌 token。 ## 访问代码仓库 - 用户名固定为:cnb - 密码为添加的`访问令牌` ## 访问制品库 - 用户名固定为:cnb - 密码为添加的`访问令牌` ## 访问OPENAPI 详见: [Open API](/cnb/develops/openapi.md) --- url: /cnb/repo/intro.md --- > For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /cnb/repo/intro.md. # 产品介绍 CNB代码托管提供了代码管理、分支管理、权限管理、版本管理等实用功能,能够帮助开发者规避本地代码管理的局限与安全性障碍,回归开发本身。 ## 核心功能 ### 高可用仓库 云端高可用仓库,数据安全有保障。支持使用 `Git` 版本控制工具实现本地和云端仓库的代码同步。 ### 在线代码浏览 浏览代码时支持上下、左右对比模式。代码提交前后改动差异皆清晰可视,分毫不差。 ### 代码评审 代码审查(Pull Request),支持逐行对比、逐行评论、分支合并自动添加评审者,提供良好的代码阅读与代码审查体验。 ### ​​问题跟踪 ​问题跟踪(Issues), 用于记录Bug、功能需求或讨论,支持标签分类、优先级标记及评论互动。 ### 版本管理 发布代码自动生成规范版本号,能够直接与任务/缺陷关联,让源码发布与交付有标准可循,更能够助力高效协同。 ### 分支保护 分支粒度管理、精细化权限设置,让团队协作规范而有序。 --- url: /cnb/repo/secret.md --- > For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /cnb/repo/secret.md. # 密钥仓库 密钥仓库是 `云原生构建` 提供的**安全型代码仓库**,专为存储敏感信息(如密码、API密钥、证书等)设计。 通过严格的访问控制、页面水印、审计追踪等机制,实现敏感数据的安全存储与合规使用。 ## 创建密钥仓库 1. **进入仓库创建页面**\ [点击此处创建密钥仓库](https://cnb.cool/new/repos)(需登录账号)。 2. **选择仓库类型**\ 在仓库类型中选择 **`密钥仓库`**,填写仓库名称与简介。 ![创建密钥仓库](https://docs.cnb.cool/images/keystore/create-keystore.zh.png) 3. **创建**\ 点击创建按钮,创建密钥仓库 ## 密钥仓库核心特点 ### 1. **安全限制** | 能力 | 普通仓库 | 密钥仓库 | | ------------- | ---- | ---- | | Git Clone 到本地 | ✅ | ❌ | | 本地推送代码 | ✅ | ❌ | | 页面编辑文件 | ✅ | ✅ | | 创建分支/Tag/PR | ✅ | ✅ | | 被流水线引用 | ✅ | ✅ | ### 2. **安全增强特性** - **动态水印**:页面自动添加当前用户名的半透明水印,防止截图泄露。 - **引用审计**:记录所有引用此仓库文件的流水线记录,支持溯源追踪。 - **强制页面操作**:仅支持在 Web 界面编辑文件,禁止本地操作。 - **严苛的权限控制**: 参考[权限说明](/cnb/guide/role-permissions.md)。 - **声明式使用范围**: 参考流水线文件引用[权限检查](/cnb/build/file-reference.md#权限检查)。 ## 在流水线中引用密钥仓库文件 ### 密钥仓库新增文件 ```yaml # env.yml DOCKER_USER: 'username' DOCKER_TOKEN: 'token' DOCKER_REGISTRY: 'https://xxx/xxx' ``` ### 导入为环境变量 在流水线配置中,通过 [imports](/cnb/build/grammar.md#Pipeline-imports) 字段引用密钥仓库文件,自动注入为环境变量: ```yaml # .cnb.yml main: push: - services: - docker imports: # 引用密钥仓库文件 - https://cnb.cool//-/blob/main/xxx/env.yml stages: - name: docker push script: | docker login -u ${DOCKER_USER} -p "${DOCKER_TOKEN}" ${CNB_DOCKER_REGISTRY} docker build -t ${DOCKER_REGISTRY}/${CNB_REPO_SLUG_LOWERCASE}:latest . docker push ${DOCKER_REGISTRY}/${CNB_REPO_SLUG_LOWERCASE}:latest ``` ### 流水线引用鉴权 默认情况下密钥仓库文件只能被管理员、负责人触发的流水线引用,参考[角色权限](/cnb/guide/role-permissions.md)。 若希望团队普通成员触发的流水线也能引用密钥仓库文件,可额外配置 `allow_slugs`、`allow_events`、`allow_branches`、`allow_images` 等字段控制被访问范围。 此时会忽略触发者是否拥有密钥仓库的权限,转而依次检查声明的 `allow_*` 属性,全部通过才能导入为环境变量。更多信息请参考文件引用[权限检查](/cnb/build/file-reference.md#权限检查)。 ## 最佳实践 1. **敏感信息分类存储** - 按环境(prod/dev)或项目拆分不同密钥仓库。 - 使用 `yaml`、`json` 等文件格式存储管理密钥。 - 独立于业务组织外新建组织管理密钥仓库,缩小可访问密钥仓库成员范围。 2. **按需使用** - 慎重分配管理员、负责人角色。 - 检查流水线配置是否有滥用、泄漏密钥仓库文件内容的情况。 - 密钥仓库文件合理配置 `allow_*` 属性。如: - 配置 `allow_slugs` 智能被指定范围的仓库流水线引用。 - 配置 `allow_events` 只能被 `Tag` 相关事件流水线引用。 - 配置 `allow_branches` 为特定的保护分支,PR 必须经过评审。 - 指定或制作用于发布、部署的插件,配置 `allow_images` 只能被这些插件引用。 3. **定期轮换密钥**\ 通过页面编辑功能更新密钥后,所有引用此文件的流水线将自动获取新值。 4. **审计复盘**\ 检查审计日志,清理无效引用,撤销离职成员权限。 --- url: /cnb/repo/annotations.md --- > For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /cnb/repo/annotations.md. # 元数据 ## 什么是元数据? 元数据是仓库提供的数据存储能力,目前支持给 Tag 和 Commit 存储元数据,表示对 Tag 或 Commit 的注解。 ## 存储形式 以 `key: value` 形式进行存储。 以 Tag v1.0.0 的元数据为例,其元数据支持 `key: value` 形式存储,如下: ```yaml key1: value1 key2: value2 # ... ``` ## 如何查看元数据? 页面查看路径: - Tag 元数据:仓库 > Tag 或 Release 列表 > Tag 或 Release 详情 > 元数据(没有元数据时不展示) - Commit 元数据:仓库 > Commit 列表 > Commit 详情 > 元数据 目前页面仅支持元数据查看,不支持增加、修改和删除。 ## 如何操作元数据? 可在云原生构建流水线中,通过插件对元数据进行增加、删除、查询元数据。 --- url: /cnb/repo/issue-template.md --- > For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /cnb/repo/issue-template.md. # ISSUE 模板 字段名和格式,与 GitHub 保持一致。[链接](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms) ## 使用要求 1. 支持 yaml 和 markdown 格式文件 2. 必须放在 `.cnb/ISSUE_TEMPLATE` 目录下 ## 模板格式 使用方式,见仓库 [issue-templates](https://cnb.cool/examples/templates/issue-templates) ### YAML - markdown 文本渲染 - 单行输入框 - 多行输入框(纯文本) - 多行输入框(markdown 文本) - 下拉框 - 分类标签 - 处理人 ### MARKDOWN - markdown --- url: /cnb/repo/label.md --- > For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /cnb/repo/label.md. # 分类标签 ## 导入CNB公开仓库的标签 1. 进入标签管理页,点击“导入”(有标签时,按钮在页面右上角;没有标签时,按钮在页面正中) 2. 在弹框里粘贴 CNB 公开仓库的完整链接,点击“导入” > 注:导入标签不会覆盖已有标签,增量导入 --- url: /cnb/repo/settings.md --- > For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /cnb/repo/settings.md. # UI 定制 可通过在仓库根目录新增 `.cnb/settings.yml` 配置文件对页面部分 UI 进行定制,解锁更多玩法 ## 配置文件说明 需在仓库根目录新增并提交 `.cnb/settings.yml` 配置文件,如下为配置文件示例: ```yaml # .cnb/settings.yml # 如下参数均为可选参数 # 云原生开发配置,读取云原生启动按钮所在页面当前分支的 .cnb/settings.yml 配置 workspace: launch: # 定制云原生开发启动按钮 button: # 按钮名称 name: 启动云原生开发 # 按钮描述 # 如果值为 null,则不显示默认描述 description: 点击此按钮启动云原生开发环境 # 鼠标悬浮在按钮上显示的图片(只能用仓库中当前分支的图片,填写相对仓库根目录的路径,如 .cnb/launch-hover.gif) # 图片最大 10MB hoverImage: .cnb/launch-hover.gif # CPU 核心数,默认为:8。仅对默认模版有效,如果有自定义云原生开发启动流水线,则此配置无效 cpus: 4 # 是否禁用默认按钮。默认为:false 表示不禁用。true 表示禁用 disabled: false # 环境创建完是否自动打开 WebIDE,默认为 false # 当开发环境中未安装 openssh(仅支持 WebIDE):无论此参数配置为 true 还是 false,环境创建完都将自动打开 WebIDE autoOpenWebIDE: false # issue 配置,读取仓库主干 .cnb/settings.yml 配置 issue: # 定制创建 issue 按钮 button: # 按钮描述 description: ~bug~ 给你! # 鼠标悬浮在按钮上显示的图片(只能用仓库中当前分支的图片,填写相对仓库根目录的路径,如 .cnb/issue-hover.png) # 图片最大 10MB hoverImage: '.cnb/issue-hover.png' # fork 配置,读取仓库主干 .cnb/settings.yml 配置 fork: # 定制 fork 按钮 button: # 按钮描述 description: 你的仓库不错,现在是我的了 # 鼠标悬浮在按钮上显示的图片(只能用仓库中当前分支的图片,填写相对仓库根目录的路径,如 .cnb/fork-hover.png) # 图片最大 10MB hoverImage: '.cnb/fork-hover.png' # 抄了么 按钮配置,读取仓库主干 .cnb/settings.yml 配置 # 仓库首页默认没有此按钮 # 抄了么按钮出现条件:仓库首页右方简介增加 example 标签(推荐可作为模板或例子的仓库增加此按钮) copyRepo: # 定制 抄了么 按钮 button: # 按钮描述 description: 你的仓库不错,现在是我的了 # 鼠标悬浮在按钮上显示的图片(只能用仓库中当前分支的图片,填写相对仓库根目录的路径,如 .cnb/copy-hover.png) # 图片最大 10MB hoverImage: '.cnb/copy-hover.png' ``` :::tip 注意:当文件解析失败或大小超过限制,将不会使用该配置 ::: ## 抄了么按钮 仓库首页默认不会出现 `抄了么` 按钮,推荐可作为模板或例子的仓库增加此按钮。 如何增加此按钮:在仓库首页右侧简介编辑按钮,增加 `example` 标签,即可出现此按钮 点击该按钮,获取快速复制该仓库的具体方法 --- url: /cnb/build/intro.md --- > For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /cnb/build/intro.md. # 云原生构建介绍 基于 Docker 生态,对环境、缓存、插件进行抽象,通过声明式的语法,帮助开发者以更酷的方式构建软件。 - 声明式:声明式语法,可编程、易分享。 - 易管理:与代码一起,同源管理。 - 云原生:资源池化,屏蔽基础设施复杂性。 ### 声明式的构建环境 ```yaml main: push: - docker: image: node:20 stages: - node -v - npm install - npm test ``` ### 声明式的构建缓存 ```yaml main: push: - docker: image: node:20 volumes: - /root/.npm:copy-on-write stages: - node -v - npm install - npm test ``` ### Docker 作为任务的运行环境 ```yaml main: push: - stages: - name: run with node 20 image: node:20 script: node -v - name: run with node 21 image: node:21 script: node -v ``` ### 基于 Docker 生态的插件 ```yaml main: push: - stages: - name: hello world image: cnbcool/hello-world ``` ### 按需获取计算资源 ```yaml main: push: - runner: cpus: 64 docker: image: node:20 stages: - node -v - npm install - npm test ``` ### 云原生开发 ```yaml $: vscode: - runner: cpus: 64 services: - vscode docker: image: node:20 volumes: - node_modules:copy-on-write stages: - npm install ``` ## 高性能 ### CPU自由 - [runner.cpus](/cnb/build/grammar.md#cpus) 通过 `runner.cpus` 可按需声明需要的 CPU资源,最高可达 `64核`。 ### 读秒克隆 基于 `OverlayFS` 的 [git-clone-yyds](https://cnb.cool/cnb/cool/git-clone-yyds) 可以在数秒内完成代码准备,轻松支持 `100GB+` 超大仓库。 ### 缓存并发 - [copy-on-write](/cnb/build/grammar.md#volumes) `copy-on-write` 可以实现缓存的写时复制,在并发场景下,无需再担心缓存读写冲突问题。 ```yaml main: push: - runner: cpus: 64 docker: image: node:20 volumes: - /root/.npm:copy-on-write stages: - node -v - npm install - npm test ``` --- url: /cnb/build/quick-start.md --- > For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /cnb/build/quick-start.md. # 快速开始 `云原生构建` 以仓库为主体,由 **配置文件** 描述在哪个 **分支** 下发生什么 **事件** 时执行什么 **任务**。 下面以一个最简示例开始,介绍如何一步步操作,创建仓库并触发一条流水线。 接着以开发中常见的 `Pull Request` 流水线检测需求为目标,介绍如何一步步编写配置文件。 在此基础上,可以在[最佳实践](https://cnb.cool/examples/showcase)中的选择具体场景的仓库,`fork` 仓库或复制其中配置文件,编写出符合自身需求的流水线配置。 ## 编写你的第一条流水线 ### 1. 创建仓库 新建一个仓库(如有跳过),创建好后,可以点击 `云原生开发` 按钮快速创建一个开发环境。 ![workspace](https://docs.cnb.cool/images/quick-start/workspace.zh.png) 选择 `WebIDE` 进入开发界面,方便快捷。 ![choose-ide](https://docs.cnb.cool/images/quick-start/choose-ide.zh.png) ### 2. 编写 .cnb.yml 配置文件 一个简单的流水线配置如下: ```yaml # 分支名 main: # 事件名 push: # 要执行的任务 - stages: - name: echo script: echo "hello world" ``` 添加 `CI` 配置文件 `.cnb.yml`,将该内容复制进配置文件,提交并 `push` 到远端 `main` 分支。 ![add-ci](https://docs.cnb.cool/images/quick-start/add-ci.zh.png) 即会触发流水线构建。 ### 3. 查看构建详情 在仓库页面点击 `云原生构建` 可以看到构建列表。 ![pipeline-push](https://docs.cnb.cool/images/quick-start/pipeline-push.zh.png) 最新一条即是刚刚触发的 `push` 事件流水线,点进去可以看到构建详情。 ## 配置说明 接下来,我们以一个常见的流水线需求,来简单介绍解释一下配置文件的语法: **“需求:主分支有 `Pull Request` 时,触发流水线进行 lint 和 test 检测,未通过则发出通知。 ”** 我们分析下这个需求,可以从中抽取一些要素: 1. 主分支,比如 `main`。 2. 仓库事件,即 `pull_request` 事件。 3. 流水线任务: 1. lint 2. test 4. 失败时的任务 1. notify 下面我们根据这些要素一步步编写 `.cnb.yml` 配置文件。 第一层属性为分支名: ```yaml #分支名 main: ``` 分支下有 `pull_request` 事件时触发构建: ```yaml #分支名 main: # 事件名 pull_request: ``` 事件可以执行多条流水线(并行),流水线有多个任务(串行或并行)。 这里我们简化,事件下只有一条流水线: ```yaml #分支名 main: # 事件名 pull_request: # 数组类型表示可以有多个流水线 - name: pr-check stages: ``` 包括两个串行的任务,分别是 lint 和 test。 ```yaml #分支名 main: # 事件名 pull_request: # 数组类型表示可以有多个流水线 - name: pr-check # 流水线下的多个任务 stages: # 要执行的任务 - name: lint script: echo "lint job" - name: test script: echo "test job" ``` 如果失败的话,要发送通知,流水线下除 `stages` 表示期望执行的任务外,还有个 `failStages` 表示 `stages` 任务执行失败时要执行的任务: ```yaml #分支名 main: # 事件名 pull_request: # 数组类型表示可以有多个流水线 - name: pr-check # 流水线下的多个任务 stages: - name: lint script: echo "lint job" - name: test script: echo "test job" # stages 失败时执行的任务 failStages: - name: lint script: echo "notify to some chat group" ``` 总结下,一个流水线的执行过程是: 1. 仓库发生事件 2. 确定所属分支 3. 确定事件名 4. 执行流水线 5. 执行任务 6. 失败时的任务 想了解配置文件更多用法请移步 [配置文件](/cnb/build/configuration.md)。 ## 语法说明 想了解配置文件详细语法请移步 [语法](/cnb/build/grammar.md)。 ## 最佳实践 更多完整示例参考 [最佳实践](https://cnb.cool/examples/showcase)。 --- url: /cnb/build/trigger-rule.md --- > For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /cnb/build/trigger-rule.md. # 构建触发规则 `云原生构建` 会在收到事件时,从对应的分支获取、解析 `.cnb.yml` 配置文件,从中获取对应分支下对应事件的流水线配置,然后分配 Runner 执行构建。 以 main 分支代码 `push` 事件为例: ```mermaid flowchart LR commit(git commit) --> push(git push) --> config(读取main分支下 .cnb.yml) --> event(获取main分支下 push 配置) --> checkout(checkout main分支代码) --> 流水线执行 ``` 代码示例: ```yaml # .cnb.yml main: # 触发分支 push: # 触发事件,对应一个构建,可以包含多条 Pipeline。即可以是数组,也可以是对象。 - stages: # 流水线1 - echo "do some job" - stages: # 流水线1 - echo "do some job" ``` ## 触发分支 对应代码仓库的分支,用于匹配事件对应的分支,指定流水线配置。 **注意:在某个分支下 .cnb.yml 配置了其他分支的流水线,并不代表其他分支的事件会按此配置执行流水线,而是看各分支下具体的 .cnb.yml 的配置。** ### 匹配模式 分支名称支持通过 `glob` 模式匹配([什么是 glob 匹配?](https://globster.xyz/)),如: ```yaml .push_pipeline: &push_pipeline - stages: - name: do something script: echo "do something" # 匹配以 dev/ 开头的所有分支 'dev/*': push: - *push_pipeline # 匹配 main 或 dev 分支 '(main|dev)': push: - *push_pipeline # 匹配除 main 和 dev 以外的所有分支 '**/!(main|dev)': push: - *push_pipeline # 匹配所有分支 '**': push: - *push_pipeline # 兜底,匹配没有 glob 匹配的分支 '$': push: - *push_pipeline tag_push: - *push_pipeline ``` ### 匹配策略 分阶段,按优先级匹配,只有没有匹配结果时,才会尝试下一阶段的匹配。 1. `glob` 匹配分支名 2. `$` 兜底匹配所有未被 `glob` 匹配的分支 如果多个 `glob` 规则都匹配,所有的被匹配规则的流水线会被并行执行。 ## 触发事件 \{#trigger-event} 指定出现哪种事件时触发构建,支持配置多条流水线并行执行。 下面列出了 `云原生构建` 所支持的事件。 ### Branch 事件 远端代码分支变动触发的事件。 #### push 分支 `push` 时触发。 #### commit.add 分支 `push` 有新的 `Commits` 时触发。 该事件会多一个环境变量 `CNB_NEW_COMMITS_COUNT`,值为新增的 `Commits` 数量,最大为 99。 可结合 `git log -n` 查看新增的 `Commits`。 #### branch.create 分支 `create` 时触发,同时会触发 `push` 事件,若存在新的commit,也会触发 `commit.add` 事件。 #### branch.delete 分支 `delete` 时触发。 流水线配置可以挂靠在 `分支名` 或 `$` 上。 流水线会使用 **默认分支** 的配置文件(原因:流水线运行时分支已删除)。 示例: ```yaml dev/1: branch.delete: - stages: - name: echo # CNB_BRANCH 值为删除的分支 script: echo $CNB_BRANCH $: branch.delete: - stages: - name: echo # CNB_BRANCH 值为删除的分支 script: echo $CNB_BRANCH ``` ### Pull Request 事件 远端代码 `Pull Request` 相关操作触发的事件 (下文简称 `PR`)。 #### pull\_request 由 `PR` 的创建、重新打开以及源分支 push 触发。同 `pull_request.target` 的区别参考[代码版本选择](#代码版本选择)。 #### pull\_request.update 由 `PR` 的创建、重新打开、源分支 push 以及 `PR` 的 title、description 修改触发。 **`pull_request` 是 `pull_request.update` 的子集,** **即 `PR` 的 title、description 修改,会触发 `pull_request.update` 但不触发 `pull_request`** **`PR` 的创建、重新打开、源分支 push 会同时触发 `pull_request` 和 `pull_request.update`** #### pull\_request.target 由 `PR` 的创建、重新打开以及源分支 push 触发。同 `pull_request` 的区别参考[代码版本选择](#代码版本选择)。 #### pull\_request.mergeable 开启中的 `PR` 同时满足以下条件时触发: 1. 目标分支为 **保护分支**,并勾选以下规则: 1. 需要评审人批准 2. 需要通过状态检查(可选) 2. 可合并 1. 无代码冲突 2. 状态检查通过(如勾选需要通过状态检查,且有状态检查) 3. 评审通过 该事件的配置文件取自目标分支,参考[代码版本选择](#代码版本选择)。 `PR` 的目标分支配置了该事件流水线,触发该事件时才会有对应流水线执行。 #### pull\_request.merged `PR` 合并完成时触发。 :::tip a 分支合并到 b 分支,会触发 b 分支下的 `pull_request.merged`、`push` 事件。 ::: #### pull\_request.approved 用户评审 `PR` `允许合并` 时触发。 :::tip 可能设置里保护分支需要多个评审人批准,有用户通过评审不代表 `PR` 是评审通过状态。 ::: #### pull\_request.changes\_requested 用户评审 `PR` `需要改进` 时触发。 #### pull\_request.comment `PR` 评论创建的事件。 ### Tag 事件 由远端代码和页面 `Tag` 相关操作触发的事件。 #### tag\_push `Tag push` 时触发。 示例: ```yaml # 对指定 tag 生效 v1.0.*: tag_push: - stages: - name: echo tag name script: echo $CNB_BRANCH # 对所有 tag 生效 $: tag_push: - stages: - name: echo tag name script: echo $CNB_BRANCH ``` #### auto\_tag 自动生成 `Tag` 事件。 1. 触发方式 仅支持在仓库的 `Tag` 列表页面,点击 `自动生成 Tag` 按钮触发。 2. 实现原理 1. 格式说明 `Tag` 默认为 `3.8.11` 类型的格式。如果最新一个 `Tag` 以 `v` 开头,则自动生成的 `Tag` 也会带上 `v`,如 `v4.1.9`。 2. 自定义 `auto_tag` 事件流水线 用户可在根目录 `.cnb.yml` 文件增加如下配置来覆盖默认模板。 ```yaml # 用户自定义 .cnb.yml 配置 main: # 默认分支,可使用仓库实际默认分支代替 auto_tag: # 事件名 - stages: - name: auto tag image: 'cnbcool/git-auto-tag:latest' settings: tagFormat: 'v\${version}' branch: $CNB_BRANCH repoUrlHttps: $CNB_REPO_URL_HTTPS exports: tag: NEW_TAG - name: show tag script: echo $NEW_TAG ``` **注意:** 默认配置会与 .cnb.yml 合并,同分支名下后者的配置会覆盖前者。 如果 `.cnb.yml` 中 `auto_tag` 配置在 `$` 下而不是默认分支名下,两边的 `auto_tag` 配置都会保留, 但 `$` 下的配置会被忽略,参考 [include 合并规则](/cnb/build/configuration.md#合并规则) 合并模式。 #### tag\_deploy.\* 在仓库 `Tag/Release` 页面通过 `部署` 按钮触发的事件。 详情参考[部署](/cnb/build/deploy.md) ### Issue 事件 由 `Issue` 的相关操作触发的事件。 `Issue` 事件流水线配置需挂靠在 `$` 下。 #### issue.open `Issue` 创建的事件。 #### issue.close `Issue` 关闭的事件。 #### issue.reopen `Issue` 重新打开的事件。 ### api\_trigger 自定义事件 \{#api\_trigger} 事件名为 `api_trigger` 或者以 `api_trigger_` 开头,如 `api_trigger_test`。 API 自定义事件有以下三种触发方式: 1. 由 [cnb:apply](/cnb/build/internal-steps.md#cnb-apply) 触发 2. 由 [cnb:trigger](/cnb/build/internal-steps.md#cnb-trigger) 触发 1. 由 [OPENAPI](https://api.cnb.cool/#/Build/StartBuild) 触发 方式 1 和 2 是对方式 3 的封装 ### web\_trigger 自定义事件 \{#web\_trigger} 事件名为 `web_trigger` 或者 `web_trigger_` 开头,如 `web_trigger_test`。 仅支持在页面触发事件。 使用场景: - 可结合[部署](/cnb/build/deploy.md)能力使用 - 页面中的[自定义按钮](/cnb/build/web-trigger.md) 手动触发构建(支持输入环境变量,仅支持触发 `web_trigger` 事件) ### 定时任务 事件 由定时任务触发的事件。 详情参考[定时任务](/cnb/build/crontab.md)。 ### 云原生开发 事件 \{#vscode} 在页面点击 `云原生开发` 按钮触发的事件。 详情参考[云原生开发](/cnb/workspaces/intro.md) ## 代码版本选择 事件触发时需要确定对应的代码版本,获取、解析对应的 `.cnb.yml`,checkout 代码执行流水线。 通常代码版本符合直觉和触发分支一致,但对于一些事件如 `PR` 相关、`branch.delete` 等事件,会有额外考虑,代码版本与触发分支不一致。 下面列举在各个事件中,`云原生构建` 是如何选择使用哪个版本的代码: 1. 对于 `push`、`commit.add`、`branch.create`、`vscode` 事件,会选择当前分支最新 Commit。 2. 对于 `auto_tag`、`branch.delete`、`issue.*` 会选择默认分支最新 Commit。 3. 对于 `tag_push`、`tag_deploy.*` 事件,会选择当前 `Tag`。 4. 对于 `pull_request`、`pull_request.update`、`pull_request.approved`、`pull_request.changes_requested` 事件,有源分支和目标分支,取预合并后的代码版本。 5. 对于 `pull_request.merged` 事件,取合并后的代码版本。 6. 对于 `pull_request.target`、`pull_request.mergeable` 事件,取合并前目标分支最新 Commit。 7. api\_trigger 自定义事件,可以指定版本,[cnb:apply](/cnb/build/internal-steps.md#cnb-apply) 则限制为当前流水线对应代码版本。 8. web\_trigger 自定义事件,会从对应 分支、Tag 读取配置文件,参考具体应用场景。 9. 定时任务事件,从指定的分支读取配置文件。 10. 重新构建,取当前构建的的代码版本。 --- url: /cnb/build/configuration.md --- > For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /cnb/build/configuration.md. # 配置文件 ## 简介 云原生构建配置文件(`.cnb.yml`)描述了当仓库发生一些事件时(有新的 Commit 被推送、有新的 PR 请求等), `云原生构建` 是否应该启动构建任务,如果启动构建的话,构建任务的每一步分别做什么。 `云原生构建` 的配置文件格式是 `YAML`,这一点与业界主流 CI 服务相同。 这是一个简单的、可工作的 `云原生构建` 配置文件: ```yaml main: # 触发分支 push: # 触发事件 - docker: image: node:22 # 流水线执行环境,可以指定任意docker镜像 stages: - name: install script: npm install - name: test script: npm test ``` 这个案例描述的流程如下: 1. 声明了在 `main` 分支在收到 `push` 事件时(即有新的 Commit 推送到 main 分支) 2. 会选择 Docker 镜像 `node:22` 作为执行环境 3. 依次执行任务 `npm install` 和 `npm test` ## 存放位置 `云原生构建` 约定的配置文件命名为 `.cnb.yml`,存放于仓库根目录下,配置文件即代码。 这意味着,配置文件可以通过 PR 进行变更,开源协作场景下,这十分重要。 构建流程纳入版本管理,与源代码保持相同的透明度和变更流程,修改历史很容易追溯。 ## 基本语法结构 配置文件的基本语法结构如下所示: ```yaml # 流水线结构:数组形式 main: push: # main 分支 - push 事件包含两条流水线:push-pipeline1 和 push-pipeline2 - name: push-pipeline1 # 流水线名称,可省略 stages: - name: job1 script: echo 1 - name: push-pipeline2 # 流水线名称,可省略 stages: - name: job2 script: echo 2 pull_request: # main 分支 - pull_request 事件包含两条流水线:pr-pipeline1 和 pr-pipeline2 - name: pr-pipeline1 # 流水线名称,可省略 stages: - name: job1 script: echo 1 - name: pr-pipeline2 # 流水线名称,可省略 stages: - name: job2 script: echo 2 ``` 等价与以下写法: ```yaml # 流水线结构:对象形式 main: push: # main 分支 - push 事件包含两条流水线:push-pipeline1 和 push-pipeline2 push-pipeline1: # 流水线名称,必须唯一 stages: - name: job1 script: echo 1 push-pipeline2: # 流水线名称,必须唯一 stages: - name: job2 script: echo 2 pull_request: # main 分支 - pull_request 事件包含两条流水线:pr-pipeline1 和 pr-pipeline2 pr-pipeline1: # 流水线名称,必须唯一 stages: - name: job1 script: echo 1 pr-pipeline2: # 流水线名称,必须唯一 stages: - name: job2 script: echo 3 ``` 其中 `main` 表示分支名称, `push` 和 `pull_request` 表示[触发事件](/cnb/build/grammar.md#trigger-event)。 一个事件包含多个 `pipeline`,支持数组和对象两种形式,并发执行。 一个 `pipeline` 包含一组顺序执行的任务,在同一个构建环境(物理机、虚拟机或 Docker 容器)中执行。 详细语法说明可参考: [流水线语法](/cnb/build/grammar.md) ## 配置文件版本选择 同[代码版本选择](/cnb/build/trigger-rule.md#代码版本选择) ## 语法检查和自动补全 ### VSCode 推荐使用 [云原生开发](/cnb/workspaces/intro.md) 书写配置文件,因为原生支持语法检查和自动补全,效果如下: ![yaml-auto](https://docs.cnb.cool/images/yaml-auto.gif) 本地开发配置方法,以 VSCode 为例: 先安装 `redhat.vscode-yaml` 插件,然后在 `settings.json` 中加入以下配置: ```text "yaml.schemas": { "https://docs.cnb.cool/conf-schema-zh.json": ".cnb.yml" }, ``` ### Jetbrains ![yaml-auto](https://docs.cnb.cool/images/jetbrains.png) 1. 「Settings」「Languages & Frameworks」「Schemas and DTDs」「JSON Schema Mappings」 2. 点击新增按钮,设置 「Name」(名称随意填写) 3. 设置「Schema file or URL」 4. 「Add mapping for a file」 ```text https://docs.cnb.cool/conf-schema-zh.json ``` ## 配置复用 ### anchor 在 YAML 中,锚点(Anchor)和引用(Alias)允许同一个文件中复用配置,从而避免重复并保持文件的简洁。 示例: ```yaml # .cnb.yml # 通用的流水线配置 .pipeline-config: &pipeline-config stages: - echo "do something" main: push: # 引用 pipeline-config - *pipeline-config dev: push: # 引用 pipeline-config - *pipeline-config ``` ### include 利用 `include` 参数,可以在当前文件导入当前仓库或其他仓库上的文件。依此可以对配置文件进行拆分,方便复用和维护。 #### 使用示例 template.yml ```yaml # template.yml main: push: pipeline_2: env: ENV_KEY1: xxx ENV_KEY3: inner services: - docker stages: - name: echo script: echo 222 ``` .cnb.yml ```yaml # .cnb.yml include: - https://cnb.cool//-/blob/main/xxx/template.yml main: push: pipeline_1: stages: - name: echo script: echo 111 pipeline_2: env: ENV_KEY2: xxx ENV_KEY3: outer stages: - name: echo script: echo 333 ``` 合并后的配置 ```yaml main: push: pipeline_1: # key不存在,合并时新增 stages: - name: echo script: echo 111 pipeline_2: env: ENV_KEY1: xxx ENV_KEY2: xxx # key不存在,合并时新增 ENV_KEY3: outer # 同名 key, 合并时覆盖 services: - docker stages: # 数组在合并时,追加 - name: echo script: echo 222 - name: echo script: echo 333 ``` #### 语法说明 ```yaml include: # 1、可直接传入配置文件路径 - 'https://cnb.cool//-/blob/main/xxx/template.yml' - 'template.yml' # 2、可传入一个对象。 # path: 配置文件路径 # ignoreError:未读取到配置文件是否抛出错误。true 不抛出错误;false 抛出错误。默认为 false - path: 'template1.yml' ignoreError: true # 3、可传入一个对象 # config: 传入 yaml 配置 - config: main: push: - stages: - name: echo script: echo "hello world" ``` #### 合并规则 不同文件的流水线配置合并规则: - 数组(Array)和数组(Array)合并:子元素追加 - 对象(Map)和对象(Map)合并:同名 key 覆盖 - 数组(Array)和对象(Map)合并:仅保留数组 - 对象(Map)和数组(Array)合并:仅保留数组 引用配置文件权限控制参考 [配置文件引用鉴权](/cnb/build/file-reference.md) :::tip 合并后的流水线配置会展示在构建详情页,与密钥仓库内容保护的理念不符,include 无法引用密钥仓库文件。 ::: :::tip 1. 本地的 .cnb.yml 会覆盖 include 中的配置,include 数组中后面的配置会覆盖前面的配置。 2. 支持嵌套 include,include 的本地文件路径相对于项目根目录。 3. 最多支持 include 50个配置文件。 4. 不支持引用 submodule 中的文件。 5. 不支持跨文件使用 YAML 锚点功能。 ::: ### reference YAML 不支持跨文件引用,`云原生构建` 通过扩展 YAML 自定义标签 `reference` 实现按属性路径引用变量值,可结合 [include](#include) 跨文件复用配置。 :::tip 1. 第一层同名变量会被覆盖,不会合并。本地的 `.cnb.yml` 会覆盖 `include` 中的变量,`include` 数组中后面的变量会覆盖前面的变量。 2. `reference` 支持嵌套引用,最多 10 层。 ::: #### 示例 \{#reference-example} a.yml ```yaml .val1: echo1: echo hello .val2: friends: - one: name: tom say: !reference [.val1, echo1] ``` .cnb.yml ```yaml include: - ./a.yml .val3: size: 100 main: push: - stages: - name: echo hello script: !reference [.val2, friends, '0', say] - name: echo size env: SIZE: !reference ['.val3', 'size'] script: echo my size ${SIZE} ``` 解析后相当于: ```yaml main: push: - stages: - name: echo hello script: echo hello - name: echo size env: SIZE: 100 script: echo my size ${SIZE} ``` #### 进阶示例 可以将流水线作为整体配置引用: ```yaml .common-pipeline: - stages: - name: echo script: echo hello main: push: !reference [.common-pipeline] test: push: !reference [.common-pipeline] ``` 解析后相当于: ```yaml main: push: - stages: - name: echo script: echo hello test: push: - stages: - name: echo script: echo hello ``` #### VSCode 配置 安装 `VSCode YAML` 插件后, 为了在 `VSCode` 编写带自定义标签 `reference` 的 `YAML` 文件时不报错,需要如下配置: setting.json ```json { "yaml.customTags": ["!reference sequence"] } ``` :::tip 为避免编写时 `YAML` 插件根据 `Schema` 把第一层变量名当做分支名, 有错误提示,`reference` 所在的第一层变量名可用 `.` 开头,如:`.var`。 ::: --- url: /cnb/build/grammar.md --- > For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /cnb/build/grammar.md. # 流水线语法 ## 基本概念 - `Pipeline`: 表示一个流水线,包含一个或者多个阶段 `Stage`,每个 `Stage` 依次执行。 - `Stage`: 表示一个构建阶段,可以由一个或者多个任务 `Job` 组成。 - `Job`: 最基本的任务执行单元。 ```yaml main: # 触发分支 push: # 触发事件,对应一个构建,可以包含多条 Pipeline。即可以是数组,也可以是对象。 - name: pipeline-1 # Pipeline 结构体 stages: - name: stage-1 # Stage 结构体 jobs: - name: job-1 # Job 结构体 script: echo ``` ```yaml main: # 触发分支 push: # 触发事件,对应一个构建,通过对象指定流水线 pipeline-key: stages: - name: stage-1 # Stage 结构体 jobs: - name: job-1 # Job 结构体 script: echo ``` ## Pipeline `Pipeline` 表示一个流水线,包含一个或者多个阶段 `Stage`,每个 `Stage` 依次执行。 一个 `Pipeline` 的基本配置如下: ```yaml name: 流水线名字 docker: image: node build: dev/Dockerfile volumes: - /root/.npm:copy-on-write git: enable: true submodules: true lfs: true services: - docker env: TEST_KEY: TEST_VALUE imports: - https://cnb.cool//-/blob/main/xxx/envs.yml - ./env.txt label: type: MASTER class: MAIN stages: - name: stage 1 script: echo "stage 1" - name: stage 2 script: echo "stage 2" - name: stage 3 script: echo "stage 3" failStages: - name: fail stage 1 script: echo "fail stage 1" - name: fail stage 2 script: echo "fail stage 2" endStages: - name: end stage 1 script: echo "end stage 1" - name: end stage 2 script: echo "end stage 2" ifModify: - a.txt - 'src/**/*' retry: 3 allowFailure: false ``` ### name \{#pipeline-name} - type: `String` 指定流水线名,默认为 `pipeline`。当有多条并行流水线时, 默认流水线名为 `pipeline`、`pipeline-1`、`pipeline-2` 依此类推, 可定义 `name` 指定流水线名来区分不同流水线。 ### runner - type: `Object` 指定构建节点相关参数。 - `tags`: 可选,指定使用具备哪些标签的构建节点 - `cpus`: 可选,指定构建需使用的 cpu 核数 #### tags - type: `String` | `Array` - default: `cnb:arch:default` 指定使用具备哪些标签的构建节点。详见[构建节点](/cnb/build/build-node.md)。 示例: ```yaml main: push: - runner: tags: cnb:arch:amd64 stages: - name: uname script: uname -a ``` #### cpus - type: `Number` 指定构建需使用的最大 cpu 核数(memory = cpu 核数 \* 2 G), 其中 cpu 和 memory 不超过 runner 机器实际大小。 未配置,则最大可用 cpu 核数由分配到的 runner 机器配置来指定。 示例: ```yaml # cpus = 1,memory = 2G main: push: - runner: cpus: 1 stages: - name: echo script: echo "hello world" ``` ### docker - type: `Object` 指定 `docker` 相关的参数。详情见[构建环境](/cnb/build/build-env.md) - `image`: 当前 `Pipeline` 的环境镜像,在当前 `Pipeline` 下的所有任务都将在这个镜像环境中执行。 - `build`: 指定一个 `Dockerfile`,构建一个临时镜像,做为 `image` 的值使用。 - `volumes`: 声明数据卷,用于缓存场景。 #### image \{#pipeline-image} - type: `Object` | `String` 指定当前 `Pipeline` 的环境镜像,在当前 `Pipeline` 下的所有任务都将在这个镜像环境中执行,支持引用环境变量。 - `image.name`: `String` 镜像名,如 `node:20`。 - `image.dockerUser`: `String` 指定 Docker 用户名,用于拉取指定的镜像。 - `image.dockerPassword`: `String` 指定 Docker 用户密码,用于拉取指定的镜像。 如果指定 `image` 为字符串,则等同于指定了 `image.name`。 示例一,使用公开镜像: ```yaml main: push: - docker: # 取 docker 官方镜像仓库中的 node:20 镜像作为构建容器 image: node:20 stages: - name: show version script: node -v ``` 示例二,使用 CNB 制品库私有镜像: ```yaml main: push: - docker: # 取非公开镜像作为构建容器,需传入 docker 用户名和密码 image: name: docker.cnb.cool/images/pipeline-env:1.0 # 使用 CI 构建时默认注入的环境变量 dockerUser: $CNB_TOKEN_USER_NAME dockerPassword: $CNB_TOKEN stages: - name: echo script: echo "hello world" ``` 示例三,使用 docker 官方镜像源私有镜像: ```yaml main: push: - imports: https://cnb.cool//-/blob/main/xxx/docker.yml docker: # 取非公开镜像作为构建容器,需传入 docker 用户名和密码 image: name: images/pipeline-env:1.0 # docker.yml 中导入的环境变量 dockerUser: $DOCKER_USER dockerPassword: $DOCKER_PASSWORD stages: - name: echo script: echo "hello world" ``` docker.yml ```yaml DOCKER_USER: user DOCKER_PASSWORD: password ``` #### build - type: `Object` | `String` 指定一个 `Dockerfile`,构建一个临时镜像,做为 `image` 的值使用,支持引用环境变量。 使用 `build` 声明构建环境的完整示例可参考[docker-build-with-by](https://cnb.cool/examples/ecosystem/docker-build-with-by)。 以下是 `build` 下各参数的说明: - `build.dockerfile`: - type: `String` `Dockerfile`路径。 - `build.target`: - type: `String` 对应 docker build 中的 --target 参数,可以选择性地构建 Dockerfile 中的特定阶段,而不是构建整个 Dockerfile。 - `build.by`: - type: `Array` | `String` 用来声明缓存构建过程中依赖的文件列表。 **注意:未出现在 `by` 列表中的文件,除了 Dockerfile,其他在构建镜像过程中,都当不存在处理。** `String` 类型时,多个文件可用英文逗号分隔。 - `build.versionBy`: - type: `Array` | `String` 用来进行版本控制,所指向的文件内容发生变化,我们就会认为是一个新的版本, 具体的计算逻辑见这个表达式:sha1(dockerfile + versionBy + buildArgs)。 `String`类型时,多个文件可用英文逗号分隔。 - `build.buildArgs`: - type: `Object` 在 build 时插入额外的构建参数 (--build-arg $key=$value), value 值为 null 时只加入 key (--build-arg $key)。 - `build.ignoreBuildArgsInVersion`: - type: `Boolean` 版本计算是否忽略buildArgs。详见 `versionBy`。 - `build.sync`: - type: `String` 是否等待 `docker push` 成功后才继续。默认为`false`。 如果指定`build`为字符串,则等同于指定了`build.dockerfile`。 **Dockerfile 用法:** ```yaml main: push: - docker: # 通过 Dockerfile 指定构建环境 build: ./image/Dockerfile stages: - stage1 - stage2 - stage3 ``` ```yaml main: push: - docker: # 通过 Dockerfile 指定构建环境 build: dockerfile: ./image/Dockerfile dockerImageName: cnb.cool/project/images/pipeline-env dockerUser: $DOCKER_USER dockerPassword: $DOCKER_PASSWORD stages: - stage1 - stage2 - stage3 ``` ```yaml main: push: - docker: # 通过 Dockerfile 指定构建环境 build: dockerfile: ./image/Dockerfile # 只构建 builder,而不是整个Dockerfile target: builder stages: - stage1 - stage2 - stage3 ``` **Dockerfile versionBy 用法:** 示例:将 pnpm 缓存到环境镜像中,加速后续pnpm i过程 ```yaml main: push: # 通过 Dockerfile 指定构建环境 - docker: build: dockerfile: ./Dockerfile versionBy: - package-lock.json stages: - name: pnpm i script: pnpm i - stage1 - stage2 - stage3 ``` ```dockerfile FROM node:20 #替换真实的源 RUN npm config set registry https://xxx.com/npm/ \ && npm i -g pnpm \ && pnpm config set store-dir /lib/pnpm WORKDIR /data/orange-ci/workspace COPY package.json package-lock.json ./ RUN pnpm i ``` ```text [pnpm i] Progress: resolved 445, reused 444, downloaded 0, added 100 [pnpm i] Progress: resolved 445, reused 444, downloaded 0, added 141 [pnpm i] Progress: resolved 445, reused 444, downloaded 0, added 272 [pnpm i] Progress: resolved 445, reused 444, downloaded 0, added 444, done [pnpm i] [pnpm i] dependencies: [pnpm i] + mocha 8.4.0 (10.0.0 is available) [pnpm i] [pnpm i] devDependencies: [pnpm i] + babel-eslint 9.0.0 (10.1.0 is available) [pnpm i] + eslint 5.16.0 (8.23.0 is available) [pnpm i] + jest 27.5.1 (29.0.2 is available) [pnpm i] [pnpm i] [pnpm i] Job finished, duration: 6.8s ``` #### volumes - type: `Array` | `String` 声明数据卷,多个数据卷可用通过数组或者用`,`号做分割符传入,可引用环境变量,支持的格式有: 1. `::` 2. `:` 3. `` 各项含义: - `group`: 可选,数据卷分组,不同组间相互隔离 - `path`: 必填,数据卷挂载绝对路径,支持绝对路径(`/` 开头) 或 相对路径(`./` 开头),相对于工作区 - `type`: 可选,数据卷类型,**缺省值为 `copy-on-write`**,支持以下类型: - `read-write` 或 `rw` : 读写,并发写冲突需自行处理,适用于串行构建场景 - `read-only` 或 `ro` : 只读,写操作抛出异常 - `copy-on-write` 或 `cow` : 读写,变更(新增、修改、删除)在 **流水线成功** 后被合并,适用于并发构建场景 - `copy-on-write-read-only` : 只读,变更(新增、删除、修改)在流水线结束后丢弃 - `data` : 创建一个临时数据卷,该数据卷在流水线结束时会自动清理 ##### copy-on-write 用于缓存场景,支持并发 `copy-on-write` 技术允许系统在需要修改数据之前共享相同的数据副本,从而实现高效的缓存复制。 在并发环境中,这种方法避免了缓存的读写冲突,因为只有在实际需要修改数据时,才会创建数据的私有副本。 这样,只有写操作会导致数据复制,而读操作可以安全地并行进行,无需担心数据一致性问题。 这种机制显著提高了性能,尤其是在读多写少的缓存场景中。 ##### data 用于共享数据,将容器中的指定目录,共享给其他容器中使用。 通过创建数据卷,然后 mount 到各容器中。 与直接将构建节点上目录 mount 到容器中方式不同的是:当指定的目录在容器中已经存在, 会先把容器中内容自动复制到数据卷,而不是将数据卷内容直接覆盖容器中目录。 ##### volumes 示例 示例1 : 挂载构建节点上目录到容器中,实现本地缓存效果 ```yaml main: push: - docker: image: node:20 # 声明数据卷 volumes: - /data/config:read-only - /data/mydata:read-write # 使用缓存,同时更新 - /root/.npm # 使用 main 缓存,同时更新 - main:/root/.gradle:copy-on-write stages: - stage1 - stage2 - stage3 pull_request: - docker: image: node:20 # 声明数据卷 volumes: - /data/config:read-only - /data/mydata:read-write # 使用 copy-on-write 缓存 - /root/.npm - node_modules # pr 使用 main 缓存,但不更新 - main:/root/.gradle:copy-on-write-read-only stages: - stage1 - stage2 - stage3 ``` 示例2:将打包在容器中的文件,共享到其他容器中使用 ```yaml # .cnb.yml main: push: - docker: image: go-app-cli # 假设有个go应用在镜像的/go-app/cli路径下 # 声明数据卷 volumes: # 此路径在go-app-cli镜像存在,所以执行环境镜像时,会将此路径内容复制到临时数据卷中,可共享给其他任务容器里使用 - /go-app stages: - name: show /go-app-cli in job container image: alpine script: ls /go-app ``` ### git - type: `Object` 提供 Git 仓库相关配置。 #### git.enable - type: `Boolean` - default: `true` 指定是否拉取代码。 `branch.delete` 事件,默认值为 `false`。其他事件,默认值为 `true`。 #### git.submodules - type: `Object` | `Boolean` - default: - enable: `true` - remote: `false` 指定是否要拉取子项目(submodules)。 当值为 `Boolean` 类型时,相当于指定 `git.submodules.enable` 为 `git.submodules` 的值,`git.submodules.remote` 为默认值 `false`。 ##### git.submodules.enable - type: `Boolean` - default: `true` 是否指定是否要拉取子项目 `submodules`。 ##### git.submodules.remote - type: `Boolean` - default: `false` 执行 `git submodule update` 时是否添加 `--remote` 参数,用于每次拉取 `submodule` 最新的代码 **基本用法:** ```yaml main: push: - git: enable: true submodules: true stages: - name: echo script: echo "hello world" - git: enable: true submodules: enable: true remote: true stages: - name: echo script: echo "hello world" ``` #### git.lfs - type: `Object` | `Boolean` - default: `true` 指定是否要拉取 LFS 文件。 支持 `Object` 形式指定具体参数,字段缺省时,默认值为: ```json { "enable": true } ``` **基本用法:** ```yaml main: push: - git: enable: true lfs: true stages: - name: echo script: echo "hello world" - git: enable: true lfs: enable: true stages: - name: echo script: echo "hello world" ``` ##### git.lfs.enable 是否指定是否要拉取 LFS 文件。 ### services - type: `Array` 用于声明构建时需要的服务,格式:`name:[version]`, `version` 是可选的。 目前支持的服务有: - docker - vscode #### service:docker 用于开启 `dind` 服务, 当构建过程中需要使用 `docker build`,`docker login` 等操作时声明, 会自动在环境注入 `docker daemon` 和 `docker cli`。 示例: ```yaml main: push: - services: - docker docker: image: alpine stages: - name: docker info script: - docker info - docker ps ``` 该服务会自动 `docker login` 到 CNB Docker 制品库的镜像源(docker.cnb.cool), 在后续任务中可直接 `docker push` 到当前仓库 Docker 制品库。 示例: ```yaml main: push: - services: - docker stages: - name: build and push script: | # 根目录存在 Dockerfile 文件 docker build -t ${CNB_DOCKER_REGISTRY}/${CNB_REPO_SLUG_LOWERCASE}:latest . docker push ${CNB_DOCKER_REGISTRY}/${CNB_REPO_SLUG_LOWERCASE}:latest ``` #### service:vscode 需要远程开发时声明。 示例: ```yaml $: vscode: - services: - vscode - docker docker: image: alpine stages: - name: uname script: uname -a ``` ### env \{#pipeline-env} - type: `Object` 指定环境变量。可以定义一组环境变量,在任务执行中使用。对当前 `Pipeline` 内的非插件任务均有效。 ### imports \{#pipeline-imports} - type: `Array` | `String` 指定 CNB Git 仓库文件路径(文件相对路径或 http 地址),可以读取此文件作为环境变量来源。 本地相对路径如 `./env.yml` 会被拼接成远端 http 文件地址进行加载。 **`云原生构建` 现支持[密钥仓库](/cnb/repo/secret.md),安全性更高,支持文件引用审计,** **一般使用一个密钥仓库来存放诸如 `npm` 、 `docker` 等账号密码。** 示例: ```yaml #env.yml DOCKER_USER: 'username' DOCKER_TOKEN: 'token' DOCKER_REGISTRY: 'https://xxx/xxx' ``` ```yaml #.cnb.yml main: push: - services: - docker imports: - https://cnb.cool//-/blob/main/xxx/env.yml stages: - name: docker push script: | docker login -u ${DOCKER_USER} -p "${DOCKER_TOKEN}" ${CNB_DOCKER_REGISTRY} docker build -t ${DOCKER_REGISTRY}/${CNB_REPO_SLUG_LOWERCASE}:latest . docker push ${DOCKER_REGISTRY}/${CNB_REPO_SLUG_LOWERCASE}:latest ``` > 注意:对插件任务无效 支持的文件格式列表: - `yaml`:解析文件后缀为 `.yml` 或 `.yaml`。 - `json`: 解析文件后缀为 `.json`。 - `plain`: 每行格式为 `key=value`,除了以上涉及的后缀都以此方式解析。**(不推荐)** 同名 key 优先级: - 当配置 imports 为数组时,如遇到参数重复的情况,后面的配置会覆盖前面的。 - 如果和 `env` 参数中重复,那么 `env` 中的参数会覆盖掉 `imports` 文件中的。 变量赋值 `imports` 文件路径可读取环境变量。若是数组,下面的文件路径可读取上面文件中的变量。 ```javascript // env.json { FILE: 'https://cnb.cool//-/blob/main/xxx/env2.yml'; } ``` ```yaml # env2.yml TEST_TOKEN: some token ``` ```yaml main: push: - imports: - ./env1.json - $FILE stages: - name: echo script: echo $TEST_TOKEN ``` 被引用文件可声明可被访问范围,参考 [配置文件引用鉴权](/cnb/build/file-reference.md#权限检查)。 示例: `team_name/project_name/*`,匹配一个项目下面的所有仓库: ```yaml key: value allow_slugs: - team_name/project_name/* ``` 允许被所有仓库引用 ```yaml key: value allow_slugs: - '**' ``` 大部份场景配置文件是简单的单层对象,比如: ```javascript // env.json { "token": "private token", "password": "private password" } ``` 为了应对复杂的配置文件和场景,`imports` 支持对象嵌套!若引入的文件解析后的对象包含深层属性(第一层不能为数组),会平铺成单层对象,规则是: 1. 属性名保留,属性值会转成字符串 2. 属性值若为对象(包括数组),则会递归平铺,属性路径以 `_` 连接 ```javascript // env.json { "key1": [ "value1", "value2" ], "key2": { "subkey1": [ "value3", "value4" ], "subkey2": "value5" }, "key3": [ "value6", { "subsubkey1": "value7" } ], "key4": "value8" } ``` 会平铺成 ```javascript { // 原属性值转成字符串 "key1": "value1,value2", // 属性值若为对象,则额外进行递归平铺操作增加属性 "key1_0": "value1", "key1_1": "value2", "key2": "[object Object]", "key2_subkey1": "value3,value4", "key2_subkey1_0": "value3", "key2_subkey1_1": "value4", "key2_subkey2": "value5", "key3": "value6,[object Object]", "key3_0": "value6", "key3_1": "[object Object]", "key3_1_subsubkey1": "value7", "key4": "value8" } ``` ```yaml main: push: - imports: - ./env.json stages: - name: echo script: echo $key3_1_subsubkey1 ``` ### label - type: `Object` 为流水线指定标签。每个标签的值可以是一个字符串,也可以是一个字符串数组。该标签可用于后续流水线记录筛选等功能。 这里举一种工作流的例子:**main 分支合并即发布预发布环境,打 tag 后发布正式环境**。 ```yaml main: push: - label: # Master 分支的常规流水线 type: - MASTER - PREVIEW stages: - name: install script: npm install - name: CCK-lint script: npm run lint - name: BVT-build script: npm run build - name: UT-test script: npm run test - name: pre release script: ./pre-release.sh $: tag_push: - label: # 产品发布分支的常规流水线 type: RELEASE stages: - name: install script: npm install - name: build script: npm run build - name: DELIVERY-release script: ./release.sh ``` ### stages - type: `Array` 定义一组阶段任务,每个阶段串行运行。 ### failStages - type: `Array` 定义一组失败阶段任务。当正常流程失败,会依次执行此阶段任务。 ### endStages - type: `Array` 定义流水线结束阶段执行的一组任务。当流水线 stages/failStages 执行完,流水线结束前,会依次执行此阶段任务。 当流水线 prepare 阶段成功,无论 stages 是否成功,endStages 都将执行。 且 endStages 是否成功不影响流水线状态(即 endStages 失败,流水线状态也可能是成功)。 ### ifNewBranch \{#pipeline-ifnewbranch} - type: `Boolean` - default: `false` 为 `true` 表示当前分支属于新分支(即 `CNB_IS_NEW_BRANCH` 为 `true`)时,才执行此 `Pipeline`。 > 当同时存在 `ifNewBranch` / `ifModify` 时,其中有一个条件满足,此 `Pipeline` 就会执行。 ### ifModify \{#pipeline-ifmodify} - type: `Array` | `String` 指定只有相应文件变动时,才执行此 `Pipeline`。 是一个 `glob` 表达式字符串或字符串数组。 示例1: 当修改文件列表中包含 `a.js` 或者 `b.js`,会执行此 `Pipeline`。 ```yaml ifModify: - a.js - b.js ``` 示例2: 当修改文件列表中包含有 `js` 后缀的文件时,会执行此 `Pipeline`。 其中 `**/*.js` 表示匹配所有子目录中的 `js` 后缀文件,`*.js` 表示所有根目录中的 `js` 后缀文件。 ```yaml ifModify: - '**/*.js' - '*.js' ``` 示例3: 反向匹配,排除目录 legacy 和排除所有 Markdown 文件,有其他文件变更时触发 ```yaml ifModify: - '**' - '!(legacy/**)' - '!(**/*.md)' - '!*.md' ``` 示例4: 反向匹配,src 目录并且除目录 src/legacy 以外有变更时触发 ```yaml ifModify: - 'src/**' - '!(src/legacy/**)' ``` #### 支持事件 - 非新建分支的 `push` 事件,会对比 `before` 和 `after` 统计变更文件。 - 非新建分支的 `push` 事件流水线中通过 `cnb:apply` 触发的事件,变更文件统计规则同上。 - `PR` 触发的事件,统计 `PR` 中的变更文件。 - `PR` 触发的事件通过 `cnb:apply` 触发的事件,统计 `PR` 中的变更文件。 因为文件变更可能非常多,变更文件的统计限制为最多300个。 ### breakIfModify \{#pipeline-breakifmodify} - type: `Boolean` - default: `false` `Job` 执行前,如果源分支已更新,则终止构建。 ### retry \{#pipeline-retry} - type: `Number` - default: `0` 失败重试次数, `0` 表示不重试。 ### allowFailure \{#pipeline-allowfailure} - type: `Boolean` - default: `false` 是否允许当前流水线 失败。 当此参数设置为 `true` 时,流水线的失败的状态不会上报到 CNB 上。 ### lock \{#pipeline-lock} - type: `Object` | `Boolean` 给 `pipeline` 设置锁,`pipeline` 执行完后自动释放锁,锁不能跨仓库使用。 表现: 流水线 A 获取到锁后,流水线 B 再申请锁,可以终止A或等待A执行完释放锁后,获取到锁再继续执行任务。 - key: - type: `String` 自定义锁名,默认为 `分支名-流水线名`,既锁范围默认为当前 `pipeline` - expires: - type: `Number` - default: `3600`(一小时) 锁过期时间,过期后自动释放锁,单位“秒”。 - timeout: - type: `Number` - default: `3600`(一小时) 超时时间,用于等待锁的场景下,单位“秒”。 - cancel-in-progress: - type: `Boolean` - default: `false` 是否终止占用锁或等待锁的流水线,让当前流水线获取锁并执行 - wait: - type: `Boolean` - default: `false` 锁被占用是否等待(不占用流水线资源和耗时),为 false 则直接报错,不能与 `cancel-in-progress` 同时使用 - cancel-in-wait: - type: `Boolean` - default: `false` 是否终止正在等待锁的流水线,让当前流水线加入等待锁队列。需配合`wait`属性使用。 若 `lock` 为 true,则 `key`、 `expires`、 `timeout`、 `cancel-in-progress`、 `wait`、 `cancel-in-wait`为各自默认值。 例1: lock 是 Boolean 格式 ```yaml main: push: - lock: true stages: - name: stage1 script: echo "stage1" ``` 例2: lock 是 Object 格式 ```yaml main: push: - lock: key: key expires: 600 # 10分钟 wait: true timeout: 60 # 最多等待 1分钟 stages: - name: stage1 script: echo "stage1" ``` 例3: 停止 pull\_request 下上一条正在进行的流水线 ```yaml main: pull_request: - lock: key: pr cancel-in-progress: true stages: - name: echo hello script: echo "stage1" ``` ## Stage - type: `Job` | `Object` `Stage` 表示一个构建阶段,可以由一个或者多个 `Job` 组成,见 [Job 介绍](#job)。 ### 单个 Job 如果一个 `Stage` 只有一个 `Job`,那么可以省掉 `Stage` 直接书写这个 `Job`。 ```yaml stages: - name: stage1 jobs: - name: job A script: echo hello ``` 可以简化为以下写法: ```yaml - stages: - name: job A script: echo hello ``` **当 `Job` 为字符串时,可以视作脚本任务,name 和 script 取该字符串,可以继续简化为:** ```yaml - stages: - echo hello ``` #### 串行 Job 当值为数组(有序)时,那么这组 `Job` 会串行执行。 ```yaml # 串行 stages: - name: install jobs: - name: job1 script: echo "job1" - name: job2 script: echo "job2" ``` #### 并行 Job 当值为对象(无序)时,那么这组 `Job` 会并行执行。 ```yaml # 并行 stages: - name: install jobs: job1: script: echo "job1" job2: script: echo "job2" ``` 多个 `Job` 串行、并行可灵活组织。 先串行后并行的示例: ```yaml main: push: - stages: - name: serial first script: echo "serial" - name: parallel jobs: parallel job 1: script: echo "1" parallel job 2: script: echo "2" - name: serial next script: echo "serial next" ``` ### name \{#Stage-name} - type: `String` `Stage` 名称。 ### ifNewBranch \{#stage-ifnewbranch} - type: `Boolean` - default: `false` 为 `true` 表示只有当前分支属于新分支(即 `CNB_IS_NEW_BRANCH` 为 `true`)时,才执行此 `Stage`。 > 当同时存在 `ifNewBranch` / `ifModify` / `if` 有一个条件满足,此 `Stage` 就会执行 ### ifModify \{#stage-ifmodify} - type: `Array` | `String` 指定只有相应文件变动时,才执行此 `Stage`。 是一个 `glob` 匹配表达式字符串或字符串数组。 ### if \{#stage-if} - type: `Array` | `String` 一个或者多个 Shell 脚本,根据脚本执行的退出程序码(exit code)来判断是否执行此 `Stage`。 当退出程序码为 `0` 时,表示需要执行本步骤。 示例1:判断某个变量的值 [shell表达式语法](https://linux.die.net/man/1/test) ```yaml main: push: - env: IS_NEW: true stages: - name: is new if: | [ "$IS_NEW" = "true" ] script: echo is new - name: is not new if: | [ "$IS_NEW" != "true" ] script: echo not new ``` 示例2: 判断任务执行的输出 ```yaml main: push: - stages: - name: make info script: echo 'haha' exports: info: RESULT - name: run if RESULT is haha if: | [ "$RESULT" = "haha" ] script: echo $RESULT ``` ### env \{#stage-env} - type: `Object` 同 [Pipeline env](#pipeline-env),只对当前 `Stage` 生效。 `Stage env` 优先级比 `Pipeline env` 高。 ### imports \{#stage-imports} - type: `Array` | `String` 同 [Pipeline imports](#pipeline-imports),只对当前 `Stage` 生效1。 ### retry \{#stage-retry} - type: `Number` - default: `0` 失败重试次数,`0` 表示不重试。 ### lock \{#stage-lock} - type: `Boolean` |`Object` 给 `Stage` 设置锁,`Stage` 执行完后自动释放锁,锁不能跨仓库使用。 表现: 任务 A 获取到锁后,任务 B 再申请锁,将等待锁释放后,才能获取到锁继续执行任务。 - lock.key - type: `String` 自定义锁名,默认值为 `分支名-流水线名-stage下标` - lock.expires - type: `Number` - default: `3600`(一小时) 锁过期时间,过期后自动释放锁,单位“秒”。 - lock.wait - type: `Boolean` - default: `false` 锁被占用是否等待。 - lock.timeout - type: `Number` - default: `3600`(一小时) 指定等待锁的超时时间,单位“秒”。 若 `lock` 为 true,则 `key`、 `expires`、 `timeout`、 `cancel-in-progress`、 `wait`、 `cancel-in-wait`为各自默认值。 例1: `lock` 是 `Boolean` 格式 ```yaml main: push: - stages: - name: stage1 lock: true jobs: - name: job1 script: echo "job1" ``` 例2: `lock` 是 `Object` 格式 ```yaml main: push: - stages: - name: stage1 lock: key: key expires: 600 # 10分钟 wait: true timeout: 60 # 最多等待 1分钟 jobs: - name: job1 script: echo "job1" ``` ### image \{#Stage-image} - type: `Object` | `String` 指定当前 `Stage` 的环境镜像,在当前 `Stage` 下的所有任务默认都将在这个镜像环境中执行。 - `image.name`: `String` 镜像名,如 `node:20`。 - `image.dockerUser`: `String` 指定 Docker 用户名,用于拉取指定的镜像。 - `image.dockerPassword`: `String` 指定 Docker 用户密码,用于拉取指定的镜像。 如果指定 `image` 为字符串,则等同于指定了 `image.name`。 ### jobs - type: `Array` | `Object` 定义一组任务,每个任务串行/并行运行。 - 当值为数组(有序)时,那么这组 `Job` 会串行执行。 - 当值为对象(无序)时,那么这组 `Job` 会并行执行。 ## Job `Job` 是最基本的任务执行单元,可以分为三类: ### 内置任务 - type: - type: `String` 指定该步骤所要执行的 [内置任务](/cnb/build/internal-steps.md)。 - options: - type: `Object` 指定内置任务的相应参数。 - optionsFrom: - `Array` | `String` 指定本地或 Git 仓库文件路径,加载为内置任务参数。与 `imports` 参数类似,配置 `optionsFrom` 为数组时,如遇到参数重复的情况,后面的配置会覆盖前面的。 `options` 中同名字段优先级高于 `optionsFrom`。 引用配置文件权限控制参考 [配置文件引用鉴权](/cnb/build/file-reference.md#权限检查)。 示例: ```yaml name: install type: INTERNAL_JOB_NAME optionsFrom: ./options.json options: key1: value1 key2: value2 ``` ```json // ./options.json { "key1": "value1", "key2": "value2" } ``` ### 脚本任务 ```yaml - name: install script: npm install ``` - script: - type: `Array` | `String` 指定该步骤所要执行的 `shell` 脚本。数组会默认使用 `&&` 连接。 如果希望 `script` 拥有自己的运行环境,而不是在 pipeline 所在环境执行,可以通过 `image` 属性指定运行环境。 - image: - type: `String` 指定脚本运行环境。 示例: ```yaml - name: install image: node:20 script: npm install ``` **脚本任务可以简化为字符串,此时 script 取该字符串,name 取该字符串第一行:** ```yaml - echo hello ``` 相当于: ```yaml - name: echo hello script: echo hello ``` ### 插件任务 插件即 Docker 镜像,也可称为镜像任务。 不同于以上两类任务,`插件任务` 具有执行环境更自由的特点。 而且更易在团队、公司内外分享,甚至可以跨 CI 复用。 `插件任务` 通过向 `ENTRYPOINT` 传递环境变量的方式,来达到隐藏内部实现的目的。 > 注意:通过 imports、env 等参数设置的自定义环境变量不会传递给插件,但可以用在 settings、args中的变量替换。CNB 系统环境变量依然会传递给插件 - name: - type: `String` 指定 `Job` 名称。 - image: - type: `String` 镜像的完整路径。 - settings: - type: `Object` 指定该插件任务参数。按照镜像提供方的文档填写即可。也可以通过 `$VAR` 或者 `${VAR}` 取到环境变量。 - settingsFrom: - type: `Array` | `String` 指定本地或 Git 仓库文件路径,加载为插件任务参数。 优先级: - 如遇到参数重复的情况,后面的配置会覆盖前面的。 - `settings` 中同名字段优先级高于 `settingsFrom`。 引用配置文件权限控制参考 [配置文件引用鉴权](/cnb/build/file-reference.md#权限检查)。 示例: 同时限制 `images` 和 `slugs`: ```yaml allow_slugs: - a/b allow_images: - a/b ``` 仅限制 `images`,不限制 `slug`: ```yaml allow_images: - a/b ``` `settingsFrom` 可以写在 `Dockerfile` 中: ```dockerfile FROM node:20 LABEL cnb.cool/settings-from="https://cnb.cool//-/blob/main/xxx/settings.json" ``` #### 示例 with imports: ```yaml - name: npm publish image: plugins/npm imports: https://cnb.cool//-/blob/main/xxx/npm.json settings: username: $NPM_USER password: $NPM_PASS email: $NPM_EMAIL registry: https://mirrors.xxx.com/npm/ folder: ./ ``` ```json { "username": "xxx", "password": "xxx", "email": "xxx@emai.com", "allow_slugs": ["cnb/**/**"], "allow_images": ["plugins/npm"] } ``` with settingsFrom: ```yaml - name: npm publish image: plugins/npm settingsFrom: https://cnb.cool//-/blob/main/xxx/npm-settings.json settings: # username: $NPM_USER # password: $NPM_PASS # email: $NPM_EMAIL registry: https://mirrors.xxx.com/npm/ folder: ./ ``` ```json { "username": "xxx", "password": "xxx", "email": "xxx@emai.com", "allow_slugs": ["cnb/cnb"], "allow_images": ["plugins/npm"] } ``` ### name \{#job-name} - type: `String` 指定 `Job` 名称。 ### ifModify \{#job-ifmodify} - type: `Array` | `String` 同 [Stage ifModify](#stage-ifmodify)。只对当前 `Job` 生效。 ### ifNewBranch \{#job-ifnewbranch} - type: `Boolean` - default: `false` 同 [Stage ifNewBranch](#stage-ifnewbranch)。只对当前 `Job` 生效。 ### if \{#job-if} - type: `Array` | `String` 同 [Stage if](#stage-if)。只对当前 `Job` 生效。 ### breakIfModify \{#job-breakifmodify} - type: `Boolean` - default: `false` 同 [Pipeline breakIfModify](#pipeline-breakifmodify)。不同点在于只对当前 `Job` 生效。 ### skipIfModify \{#job-skipifmodify} - type: `Boolean` - default: `false` `Job` 执行前,如果源分支已更新,则跳过当前 `Job`。 ### env \{#job-env} - type: `Object` 同 [Stage env](#stage-env),只对当前 `Job` 生效。 `Job env` 优先级比 `Pipeline env`、`Stage env` 高。 ### imports \{#job-imports} - type: `Array` | `String` 同 [Stage imports](#stage-imports),只对当前 `Job` 生效。 ### exports \{#job-exports} - type: `Object` `Job` 执行结束后,有一个 `result` 对象,可通过 `exports` 将 `result` 中的属性导出到环境变量,生命周期为当前 `Pipeline`。 详情请见 [环境变量](/cnb/build/env.md#导出环境变量) ### timeout - type: `Number` | `String` 设置单个任务的超时时间,默认为 1 小时,最大不能超过 12 小时。 对 `script-job` 和 `image-job` 有效。 同时支持以下单位: - `ms`: 毫秒(默认) - `s` : 秒 - `m` : 分钟 - `h` : 小时 ```yaml name: timeout job script: sleep 1d timeout: 100s #任务将在100秒后超时退出 ``` 详见 [超时策略](/cnb/build/timeout.md) ### allowFailure \{#job-allowfailure} - type: `Boolean` | `String` - default: `false` 为 `true` 表示本步骤如果失败,也不会影响接下来流程的执行,并且不会影响最后的结果。 值为 `String` 类型时可以读取环境变量 ### lock \{#job-lock} - type: `Object` | `Boolean` 给 `Job` 设置锁,`Job` 执行完后自动释放锁,锁不能跨仓库使用。 表现: 任务 A 获取到锁后,任务 B 再申请锁,将等待锁释放后,才能获取到锁继续执行任务。 - lock.key - type: `String` 自定义锁名,默认为 `分支名-流水线名-stage下标-job名` - lock.expires - type: `Number` - default: `3600`(一小时) 锁过期时间,过期后自动释放锁,单位“秒”。 - lock.wait - type: `Boolean` - default: `false` 锁被占用是否等待。 - lock.timeout - type: `Number` - default: `3600`(一小时) 指定等待锁的超时时间,单位“秒”。 若 `lock` 为 true,则 `key`、 `expires`、 `timeout`、 `cancel-in-progress`、 `wait`、 `cancel-in-wait`为各自默认值。 例1: lock 是 Boolean 格式 ```yaml name: 锁 lock: true script: echo 'job 锁' ``` 例2: lock 是 Object 格式 ```yaml name: 锁 lock: key: key expires: 10 wait: true script: echo 'job 锁' ``` ### retry \{#job-retry} - type: `Number` - default: `0` 失败重试次数,`0` 表示不重试。 ### type - type: `String` 指定该步骤所要执行的 [内置任务](/cnb/build/internal-steps.md)。 ### options - type: `Object` 指定内置任务参数。 ### optionsFrom - type: `Array` | `String` 指定本地或 Git 仓库文件路径,加载为内置任务参数。与 `imports` 参数类似,配置 `optionsFrom` 为数组时,如遇到参数重复的情况,后面的配置会覆盖前面的。 `options` 同名字段优先级高于 `optionsFrom`。 ### script - type: `Array` | `String` 指定任务要执行的脚本。为数组时会自动使用 `&&` 拼接。执行脚本的进程退出码会作为这个 `Job` 的退出码。 **注意: 流水线使用的基础镜像的默认命令行解释器是 `sh`,指定不同的 image 作为执行环境,命令行解释器可能有所不同** ### commands - type: `Array` | `String` 作用同 `script` 参数, 优先级比 `script` 高。主要为了兼容 `Drone CI` 语法。 ### image \{#job-image} - type: `Object` | `String` 指定用哪个 Image 作为当前 `Job` 执行环境, 用于 `docker image as env` 或 `docker image as plugins` - `image.name`: `String` 镜像名,如 `node:20`。 - `image.dockerUser`: `String` 指定 Docker 用户名,用于拉取指定的镜像。 - `image.dockerPassword`: `String` 指定 Docker 用户密码,用于拉取指定的镜像。 如果指定 `image` 为字符串,则等同于指定了 `image.name`。 ### settings - type: `Object` 指定该插件任务执行所需的参数。详细[插件任务介绍](#插件任务) ### settingsFrom - `Array` | `String` 指定本地或 Git 仓库文件路径,加载为插件任务参数。与 `imports` 参数类似,配置 `settingsFrom` 为数组时,如遇到参数重复的情况,后面的配置会覆盖前面的。 详细[插件任务介绍](#插件任务) ### args - `Array` 指定执行镜像时传递的参数,内容将会追加到 `ENTRYPOINT` 中,仅支持数组。 ```yaml - name: npm publish image: plugins/npm args: - ls ``` 将执行 ```bash docker run plugins/npm ls ``` ### 任务退出码 - 0: 任务成功, 继续执行。 - 78: 任务成功,但中断当前 `Pipeline` 的执行。可在自定义脚本中主动执行 `exit 78` ,达到中断流水线效果。 - other: `Number`,任务失败,同时中断当前 `Pipeline` 的执行。 --- url: /cnb/build/build-env.md --- > For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /cnb/build/build-env.md. # 构建环境 构建环境确定了在运行构建任务的时候,环境中拥有哪些软件和工具,例如 JDK、Node、Python 等。 `云原生构建` 使用 Docker 容器作为构建环境。 相比于传统的虚拟机容器,Docker 容器有非常巨大的优势,行业中各个 CI 厂商也在向这方面发展。 拥有 Docker 相关知识和容器开发经验,有助于理解和使用 `云原生构建` ## 配置方式 流水线构建环境的配置方式有两种: 1. **指定一个 image** 这些镜像是之前由其他人制作出来并且推送到镜像仓库中的。 若为私有镜像,还需配置对应的用户名和密码才能使用。 参考语法[pipeline.docker.image](/cnb/build/grammar.md#pipeline-image) 2. **指定一个 Dockerfile** 在构建开始时,`云原生构建` 会先依据一些规则计算镜像版本号,若当前构建节点或远端镜像仓库中存在此版本镜像,则直接使用。 否则,`云原生构建` 会用 Dockerfile 通过 `docker build` 的方式制作、生成镜像后,再使用它,同时推送到流水线所属仓库的 Docker 制品库,供后续使用。 参考语法[pipeline.docker.build](/cnb/build/grammar.md#build) 流水线指定的构建环境将作为该流水线下脚本任务的默认构建环境。 另外,脚本任务还可以单独指定 Image 作为该任务的构建环境,此时无法指定 Dockerfile。 参考语法[脚本任务](/cnb/build/grammar.md#脚本任务)。 ### 指定 Image ```yaml main: push: - docker: # 通过此参数控制使用的 image image: node:22 stages: - stage1 - stage2 - stage3 ``` 用 [pipeline.docker.image](/cnb/build/grammar.md#image) 参数指定 Docker Image。 其值可以是 公网中的官方镜像源或其他可以被访问到的镜像源 中的公开镜像。 ### 指定 Dockerfile ```yaml main: push: - docker: # 通过此参数控制使用的 Dockerfile build: ./image/Dockerfile stages: - stage1 - stage2 - stage3 ``` 用 [pipeline.docker.build](/cnb/build/grammar.md#build) 参数指定 Dockerfile。 ### 缺省镜像 当未指定 image 和 Dockerfile 时,image 会被设置为缺省镜像:[cnbcool/default-build-env:latest](https://cnb.cool/cnb/cool/default-build-env) ```yaml main: push: - stages: - stage1 - stage2 - stage3 # 未指定 image 和 Dockerfile 相当于如下声明 # docker: # image: cnbcool/default-build-env:latest ``` ### 镜像中的 VOLUME 镜像中可能包含`VOLUME`命令。 用**插件任务**的容器启动时会通过 `--volumes-from` 参数,将这些 volume 共享给 **插件任务**。 例如,在 Dockerfile 中准备了文件: ```dockerfile RUN mkdir /cache && echo 'hello world' > /cache/data.txt VOLUME /cache ``` 在后续的 image-commands 中也可以访问到它。 ```yaml - name: image-commands中访问pipeline volume image: alpine commands: - cat /cache/data.txt ``` ## 使用案例 ### NodeJS 当需要使用 NodeJS 的构建环境时,可以直接使用 Docker Hub 之中的官方 NodeJS 镜像。 ```yaml main: push: - docker: image: node:20 stages: - name: 依赖安装 script: npm install - name: 测试用例检查 script: npm test ``` --- url: /cnb/build/build-node.md --- > For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /cnb/build/build-node.md. # 构建集群 当您在使用云原生构建时,本质上是将构建任务下发到各构建集群中执行。集群以指定的 Docker 镜像作为构建环境执行构建任务。 ## 配置方式 在流水线配置里指定 `pipeline.runner.tags` 属性,即可选择不同构建集群。指定 `pipeline.runner.cpus` 属性,即可配置需使用的最大 `CPU` 核数。 云原生构建会以实际分配的 `核数` 乘以 流水线的耗时,作为流水线使用的核时。 官方可用构建集群 `tags` 及可声明的 `cpus` 如下: 1. `cnb:arch:amd64` 代表 `amd64` 架构的 `CPU` 集群 - `cpus` 可配置范围为 1 \~ 64,默认为 8 2. `cnb:arch:arm64:v8` 代表 `arm64/v8` 架构的 `CPU` 集群 - `cpus` 可配置范围为 1 \~ 16,默认为 8 3. `cnb:arch:amd64:gpu` 代表 `amd64` 架构的 `GPU` 集群 - `cpus` 固定为 32 - `GPU` 显存最大为 96GB,共享模式 4. `cnb:arch:amd64:gpu:L20` 代表 `amd64` 架构的 `GPU` 集群 - `cpus` 固定为 16 - `GPU` 显存最大为 48GB,共享模式 示例: ```yaml main: push: # 指定在 amd64 架构构建集群上执行 - runner: tags: cnb:arch:amd64 stages: - name: uname script: uname -a # 指定在 arm64/v8 架构构建集群上执行 - runner: tags: cnb:arch:arm64:v8 stages: - name: uname script: uname -a # 启动一个能使用 gpu 的远程开发环境 $: vscode: - runner: tags: cnb:arch:amd64:gpu services: - vscode ``` --- url: /cnb/build/env.md --- > For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /cnb/build/env.md. # 环境变量 在构建过程中可以使用环境变量,`云原生构建` 内置了一些[默认环境变量](/cnb/build/build-in-env.md)。 ## 声明环境变量 1. 通过 `env` 声明环境变量 2. 在 `Pipeline` 里声明的环境变量对当前 `Pipeline` 有效 3. 在 `Job` 里声明的环境变量对当前 `Job` 有效 ```yaml main: push: - env: RELEASE_MSG: release message stages: - name: release type: git:release env: RELEASE_NAME: release-1 options: description: ${RELEASE_MSG} name: ${RELEASE_NAME} ``` ## 导入环境变量 1. 通过 `imports` 导入一个密钥仓库文件,可将敏感信息注入到环境变量,供后续任务使用。 2. 当 `env` 和 `imports` 的 `key` 冲突时,优先使用 `env` ```yaml main: push: - services: - docker # 导入密钥仓库文件为环境变量 imports: https://cnb.cool//-/blob/main/xxx/envs.yml stages: - name: docker info script: docker info - name: docker login # 其中 TEST_DOCKER_DOMAIN、TEST_DOCKER_USER、TEST_DOCKER_PWD 为密钥仓库文件中的变量 script: docker login $TEST_DOCKER_DOMAIN -u $TEST_DOCKER_USER -p $TEST_DOCKER_PWD ``` `https://cnb.cool//-/blob/main/xxx/envs.yml` 内容示例 ```yaml # docker 镜像源域名 TEST_DOCKER_DOMAIN: registry.example.com # docker 用户名 TEST_DOCKER_USER: your_docker_username # docker 密码 TEST_DOCKER_PWD: your_docker_password ``` ## 变量名限制 在 Shell 中,环境变量名的命名规则有一些限制。根据 POSIX 标准,环境变量名应符合以下规则: 1. 只能包含字母(大小写均可)、数字和下划线(\_)字符。 2. 第一个字符不能是数字。 不符合上述规则的变量会被忽略 ## 导出环境变量 `Job` 执行结束后,有一个 `result` 对象,可通过 [exports](/cnb/build/grammar.md#exports) 将 `result` 中的属性导出到环境变量,生命周期为当前 `Pipeline`。 语法格式为: ```yaml exports: from-key: to-key ``` - `from-key` 要导出的 `Job result` 对象中的属性名,支持环境变量,支持深层取值,参考 `lodash.get`。 - `to-key` 映射到环境变量中的变量名。 有如下三种方式设置 result: - 脚本任务执行结果 - 解析输出中的自定义变量 - 内置任务的 result ### 脚本任务执行结果 `script` 自定义脚本任务执行完,`Job result`的属性有: - `code`: 返回码 - `stdout`: 标准输出 - `stderr`: 标准错误 - `info`: 标准输出、标准错误,按时序的混合体 **注意:可使用 `printf "%s" "hello\nworld"` 来输出变量,以消除标准输出流最后的换行符,同时保留 `\n` 等转义字符。** ```yaml main: push: - stages: - name: set env script: echo -n $(date "+%Y-%m-%d %H:%M") exports: code: CUSTOM_ENV_DATE_CODE info: CUSTOM_ENV_DATE_INFO - name: echo env script: - echo $CUSTOM_ENV_DATE_CODE - echo $CUSTOM_ENV_DATE_INFO ``` 包含 `if`、`ifModify`、`ifNewBranch` 等判断逻辑时,可设置的属性有: - `skip`: 如果执行上述判断逻辑后跳过任务执行则返回跳过原因,否则为空字符串。 ```yaml - name: use if if: exit -1 exports: skip: REASON - name: tell last # $REASON 的值为 if 这个字符串 script: echo $REASON ``` ### 解析输出中的自定义变量 CI 会从标准输出流里按行识别 `##[set-output key=value]` 格式的内容,自动放入 `result` 对象中。 若变量值包含换行符 `\n`,可对变量值进行 `base64` 或 `escape` 编码。 变量值若以 `base64,` 开始,`云原生构建` 会对 `base64,` 后面的内容做 `base64` 解码,否则会对变量值做 `unescape` 解码。 使用 `Node.js` 示例代码如下: ```javascript // test.js const value = '测试字符串\ntest string'; // 输出 base64 编码的变量值 console.log( `##[set-output redline_msg_base64=base64,${Buffer.from(value, 'utf-8').toString('base64')}]` ); // 输出 escape 编码的变量值 console.log(`##[set-output redline_msg_escape=${escape(value)}]`); ``` ```yaml main: push: - docker: image: node:20-alpine stages: - name: set output env script: node test.js # 将 test.js 输出的变量导出为环境变量 exports: redline_msg_base64: BASE64_KEY redline_msg_escape: ESCAPE_KEY - name: echo env script: - echo "BASE64_KEY $BASE64_KEY" - echo "ESCAPE_KEY $ESCAPE_KEY" ``` 使用 `echo` 示例代码如下: ```yaml main: push: - stages: - name: set output env script: echo "##[set-output redline_msg_base64=base64,$(echo -e "测试字符串\ntest string" | base64 -w 0)]" exports: redline_msg_base64: BASE64_KEY - name: echo env script: - echo -e "BASE64_KEY $BASE64_KEY" ``` **注意:在 Unix-like 系统中,base64 命令默认会在每76个字符后添加一个换行符,可使用 `-w 0` 选项来禁用换行避免 CI 未能按行解析出变量。** 不包含 `\n` 的变量值可直接输出 ```bash echo "##[set-output redline_msg=some value]" ``` :::tip 受限于系统环境变量值长度限制,过大的变量值无效。 CI 会忽略大于等于 `100KB` 的变量值。可写入文件中自行解析。 对于敏感信息,建议使用 [read-file](/cnb/build/internal-steps.md#read-file) 内置任务。 ::: ### 内置任务中导出环境变量 一些内置任务会有输出结果,可通过 `exports` 导出为环境变量。 ```yaml main: push: - stages: - name: xxxx type: xxx:xxx options: product: public name: cnb dist: release/ exports: version: CUSTOM_ENV_VERSION url: CUSTOM_ENV_URL #支持对象深层取值 nextRelease.gitTag: CUSTOM_ENV_GIT_TAG - name: echo env script: - echo $CUSTOM_ENV_VERSION - echo $CUSTOM_ENV_URL ``` `result` 内容参考各内置任务文档。 ### 增删改查环境变量 可以覆盖已有的环境变量,设为空字符串或 null 即为删除。 ```yaml main: push: - env: CUSTOM_ENV_DATE_INFO: default CUSTOM_ENV_FOR_DELETE: default stages: - name: set env script: echo -n $(date "+%Y-%m-%d %H:%M") exports: # 新增 code: CUSTOM_ENV_DATE_CODE # 修改 info: CUSTOM_ENV_DATE_INFO # 删除 CUSTOM_ENV_FOR_DELETE: null # 删除 # CUSTOM_ENV_FOR_DELETE: - name: echo env script: - echo $CUSTOM_ENV_DATE_CODE - echo $CUSTOM_ENV_DATE_INFO - echo $CUSTOM_ENV_DATE_STDOUT - echo $CUSTOM_ENV_FOR_DELETE - echo $CUSTOM_ENV_GIT_TAG ``` ## 使用环境变量 ### 在 脚本任务 中使用 执行脚本任务时,流水线设置的环境变量作为任务执行时的环境变量 ```yaml main: push: - stages: - name: test internal env # CNB_BRANCH 为内置环境变量 script: echo $CNB_BRANCH - name: test self defined env env: cat_name: tomcat script: echo $cat_name ``` ### 变量替换 配置文件中的一些属性值会进行变量替换。 如有环境变量 `env_name=env_value`,那么属性值中 `$env_name` 会被替换成 `env_value`,若 `env_name` 无值,则会替换成空字符串。 下面列出了会进行变量替换的属性: - 内置任务 内置任务 options 内的属性值和 optionsFrom 会进行变量替换。 ```yaml # options.yml name: Nightly ``` ```yaml main: push: - env: address: options.yml description: publish for xx task stages: - name: git release type: git:release # $address 会被替换成 env 中的 "options.yml" optionsFrom: $address # options.yml 中的 name 会合并到 options 中 options: # $description 会被替换成 env 中的 "publish for xx task" description: $description ``` options 的最终内容为: ```yaml name: Nightly description: publish for xx task ``` - 插件任务 插件任务 settings 内的属性值和 settingsFrom 会进行变量替换。 ```yaml # settings.yml robot: https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx ``` ```yaml main: push: - env: address: settings.yml message: pr check stages: - name: notify image: tencentcom/wecom-message # $address 会被替换成 env 中的 "settings.yml" settingsFrom: $address # settings.yml 中的 robot 会合并到 settings 中 settings: # $message 会被替换成 env 中的 "pr check" content: $message ``` settings 的最终内容为: ```yaml robot: https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx message: pr check ``` 另外写在 Dockerfile 中的 `LABEL` 指定的 `settingsFrom` 同样可以进行变量替换 ```dockerfile FROM node:20 LABEL cnb.cool/settings-from="$address" ``` - env env 下声明的属性值可以引用上层 env 中的变量进行替换 ```yaml # .cnb.yml main: push: - env: cat_name: tomcat stages: - name: echo env env: # 使用上层 env 声明的 cat_name 值进行替换 name: 'cat $cat_name' # 输出 cat tomcat script: echo $name ``` - imports imports 的属性值以及所声明的文件中的属性值均会进行变量替换。 若 imports 为数组,数组前面文件中声明的变量对数组后面元素有效。 ```yaml # env1.yml address: env2.yml platform: amd64 ``` ```yaml # env2.yml # 读取 env1.yml 中的 platform 属性值进行替换 action: build for $platform ``` ```yaml # .cnb.yml main: push: - imports: - env1.yml # env1.yml 中声明了 address,$address 会被替换成 env2.yml - $address stages: - name: echo action # 读取 env2.yml 中的 action 属性值进行替换 script: echo $action ``` - pipeline.runner.tags ```yaml # 构建不同架构下的镜像 .build: &build runner: tags: cnb:arch:$CNB_PIPELINE_NAME services: - docker stages: - name: docker build script: echo "docker build for $CNB_PIPELINE_NAME" main: push: # 下面 "amd64" 和 "arm64:v8" 会被声明为内置环境变量 CNB_PIPELINE_NAME 的值 amd64: *build 'arm64:v8': *build ``` - pipeline.docker.volumes ```yaml .docker-volume: &docker-volume docker: image: node:22-alpine volumes: - $volume_path main: push: install: env: volume_path: node_modules <<: *docker-volume stages: - name: install script: npm install axios # 通知其他流水线执行 - name: resolve type: cnb:resolve options: key: install build: env: volume_path: node_modules <<: *docker-volume stages: # 等待 install 流水线 - name: await type: cnb:await options: key: install - name: ls script: ls node_modules ``` - ifModify ```yaml # 不同模块下代码有变更才进行对应模块的编译 .build: &build ifModify: $CNB_PIPELINE_NAME/* stages: - name: build $CNB_PIPELINE_NAME script: echo "build $CNB_PIPELINE_NAME" main: push: module-a: *build module-b: *build ``` - name pipeline.name 、stage.name 和 job.name 的属性值会进行变量替换。 ```yaml main: push: - name: build in $CNB_REPO_SLUG env: platform: amd64 imports: - env1.yml - env2.yml stages: - name: stage_$SOME_ENV script: echo "hello world" ``` - lock.key ```yaml # env.yml build_key: build key ``` ```yaml .build: &build imports: env.yml lock: key: $build_key stages: - name: echo script: echo "hello world" main: push: # 以下两条流水线,一条占用了锁成功执行,另一条位占到锁执行失败 - *build - *build ``` - allowFailure ```yaml main: push: - env: allow_fail: true stages: - name: echo allowFailure: $allow_fail # 脚本执行会报错,但 allowFailure 为 true,任务被认为是成功的 script: echo1 1 ``` ### 阻止变量替换 如果不希望 `$env_name` 被替换,可以通过 `\$` 阻止替换 ```yaml main: push: - stages: - name: git release type: git:release options: name: Development # 属性值是 "some code update $description" description: some code update \$description ``` ## 限制 环境变量名需由字母、数字或 `_` 组成,不能以数字开头。 变量值的长度不能超过 `100KiB`。 --- url: /cnb/build/build-in-env.md --- > For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /cnb/build/build-in-env.md. # 默认环境变量 `云原生构建` 内置了一些默认环境变量,只可读不可写,如果构建过程中尝试覆盖默认环境变量不会生效。 下文 `合并类事件` 包含以下六种: - `pull_request` - `pull_request.update` - `pull_request.target` - `pull_request.approved` - `pull_request.changes_requested` - `pull_request.mergeable` - `pull_request.merged` - `pull_request.comment` 了解更多[触发事件](/cnb/build/trigger-rule.md#trigger-event)。 \[\[TOC]] ## 基础变量 ### CI true ### CNB true ### CNB\_WEB\_PROTOCOL 当前 web 使用的协议,http | https ### CNB\_WEB\_HOST 当前 web 使用的 HOST ### CNB\_WEB\_ENDPOINT 当前 web 使用的地址,包含协议、HOST、路径(如有) ### CNB\_API\_ENDPOINT 当前 API 地址,包含协议、HOST、路径(如有) 可与 `CNB_TOKEN` 配合在 CI 中调用 API 接口 ### CNB\_GROUP\_SLUG 仓库所属组织路径 ### CNB\_GROUP\_SLUG\_LOWERCASE 仓库所属组织路径(小写格式) ### CNB\_EVENT 值为触发构建的事件名称 事件类型参见[事件](/cnb/build/trigger-rule.md#trigger-event) ### CNB\_EVENT\_URL - 对于由 ==合并类事件== 触发的构建,值为该 `PR` 的链接 - 对于由 `push`、`commit.add`、`branch.create`、`tag_push` 触发的构建,值为最新 `Commit` 的链接 - 否则值为空字符串 ### CNB\_BRANCH - 对于由 `push`、`commit.add`、`branch.create`、`branch.delete` 触发的构建,值为当前的分支名 - 对于由 `合并类事件` 触发的构建,值为目标分支的分支名 - 对于由 `tag_push` 触发的构建,值为 `tag` 名 - 对于由 `自定义事件` 触发的构建,值为对应的分支名称 - 对于由 `crontab` 触发的构建,值为对应的分支名称 ### CNB\_BRANCH\_SHA - 对于 `branch.delete` 触发的构建,为空字符串 - 其他情况为 `CNB_BRANCH` 最近一次提交的 `sha` ### CNB\_DEFAULT\_BRANCH 仓库默认分支 ### CNB\_TOKEN\_USER\_NAME 用户临时令牌对应的用户名,固定为 `cnb` ### CNB\_TOKEN 用户令牌,可用于代码提交、API 调用等 对于 pull\_request 事件,权限有: - `repo-code:r` - `repo-pr:r` - `repo-issue:r` - `repo-notes:rw` - `repo-contents:r` - `repo-registry:r` - `repo-commit-status:rw` - `account-profile:r` 对于非 pull\_request 事件,权限有: - `repo-code:rw` - `repo-pr:rw` - `repo-issue:rw` - `repo-notes:rw` - `repo-contents:rw` - `repo-registry:rw` - `repo-commit-status:rw` - `repo-cnb-trigger:rw` - `repo-cnb-history:r` - `repo-cnb-detail:r` - `repo-basic-info:r` - `repo-manage:r` - `account-profile:r` - `group-resource:r` 权限含义参考页面 个人设置 页面的 访问令牌 ### CNB\_TOKEN\_FOR\_AI 用户令牌,在 合并类事件 中由 AI 使用 权限有: - repo-notes:rw 权限含义参考页面 `个人设置` 页面的 访问令牌 ### CNB\_IS\_CRONEVENT 是否是定时任务事件 ### CNB\_DOCKER\_REGISTRY 制品库 Docker 源地址 ### CNB\_HELM\_REGISTRY 制品库 Helm 源地址 ## 提交类变量 ### CNB\_BEFORE\_SHA - 对于由 `push`、`commit.add` 触发的构建,值为分支推送前远端仓库该分支最近一次提交的 `sha`,若是新建分支,值为 `0000000000000000000000000000000000000000` - 对于 `branch.create` 触发的构建,值为 `0000000000000000000000000000000000000000` ### CNB\_COMMIT 构建时对应的代码 sha - 对于 `push`、`commit.add`、`branch.create` 触发的构建,是最后一次提交的 `sha` - 对于 `tag_push`、`tag_deploy.*` 触发的构建,是该 `tag` 最后一次提交的 `sha` - 对于 `auto_tag`、`branch.delete`、`issue.*` 类事件,是主分支最后一次提交的 `sha` - 对于 `pull_request.merged` 触发的构建,是合并后的 `sha` - 对于 `pull_request.target`、`pull_request.mergeable` 触发的构建,是目标分支最后一次提交的 `sha` - 对于 `pull_request`、`pull_request.approved`、`pull_request.changes_requested`、`pull_request.comment`,代码尚未真正合并,取源分支最后一次提交的 `sha`,但构建时会进行预合并,即合并后的内容会作为最终结果 - 对于 `云原生开发`、`自定义事件` 触发的构建,是指定分支的最后一次提交的 `sha` ### CNB\_COMMIT\_SHORT `CNB_COMMIT` 的缩写,取其前 8 位字符 ### CNB\_COMMIT\_MESSAGE CNB\_COMMIT 对应的提交信息 ### CNB\_COMMIT\_MESSAGE\_TITLE `CNB_COMMIT_MESSAGE` 的 `title` 部分,即首行 ### CNB\_COMMITTER `CNB_COMMIT` 对应的提交者 ### CNB\_COMMITTER\_EMAIL `CNB_COMMITTER` 对应的邮箱 ### CNB\_NEW\_COMMITS\_COUNT 对于由 `commit.add` 触发的构建,值为新增的 `Commits` 的数量,最大为 99。 可结合 `git log -n` 查看新增的 `Commits`。 ### CNB\_IS\_TAG 对于分支为 `Tag` 的构建,值为 ture ### CNB\_TAG\_MESSAGE - `Tag message`:对于分支为 `Tag` 的构建, 会有该环境变量 - 否则值为空字符串 ### CNB\_TAG\_RELEASE\_TITLE - `Release 标题`:对于分支为 `Tag` 的构建, 如果 `Release` 标题不为空,才会有值 - 否则值为空字符串 ### CNB\_TAG\_RELEASE\_DESC - `Release 描述`:对于分支为 `Tag` 的构建, 且 `Release` 描述不为空,才会有值 - 否则值为空字符串 ### CNB\_TAG\_IS\_RELEASE - `Tag 是否存在对应的 Release`:对于分支为 Tag 的构建,如果 `Tag` 存在对应的 `Release`,则为 true - 否则为 `false` ### CNB\_TAG\_IS\_PRE\_RELEASE - 对于分支为 Tag 的构建,若存在对应的 `Release`,且 `Release` 为 预发布,则值为 `true` - 否则为 false ### CNB\_IS\_NEW\_BRANCH 当前分支是否属于一个新创建的分支,默认为 `false` ### CNB\_IS\_NEW\_BRANCH\_WITH\_UPDATE 当前分支是否属于一个新创建的分支,且带有新 commit,默认为 `false` ## 仓库类变量 ### CNB\_REPO\_SLUG 目标仓库路径,格式为 `group_slug/repo_name`,`group_slug/sub_gourp_slog/.../repo_name` ### CNB\_REPO\_SLUG\_LOWERCASE 目标仓库路径小写格式 ### CNB\_REPO\_NAME 目标仓库名称 ### CNB\_REPO\_NAME\_LOWERCASE 目标仓库名称小写格式 ### CNB\_REPO\_ID 目标仓库的 `id` ### CNB\_REPO\_URL\_HTTPS 目标仓库仓库 https 地址 ## 构建类变量 ### CNB\_BUILD\_ID 当前构建的流水号,全局唯一 ### CNB\_BUILD\_WEB\_URL 当前构建的日志地址 ### CNB\_BUILD\_START\_TIME 当前构建的开始时间,UTC 格式,示例 `Tue, 24 Dec 2024 07:42:58 GMT` ### CNB\_BUILD\_USER 当前构建的触发者名称 ### CNB\_BUILD\_USER\_ID 当前构建的触发者 `id` ### CNB\_BUILD\_STAGE\_NAME 当前构建的 `stage` 名称 ### CNB\_BUILD\_JOB\_NAME 当前构建的 `job` 名称 ### CNB\_BUILD\_JOB\_KEY 当前构建的 `job` key,同 `stage` 下唯一 ### CNB\_BUILD\_WORKSPACE 自定义 `shell` 脚本执行的工作空间根目录 ### CNB\_BUILD\_FAILED\_MSG 流水线构建失败的错误信息,可在 `failStages` 中使用 ### CNB\_BUILD\_FAILED\_STAGE\_NAME 流水线构建失败的 `stage` 的名称,可在 `failStages` 中使用 ### CNB\_PIPELINE\_NAME 当前 `pipeline` 的 `name`,没声明时为空 ### CNB\_PIPELINE\_KEY 当前 `pipeline` 的索引 `key`,例如 `pipeline-0` ### CNB\_PIPELINE\_ID 当前 `pipeline` 的 `id`,全局唯一字符串 ### CNB\_PIPELINE\_DOCKER\_IMAGE 当前 `pipeline` 所使用的 `docker image`,如:`alpine:latest` ### CNB\_PIPELINE\_STATUS 当前流水线的构建状态,可在 `endStages` 中查看,其可能的值包括: - `success`:表示流水线构建成功完成。 - `error`:表示流水线构建过程中发生了错误。 - `cancel`:表示流水线构建被取消。 ### CNB\_RUNNER\_IP 当前 `pipeline` 所在 `Runner` 的 `ip` ### CNB\_CPUS 当前构建流水线可以使用的最大 `CPU` 核数 ### CNB\_MEMORY 当前构建流水线可以使用的最大 `内存` 大小,单位为 `GiB` ### CNB\_IS\_RETRY 当前构建是否由 `rebuild` 触发 ### HUSKY\_SKIP\_INSTALL 兼容 ci 环境下 husky ## 合并类变量 ### CNB\_PULL\_REQUEST - 对于由 `pull_request`、`pull_request.update`、`pull_request.target` 触发的构建,值为 `true` - 否则值为 `false` ### CNB\_PULL\_REQUEST\_LIKE - 对于由 `合并类事件` 触发的构建,值为 `true` - 否则值为 `false` ### CNB\_PULL\_REQUEST\_PROPOSER - 对于由 `合并类事件` 触发的构建,值为提出 `PR` 者名称 - 否则值为空字符串 ### CNB\_PULL\_REQUEST\_TITLE - 对于由 `合并类事件` 触发的构建,值为提 `PR` 时候填写的标题 - 否则值为空字符串 ### CNB\_PULL\_REQUEST\_BRANCH - 对于由 `合并类事件` 触发的构建,值为发起 `PR` 的源分支名称 - 否则值为空字符串 ### CNB\_PULL\_REQUEST\_SHA - 对于由 `合并类事件` 触发的构建,值为当前 `PR` 源分支最新的提交 `sha` - 否则值为空字符串 ### CNB\_PULL\_REQUEST\_TARGET\_SHA - 对于由 `合并类事件` 触发的构建,值为当前 `PR` 目标分支最新的提交 `sha` - 否则值为空字符串 ### CNB\_PULL\_REQUEST\_MERGE\_SHA - 对于由 `pull_request.merged` 事件触发的构建,值为当前 `PR` 合并后的 `sha` - 对于由 `pull_request`、`pull_request.update`、`pull_request.target`、`pull_request.mergeable`、`pull_request.comment` 触发的构建,值为当前 `PR` 预合并后的 `sha` - 否则值为空字符串 ### CNB\_PULL\_REQUEST\_SLUG - 对于由 `合并类事件` 触发的构建,值为源仓库的仓库 slug,如 `group_slug/repo_name`,`group_slug/sub_gourp_slog/.../repo_name` - 否则值为空字符串 ### CNB\_PULL\_REQUEST\_ACTION 对于由 `合并类事件` 触发的构建,可能的值有: - created: 新建 PR - code\_update: 源分支 push - status\_update: 评审通过或 CI 状态变更时 `PR` 变成可合并 否则值为空字符串 ### CNB\_PULL\_REQUEST\_ID - 对于由 `合并类事件` 触发的构建,值为当前或者关联 `PR` 的全局唯一 `id` - 否则值为空字符串 ### CNB\_PULL\_REQUEST\_IID - 对于由 `合并类事件` 触发的构建,值为当前或者关联 `PR` 在仓库中的编号 `iid` - 否则值为空字符串 ### CNB\_PULL\_REQUEST\_REVIEWERS - 对于由 `合并类事件` 触发的构建,值为评审人列表,多个以 `,` 分隔 - 否则值为空字符串 ### CNB\_PULL\_REQUEST\_REVIEW\_STATE 对于由 `合并类事件` 触发的构建 - 有评审者且有人通过评审,值为 `approve` - 有评审者但无人通过评审,值为 `unapprove` - 否则值为空字符串 ### CNB\_REVIEW\_REVIEWED\_BY - 对于由 `合并类事件` 触发的构建,值为同意评审的评审人列表,多个以 `,` 分隔 - 否则值为空字符串 ### CNB\_REVIEW\_LAST\_REVIEWED\_BY - 对于由 `合并类事件` 触发的构建,值为最后一个同意评审的评审人 - 否则值为空字符串 ## 远程开发类变量 ### CNB\_VSCODE\_WEB\_URL 远程开发地址,仅声明了 `services : vscode` 时存在 ## Issue 类变量 ### CNB\_ISSUE\_ID - 对于 `issue.*` 触发的构建,值为 `Issue` 全局唯一 `ID` - 否则值为空字符串 ### CNB\_ISSUE\_IID - 对于 `issue.*` 触发的构建,值为 `Issue` 在仓库中的编号 `iid` - 否则值为空字符串 ### CNB\_ISSUE\_TITLE - 对于 `issue.*` 触发的构建,值为 `Issue` 的 `title` - 否则值为空字符串 ### CNB\_ISSUE\_DESCRIPTION - 对于 `issue.*` 触发的构建,值为 `Issue` 的 `description` - 否则值为空字符串 ### CNB\_ISSUE\_OWNER - 对于 `issue.*` 触发的构建,值为 `Issue` 作者用户名 - 否则值为空字符串 ### CNB\_ISSUE\_STATE - 对于 `issue.*` 触发的构建,值为 `Issue` 状态:`open`、`closed` - 否则值为空字符串 ### CNB\_ISSUE\_IS\_RESOLVED - 对于 `issue.*` 触发的构建,表示 `Issue` 是否被解决:`true`、`false` - 否则值为空字符串 ## 评论类变量 ### CNB\_COMMENT\_ID - 对于评论事件触发的构建,值为评论全局唯一 `ID` - 否则值为空字符串 ### CNB\_COMMENT\_BODY - 对于评论事件触发的构建,值为评论内容 - 否则值为空字符串 --- url: /cnb/build/timeout.md --- > For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /cnb/build/timeout.md. # 超时策略 云原生构建中,每个流水线或者任务都有最长执行时长限制,超过时长,将自动推出。 ## 流水线超时 流水线最长使用时间 `20h`,超过 `20h`,流水线容器将自动销毁 ## 任务超时 ### 无输出超时 默认每个 `Job` 如果连续 `10min` 内,输出流没有任何内容,会触发超时。 如果有声明 [timeout](/cnb/build/grammar.md#timeout) 参数, 则无输出超时时间改为 `timeout`,同 `Job` 超时时长。 ### 最大超时时间 默认整个 `Job` 执行时长超过 `1h`,会触发超时逻辑。 如果有声明 [timeout](/cnb/build/grammar.md#timeout) 参数, 则超时时间改为 `timeout`,但最大不能超过 `12h`。 --- url: /cnb/build/permission.md --- > For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /cnb/build/permission.md. # 权限说明 云原生构建的权限对齐`代码仓库`的权限。具体表现在: - 具有代码仓库写权限的用户,即可触发云原生构建。 - 具有代码仓库读权限的用户,即可查看云原生构建日志。 --- url: /cnb/build/faq.md --- > For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /cnb/build/faq.md. # 常见问题 问题反馈前,建议先在下面常见问题和 [feedback](https://cnb.cool/cnb/feedback) 中查看问题是否已经存在。 若未能找到答案,请于 `feedback` 中提交 `issue`。 \[\[TOC]] ## 流水线为什么没触发 要定位流水线没触发问题,先要了解流水线从触发到执行的流程。 以 `push` 事件为例: ```mermaid flowchart LR commit(git commit) --> push(git push) --> config(CI 读取对应分支下 .cnb.yml) --> event(获取对应分支 push 事件配置) --> skip(skip 检测) --> 流水线执行 ``` > 其中 `skip 检测` 包括 `ifNewBranch`、`ifModify`,参考[语法](/cnb/build/grammar.md#Pipeline-ifModify)。 那么可以按照这个流程一层层查下去: 1. 代码是否 push 到远端 2. 对应分支是否有 `.cnb.yml` 3. 是否配了 `push` 事件流水线 4. 是否命中了 skip 检测 ## 在本地明明好的,为什么在 CI 上跑失败了 要定位这个问题,首先要明确本地环境和 CI 环境的区别: | | 本地 | CI 环境 | | ----- | -------------- | --------------- | | 网络 | 本地网络(比如一些办公内网) | CI 机器所在网络 | | 文件 | 本地整个目录下所有文件 | Git仓库对应分支代码 | | 环境 | 原生 | 指定的 Docker 容器环境 | | Shell | 本地指定 | sh | 了解到差异,我们可以依次排查: 1. 是否访问了本地内网才能访问的资源。 2. 是否有文件未提交。 3. 构建依赖的文件是否命中 .gitignore。 4. 本地运行相同的镜像,得到与 CI 相同的构建环境,进行调试。 `云原生构建` 的默认镜像为 [cnbcool/default-build-env](https://cnb.cool/cnb/cool/default-build-env)。 那么,我们可以执行下面命令,进入默认 CI 环境进行调试 ```bash docker run --rm -it -v $(pwd):$(pwd) -w $(pwd) cnbcool/default-build-env:latest sh ``` 如果声明了其他镜像作为流水线构建环境,请将上述命令中 `cnbcool/default-build-env:latest` 替换成对应镜像地址。 ## 如何登录到流水线容器调试 参考 [登录调试](/cnb/build/login-debug.md) ## 流水线执行脚本和登陆调试执行脚本结果不一样 流水线里的默认使用 sh,登陆调试的是 bash。 如果确认指定的流水线容器是支持bash的(默认的流水线容器是支持的,但如果是自定义容器,可能不支持),可以把执行脚本改成 bash xxx.sh 或者 bash -c '\{原来的语句}'。 ## 超时无输出 一个 job 如果超过 10 分钟没有 log 输出,那么就会被终止掉。可以考虑增加 log,例如针对 `npm install` 的情况,可以加上 verbose 参数。 注意这个跟 job 的 timeout 声明的超时不一样,不能通过配置修改。 ## 没改代码为什么流水线就失败了 可以检查依赖的其他资源是否有变动,比如: 1. 插件任务声明镜像版本为 latest,镜像是否有变动。 2. CI 配置文件引用了其他仓库文件,被引用文件是否有变动。 3. 有可能网络波动,Rebuild 试试。 ### 代码合并冲突 若创建 PR 或在 PR 相关事件的构建中碰到代码冲突问题,可以通过如下命令解决: ```bash git fetch origin # 从远端仓库获取更新 git rebase -i origin/main # 实际的目标分支名 # 本地处理冲突 git commit # 根据实际情况提交代码到本地仓库 git push -f # 推送到远端仓库 ``` ## 流水线报错 docker not found? 在 `Pipeline` 配置的 `services` 字段中需声明 `docker` 服务: ```yaml services: - docker # 声明 Docker 服务以使用 docker 命令 ``` --- url: /cnb/build/internal-steps.md --- > For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /cnb/build/internal-steps.md. # 内置任务 在每一阶段(Stage)操作中,除了使用自定义任务, CNB 还扩展了一些常用的内置任务,以供开发者使用。 ## Docker ### cache \{#docker-cache} `docker:cache` \==Docker 缓存==,构建一个 `Docker` 镜像作为缓存,在未来的构建中重复使用。 可以避免网络资源如 `依赖包` 重复下载。 - [适用事件](#docker-cache-applicable-events) - [参数](#docker-cache-parameters) - [输出结果](#docker-cache-output) - [配置样例](#docker-cache-configuration-examples) #### 适用事件 \{#docker-cache-applicable-events} [所有事件](/cnb/build/trigger-rule.md#trigger-event) #### 参数 \{#docker-cache-parameters} - [dockerfile](#docker-cache-parameters-dockerfile) - [by](#docker-cache-parameters-by) - [versionBy](#docker-cache-parameters-versionBy) - [buildArgs](#docker-cache-parameters-buildArgs) - [target](#docker-cache-parameters-target) - [sync](#docker-cache-parameters-sync) - [ignoreBuildArgsInVersion](#docker-cache-parameters-ignoreBuildArgsInVersion) ##### dockerfile \{#docker-cache-parameters-dockerfile} - type: `String` - required: `true` 用于构建缓存镜像的 Dockerfile 路径。 为避免超长时间构建,Docker 镜像构建超时时间受 [job.timeout](/cnb/build/grammar.md#timeout) 参数控制。 ##### by \{#docker-cache-parameters-by} - type: `Array` | `String` - required: `false` 用来声明缓存镜像构建过程中依赖的文件列表。**注意:未出现在 by 列表中的文件,除了 Dockerfile,其他在构建镜像过程中,都当不存在处理。** - 支持数组格式 - 支持字符串格式,多个文件用英文逗号分隔。 ##### versionBy \{#docker-cache-parameters-versionBy} - type: `Array` | `String` - required: `false` 用来进行版本控制,未传入 `versionBy`,则默认取 `by` 的值进行版本控制。 `versionBy` 所指向的文件内容发生变化,我们就会认为是一个新的版本, 具体的计算逻辑见这个表达式:sha1(Dockerfile + versionBy + buildArgs + target + arch)。 - 支持数组格式。 - 支持字符串格式,多个文件用英文逗号分隔。 ##### buildArgs \{#docker-cache-parameters-buildArgs} - type: `Object` - required: `false` 在 build 时插入额外的构建参数 (`--build-arg $key=$value`), value 值为 null 时只加入 key (`--build-arg $key`)。 ##### target \{#docker-cache-parameters-target} - type: `String` - required: `false` 对应 docker build 中的 --target 参数,可以选择性地构建 Dockerfile 中的特定阶段,而不是构建整个 Dockerfile。 ##### sync \{#docker-cache-parameters-sync} - type: `Boolean` - required: `false` - default: `false` 是否同步模式,等待缓存镜像 `docker push` 成功后才继续。 ##### ignoreBuildArgsInVersion \{#docker-cache-parameters-ignoreBuildArgsInVersion} - type: `Boolean` - required: `false` - default: `false` 版本计算是否忽略 `buildArgs`。 详见`版本控制` #### 输出结果 \{#docker-cache-output} ```javascript { // 缓存对应的 docker image name name; } ``` #### 配置样例 \{#docker-cache-configuration-examples} ```yaml main: push: - docker: image: node:14 stages: - name: build cache image type: docker:cache options: dockerfile: cache.dockerfile # by 支持以下两种形式:数组、字符串 by: - package.json - package-lock.json # versionBy: package-lock.json versionBy: - package-lock.json exports: name: DOCKER_CACHE_IMAGE_NAME - name: use cache image: $DOCKER_CACHE_IMAGE_NAME # 将 cache 中的文件拷贝过来使用 commands: - cp -r "$NODE_PATH" ./node_modules - name: build with cache script: - npm run build ``` 其中,`cache.dockerfile` 是一个用于构建缓存镜像的 Dockerfile。示例: ```dockerfile # 选择一个 Base 镜像 FROM node:14 # 设置工作目录 WORKDIR /space # 将 by 中的文件列表 COPY 过来 COPY . . # 根据 COPY 过来的文件进行依赖的安装 RUN npm ci # 设置好需要的环境变量 ENV NODE_PATH=/space/node_modules ``` ## cnb ### await \{#cnb-await} 参见 [await-resolve](#cnb-await-resolve) ### resolve \{#cnb-resolve} 参见 [await-resolve](#cnb-await-resolve) ### await-resolve \{#cnb-await-resolve} - `cnb:await` - `cnb:resolve` `await` 会等待 `resolve` 的执行,`resolve` 可以向 `await`传递变量。 通过 `await-resolve`,可以让多个并发的 `pipeline` 相互配合,实现更灵活的顺序控制。 :::tip `await-resolve` 同 `apply`、`trigger` 的区别: 前者指一个构建中某 `pipeline` 执行到 `await` 任务时等待对应 `key` 的 `resolve` 通知才会继续进行。 后者指一个 `pipeline` 触发新事件,开启新的构建。可以跨仓库。可以异步调用,也可以同步等待。 ::: - [使用限制](#cnb-await-resolve-usage-limitations) - [死锁检测](#cnb-await-resolve-deadlock-detection) - [适用事件](#cnb-await-resolve-applicable-events) - [await 参数](#cnb-await-resolve-await-parameters) - [resolve 参数](#cnb-await-resolve-resolve-parameters) - [输出结果](#cnb-await-resolve-output) #### 使用限制 \{#cnb-await-resolve-usage-limitations} 1. 只能对同一个事件触发的 `pipeline` 进行 `await` 和 `resolve` 操作 2. 一个 `key` 仅能 `resolve` 一次,但可以 `await` 多次 3. 通过 `key` 对 `await` 和 `resolve` 进行分组 #### 死锁检测 \{#cnb-await-resolve-deadlock-detection} `await` 和 `resolve` 相互配合可以完成灵活的流程控制,但也会引入更复杂的边界情况,比如: 1. `pipeline-1` 和 `pipeline-2` 相互 `await`,即:死锁 2. 多条 `pipeline` 间存在 `await` 环,即:间接死锁 3. `await` 一个不存在的 `key`,或者 `key` 没有关联 `resolve`,即:无限等待 4. `resolve` 所在 `pipeline` 执行失败,对应的 `await` 陷入无限等待 5. 多个 `resolve` 任务关联同一个 `key`,即重复 `resolve` 抛出异常 `死锁检测` 机制会自动检测以上异常,结束 `await` 的等待状态,抛出 `dead lock found.` 异常。 `await` 和 `resolve` 的在配置文件中顺序不影响运行结果,即最后 `await` 任务一定是会等待相应的 `resolve` 完成,这种情况不会被`死锁检测`机制终止。 #### 适用事件 \{#cnb-await-resolve-applicable-events} [所有事件](/cnb/build/trigger-rule.md#trigger-event) #### await 参数 \{#cnb-await-resolve-await-parameters} ##### key \{#cnb-await-resolve-await-parameters-key} - type: String - required: true 配对 ID ##### resolve 参数 \{#cnb-await-resolve-resolve-parameters} ###### key \{#cnb-await-resolve-resolve-parameters-key} - type: String - required: true 配对 ID ###### data \{#cnb-await-resolve-resolve-parameters-data} - type: object - required: false 要传递的对象 `key: value` 格式,支持多级。示例: ```yaml - name: resolve a json type: cnb:resolve options: key: demo data: a: 1 b: c: 2 ``` `await` 任务的结果,是 `resolve` 声明的 `data` 对象。 可以通过 `exports` 访问这个对象,示例: ```yaml - name: await a json type: cnb:await options: key: demo exports: a: VAR_A b.c: VAR_B - name: show var script: - echo ${VAR_A} # 1 - echo ${VAR_B} # 2 ``` 当然,也可以不传送任务内容,仅仅表示一个等待动作: ```yaml - name: ready type: cnb:resolve options: key: i-am-ready ``` ```yaml - name: ready type: cnb:await options: key: i-am-ready ``` ###### 输出结果 \{#cnb-await-resolve-output} ```javascript { // resolve 返回的 data 内容 data; } ``` ### apply \{#cnb-apply} `cnb:apply` - [适用事件](#cnb-apply-applicable-events) - [参数](#cnb-apply-parameters) - [环境变量相关](#cnb-apply-environment-variables) - [config 取值优先级](#cnb-apply-config-priority) - [输出结果](#cnb-apply-output) - [配置样例](#cnb-apply-configuration-examples) #### 适用事件 \{#cnb-apply-applicable-events} - `push` - `commit.add` - `branch.create` - `pull_request.target` - `pull_request.mergeable` - `tag_push` - `pull_request.merged` - `api_trigger` - `web_trigger` - `crontab` - `tag_deploy` #### 参数 \{#cnb-apply-parameters} - [config](#cnb-apply-parameters-config) - [configFrom](#cnb-apply-parameters-configFrom) - [event](#cnb-apply-parameters-event) - [sync](#cnb-apply-parameters-sync) - [continueOnBuildError](#cnb-apply-parameters-continueOnBuildError) - [title](#cnb-apply-parameters-title) ##### config \{#cnb-apply-parameters-config} - type: `String` - required: `false` 完整的 CI 配置文件内容 ##### configFrom \{#cnb-apply-parameters-configFrom} - type: `String` - required: `false` 指定一个本地文件作为配置文件。 ##### event \{#cnb-apply-parameters-event} - type: `String` - required: `false` - default: `api_trigger` 要执行的自定义事件名,必须为 `api_trigger` 或以 `api_trigger_` 开头。 ##### sync \{#cnb-apply-parameters-sync} - type: `Boolean` - required: `false` - default: `false` 是否同步执行。 同步模式下会等待本次 apply 流水线执行成功,再执行下一个任务。 ##### continueOnBuildError \{#cnb-apply-parameters-continueOnBuildError} - type: `Boolean` - required: `false` - default: `false` 同步模式下,触发的流水线构建失败时,是否继续执行下个任务。 ##### title \{#cnb-apply-parameters-title} - type: `String` - required: `false` 自定义流水线标题 #### 环境变量相关 \{#cnb-apply-environment-variables} 当前 `Job` 可见的,业务定义的环境变量全部传递给新的流水线。 默认值中有如下环境变量,**用户无法覆盖**: - `APPLY_TRIGGER_BUILD_ID`,含义同 CI 默认环境变量中的 `CNB_BUILD_ID` - `APPLY_TRIGGER_PIPELINE_ID`,含义同 CI 默认环境变量中的 `CNB_PIPELINE_ID` - `APPLY_TRIGGER_REPO_SLUG`,含义同 CI 默认环境变量中的 `CNB_REPO_SLUG` - `APPLY_TRIGGER_REPO_ID`,含义同 CI 默认环境变量中的 `CNB_REPO_ID` - `APPLY_TRIGGER_USER`,含义同 CI 默认环境变量中的 `CNB_BUILD_USER` - `APPLY_TRIGGER_BRANCH`,含义同 CI 默认环境变量中的 `CNB_BRANCH` - `APPLY_TRIGGER_COMMIT`,含义同 CI 默认环境变量中的 `CNB_COMMIT` - `APPLY_TRIGGER_COMMIT_SHORT`,含义同 CI 默认环境变量中的 `CNB_COMMIT_SHORT` - `APPLY_TRIGGER_ORIGIN_EVENT`,含义同 CI 默认环境变量中的 `CNB_EVENT` - `CNB_PULL_REQUEST_ID`,含义同 CI 默认环境变量中的 `CNB_PULL_REQUEST_ID` - `CNB_PULL_REQUEST_IID`,含义同 CI 默认环境变量中的 `CNB_PULL_REQUEST_IID` - `CNB_PULL_REQUEST_MERGE_SHA`,含义同 CI 默认环境变量中的 `CNB_PULL_REQUEST_MERGE_SHA` ##### config 取值优先级 \{#cnb-apply-config-priority} 按以下顺序依次取值,取到为止: 1. `config` 2. `configFrom` 3. 当前仓库 `.cnb.yml` 4. 若在 `pull_request.merged` 事件中调用 `apply` 内置任务,取合并后的配置文件 5. 若在 `pull_request.target`、`pull_request.mergeable` 事件中调用 `apply` 内置任务,取目标分支的配置文件 6. 其他情况取当前分支配置文件 `configFrom` 只支持本地文件如 `./test/.cnb.yml`,远程文件可先自行下到本地。 #### 输出结果 \{#cnb-apply-output} ```json { "sn": "cnb-i5o-1ht8e12hi", // 构建号 "buildLogUrl": "http://xxx/my-group/my-repo/-/build/logs/cnb-i5o-1ht8e12hi", // 构建日志链接 "message": "success", "buildSuccess": true, // 触发的构建是否成功,此key仅在同步模式下存在 "lastJobExports": {} // 触发的流水线最后一个job导出的环境变量 } ``` #### 配置样例 \{#cnb-apply-configuration-examples} ```yaml main: push: - stages: - name: trigger type: cnb:apply options: configFrom: ./test/.cnb.yml event: api_trigger_test ``` ```yaml main: push: - stages: - name: trigger type: cnb:apply options: config: | main: api_trigger_test: - stages: - name: test script: echo test event: api_trigger_test ``` ```yaml main: push: - stages: - name: trigger type: cnb:apply options: # 执行当前配置文件的其它事件 event: api_trigger_test api_trigger_test: - stages: - name: test script: echo test ``` ```yaml main: push: - stages: - name: trigger type: cnb:apply options: configFrom: .xxx.yml event: api_trigger_test sync: true ``` ### read-file \{#cnb-read-file} `cnb:read-file` 读取文件内容解析输出给后续任务。 用 `##[set-output key=value]` 指令输出变量更便捷,但会将内容输出到日志,不适用于敏感信息。 对于事先确定的敏感信息可以用 `imports` 导入,对于构建过程中生成的敏感信息,可写入文件,用该内置任务读取。 `imports` 只支持远端仓库存在的文件,该内置任务只支持读取本地存在的文件。 文件类型通过后缀判断,目前支持 json、 yml(yaml)、 纯文本(`key=value` 结构)。 - [适用事件](#cnb-read-file-applicable-events) - [参数](#cnb-read-file-parameters) - [输出结果](#cnb-read-file-output) - [配置样例](#cnb-read-file-configuration-examples) #### 适用事件 \{#cnb-read-file-适用事件} [所有事件](/cnb/build/trigger-rule.md#trigger-event) #### 参数 \{#cnb-read-file-parameters} ##### filePath - type: String - required: true 本地文件路径 #### 输出结果 \{#cnb-read-file-output} ```json { // 读到的对象 } ``` #### 配置样例 \{#cnb-read-file-configuration-examples} 将一些后续任务需要的变量写入文件,用该内置任务读取文件导出为环境变量,供后续任务使用。 ```json title="myJson.json" { "myVar": "myVar", "deep": { "myVar": "myVar in deep" }, "deepWithEnvKey": { "myVar": "myVar in deepWithEnvKey" } } ``` ```yaml title="cnb.yml" main: push: - env: myKey: deepWithEnvKey stages: - name: write env file script: echo "write env to myJson.json" - name: export env type: cnb:read-file options: filePath: myJson.json exports: myVar: ENV_MY_VAR deep.myVar: ENV_DEEP_MY_VAR #指定多级的key $myKey.myVar: ENV_ENV_KEY_MY_VAR #通过环境变量指定获取的key - name: echo env script: - echo $ENV_MY_VAR - echo $ENV_DEEP_MY_VAR - echo $ENV_ENV_KEY_MY_VAR ``` ### trigger \{#cnb-trigger} `cnb:trigger` 在当前仓库中,触发另外一个仓库的自定义事件流水线。 - [适用事件](#cnb-trigger-applicable-events) - [参数](#cnb-trigger-parameters) - [输出结果](#cnb-trigger-output) - [配置样例](#cnb-trigger-configuration-examples) - [基本使用](#cnb-trigger-configuration-examples-basic-usage) #### 适用事件 \{#cnb-trigger-applicable-events} [所有事件](/cnb/build/trigger-rule.md#trigger-event) #### 参数 \{#cnb-trigger-parameters} - [token](#cnb-trigger-parameters-token) - [slug](#cnb-trigger-parameters-slug) - [event](#cnb-trigger-parameters-event) - [branch](#cnb-trigger-parameters-branch) - [sha](#cnb-trigger-parameters-sha) - [env](#cnb-trigger-parameters-env) - [sync](#cnb-trigger-parameters-sync) - [continueOnBuildError](#cnb-trigger-parameters-continueOnBuildError) - [title](#cnb-trigger-parameters-title) ##### token \{#cnb-trigger-parameters-token} - type: `String` - required: `true` 个人访问令牌。 新流水线触发者为令牌对应用户,会判断有无目标仓库权限。 ##### slug \{#cnb-trigger-parameters-slug} - type: `String` - required: `true` 目标仓库的完整路径,如:group/repo。 ##### event \{#cnb-trigger-parameters-event} - type: `String` - required: `true` 触发的自定义事件名,必须是 `api_trigger` 或以 `api_trigger_` 开头。 需要目标仓库配置了对应事件的流水线,才可以触发。 ##### branch \{#cnb-trigger-parameters-branch} - type: `String` - required: `false` 触发分支,默认为主分支。 ##### sha \{#cnb-trigger-parameters-sha} - type: `String` - required: `false` 触发分支中的 CommitId,默认取 branch 的最新提交记录。 ##### env \{#cnb-trigger-parameters-env} - type: [TriggerEnv](#cnb-trigger-parameters-type-definitions-TriggerEnv) - required: `false` 触发目标仓库流水线时的环境变量。 默认值中有如下环境变量,用户无法覆盖: - `API_TRIGGER_BUILD_ID`,含义同 CI 默认环境变量中的 `CNB_BUILD_ID` - `API_TRIGGER_PIPELINE_ID`,含义同 CI 默认环境变量中的 `CNB_PIPELINE_ID` - `API_TRIGGER_REPO_SLUG`,含义同 CI 默认环境变量中的 `CNB_REPO_SLUG` - `API_TRIGGER_REPO_ID`,含义同 CI 默认环境变量中的 `CNB_REPO_ID` - `API_TRIGGER_USER`,含义同 CI 默认环境变量中的 `CNB_BUILD_USER` - `API_TRIGGER_BRANCH`,含义同 CI 默认环境变量中的 `CNB_BRANCH` - `API_TRIGGER_COMMIT`,含义同 CI 默认环境变量中的 `CNB_COMMIT` - `API_TRIGGER_COMMIT_SHORT`,含义同 CI 默认环境变量中的 `CNB_COMMIT_SHORT` ##### sync \{#cnb-trigger-parameters-sync} - type: Boolean - required: false - default: false 是否同步执行,同步模式下会等待本次 trigger 流水线执行成功后,再执行下一个任务。 ##### continueOnBuildError \{#cnb-trigger-parameters-continueOnBuildError} - type: Boolean - required: false - default: false 同步模式下,触发的流水线构建失败时,是否继续执行下个任务。 ##### title \{#cnb-trigger-parameters-title} - type: String - required: false 自定义流水线标题 ##### 类型定义 \{#cnb-trigger-parameters-type-definitions} ###### TriggerEnv \{#cnb-trigger-parameters-type-definitions-TriggerEnv} ```txt { [key: String]: String | Number | Boolean } ``` #### 输出结果 \{#cnb-trigger-output} ```json { "sn": "cnb-i5o-1ht8e12hi", // 构建号 "buildLogUrl": "http://xxx/my-group/my-repo/-/build/logs/cnb-i5o-1ht8e12hi", // 构建日志链接 "message": "success", "buildSuccess": true, // 触发的构建是否成功,此key仅在同步模式下存在 "lastJobExports": {} // 触发的流水线最后一个job导出的环境变量 } ``` #### 配置样例 \{#cnb-trigger-configuration-examples} ##### 基本使用 \{#cnb-trigger-configuration-examples-basic-usage} 在当前仓库触发一个仓库 `main` 分支的事件名为 `api_trigger_test` 的流水线。 该流水线配置文件使用仓库 `main` 分支的 `.cnb.yml` 文件。 使用访问令牌 `$TOKEN` 查询用户是否有仓库权限。 ```yaml title="cnb.yml" main: push: - stages: - name: trigger type: cnb:trigger imports: https://cnb.cool//-/blob/main/xxx/envs.yml options: token: $TOKEN slug: a/b branch: main event: api_trigger_test ``` ## vscode ### go \{#vscode-go} `vscode:go` 远程开发中是否配置该内置任务的区别: - \==使用该任务==: 启动云原生开发时,需等待该任务执行完,才出现 WebIDE 和 VSCode/Cursor 客户端入口。 - \==不使用该任务==: 流水线 prepare 阶段执行完(code-server 代码服务启动),stages 任务执行前,就会出现 WebIDE 和 VSCode/Cursor 客户端入口。 上述入口出现时机区别:仅指从 `loading` 等待页到跳转入口选择页出现的时机。 实际上无论是否使用该任务,在 `code-server` 代码服务启动后,远程开发已经是可用状态。 注意:使用该任务将增加等待时间。如果需要延迟开发者进入时机,在某些任务执行完才允许进入远程开发环境,可使用该任务。 - [适用事件](#vscode-go-applicable-events) - [输出结果](#vscode-go-output) - [配置样例](#vscode-go-configuration-examples) #### 适用事件 \{#vscode-go-applicable-events} - `vscode` - `branch.create` - `api_trigger` - `web_trigger` #### 输出结果 \{#vscode-go-output} ```json { // webide url "url": "" } ``` #### 配置样例 \{#vscode-go-configuration-examples} ```yaml title=".cnb.yml" $: # vscode 事件:专供页面中启动远程开发用 vscode: - docker: # 使用自定义镜像作为开发环境,未传入此参数,将使用默认镜像 cnbcool/default-dev-env:latest image: cnbcool/default-dev-env:latest services: - vscode - docker stages: # 希望等该任务执行完再进入开发环境 - name: ls script: ls -al - name: vscode go type: vscode:go # 可以在进入开发环境后再执行的任务 - name: ls script: ls -al ``` ## git ### auto-merge \{#git-auto-merge} `git:auto-merge` \==自动合并 Pull Request==,一般用于 PR 通过 `pull_request` 流水线检查 和 `Code Review` 后,在 `pull_request.mergeable` 流水线中自动合并 `PR`。无需人工点击合并按钮。 `pull_request.mergeable` 事件触发条件和时机参考[事件](/cnb/build/trigger-rule.md#trigger-event)。 - [适用事件](#git-auto-merge-applicable-events) - [参数](#git-auto-merge-parameters) - [输出结果](#git-auto-merge-output) - [配置样例](#git-auto-merge-configuration-examples) - [单独使用](#git-auto-merge-configuration-examples-standalone-usage) - [配合目标分支的 push 事件使用](#git-auto-merge-configuration-examples-used-with-target-branch-push-event) - [最佳实践](#git-auto-merge-best-practices) - [使用 squash 自动合并](#git-auto-merge-best-practices-using-squash-auto-merge) - [使用 auto 自动选择合并类型](#git-auto-merge-best-practices-using-auto-automatically-select-merge-type) - [建立专用的 CR 群交叉走查自动合并](#git-auto-merge-best-practices-establishing-dedicated-cr-group-cross-review-auto-merge) #### 适用事件 \{#git-auto-merge-applicable-events} `pull_request.mergeable` #### 参数 \{#git-auto-merge-parameters} - [mergeType](#git-auto-merge-parameters-mergeType) - [mergeCommitMessage](#git-auto-merge-parameters-mergeCommitMessage) - [mergeCommitFooter](#git-auto-merge-parameters-mergeCommitFooter) - [removeSourceBranch](#git-auto-merge-parameters-removeSourceBranch) - [ignoreAssignee](#git-auto-merge-parameters-ignoreAssignee) ##### mergeType \{#git-auto-merge-parameters-mergeType} - type: `String` - required: false - default: auto - 合并策略,默认为 auto:如果多人提交走 merge ,否则走 squash 。 ##### mergeCommitMessage \{#git-auto-merge-parameters-mergeCommitMessage} - type: String - required: false - 合并点提交信息。 当合并策略为 `rebase` 的时候,该信息无效,无需填写。 当合并策略为 `merge` ,默认为 `chore: merge node(merged by CNB)` ,会自动追加 `PR` 引用、`reviewers` 名单、`PR` 包含的提交人名单。举例说明: ```txt chore: merge node(merged by CNB) PR-URL: !916 Reviewed-By: tom Reviewed-By: jerry Co-authored-by: jack ``` 当合并策略为 squash 时,默认值为该 pr 的第一条 commit message。并会自动追加 pr 引用和 reviewers 名单、pr 包含的提交人名单。举例说明: ```yaml title=".cnb.yml" main: pull_request.mergeable: - stages: - name: automerge type: git:auto-merge options: mergeType: squash ``` 该配置会产生如下效果: 某个 `PR` (feat/model-a -> main) 中有两条提交记录: 提交记录 1,2023-10-1 日提交 ```txt feat(model-a): 给模块 A 增加一个新特性 由于某某原因,新增某某特性 close #10 ``` 提交记录 2,修复了在 cr 时被指出的一些问题,2023-10-2 日提交 ```txt fix(model-a): 修复评审中指出的问题 ``` 在自动合并后将会在 `main` 分支上产生一个这样的提交节点,即后续的提交记录(也就是提交记录 2)将会被抹掉 ```txt feat(model-a): 给模块 A 增加一个新特性 由于某某原因,新增某某特性 close #10 PR-URL: !3976 Reviewed-By: tom Reviewed-By: jerry Co-authored-by: jack ``` ##### mergeCommitFooter \{#git-auto-merge-parameters-mergeCommitFooter} - type: `String` - required: `false` 合并点需要设置的脚注,多个脚注用 `\n` 分隔,仅在 `merge` 和 `squash` 生效。 当合并策略为 `rebase` 的时候,该信息无效,无需填写。 当合并策略为 `merge` 或 `squash` 时,会将传入信息按行加入到脚注中,再追加 `PR` 引用、`reviewers` 名单、`pr` 包含的提交人名单。举例说明: ```yaml title=".cnb.yml" main: pull_request.mergeable: - stages: - name: automerge type: git:auto-merge options: mergeType: squash mergeCommitMessage: 'add feature for some jobs' mergeCommitFooter: "--story=123\n--story=456" ``` ```txt add feature for some jobs --story=123 --story=456 PR-URL: !916 Reviewed-By: tom Reviewed-By: jerry Co-authored-by: jack ``` ##### removeSourceBranch \{#git-auto-merge-parameters-removeSourceBranch} - type: Boolean - required: false - default: false 合并后是否删除源分支。 源分支与目标分支不同仓库时,该值无效。 ##### ignoreAssignee \{#git-auto-merge-parameters-ignoreAssignee} - type: Boolean - required: false - default: false 是否忽略 `assignee`。 当该 `PR` 有指定 `assignee` (指派人)的时候,本任务不会执行自动合并的逻辑。 因为 `assignee` 的本意就是指派某人手动来处理。 当为 `true` 时,可忽略 `assignee` 强行合并。 #### 输出结果 \{#git-auto-merge-output} ```txt { reviewedBy, // String,追加在提交信息后面的提交者信息 reviewers, // Array, 走查者列表 } ``` #### 配置样例 \{#git-auto-merge-configuration-examples} ##### 单独使用 \{#git-auto-merge-configuration-examples-standalone-usage} ```txt main: pull_request.mergeable: - stages: - name: automerge type: git:auto-merge options: mergeType: merge ``` 当分支 `main` 上 的 `PR` 触发了 `pull_request.mergeable` 事件,那么会将这个 `PR` 以 `merge` 的方式自动合并。 ##### 配合目标分支的 push 事件使用 \{#git-auto-merge-configuration-examples-used-with-target-branch-push-event} ```yaml title=".cnb.yml" main: push: - stages: - name: build script: npm run build - name: publish script: npm run publish pull_request.mergeable: - stages: - name: automerge type: git:auto-merge options: mergeType: merge ``` 当分支 `main` 上 的 `PR` 触发了 `pull_request.mergeable` 事件,那么会将这个 `PR` 以 `merge` 的方式自动合并。 在自动合并之后,会触发目标分支(main)上的 `push` 事件,继续执行声明的 `build` 和 `publish` 流程。 **这里有一个谁应该对产生的 push 事件流程负责的问题,这里的设定是这样的:** 1. 如果提出 `PR` 者,是目标仓库的成员,那么提出 `PR` 的人对后续产生的 `push` 事件流程负责(即 `push` 构建流水会推送到这里)。 2. 如果提出 `PR` 者,不是目标仓库的成员(比如在开源项目中,从 `Forked Repo` 提出 `PR`)。那么最后一个 `Code Review` 的 `Reviewer` 将对后续产生的 `push` 事件流程负责。 #### 最佳实践 \{#git-auto-merge-best-practices} ##### 使用 squash 自动合并 \{#git-auto-merge-best-practices-using-squash-auto-merge} 使用 `squash` 合并,一次 `PR` 操作只在目标分支产生一个 `commit` 节点,并且在有权限的情况下删除源分支。 ```yaml title=".cnb.yml" main: review: - stages: - name: automerge type: git:auto-merge options: mergeType: squash removeSourceBranch: true ``` ##### 使用 auto 自动选择合并类型 \{#git-auto-merge-best-practices-using-auto-automatically-select-merge-type} 如果多人提交走 `merge` ,否则走 `squash`。 ```yaml title=".cnb.yml" main: review: - stages: - name: automerge type: git:auto-merge options: mergeType: auto ``` ##### 建立专用的 CR 群交叉走查自动合并 \{#git-auto-merge-best-practices-establishing-dedicated-cr-group-cross-review-auto-merge} 1. 走查通过后自动合并 2. 记录走查者信息在提交信息中 ```yaml title=".cnb.yml" main: pull_request.mergeable: - stages: - name: CR 通过后自动合并 type: git:auto-merge options: mergeType: squash mergeCommitMessage: $CNB_LATEST_COMMIT_MESSAGE exports: reviewedBy: REVIEWED_BY - name: notify image: tencentcom/wecom-message settings: robot: '155af237-6041-4125-9340-000000000000' msgType: markdown content: | > CR 通过后自动合并 <@${CNB_BUILD_USER}> >   > ${CNB_PULL_REQUEST_TITLE} > [${CNB_EVENT_URL}](${CNB_EVENT_URL}) > > ${REVIEWED_BY} pull_request: - stages: # ...省略其它任务 - name: notify image: tencentcom/wecom-message options: robot: '155af237-6041-4125-9340-000000000000' msgType: markdown content: | > ${CURR_REVIEWER_FOR_AT} > > ${CNB_PULL_REQUEST_TITLE} > [${CNB_EVENT_URL}](${CNB_EVENT_URL}) > > from ${CNB_BUILD_USER} ``` ### issue-update \{#git-issue-update} `git:issue-update` \==更新 Issue 状态==,关闭或打开 `Issue`,修改 `Issue` 标签。 - [适用事件](#git-issue-update-applicable-events) - [工作机制](#git-issue-update-work-mechanism) - [Issue ID 获取方式](#git-issue-update-how-to-get-issue-id) - [提交日志中如何带上 Issue ID](#git-issue-update-how-to-include-issue-id-in-commit-logs) - [参数](#git-issue-update-parameters) - [输出结果](#git-issue-update-output) - [配置样例](#git-issue-update-configuration-examples) #### 适用事件 \{#git-issue-update-applicable-events} [所有事件](/cnb/build/trigger-rule.md#trigger-event) #### 工作机制 \{#git-issue-update-work-mechanism} 查找 `Issue` 是否存在 -> 检查是否符合 when 条件(可选) -> 检查是否符合 lint 条件(可选)-> 更新 issue 状态或标签 #### Issue ID 获取方式 \{#git-issue-update-how-to-get-issue-id} - 如果传入了 `fromText` 参数,则从 `fromText` 中获取。其中 `branch.delete` 必传 `fromText`(分支已删除,无法从上下文中获取)。 - 如果没传入 `fromText` 参数,则从上下文中获取。 - `push` 事件:从本次推送的所有 `commit` 的提交日志中获取。 - 合并请求类事件:从合并请求中的所有 `commit` 的提交日志中获取。 - 其他事件:从最新的一个 `commit` 的提交日志中获取。 获取方式:提取上述文本中如下两种格式 - \#issueID:表示当前仓库的 issue。例如 #123,表示当前仓库 id 为 123 的 issue。 - groupName/repoName#issueID:表示跨仓库(其他仓库)的 issue。例如:test/test#123,表示 test/test 仓库中 id 为 123 的 issue。 注意 #123 或 test/test#123 前需要有空格。 #### 提交日志中如何带上 Issue ID \{#git-issue-update-how-to-include-issue-id-in-commit-logs} 提交代码时,可以在提交日志中加上关联的 `Issue ID`, 可以在使用当前内置任务时可以自动提取到关联 `Issue`,用来更新 `Issue` 标签和状态 推荐在提交日志的 body 中带上 `Issue ID`,命令行操作方式如下: - 方法一:用 `shift + enter` 换行,建议 title 和 body 之间加上一个空行 ```txt git commit -m "fix(云原生构建): 修复一个错误 cnb/feedback#123" ``` - 方法二: 以下提交方式 title 和 body 之间会产生两个换行 ```txt git commit -m "fix(云原生构建): 修复一个错误" -m "cnb/feedback#123" ``` #### 参数 \{#git-issue-update-parameters} - [fromText](#git-issue-update-parameters-fromText) - [state](#git-issue-update-parameters-state) - [label](#git-issue-update-parameters-label) - [when](#git-issue-update-parameters-when) - [lint](#git-issue-update-parameters-lint) - [defaultColor](#git-issue-update-parameters-defaultColor) ##### [fromText](#git-issue-update-parameters-fromText) - type: `String` - required: `false` 从给定的文本中解析 `Issue Id`。 不声明时,自动从上下文里的提交记录解析。 > 可以指定一个包含 issue id 引用的文本来声明操作对象,比如: $\{LATEST\_CHANGE\_LOG} 。 ##### [state](#git-issue-update-parameters-state) - type: [IssueStateMap](#git-issue-update-parameters-type-definitions-IssueStateMap) - required: `false` 对应 `state` 属性,为 `close` 时,可关闭 `Issue`。 ##### [label](#git-issue-update-parameters-label) - type: [IssueUpdateLabel](#git-issue-update-parameters-type-definitions-IssueUpdateLabel) - required: `false` 对 `label` 的操作描述。 ##### [when](#git-issue-update-parameters-when) - type: [IssueUpdateStatus](#git-issue-update-parameters-type-definitions-IssueUpdateStatus) - required: `false` 过滤条件,多个条件之间是 `or` 关系。为空时表示对所有 `Issue` 操作。 ##### [lint](#git-issue-update-parameters-lint) - type: [IssueUpdateStatus](#git-issue-update-parameters-type-definitions-IssueUpdateStatus) - required: `false` 检查 `Issue` 是否满足条件,不满足时抛出异常,多个条件之间是 or 关系,为空时表示不做检查。 ##### [defaultColor](#git-issue-update-parameters-defaultColor) - type: `String` - required: `false` 添加的标签的默认颜色,当有传入 `label.add` 参数时才有效。 ##### 类型定义 \{#git-issue-update-parameters-type-definitions} ###### IssueStateMap \{#git-issue-update-parameters-type-definitions-IssueStateMap} - `Enum` open | close ###### IssueUpdateLabel \{#git-issue-update-parameters-type-definitions-IssueUpdateLabel} - add - type: `Array` | `String` - required: `false` - 要添加的标签列表,标签不存在时,会自动创建。 - remove - type: `Array` | `String` - required: `false` - 要移除的标签列表 ###### IssueUpdateStatus \{#git-issue-update-parameters-type-definitions-IssueUpdateStatus} - label - type: `Array` | `String` - required: `false` - 标签,多个值之间是 `or` 关系 #### 输出结果 \{#git-issue-update-output} ```txt { issues // issue 列表 } ``` #### 配置样例 \{#git-issue-update-configuration-examples} - 合并到 main 后,更新标签 ```yaml title=".cnb.yml" main: push: - stages: - name: update issue type: git:issue-update options: # 移除 “开发中” 标签,添加 “预发布” 标签 label: add: 预发布 remove: 开发中 # 当有 “feature” 或 “bug” 标签才进行上述标签操作 when: label: - feature - bug ``` - tag\_push 时,关闭 issue,更新标签 ```yaml title=".cnb.yml" $: tag_push: - stages: - name: 发布操作 script: echo "可用发布任务替代当前任务" # 发布操作后执行 issue 更新操作 - name: update issue type: git:issue-update options: # 关闭 issue state: close # 移除 “预发布” 标签,添加 “已发布” 标签 label: add: 已发布 remove: 预发布 # 当有 “feature” 或 “bug” 标签才进行上述操作 when: label: - feature - bug ``` - 根据 changelog 添加标签 ```yaml title=".cnb.yml" $: tag_push: - stages: - name: changelog image: cnbcool/changelog exports: latestChangeLog: LATEST_CHANGE_LOG - name: update issue type: git:issue-update options: fromText: ${LATEST_CHANGE_LOG} label: add: 需求已接收 when: label: feature ``` ### reviewer \{#git-reviewer} `git:reviewer` \==配置评审人或处理人==给 PR 添加、删除评审人/处理人,可指定备选评审人/处理人范围。 - [适用事件](#git-reviewer-applicable-events) - [参数](#git-reviewer-parameters) - [输出结果](#git-reviewer-output) - [配置样例](#git-reviewer-configuration-examples) - [最佳实践](#git-reviewer-best-practices) #### 适用事件 \{#git-reviewer-applicable-events} - `pull_request` - `pull_request.target` - `pull_request.update` #### 参数 \{#git-reviewer-parameters} - [type](#git-reviewer-parameters-type) - [reviewers](#git-reviewer-parameters-reviewers) - [count](#git-reviewer-parameters-count) - [exclude](#git-reviewer-parameters-exclude) - [reviewersConfig](#git-reviewer-parameters-reviewersConfig) - [role](#git-reviewer-parameters-role) ##### type \{#git-reviewer-parameters-type} - type: [REVIEW\_OPERATION\_TYPE](#git-reviewer-parameters-type-definitions-REVIEW_OPERATION_TYPE) - required: `false` - default: `add-reviewer` 操作类型: - `add-reviewer`: 添加评审人,会从 `reviewers` 参数中选择指定数量的评审人 - `add-reviewer-from-repo-members`: 从仓库直接成员里选一名,添加为评审人 - `add-reviewer-from-group-members`: 从仓库父组织(直接上级组织)里选一名,添加为评审人 - `add-reviewer-from-outside-collaborator-members`: 从仓库的外部协作者里选一名,添加为评审人 - `remove-reviewer`: 从已有的评审人中删除指定的成员 - `add-assignee`: 添加处理人,添加 `reviewers` 参数传入的成员 - `remove-assignee`: 从已有的处理人中删除指定的成员 ##### reviewers \{#git-reviewer-parameters-reviewers} - type: `Array` | `String` - required: `false` 要 `添加` 或 `删除` 的 `reviewer` 用户名。多个使用 `,` 或 `;` 分隔。 `type` 为 `add-reviewer`、`remove-reviewer`、`add-assignee`、`remove-assignee` 时有效。 若同时配置了 `reviewers` 、 `reviewersConfig` ,则会在两者中随机选指定数量的评审人或处理人 ##### count \{#git-reviewer-parameters-count} - type: `Number` - required: `false` 指定要添加的评审人或处理人数量,随机抽取指定数量的评审人或处理人。 - 当 `type=add-reviewer`,count 缺省值为 `reviewers` 的数量,即全部添加 - 当 `type=add-reviewer-from-repo-members`,count 缺省值为 1 - 当 `type=add-reviewer-from-group-members`,count 缺省值为 1 - 当 `type=add-reviewer-from-outside-collaborator-members`,count 缺省值为 1 - 当 `type=add-assignee`,count 缺省值为 `reviewers` 的数量,即全部添加 如果已有评审人或处理人的数量 `< count` ,那么补齐。 如果已有评审人或处理人的数量 `>= count` ,那么什么也不做。 ##### exclude \{#git-reviewer-parameters-exclude} - type: `Array` | `String` - required: `false` 排除指定的用户。 ##### reviewersConfig \{#git-reviewer-parameters-reviewersConfig} - type: [IReviewersConfig](#git-reviewer-parameters-type-definitions-IReviewersConfig) | `String` - required: `false` 文件评审人或处理人配置,如果配置中有配置当前变更文件的评审人或处理人,则会被添加为评审人或处理人。 `type` 为 `add-reviewer` 或 `add-assignee` 时有效。 支持两种格式: - 字符串格式,传入配置文件相对路径(支持 `json` 文件): ```txt reviewersConfig: config.json ``` ```txt { "./src": "name1,name2", ".cnb.yml": "name3" } ``` - 对象格式,传入文件评审人配置: ```txt reviewersConfig: ./src: name1,name2 .cnb.yml: name3 ``` 其中,文件评审人或处理人配置的 `key` 为文件相对路径;`value` 为评审人或处理人英文名,用英文逗号分隔。 若同时配置了 `reviewers` 、`reviewersConfig`,则会在两者中随机选指定数量的评审人或处理人。 ##### role \{#git-reviewer-parameters-role} - type: [ROLE\_TYPE](#git-reviewer-parameters-type-definitions-ROLE_TYPE) - required: `false` 评审人或处理人可以添加的角色可选包括:`Developer`、`Master`、`Owner` 如果选择 `Developer`,则可添加 `Developer` 及以上权限成员,包括 `Developer`、`Master`、`Owner` ##### 类型定义 \{#git-reviewer-parameters-type-definitions} ###### REVIEW\_OPERATION\_TYPE \{#git-reviewer-parameters-type-definitions-REVIEW\_OPERATION\_TYPE} - `Enum` add-reviewer | add-reviewer-from-repo-members | add-reviewer-from-group-members | add-reviewer-from-outside-collaborator-members | remove-reviewer | add-assignee | remove-assignee ###### IReviewersConfig \{#git-reviewer-parameters-type-definitions-IReviewersConfig} ```txt { [key: String]: String } ``` ###### ROLE\_TYPE \{#git-reviewer-parameters-type-definitions-ROLE\_TYPE} - `Enum` Developer | Master | Owner #### 输出结果 \{#git-reviewer-output} 添加评审人的输出结果: ```json { // 当前有效的评审人 "reviewers": [], // reviewers 对应的 at 消息格式,方便发送通知 "reviewersForAt": [] } ``` 添加处理人的输出结果: ```json { // 当前有效的处理人 "assignees": [], // assignees 对应的 at 消息格式,方便发送通知 "assigneesForAt": [] } ``` #### 配置样例 \{#git-reviewer-configuration-examples} - 添加评审人和处理人 ```yaml title=".cnb.yml" main: pull_request: - stages: - name: 添加评审人 type: git:reviewer options: type: add-reviewer reviewers: aaa;bbb - name: 添加处理人 type: git:reviewer options: type: add-assignee reviewers: ccc;ddd ``` - 删除指定成员的评审人和处理人 ```yaml title=".cnb.yml" main: pull_request: - stages: - name: 删除评审人 type: git:reviewer options: type: remove-reviewer reviewers: aaa - name: 删除处理人 type: git:reviewer options: type: remove-assignee reviewers: aaa ``` - 结合 ifModify,指定文件被修改时添加评审人和处理人 ```yaml title=".cnb.yml" main: pull_request: - stages: - name: 改配置?需要特别 review ifModify: - '.cnb.yml' - 'configs/**' type: git:reviewer options: type: add-reviewer reviewers: bbb - name: 改配置?需要特别处理 ifModify: - '.cnb.yml' - 'configs/**' type: git:reviewer options: type: add-assignee reviewers: ccc ``` - 结合 if,在指定条件下将某些人添加为评审人或处理人 ```yaml title=".cnb.yml" main: pull_request: - stages: - name: 下班时间发版本?需指定人评审。 if: | [ $(date +%H) -ge 18 ] type: git:reviewer options: type: add-reviewer reviewers: bbb - name: 下班时间发版本?需指定人处理。 if: | [ $(date +%H) -ge 18 ] type: git:reviewer options: type: add-assignee reviewers: ccc ``` - 随机选择一名负责人走查代码 ```yaml title=".cnb.yml" main: pull_request: - stages: - name: random image: tencentcom/random settings: from: - aaa - bbb exports: result: CURR_REVIEWER - name: show CURR_REVIEWER script: echo ${CURR_REVIEWER} - name: add reviewer type: git:reviewer options: type: add-reviewer reviewers: ${CURR_REVIEWER} ``` - 从当前仓库成员里选一名评审人进行 review ```yaml title=".cnb.yml" main: pull_request: - stages: - name: add reviewer type: git:reviewer options: type: add-reviewer-from-repo-members ``` #### 最佳实践 \{#git-reviewer-best-practices} 建立专用的 CR 群,交叉评审自动合并 1. `PR` 随机选择N名评审者,通知到群 2. 评审通过后自动合并 3. 记录评审者信息在提交信息中 4. `Git` 设置满足多人评审自动合并策略实现多人交叉评审 ```yaml title=".cnb.yml" main: review: - stages: - name: CR 通过后自动合并 type: git:auto-merge options: mergeType: squash removeSourceBranch: true mergeCommitMessage: $CNB_LATEST_COMMIT_MESSAGE exports: reviewedBy: REVIEWED_BY # 将评审消息发送到企业微信机器人 - name: notify image: tencentcom/wecom-message settings: msgType: markdown robot: '155af237-6041-4125-9340-000000000000' content: | > CR 通过后自动合并 <@${CNB_BUILD_USER}> >   > ${CNB_PULL_REQUEST_TITLE} > [${CNB_EVENT_URL}](${CNB_EVENT_URL}) > > ${REVIEWED_BY} pull_request: - stages: # ...省略其它任务 # 发送到 CR 专用群 - name: add reviewer type: git:reviewer options: reviewers: aaa,bbb,ccc,ddd count: 2 exports: reviewersForAt: CURR_REVIEWER_FOR_AT - name: notify image: tencentcom/wecom-message settings: msgType: markdown robot: '155af237-6041-4125-9340-000000000000' message: | > ${CURR_REVIEWER_FOR_AT} >   > ${CNB_PULL_REQUEST_TITLE} > [${CNB_EVENT_URL}](${CNB_EVENT_URL}) >   > from ${CNB_BUILD_USER} ``` ### release \{#git-release} `git:release` \==仓库发布 Release== - [适用事件](#git-release-applicable-events) - [参数](#git-release-parameters) - [输出结果](#git-release-output) - [配置样例](#git-release-configuration-examples) #### 适用事件 \{#git-release-applicable-events} - `push` - `commit.add` - `branch.create` - `tag_push` - `pull_request.merged` - `api_trigger` - `web_trigger` - `tag_deploy` #### 参数 \{#git-release-parameters} - [overlying](#git-release-parameters-overlying) - [tag](#git-release-parameters-tag) - [title](#git-release-parameters-title) - [description](#git-release-parameters-description) - [preRelease](#git-release-parameters-preRelease) - [latest](#git-release-parameters-latest) ##### overlying \{#git-release-parameters-overlying} - type: `Boolean` - required: `false` - default: `false` 叠加模式 - `true`:叠加模式,同一个 `release` 可以提交多次,最终的 `release` 是多次提交的并集。如果同名附件已经存在,会先删除再上传,达到更新的效果。 - `false`:非叠加模式,以最后一个提交的为准,前面的会被清除。 ::: warning 默认情况下,当 release 版本已经存在时,会先删除这个版本,重新生成。 ::: ##### tag \{#git-release-parameters-tag} - type: `String` - required: `false` `release` 对应的 `tag` 名,非必填 `tag_push` 事件无需传入,直接取触发 `tag_push` 事件的 `tag` 名。 非 `tag_push` 事件必填,用来作为 `release` 对应的 `tag` 名。 ##### title \{#git-release-parameters-title} - type: `String` - required: `false` - default: `tag` 名 release 的标题 ##### description \{#git-release-parameters-description} - type: `String` - required: `false` `release` 的描述 ##### preRelease \{#git-release-parameters-preRelease} - type: `Boolean` - required: `false` - default: `false` 是否将 `release` 设置为 预发布 ##### latest \{#git-release-parameters-latest} - type: "true" | "false" | true | false - required: `false` - default: `false` 是否将 `release` 设置为最新版本 #### 输出结果 \{#git-release-output} 无 #### 配置样例 \{#git-release-configuration-examples} - 生成 changelog 并自动更新 release 描述 ```yaml title=".cnb.yml" $: tag_push: - stages: - name: changelog image: cnbcool/changelog exports: latestChangeLog: LATEST_CHANGE_LOG - name: upload release type: git:release options: title: release description: ${LATEST_CHANGE_LOG} ``` - 主分支 push 时发布 release ```yaml title=".cnb.yml" main: push: - stages: - name: git release type: git:release options: tag: Nightly description: description ``` ## testing ### coverage \{#testing-coverage} `testing:coverage` \==单测覆盖率==,通过单测结果报告,计算单测覆盖率结果,并上报徽章。 - [适用事件](#testing-coverage-applicable-events) - [全量覆盖率](#testing-coverage-full-coverage) - [增量覆盖率](#testing-coverage-incremental-coverage) - [参数](#testing-coverage-parameters) - [输出结果](#testing-coverage-output) - [配置样例](#testing-coverage-configuration-examples) #### 适用事件 \{#testing-coverage-applicable-events} [所有事件](/cnb/build/trigger-rule.md#trigger-event) #### 全量覆盖率 \{#testing-coverage-full-coverage} ![coverage](https://cnb.cool/svg/badge/coverage?message=18.67%25\&color=l2) ![coverage](https://cnb.cool/svg/badge/coverage?message=38.67%25\&color=l3) ![coverage](https://cnb.cool/svg/badge/coverage?message=58.67%25\&color=l4) ![coverage](https://cnb.cool/svg/badge/coverage?message=78.67%25\&color=l5) 从本地覆盖率报告文件解析而来,目前可识别以下格式的报告: - `json(js)`(推荐使用) - `json-summary` - `lcov`(推荐使用) - `jacoco` - `golang` #### 增量覆盖率 \{#testing-coverage-incremental-coverage} ![coverage-pr](https://cnb.cool/svg/badge/coverage%20%40pr?message=18.67%25\&color=l2) ![coverage-pr](https://cnb.cool/svg/badge/coverage%20%40pr?message=38.67%25\&color=l3) ![coverage-pr](https://cnb.cool/svg/badge/coverage%20%40pr?message=58.67%25\&color=l4) ![coverage-pr](https://cnb.cool/svg/badge/coverage%20%40pr?message=78.67%25\&color=l5) 变更行对应的单测覆盖率,仅支持 `pull_request`、`pull_request.update`、`pull_request.target` 事件 #### 参数 \{#testing-coverage-parameters} - [pattern](#testing-coverage-parameters-pattern) - [lines](#testing-coverage-parameters-lines) - [diffLines](#testing-coverage-parameters-diffLines) - [allowExts](#testing-coverage-parameters-allowExts) - [lang](#testing-coverage-parameters-lang) - [breakIfNoCoverage](#testing-coverage-parameters-breakIfNoCoverage) ##### pattern \{#testing-coverage-parameters-pattern} - type: `String` - required: `false` Glob 格式,指定覆盖率报告文件位置,相对于当前工作目录。 缺省时,将尝试查找当前目录(包括子目录)下的以下文件:coverage.json、jacoco\*.xml、lcov.info、\*.lcov。 ##### lines \{#testing-coverage-parameters-lines} - type: `Number` - required: `false` 指定全量覆盖率红线,判断如果全量覆盖率百分比小于该值,阻断工作流退出流水线。 ##### diffLines \{#testing-coverage-parameters-diffLines} - type: `Number` - required: `false` 指定增量覆盖率红线,判断如果全量覆盖率百分比小于该值,阻断工作流退出流水线。 `pull_request`、`pull_request.update`、`pull_request.target` 事件支持计算增量覆盖率结果,其他事件只计算全量覆盖率。 ##### allowExts \{#testing-coverage-parameters-allowExts} - type: `String` - required: `false` 参与覆盖率计算的代码文件类型白名单,逗号分隔, 如:`.json,.ts,.js`。 缺省时报告中的文件都会参与计算。 ##### lang \{#testing-coverage-parameters-lang} - type: `String` - required: `false` 当覆盖率结果报告目标格式为 `golang` 时,请指定此参数 为 `go`,否则会出现计算误差。其他情况可忽略该参数。 ##### breakIfNoCoverage \{#testing-coverage-parameters-breakIfNoCoverage} - type: `Boolean` - required: `false` 没有找到覆盖率报告文件时,是否抛出错误终止流程。 #### 输出结果 \{#testing-coverage-output} ```json { // 代码行覆盖率,例如 100,计算出错时值为 NA "lines": 100, // 代码增量行覆盖率,例如 100,计算出错时值为 NA "diff_pct": 100 } ``` #### 配置样例 \{#testing-coverage-configuration-examples} ```yaml title=".cnb.yml" main: push: - stages: - name: coverage type: testing:coverage options: breakIfNoCoverage: false exports: lines: LINES - name: result script: echo $LINES ``` ## artifact ### remove-tag \{#artifact-remove-tag} `artifact:remove-tag` \==删除 CNB 制品标签==,目前仅删除支持 CNB docker 和 helm 标签。需要有仓库写权限。 - [适用事件](#artifact-remove-tag-applicable-events) - [参数](#artifact-remove-tag-parameters) - [配置样例](#artifact-remove-tag-configuration-examples) #### 适用事件 \{#artifact-remove-tag-applicable-events} - `push` - `commit.add` - `tag_push` - `tag_deploy` - `pull_request.merged` - `api_trigger` - `web_trigger` - `crontab` - `branch.create` #### 参数 \{#artifact-remove-tag-parameters} - [name](#artifact-remove-tag-parameters-name) - [tags](#artifact-remove-tag-parameters-tags) - [type](#artifact-remove-tag-parameters-type) ##### name \{#artifact-remove-tag-parameters-name} - type: `String` - required: `true` 制品包名 ##### tags \{#artifact-remove-tag-parameters-tags} - type: `Array` - required: true ##### type \{#artifact-remove-tag-parameters-type} - type: `String` - required: `false` - default: `docker` 制品类型,目前仅支持 docker 和 helm #### 配置样例 \{#artifact-remove-tag-configuration-examples} ```yaml title=".cnb.yml" main: push: - stages: - name: remove tag type: artifact:remove-tag options: # 包名 # 包名示例1,仓库同名制品:reponame # 包名示例2,仓库非同名制品:reponame/name name: reponame/name tags: - tag1 - tag2 type: docker ``` --- url: /cnb/build/plugins.md --- > For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /cnb/build/plugins.md. # 插件市场 --- url: /cnb/build/create-plugin.md --- > For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /cnb/build/create-plugin.md. # 插件制作 在 `云原生构建` 中,一个插件就是一个 `Docker` 镜像。 下面我们介绍如何使用 `Bash` 从零开发一个镜像插件。 这个插件的功能是打印 `hello world`。 这篇内容应该可以给你创作自己的插件提供一个清晰的思路。 我们这里假设你已经知道 `Docker` 的一些基本知识。 ## 设计插件 ### 参数设计 第一步应该是去设计插件所需要的参数: - `text`: 要输出到控制台的文本内容 ```yaml main: push: - stages: - name: hello world image: cnbcool/hello-world settings: text: hello world ``` 这些入参将会以环境变量的形式传给容器,不同的是,他们将会变成大写且辅以 `PLUGIN_` 前缀。 上面的入参将会转化为如下环境变量: ```text PLUGIN_TEXT="hello world" ``` ### 支持的参数类型 参数类型支持`字符串`、`数值`、`布尔值`、`一维数组`、`普通对象` 其中: - 数组在传给容器时将会以英文逗号 `,` 分割 - 普通对象在传给容器时,会转成 `JSON` 字符串 比如: ```yaml main: push: - stages: - name: hello world image: cnbcool/hello-world settings: boolean: true number: 123 array: [hello, world] map: key: value ``` 上传参数值将会转化为以下环境变量: ```text PLUGIN_BOOLEAN='true' PLUGIN_NUMBER='123' PLUGIN_ARRAY='hello,world' PLUGIN_MAP='{"key":"value"}' ``` 特别复杂的参数值可以存到一个文件中,插件运行时加载。 如果你遇到参数值异常复杂的情况,往往不是格式能解决的,应当简化这些参数,或者将他们做成多个插件。 ## 书写脚本 下一步写一个打印参数的 Bash 脚本,如下: ```bash #!/bin/sh echo "$PLUGIN_TEXT" ``` ## 构建插件镜像 插件将会被打包成 `Docker` 镜像进行分发使用。 因此需要创建一个 `Dockerfile` 把我们之前写好的脚本打包进去, 并且把它设置为 `Entrypoint`。 ```bash FROM alpine ADD entrypoint.sh /bin/ RUN chmod +x /bin/entrypoint.sh ENTRYPOINT /bin/entrypoint.sh ``` 构建你的镜像: ```bash docker build -t cnbcool/hello-world . ``` ## 测试插件 你应当在本地测试好你的插件,可以使用 `docker run` 来运行插件,并且把参数通过环境变量的方式传进去: ```bash docker run --rm \ -e PLUGIN_TEXT="hello world" \ cnbcool/hello-world ``` ### 测试文件系统读取 插件有读取你构建流程工作区目录的权限,它会默认把构建的目录映射到插件的某个目录,然后把这个目录设置为工作区: ```bash docker run --rm \ -e PLUGIN_TEXT="hello world" \ -v $(pwd):$(pwd) \ -w $(pwd) \ cnbcool/hello-world ``` ## 导出变量 如果插件执行完后,需要返回结果并导出为变量供后续任务使用,可以参考 [exports](/cnb/build/grammar.md#exports) ## 发布插件 插件是一个 `Docker` 镜像,所以发布一个插件,就意味着需要把镜像发布到一个镜像源。 可以发布到 `云原生构建` 仓库自带的[制品库](/cnb/artifact/docker.md)。 对于全球可用的插件,也可以发布到 `Docker Hub`。 ### 发布镜像 ```bash docker push cnbcool/hello-world ``` --- url: /cnb/build/contribute-plugin.md --- > For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /cnb/build/contribute-plugin.md. # 贡献插件 如果你做了个比较通用、好用的插件,希望大家都可以用上, 可以在[这里](https://cnb.cool/cnb/plugins/market?tabValue=CONTRIBUTING-ov-file)贡献到[插件市场](/cnb/build/plugins.md)。 --- url: /cnb/build/simplify-configuration.md --- > For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /cnb/build/simplify-configuration.md. # 简化配置文件 ## YAML 高级语法 由于`.cnb.yml`配置文件是 `YAML` 格式,所以可以利用更多 `YAML` 特性(如锚点 `&` 、别名 `*` 和对象合并 `<<` 符号)来简化配置文件。 一个简单的运用锚点和别名简化的例子如下: ```yaml # pull_request 和 push 事件的流水线完全一致,这种方式可以减少重复 .pipeline: &pipeline docker: image: node:22 stages: - name: install script: npm install - name: test script: npm test main: pull_request: - <<: *pipeline push: - <<: *pipeline ``` 支持多级嵌套: ```yaml .jobs: &jobs - name: install script: npm install - name: test script: npm test .pipeline: &pipeline docker: image: node:22 stages: *jobs main: pull_request: - <<: *pipeline push: - <<: *pipeline ``` :::tip 以上是 `YAML` 自带特性,仅在解析单个YAML文件时有效,不能跨文件使用。 ::: ## 文件引用 为了方便复用流水线配置,`云原生构建` 实现了以下特性: - [include](/cnb/build/grammar.md#include):可以跨文件引用流水线模板。 - [imports](/cnb/build/grammar.md#Pipeline-imports):可以跨文件引用变量。 - [optionsFrom](/cnb/build/grammar.md#optionsfrom):可以跨文件引用内置任务参数。 - [settingsFrom](/cnb/build/grammar.md#settingsfrom):可以跨文件引用插件任务参数。 详细文件引用说明见 [文件引用](/cnb/build/file-reference.md) ## 变量引用 为了解决YAML锚点和别名不能跨文件使用的问题。`云原生构建` 实现了以下特性: [reference](/cnb/build/grammar.md#reference): 可以跨文件按属性路径引用变量。 --- url: /cnb/build/file-reference.md --- > For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /cnb/build/file-reference.md. # 文件引用 ## 背景 流水线配置文件可以引用其他文件,用作流水线配置、环境变量、任务参数等。 文件中可能存在敏感信息,需要对文件引用进行权限检查,以避免敏感信息泄漏。 ## 引用方式 CNB 中有如下四种配置文件引用方式: - 流水线模版引用:[include](/cnb/build/configuration.md#include) - 环境变量引用:[imports](/cnb/build/grammar.md#Pipeline-imports) - 内置任务参数引用:[optionsFrom](/cnb/build/grammar.md#optionsfrom) - 插件任务参数引用:[settingsFrom](/cnb/build/grammar.md#settingsfrom) **注意:** 为了方便灵活的配置流水线任务的参数,`imports`、`optionsFrom` 和 `settingsFrom` 声明的文件路径支持使用环境变量。 可事先在流水线中声明环境变量,然后在任务中引用,如: ```yaml main: push: - env: CNB_CONFIG_URL: https://cnb.cool//-/blob/main/xxx CNB_CONFIG_FILE: account.yml imports: # 假设 env1.yml 声明变量 CNB_ENV_FILE_URL - https://cnb.cool//-/blob/main/xxx/env1.yml # imports后面的文件路径支持使用前面文件中声明的环境变量 - ${CNB_ENV_FILE_URL}/env2.yml stages: - name: echo script: echo 1 - name: 内置任务 type: some-type optionsFrom: - ${CNB_CONFIG_URL}/${CNB_CONFIG_FILE} - name: 插件任务 image: some-image settingsFrom: - ${CNB_CONFIG_URL}/${CNB_CONFIG_FILE} ``` 同时 `optionsFrom` 和 `settingsFrom` 支持读取本地文件,即便仓库中无 `./path/to/file`,但可以在流水线中写入该文件,让流水线执行时加载,如: ```yaml main: push: - env: CNB_CONFIG_URL: https://xxx.com/p1/xxx CNB_CONFIG_FILE: account.yml stages: - name: echo script: echo some-content > ./path/to/file-not-in-git - name: 内置任务 type: some-type optionsFrom: # 引用仓库不存在但流水线生成的文件 - ./path/to/file-not-in-git - name: 插件任务 image: some-image settingsFrom: # 引用仓库存在的文件 - ./path/to/file-in-git ``` ## 文件类型 CNB 中,支持引用的配置文件分为三种类型: ### yaml 文件 文件名后缀为 `.yml` 或 `.yaml`,如: `account.yml` ```yaml SOME_ACCOUNT: some-account SOME_PASSWORD: some-password ``` ### json 文件 文件名后缀为 `.json`,如: `account.json` ```json { "SOME_ACCOUNT": "some-account", "SOME_PASSWORD": "some-password" } ``` ### 文本文件 非以上两种文件类型,会被当作文本文件解析,如: `account.txt` ```text SOME_ACCOUNT=some-account SOME_PASSWORD=some-password ``` ## 权限检查 对于公开或同源仓库的配置文件,流水线可直接引用。 对于私有且非同源仓库的配置文件,可声明四个字段:`allow_slugs`、`allow_events`、`allow_branches`、`allow_images` 控制可被访问范围,四个字段均为 `glob` 模式`字符串`或`字符串数组`。 若未声明上述四个字段,则会检查流水线触发者是否有用配置文件所属仓库的`读权限`。 其中: - `allow_slugs` 用于声明允许哪些仓库的流水线读取当前文件。 - `allow_events` 用于声明允许哪些事件下流水线可以读取当前文件,可配置的事件名参考[触发事件](/cnb/build/trigger-rule.md#trigger-event)。 - `allow_branches` 用于声明允许哪些分支下流水线可以读取当前文件。 - `allow_images` 用于声明允许哪些镜像插件可以读取当前文件。 CNB 关于流水线是否可以加载目标文件的权限检查流程图如下: 整体流程: ```mermaid flowchart LR subgraph allow检查 slug检查 --> branch检查 --> image检查 --> event检查 end subgraph allow必要性检查 allow_events必要性检查 --> allow_images必要性检查 end start([开始]) --> 公开仓库{公开仓库?} 公开仓库 --是--> 可访问 公开仓库 --否--> 同源仓库{同源仓库?} 同源仓库 --是--> 可访问 同源仓库 --否--> allow必要性检查[allow必要性检查] allow必要性检查 --> 必要性检查通过{检查通过?} 必要性检查通过 -- 是 --> allow声明{有allow声明?} 必要性检查通过 -- 否 --> 不可访问 allow声明 -- 否 --> 有文件读权限{文件读权限?} allow声明 -- 是 --> allow检查[allow检查] 有文件读权限 --有--> 可访问 有文件读权限 --无--> 不可访问 allow检查 --> allow检查通过{检查通过?} allow检查通过 --是--> 可访问 allow检查通过 --否--> 不可访问 ``` 流程图说明: - 同源仓库:流水线和目标文件属于同一个仓库。 - allow检查:声明的 allow 字段依次检查,每个都通过了才算通过。 - 文件读权限:指流水线触发者拥有被引用文件所属仓库的读权限,参见[角色权限](/cnb/guide/role-permissions.md) ```mermaid flowchart LR strat([allow必要性检查]) --> pull_request事件{pull_request事件?} pull_request事件 --否--> 镜像任务{镜像任务?} pull_request事件 --是--> 声明allow_events{声明allow_events?} 声明allow_events --是--> 镜像任务{镜像任务?} 声明allow_events --否--> 不通过 镜像任务 --否--> 通过 镜像任务 --是--> 声明allow_images{声明allow_images?} 声明allow_images --否--> 不通过 声明allow_images --是--> 通过 ``` allow 必要性检查说明: - 文中 `pull_request` 事件包含 `pull_request` 和 `pull_request.update` 事件。 - `PR` 中,特别是 `fork` 仓库提 `PR` 时,源分支代码未经管理员评审,代码不可信。出于安全考虑,配置文件必须配置了 `allow_events` 才能被 `pull_request` 流水线引用。 - 流水线可使用第三方插件,出于安全考虑,配置文件必须声明 `allow_images` 才能被插件任务引用。 ```mermaid flowchart LR strat([slug检查]) --> 声明allow_slugs{声明allow_slugs?} 声明allow_slugs --是--> slug匹配allow_slugs{slug匹配allow_slugs?} 声明allow_slugs --否--> 通过 slug匹配allow_slugs --是--> 通过 slug匹配allow_slugs --否--> 不通过 ``` ```mermaid flowchart LR strat([branch检查]) --> 声明allow_branches{声明allow_branches?} 声明allow_branches --是--> branch匹配allow_branches{branch匹配allow_branches?} 声明allow_branches --否--> 通过 branch匹配allow_branches --是--> 通过 branch匹配allow_branches --否--> 不通过 ``` `allow_branches` 检查的 branch 同 [CNB\_BRANCH](/cnb/build/build-in-env.md#CNB_BRANCH)。 ```mermaid flowchart LR strat([event检查]) --> 声明allow_events{声明allow_events?} 声明allow_events --是--> event匹配allow_events{event匹配allow_events?} 声明allow_events --否--> 通过 event匹配allow_events --是--> 通过 event匹配allow_events --否--> 不通过 ``` ```mermaid flowchart LR strat([image检查]) --> 声明allow_images{声明allow_images?} 声明allow_images --是--> image匹配allow_images{image匹配allow_images?} 声明allow_images --否--> 通过 image匹配allow_images --是--> 通过 image匹配allow_images --否--> 不通过 ``` image 检查说明: - 镜像任务参数可以通过 `settingsFrom` 设置,也可以 `imports` 引入后通过环境变量的方式设置,这两种方式均被认为是插件任务引用文件。 - 镜像名不带标签时,会以 `镜像名` 和 `镜像名:latest` 去匹配 `allow_images`,匹配一个即算通过。 - 非插件任务的 image 是空字符串,不能匹配任何 `glob` 表达式,即:配置文件声明了 `allow_images` 不能被非插件任务引用。 - **注意:Job 同时设置了 image、script 属于以 image 作为执行环境的脚本任务。** - 语法上流水线可以声明 image 作为构建环境,但不算插件任务,即:配置文件声明了 `allow_images` 不能在流水线级别被引用。 ## 示例 ### 流水线密钥文件引用 ```yaml # 密钥仓库中的配置文件 secret.yml allow_slugs: - 'p1/**' allow_events: - push allow_branches: - main # dockerhub 用户名和密码 DOCKER_USER: docker-user DOCKER_PWD: docker-pwd ``` ```yaml # 流水线配置文件 .cnb.yml main: push: - services: - docker imports: https://cnb.cool//-/blob/main/xxx/secret.yml stages: - name: docker login script: | # 登录到 dockerhub docker login -u ${DOCKER_USER} -p "${DOCKER_PWD}" # docker build xxx # docker push xxx ``` 流水线引用其他密钥仓库中的配置文件 `secret.yml`,但流水线触发者无该文件读权限。 被引用文件 `secret.yml` 声明了 `allow_slugs`、`allow_events` 和 `allow_branches`。 若 `p1` 组织下的仓库的分支 `main` 触发了 `push` 事件,那么流水线就能引用该密钥文件,使用其中的敏感信息。 这样限制了只有密钥仓库的负责人、管理员才能查看、修改 `secret.yml` 中的敏感内容,同时又能被符合条件的流水线引用。 ### 插件任务参数引用 ```yaml # 密钥仓库中的配置文件 image-settings.yml allow_images: - 'registry.com/image1/**' allow_slugs: - 'p1/**' arg1: arg1 arg2: arg2 ``` ```yaml # 流水线配置文件 .cnb.yml 配置插件任务 name: image job image: registry.com/image1/print:latest settingsFrom: - https://cnb.cool//-/blob/main/xxx/image-settings.yml ``` 镜像如果是第三方制作的,可能存在泄漏信息的风险,可以通过 `allow_images` 限制该配置文件只能被确定安全性的特定镜像名的插件任务使用。 `image: registry.com/image1/print:latest` 符合 `registry.com/image1/**`,image 检查通过。 `allow_slugs` 指定了只能被组织 `p1` 下的仓库流水线引用,进一步控制配置文件的使用范围。 --- url: /cnb/build/pipeline-cache.md --- > For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /cnb/build/pipeline-cache.md. # 流水线缓存 流水线构建过程中,往往会有很多依赖或者中间产物,通过将这些依赖或者中间产物,缓存起来,供下次流水线使用。往往可以极大的减少构建时间,提高构建效率。 ## 节点缓存 流水线是会跑在云平台上多个构建节点上的,为了平衡单点故障问题和缓存命中率,默认情况下,每个仓库的流水线,会分配到固定的3个节点上跑。(随着仓库流水线资源使用情况,也会动态增加节点数) :::tip 固定的3个节点也是相对的,随着整个云平台节点扩缩容, 也可能会分配到另外的3个节点上 ::: ### 代码缓存 流水线执行时,会自动拉取代码文件到构建节点上,同时也会将代码缓存到构建节点。供下次流水线使用。 ### 文件缓存 构建过程中,可以把一些`项目依赖`,`构建缓存` 等文件,缓存到构建节点上。供下次流水线使用。 配置方式参考:[pipeline.runner.volumes](/cnb/build/grammar.md#volumes) :::tip 依赖基于 `OverlayFS` 的缓存瞬间复制技术, 可以实现高并发复用缓存。 ::: ## 跨节点缓存 为了实现每个构建节点都使用同一份缓存,可以将需要缓存的内容构建成 Docker缓存镜像。 具体方法参考内置任务:[docker:cache](/cnb/build/internal-steps.md#docker-cache) --- url: /cnb/build/crontab.md --- > For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /cnb/build/crontab.md. # 定时任务 ## 简介 与普通流水线不同,定时流水线的触发方式是定时器。 定时任务格式使用 `POSIX cron` 语法。 时区使用 `Asia/Shanghai`。 下面案例中的定时流水线会在每天 `Asia/Shanghai` 时间 5:30 和 17:30 时执行。在执行时,会以定时任务负责人作为流水线触发人,取 `main` 分支的代码来运行。 负责人是把定时任务配置(添加或变更)推送到仓库的用户。例如 `A` 用户将案例的配置推送到 `main` 分支, 负责人就是 `A`,后续 `B` 用户改了 `crontab: 30 5,17 * * *` 事件中的配置,负责人则变成 `B`。 当定时任务负责人被移除仓库时,定时任务流水线会失败,可通过修改定时任务配置内容重新推送以更新负责人。 ```yaml main: # 普通 push 事件流水线 push: - stages: - name: test script: echo 1 # 定时流水线 'crontab: 30 5,17 * * *': # 修改内容可重新关联定时任务触发者,建议修改name,改出问题的风险低 - name: crontab-a stages: - name: test script: echo 1 ``` 为了提供更可靠的服务,我们限制了定时任务最小的时间间隔为 5 分钟,低于 5 分钟间隔的定时任务(例如:`* * * * *`)将无法成功添加。 ## 配置解析 这部分内容将会将定时流水线每部分的配置格式和含义进行详细解释。 ```yaml main: 'crontab: 30 5,17 * * *': - stages: - name: test script: echo 1 ``` ### main 此处和普通流水线一样,可以填写仓库中的已存在分支名。含义为,定时流水线执行时所采用的代码。 比如写为 `main`,那么当流水线执行时候,会采用 `main` 分支的 `HEAD` 处代码。 > 为提高资源利用率,定时任务流水线分支名不支持 `glob` 表达式,只能是明确的分支名。 ### `crontab: 30 5,17 * * *` 普通流水线一般是某个操作触发的事件,如 `push` 或者 `pull_request`,是一次性的事件。 但是定时流水线是用定时器触发,填写的格式为 `crontab: ${CRON}`。 - `crontab:` 为定时流水线事件名固定前缀。 - `${CRON}` 为实际的执行时间,格式为标准 `POSIX cron` 语法。 --- url: /cnb/build/skip-pipeline.md --- > For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /cnb/build/skip-pipeline.md. # 跳过流水线 ## 主动跳过流水线 有时候,我们不想触发流水线,此时,我们可以下面的方式主动跳过流水线。 `push`、`commit.add` 和 `branch.create` 事件里,以下两种情况会跳过流水线: 1. 最近一个 commit message 里带 `[ci skip]` 或 `[skip ci]` 2. git push -o ci.skip 如: ```bash git commit -m "feat: some feature [ci skip]" git push origin main ``` 或 ```bash git commit -m "feat: some feature" git push origin main -o ci.skip ``` ## 事件忽略 为避免无意义的流水线,`云原生构建` 会忽略如下情形的事件: 1. 密钥仓库的文件变更。 2. 仓库迁移时 head commit 的时间戳早于仓库创建时间十分钟前的事件。 3. 仓库设置里未勾选 `允许自动触发` 的 git 操作引起的事件。 4. 仓库设置中未勾选 `Fork 的仓库默认允许自动触发`,fork 后的仓库 `允许自动触发` 自动为未勾选状态。 --- url: /cnb/build/login-debug.md --- > For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /cnb/build/login-debug.md. # 登录调试 ## 什么情况需要登录调试? 用户自定义脚本在 `docker` 容器内执行,由于本地和 CI 环境不一致,可能会遇到本地没问题,CI 构建有问题的情况, 此时可通过日志页面 `登录调试` 入口,登录到流水线 `docker` 容器里进行调试。 ## 如何使用? 每个流水线执行前,会先启动一个流水线 `docker` 容器来执行用户脚本,构建结束默认情况下会销毁 `docker` 容器。 因此,在流水线构建环境存在的时候,可登录 `docker` 容器调试问题。 以下两种情况,登录调试可用: 1. 构建过程中,可登录调试。 2. 构建结束时 Debug 模式。 在日志页面先勾选 `Rebuild` 按钮旁的 `Debug` 选项,然后点击 `Rebuild` 按钮,新触发的构建,在构建结束时, 如果未登录调试,构建环境会先保留 5 分钟,此时可登录调试。之后会定时检测是否有用户登录 `docker` 调试, 没有就自动销毁,有则继续保留环境。构建环境最长保留1个小时。 ## 调试技巧 点击 `Rebuild` 时,可选择需要执行的`Pipeline`、`Stage`、`Job`,方便帮助开发者复现问题环境。 --- url: /cnb/build/web-trigger.md --- > For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /cnb/build/web-trigger.md. # 手动触发流水线 云原生构建支持在页面上配置自定义按钮,点击按钮触发执行流水线(仅支持触发 [页面自定义事件](/cnb/build/grammar.md#web_trigger))。同时支持在页面上输入环境变量。 效果如下: ![](https://docs.cnb.cool/images/build/web-trigger-btn.zh.png) :::tip 目前仅支持在 `代码-分支详情页` 上配置的自定义按钮。 ::: ## 自定义按钮配置 在仓库根目录下增加 `.cnb/web_trigger.yml` 文件用于配置自定义按钮。 注意 `.cnb/web_trigger.yml` 配置文件中不支持 `include` 和 `imports` 语法。 ```yaml # .cnb/web_trigger.yml branch: # 如下按钮在分支名以 release 开头的分支详情页面显示 - reg: '^release' buttons: - name: 按钮名1 # 如存在,则将作为流水线 title,否则流水线使用默认 title description: 按钮描述 event: web_trigger_one # 触发的 CI 事件名 # 权限控制,不配置则有仓库写权限的用户可触发构建 # 如果配置,则需要有仓库写权限,并且满足 roles 或 users 其中之一才有权限触发构建 permissions: # roles 和 users 配置其中之一或都配置均可,二者满足其一即可 roles: - owner - developer users: - name1 - name2 # 环境变量 env: # 默认传入的环境变量,其中 key 值(a,b,c)为环境变量名,支持如下两种格式 a: 1 b: 2 c: # 环境变量别名 name: 变量c # 环境变量值 value: 3 # 可输入环境变量,可覆盖上述 env 的变量配置 inputs: # 目前支持以下三种格式:输入框(input)、多行文本输入框(textarea)、下拉选择框(select 支持单选和多选),switch 开关 # 其中 key 值(var1、var2、var3、var4、var5)为环境变量名 var1: # 输入框 name: 变量1 description: 输入变量1 required: true # 是否必填 type: input default: 默认值1 var2: # 输入框 name: 变量2 description: 输入变量2 required: true type: textarea default: 默认值2 var3: # 单选下拉选择框 name: 变量3 description: 输入变量3 required: false type: select default: value1 options: - name: 选项1 value: value1 description: 选项1描述 - name: 选项2 value: value2 description: 选项2描述 var4: # 多选下拉选择框 name: 变量4 description: 输入变量4 required: false type: select # 是否支持多选,多选结果用分号分隔 multiple: true default: value1,value2 options: - name: 选项1 value: value1 description: 选项1描述 - name: 选项2 value: value2 description: 选项2描述 - name: 选项3 value: value3 description: 选项3描述 var5: # switch 开关 name: 变量5 description: 选择变量5 required: false type: switch default: value1 options: - name: 选项1 value: value1 description: 选项1描述 - name: 选项2 value: value2 description: 选项2描述 # 如下按钮在分支名以 dev 开头的分支详情页面显示 - reg: '^dev' buttons: - name: 按钮名2 description: 按钮描述 event: web_trigger_two - name: 按钮名3 description: 按钮描述 event: web_trigger_three # 如下自定义按钮在所有分支详情页面显示 - buttons: - name: 按钮名4 description: 按钮描述 event: web_trigger_four ``` 目前仅支持配置分支详情页面的自定义按钮,yaml 中键值为 `branch`,值为数组格式,数组元素定义如下: - `reg`: 选填,`String`,正则表达式,用于匹配分支名(仅匹配到的分支显示 `buttons` 配置的自定义按钮), 未填则匹配全部分支 - `buttons`: 必填,`Array