---
url: /zh/faq.md
---
问题反馈前，建议先查看对应文档，在下面常见问题和 [feedback]() 中查看问题是否已经存在。

若未能找到答案，请于 [feedback]() 中提交 `issue`。

\[\[TOC]]

## 流水线相关

### 流水线为什么没触发？

要定位流水线没触发问题，先要了解流水线从触发到执行的流程。

以 `push` 事件为例：

```mermaid
flowchart LR
    push(git push) --> config(CI 读取对应分支下 .cnb.yml) --> event(获取对应分支 push 事件配置) --> skip(skip 检测) --> 流水线执行
```

> 其中 `skip 检测` 包括 `ifNewBranch`、`ifModify`，参考[语法](./build/grammar.md#Pipeline-ifModify)。

那么可以按照这个流程一层层查下去：

1. 代码是否 push 到远端？
2. 对应分支是否有 `.cnb.yml`？
   1. include 的文件是否有权限
   2. 配置内容无格式、语法问题
3. `.cnb.yml` 是否声明了当前分支的 `push` 事件流水线？
4. 是否命中了 skip 检测？

> CNB 中默认分支通常为 `main`，一些迁移自其他平台的仓库可能默认分支为 `master`，请注意区分。

### 在本地明明好的，为什么在 CI 上跑失败了？

要定位这个问题，首先要明确本地环境和 CI 环境的区别：

|       | 本地                         | CI 环境                |
| ----- | ---------------------------- | ---------------------- |
| 网络  | 本地网络（比如一些办公内网） | CI 机器所在网络        |
| 文件  | 本地整个目录下所有文件       | GIT仓库对应分支代码    |
| 环境  | 原生                         | 指定的 Docker 容器环境 |
| Shell | 本地指定                     | sh                     |

了解到差异，我们可以依次排查：

1. 是否有文件未提交？
2. 构建依赖的文件是否命中 .gitignore？
3. 是否依赖本地才有的资源（如本地接口、凭证等）？
4. CI 声明的 [cpus](./build/grammar.md#runner) 是否满足要求？
5. 本地运行相同的镜像，得到与 CI 相同的构建环境，进行调试。

`云原生构建` 的默认镜像为 [\_\_ENV\_\_CNB\_DEFAULT\_DOCKER\_IMAGE](https://cnb.cool/cnb/cool/default-build-env)。

那么，我们可以执行下面命令，进入默认 CI 环境进行调试

```bash
docker run --rm -it -v $(pwd):$(pwd) -w $(pwd) cnbcool/default-build-env sh
```

如果声明了其他镜像作为流水线构建环境，请将上述命令中 `cnbcool/default-build-env` 替换成对应镜像地址。

### 如何登录到流水线容器调试？

参考 [登录调试](./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 试试。

### 如何查看流水线完整日志？

CI 服务发送插件任务和脚本任务至 Runner 执行。如果任务日志过长，将会被截断并返回给 CI 服务。

阶段会汇总其下所有任务的日志。若阶段日志过长，也会被截断以便更好地展示在日志页面上。

构建完成后，您可在日志页面流水线右上角点击日志下载按钮查看完整日志。

### 为什么不提供固定的出口 IP？

CNB 的出口 IP 地址是动态的，可能会随时间变化。

这是因为：

1. **运维弹性**：平台会根据负载自动扩缩容、迁移节点等运维操作，出口 IP 随之动态变化。
2. **安全建议**：不建议对 CNB 出口 IP 加白名单。CNB 是公开开放的平台，对出口 IP 加白等同于对公网加白，存在安全风险。

替代方案（如需固定 IP 访问内部服务）：

* **私有代理**：配置自有代理服务器，通过代理路由请求，使用代理的固定 IP。
* **跳板机**：通过 SSH 跳板机连接目标机器执行命令。可使用 [cnbcool/ssh](../../plugin/#public/cnbcool/ssh) 插件。[参考示例](https://cnb.cool/examples/ecosystem/springboot-maven-docker-jumpserver)
* **腾讯云插件**：推荐 [tencentcom/tcloud-cmd](../../plugin/#public/tencentcom/tcloud-cmd) 插件，可远程执行命令，无需白名单配置。

### 如何构建多架构/多平台镜像？

若需要使用`buildx`构建多种架构/平台的镜像，可以开启`rootlessBuildkitd`特性。需要在服务中声明：

```yaml title=".cnb.yml"
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 .
```

### 为什么流水线的仓库存储用量跟页面上显示不一致？

一般来说，流水线上看到的仓库大小应该是跟页面上显示接近的。

但对于所有公开的`Fork仓库`，为了加速构建流程和优化存储空间，目前所有的`Fork仓库`，在构建节点上都会复用其祖先仓库的`.git`目录，然后再通过`OverlayFS`技术裂变出多份副本供不同仓库使用。因此在流水线上看到的仓库大小，实际上是包含祖先仓库和所有子孙仓库的仓库大小。

另外，对于普通的仓库，在页面上触发仓库GC之后，流水线上仓库大小也不会立马变化，需要等待构建机本身的缓存gc逻辑运行后，才会跟页面上显示一致。

## 代码仓库相关

### 如何解决代码合并冲突？{#dai-ma-he-bing-chong-tu}

若创建 PR 或在 PR 相关事件的构建中碰到代码冲突问题，可以通过如下命令解决：

```bash
git fetch origin          # 从远端仓库获取更新
git rebase -i origin/main # 实际的目标分支名

# 本地处理冲突
git commit  # 根据实际情况提交代码到本地仓库
git push -f # 推送到远端仓库
```

### 如何彻底删除GIT仓库里的文件，释放空间？

由于GIT仓库支持恢复任意历史提交，因此`.git`目录会存储历史上提交的所有文件。单纯删除工作目录中的文件，并不会释放空间。

因此要彻底删除GIT仓库里的文件，释放空间，建议通过以下两种方法进行：

方法一(操作最简单): 直接远端建一个新的仓库, 然后把需要的文件复制过去，再改名为原来的仓库。

方法二(操作复杂): 通过`git filter-branch`命令或者其他第三方工具（如：`BFG Repo-Cleaner`）。在本地彻底删除对应文件后，再强制推送到远程，然后再触发远程仓库GC流程。
