2878 字约 10 分钟
反馈问题前,建议先查看对应文档或在以下常见问题和 feedback(在新窗口打开) 中查找。
若未找到答案,请在 feedback(在新窗口打开) 中提交 issue。
触发与配置
流水线为什么没触发?
定位流水线未触发问题,需先理解从触发到执行的流程。
以 push 事件为例:
其中
skip 检测包括ifNewBranch、ifModify,参考语法。
可按此流程逐层排查:
- 代码是否 push 到远端?
- 对应分支是否有
.cnb.yml?- include 的文件是否有权限
- 配置内容无格式、语法问题
.cnb.yml是否声明了当前分支的push事件流水线?- 是否命中了 skip 检测?
CNB 默认分支通常为
main,部分从其他平台迁移的仓库可能为master,请注意区分。
在一个分支配置了另一个分支的流水线,为什么没生效?
.cnb.yml 中的流水线配置只对当前分支生效。在 A 分支配置 B 分支的流水线,B 分支不会按此配置执行,实际取决于各分支自身的 .cnb.yml。
例如,在 main 分支的 .cnb.yml 中配置了 dev 的 push,当 dev 分支 push 时,系统会读取 dev 分支自身的 .cnb.yml,而非 main 分支的。
详细说明参考 触发分支。
Fork 仓库为什么不自动触发流水线?
出于安全考虑,Fork 后的仓库默认不会自动触发流水线(包括 Git 操作事件、定时任务事件、Issue 事件)。
如需启用,可在源仓库页面依次进入 设置 → 云原生构建,勾选「Fork 的仓库默认允许自动触发」。
注意:即使启用了自动触发,Fork 仓库流水线中的
CNB_TOKEN权限也会被限制在当前仓库范围内。
详细说明参考 Fork 仓库触发限制。
如何跳过流水线执行?
在 push、commit.add 和 branch.create 事件中,可通过以下两种方式跳过:
- 在 commit message 中添加
[ci skip]或[skip ci]:
git commit -m "docs: update readme [ci skip]"
git push origin main- 使用 git push 选项:
git push origin main -o ci.skip详细说明参考 跳过流水线。
为什么插件任务拿不到 env / imports 设置的环境变量?
这是脚本任务和插件任务的核心区别之一。插件任务不会接收通过 env 或 imports 声明的自定义环境变量,只能使用 CNB 内置的系统环境变量。
插件任务的参数应通过 settings 传递:
# ❌ 错误:env 声明的变量不会传递给插件
- name: wrong
image: plugins/npm
env:
PLUGIN_USERNAME: $NPM_USER
# ✅ 正确:通过 settings 传递参数
- name: correct
image: plugins/npm
settings:
username: $NPM_USER详细对比参考 脚本任务 vs 插件任务。
执行与调试
在本地明明好的,为什么在 CI 上跑失败了?
定位此问题,需先明确本地与 CI 环境的区别:
| 本地 | CI 环境 | |
|---|---|---|
| 网络 | 本地网络(比如一些办公内网) | CI 机器所在网络 |
| 文件 | 本地整个目录下所有文件 | Git 仓库对应分支代码 |
| 环境 | 原生 | 指定的 Docker 容器环境 |
| Shell | 本地指定 | sh |
了解差异后,可依次排查:
- 是否有文件未提交?
- 构建依赖的文件是否命中
.gitignore? - 是否依赖本地才有的资源(如本地接口、凭证等)?
- CI 声明的 cpus 是否满足要求?
- 本地运行相同镜像获得一致的构建环境进行调试。
云原生构建 的默认镜像为 cnbcool/default-build-env(在新窗口打开)。
那么,我们可以执行下面命令,进入默认 CI 环境进行调试:
docker run --rm -it -v $(pwd):$(pwd) -w $(pwd) cnbcool/default-build-env sh若声明了其他镜像作为构建环境,将上述命令中 cnbcool/default-build-env 替换为对应镜像地址即可。
如何登录到流水线容器调试?
参考 登录调试。
流水线执行脚本与登录调试结果不一致?
流水线默认使用 sh,登录调试使用 bash,两者语法存在差异。
如果确认流水线容器支持 bash(默认容器支持,自定义容器可能不支持),可以将执行脚本改为:
bash xxx.sh
# 或
bash -c '原来的语句'流水线超时无输出?
一个 Job 超过 10 分钟无日志输出将被终止。可考虑增加日志输出,例如为 npm install 添加 --verbose 参数。
这与 Job 的 timeout 超时不同,无法通过配置修改。
为什么 PR 流水线中 docker push / git push 失败?
PR 相关事件属于不可信事件,流水线中 CNB_TOKEN 权限受限——代码和制品库仅有只读权限,docker push、git push 等写操作会失败。
出于安全考虑:PR 源分支代码可能被未授权用户修改,赋予写权限可能导致恶意代码注入或构建产物被篡改。
解决方案:将涉及推送的任务放到 push、pull_request.target 或 tag_push 等可信事件中执行即可。
为什么公开仓库流水线无法访问私有资源?
如果流水线所在仓库是公开仓库,流水线中的 CNB_TOKEN 只能访问公开资源,不能访问私有代码仓库、私有制品仓库等私有资源。
这是为了避免公开仓库中的流水线代码获得私有资源访问权限。
若需要访问私有资源,可选择以下方式:
- 在私有仓库中触发流水线。
- 调整目标资源的访问范围。
- 自行创建具备所需权限的个人令牌或部署令牌,并在流水线中使用。
详细说明参考 CNB_TOKEN 安全限制。
没改代码为什么流水线就失败了?
可检查依赖的其他资源是否有变动:
- 插件任务镜像版本是否为
latest,镜像是否有变动。 - CI 配置文件引用的其他仓库文件是否有变动。
- 可能是网络波动,尝试 Rebuild。
如何查看流水线完整日志?
CI 服务将插件任务和脚本任务发送至 Runner 执行。任务日志过长时会被截断返回。
阶段会汇总其下所有任务的日志,过长时也会截断以便更好地展示在日志页面。
构建完成后,可在日志页面流水线右上角点击日志下载按钮查看完整日志。
缓存与环境
为什么缓存(volumes)有时不生效?
流水线的文件缓存(volumes)是节点级别的,存储在构建节点本地磁盘。默认情况下,每个仓库的流水线分配到固定的 3 个节点执行,因此:
- 跨节点不共享:上次构建在节点 A 写入的缓存,这次如果分配到节点 B,则无法命中。
- 节点可能变化:随着平台扩缩容,分配的节点可能发生变化,旧节点上的缓存不会自动迁移。
如需每次构建都能使用同一份缓存,可以使用 docker:cache 内置任务将缓存构建为 Docker 镜像,实现跨节点缓存。
详细说明参考 流水线缓存。
为什么不提供固定的出口 IP?
CNB 的出口 IP 是动态的,可能随时间变化。
原因:
- 运维弹性:平台根据负载自动扩缩容、迁移节点,出口 IP 随之动态变化。
- 安全建议:不建议对 CNB 出口 IP 加白名单。CNB 是公开平台,对出口 IP 加白等同于对公网加白,存在安全风险。
替代方案(需要固定 IP 访问内部服务时):
- 私有代理:配置自有代理服务器,通过代理路由请求,使用代理的固定 IP
- 跳板机:通过 SSH 跳板机连接目标机器执行命令,可使用 cnbcool/ssh 插件。参考示例
- 腾讯云插件:推荐 tencentcom/tcloud-cmd 插件,可远程执行命令,无需白名单配置
如何构建多架构/多平台镜像?
若需要使用 buildx 构建多种架构/平台的镜像,可以开启 rootlessBuildkitd 特性。需要在服务中声明:
main:
push:
- docker:
image: golang:1.24
services:
- name: docker
options:
rootlessBuildkitd:
enabled: true
env:
IMAGE_TAG: ${CNB_DOCKER_REGISTRY}/${CNB_REPO_SLUG_LOWERCASE}:latest
stages:
- name: go build
script: ./build.sh
- name: docker login
script: docker login -u ${CNB_TOKEN_USER_NAME} -p "${CNB_TOKEN}" ${CNB_DOCKER_REGISTRY}
- name: docker build and push
script: docker buildx build -t ${IMAGE_TAG} --platform linux/amd64,linux/amd64/v2,linux/amd64/v3,linux/arm64,linux/riscv64,linux/ppc64le,linux/s390x,linux/386,linux/mips64le,linux/mips64,linux/loong64,linux/arm/v7,linux/arm/v6 --push .流水线中运行 Docker 镜像时报错 UID/GID 超过 65535?
如果在流水线中遇到类似以下错误:
docker: failed to extract layer ... failed to Lchown ... for UID 100000, GID 100000: lchown ...: invalid argument
(Hint: try increasing the number of subordinate IDs in /etc/subuid and /etc/subgid)原因:
CNB 的 Docker 采用 uidmap 技术,将容器内 UID 范围限制在 0-65535。当镜像中存在 UID/GID 超过 65535 的文件时,Docker 无法正确映射,导致镜像层解压失败。
解决方案:
重新制作镜像,清理这类文件或改为正常 UID/GID,避免使用包含超过 65535 的 UID/GID 的基础镜像。
为什么流水线的仓库存储用量跟页面上显示不一致?
流水线上看到的仓库大小通常与页面显示接近。
但对于所有公开的 Fork 仓库,为加速构建和优化存储,所有 Fork 仓库在构建节点上会复用其祖先仓库的 .git 目录,再通过 OverlayFS 技术裂变出多份副本供不同仓库使用。因此流水线上看到的仓库大小实际包含祖先仓库和所有子孙仓库。
对于普通仓库,页面上触发仓库 GC 后,流水线上仓库大小不会立即变化,需等待构建机缓存 GC 逻辑运行后才与页面一致。
代码仓库相关
如何解决代码合并冲突?
创建 PR 或在 PR 相关事件构建中遇到代码冲突时,可通过以下命令解决:
git fetch origin # 从远端仓库获取更新
git rebase -i origin/main # 实际的目标分支名
# 本地处理冲突
git commit # 根据实际情况提交到本地仓库
git push -f # 推送到远端仓库如何彻底删除 Git 仓库里的文件,释放空间?
Git 仓库支持恢复任意历史提交,.git 目录会存储所有历史文件。仅删除工作目录中的文件不会释放空间。
要彻底删除 Git 仓库中的文件并释放空间,可通过以下两种方法:
方法一(最简单):在远端新建仓库,复制需要的文件过去,再改名为原仓库名。
方法二(较复杂):通过 git filter-branch 命令或第三方工具(如 BFG Repo-Cleaner)在本地彻底删除对应文件后,强制推送到远端,再触发远端仓库 GC 流程。