{{< details >}}

  • Tier: 基础版,专业版,旗舰版
  • Offering: JihuLab.com, 私有化部署

{{< /details >}}

极狐GitLab 提供了几个工具来帮助你更容易地调试 CI/CD 配置。

如果你无法解决流水线议题,你可以从以下地方获得帮助:

如果你对特定的 CI/CD 功能有议题,请查看该功能的相关故障排除部分:

调试技术

验证语法

问题的早期来源可能是语法错误。如果发现任何语法或格式问题,流水线将显示 yaml invalid 徽章并且不会开始运行。

使用流水线编辑器编辑 .gitlab-ci.yml

流水线编辑器是推荐的编辑体验(而不是单文件编辑器或 Web IDE)。它包括:

  • 确保你只使用接受的关键字的代码补全建议。
  • 自动语法高亮和验证。
  • CI/CD 配置可视化,你的 .gitlab-ci.yml 文件的图形表示。

本地编辑 .gitlab-ci.yml

如果你更喜欢在本地编辑流水线配置,你可以在编辑器中使用极狐GitLab CI/CD 模式来验证基本语法问题。

如果你需要直接链接到模式,请使用以下 URL:

https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/assets/javascripts/editor/schema/ci.json

要查看 CI/CD 模式覆盖的自定义标签的完整列表,请检查模式的最新版本。

使用 CI Lint 工具验证语法

你可以使用 CI Lint 工具来验证 CI/CD 配置片段的语法是否正确。粘贴完整的 .gitlab-ci.yml 文件或单个作业配置,以验证基本语法。

当项目中存在 .gitlab-ci.yml 文件时,你还可以使用 CI Lint 工具来模拟创建完整流水线。它会对配置语法进行更深入的验证。

使用流水线名称

使用 workflow:name 为所有流水线类型命名,这使得在流水线列表中更容易识别流水线。例如:

variables:
  PIPELINE_NAME: "Default pipeline name"

workflow:
  name: '$PIPELINE_NAME'
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
      variables:
        PIPELINE_NAME: "Merge request pipeline"
    - if: '$CI_PIPELINE_SOURCE == "schedule" && $PIPELINE_SCHEDULE_TYPE == "hourly_deploy"'
      variables:
        PIPELINE_NAME: "Hourly deployment pipeline"
    - if: '$CI_PIPELINE_SOURCE == "schedule"'
      variables:
        PIPELINE_NAME: "Other scheduled pipeline"
    - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
      variables:
        PIPELINE_NAME: "Default branch pipeline"
    - if: '$CI_COMMIT_BRANCH =~ /^\d{1,2}\.\d{1,2}-stable$/'
      variables:
        PIPELINE_NAME: "Stable branch pipeline"

CI/CD 变量

验证变量

故障排除 CI/CD 的关键部分是验证流水线中存在哪些变量,以及它们的值是什么。很多流水线配置依赖于变量,验证它们是找到问题源的最快方法之一。

导出每个问题作业中可用的变量的完整列表。检查你期望的变量是否存在,并检查它们的值是否符合你的期望。

使用变量向 CLI 命令添加标志

你可以定义不在标准流水线运行中使用的 CI/CD 变量,但可以用于按需调试。如果你像下面的示例中那样添加变量,你可以在手动运行流水线单个作业时添加它,以修改命令的行为。例如:

my-flaky-job:
  variables:
    DEBUG_VARS: ""
  script:
    - my-test-command $DEBUG_VARS /test-dirs

在这个例子中,DEBUG_VARS 在标准流水线中默认为空白。如果你需要调试作业的行为,手动运行流水线并设置 DEBUG_VARS--verbose 以获得额外输出。

依赖关系

依赖相关问题是流水线中意外问题的另一个常见来源。

验证依赖版本

为了验证在作业中使用的依赖的正确版本,你可以在运行主脚本命令之前输出它们。例如:

job:
  before_script:
    - node --version
    - yarn --version
  script:
    - my-javascript-tests.sh

固定版本

虽然你可能希望始终使用最新版本的依赖或镜像,但更新可能会意外地包含破坏性更改。考虑固定关键依赖和镜像以避免意外更改。例如:

variables:
  ALPINE_VERSION: '3.18.6'

job1:
  image: alpine:$ALPINE_VERSION  # This will never change unexpectedly
  script:
    - my-test-script.sh

job2:
  image: alpine:latest  # This might suddenly change
  script:
    - my-test-script.sh

你仍然应该定期检查依赖和镜像更新,因为可能有重要的安全更新。然后你可以手动更新版本,作为验证更新的镜像或依赖仍然与流水线一起工作的过程的一部分。

验证作业输出

使输出详细

如果你使用 --silent 减少作业日志中的输出量,可能会使得难以识别作业中的错误原因。此外,尽量使用 --verbose,以获得更多详细信息。

job1:
  script:
    - my-test-tool --silent         # 如果失败,可能无法识别议题。
    - my-other-test-tool --verbose  # 这条命令可能更容易调试。

将输出和报告保存为产物

一些工具可能会生成仅在作业运行时需要的文件,但这些文件的内容可能会被用于调试。你可以使用 artifacts 将它们保存以供后续分析:

job1:
  script:
    - my-tool --json-output my-output.json
  artifacts:
    paths:
      - my-output.json

配置为 artifacts:reports 的报告默认不可下载,但可能也包含帮助调试的信息。使用相同的技术使这些报告可供检查:

job1:
  script:
    - rspec --format RspecJunitFormatter --out rspec.xml
  artifacts:
    reports:
      junit: rspec.xml
    paths:
      - rspec.xmp

{{< alert type=”warning” >}}

不要在产物中保存令牌、密码或其他敏感信息,因为任何有权限访问流水线的用户都可以查看这些信息。

{{< /alert >}}

在本地运行作业的命令

你可以使用像 Rancher Desktop 或类似替代品这样的工具在你的本地机器上运行作业的容器镜像。然后,在容器中运行作业的 script 命令并验证行为。

作业配置议题

许多常见的流水线议题可以通过分析用于控制何时将作业添加到流水线rulesonly/except 配置的行为来解决。你不应该在同一个流水线中使用这两个配置,因为它们的行为不同。混合使用这些配置很难预测流水线如何运行。rules 是控制作业的首选选择,因为 onlyexcept 不再被积极开发。

如果你的 rulesonly/except 配置使用了像 CI_PIPELINE_SOURCECI_MERGE_REQUEST_ID 这样的预定义变量,你应该将验证它们作为第一个故障排除步骤。

作业或流水线未在预期时间运行

rulesonly/except 关键字决定了作业是否被添加到流水线中。如果流水线运行但作业未被添加到流水线中,通常是由于 rulesonly/except 配置议题。

如果流水线似乎根本没有运行,没有错误消息,这也可能是由于 rulesonly/except 配置或 workflow: rules 关键字。

如果你从 only/except 转换到 rules 关键字,你应该仔细检查rules 配置细节only/exceptrules 的行为不同,在迁移时可能会导致意外行为。

用于 rules 的常见 if 子句对于如何编写符合你期望的规则非常有帮助。

如果流水线只包含 .pre.post 阶段中的作业,则不会运行。必须至少有一个其他阶段中的作业。

.gitlab-ci.yml 文件包含字节顺序标记 (BOM) 时出现意外行为

.gitlab-ci.yml 文件或其他包含的配置文件中的 UTF-8 字节顺序标记 (BOM) 会导致流水线行为不正确。字节顺序标记影响文件的解析,导致某些配置被忽略 - 作业可能丢失,变量可能有错误值。某些文本编辑器如果配置为这样做,可能会插入 BOM 字符。

如果你的流水线有令人困惑的行为,你可以使用能够显示 BOM 字符的工具来检查它们的存在。流水线编辑器无法显示这些字符,因此你必须使用外部工具。

带有 changes 关键字的作业意外运行

作业意外添加到流水线的一个常见原因是 changes 关键字在某些情况下总是评估为真。例如,changes 在某些流水线类型中总是为真,包括计划的流水线和标签的流水线。

changes 关键字与 only/exceptrules 一起使用。建议仅将 changesrulesonly/except 配置中的 if 部分一起使用,以确保作业仅被添加到分支流水线或合并请求流水线。

两个流水线同时运行

当你将提交推送到与其关联的打开合并请求的分支时,可能会运行两个流水线。通常一个流水线是合并请求流水线,另一个是分支流水线。

这种情况通常是由 rules 配置引起的,有几种方法可以防止重复流水线

没有流水线或运行了错误类型的流水线

在流水线运行之前,极狐GitLab 会评估配置中的所有作业,并尝试将它们添加到所有可用的流水线类型中。如果在评估结束时没有作业被添加到流水线中,则不会运行流水线。

如果流水线未运行,可能是所有作业都具有阻止它们被添加到流水线的 rulesonly/except

如果运行了错误的流水线类型,则应检查 rulesonly/except 配置以确保作业被添加到正确的流水线类型。例如,如果合并请求流水线未运行,则作业可能已被添加到分支流水线中。

你的 workflow: rules 配置也可能阻止了流水线,或允许了错误的流水线类型。

具有许多作业的流水线无法启动

具有超过实例定义的 CI/CD 限制 的流水线无法启动。

要减少单个流水线中的作业数量,你可以将 .gitlab-ci.yml 配置拆分为更多独立的父子流水线

流水线警告

当你:

Job may allow multiple pipelines to run for a single action 警告

当你在 rules 中使用 when 子句而没有 if 子句时,可能会运行多个流水线。通常,当你将提交推送到与其关联的打开合并请求的分支时会发生这种情况。

防止重复流水线,请使用 workflow: rules 或重写你的规则以控制可以运行的流水线。

流水线错误

A CI/CD pipeline must run and be successful before merge 消息

如果项目中启用了 流水线必须成功 设置,并且流水线尚未成功运行,则会显示此消息。这也适用于流水线尚未创建,或者你正在等待外部 CI 服务。

如果你不为项目使用流水线,则应禁用 流水线必须成功 以便接受合并请求。

Checking ability to merge automatically 消息

如果你的合并请求停留在 Checking ability to merge automatically 消息上,且在几分钟后仍未消失,你可以尝试以下解决方法:

  • 刷新合并请求页面。
  • 关闭并重新打开合并请求。
  • 使用 /rebase 快速操作重新基合并请求。
  • 如果你已经确认合并请求准备好合并,可以使用 /merge 快速操作合并。

Checking pipeline status 消息

此消息显示为旋转状态图标 ({{< icon name=”spinner” >}}) ,当合并请求尚未与最新提交关联的流水线时。可能是因为:

  • 极狐GitLab 还没有完成创建流水线。
  • 你正在使用外部 CI 服务,极狐GitLab 尚未收到服务的回复。
  • 你未在项目中使用 CI/CD 流水线。
  • 你在项目中使用 CI/CD 流水线,但你的配置阻止了流水线在合并请求的源分支上运行。
  • 最新的流水线已被删除。
  • 合并请求的源分支在私有分叉上。

在创建流水线后,消息将更新为流水线状态。

在这些情况下,如果启用了 流水线必须成功 设置,消息可能会卡住,图标会无休止地旋转。有关更多详细信息,请参阅议题 334281

Project <group/project> not found or access denied 消息

如果在使用 include 添加配置时发生以下情况,则会显示此消息:

  • 配置指向无法找到的项目。
  • 运行流水线的用户无法访问任何包含的项目。

要解决此问题,请检查:

  • 项目的路径格式为 my-group/my-project,不包含存储库中的任何文件夹。
  • 运行流水线的用户是包含文件的项目的成员。用户还必须具有在相同项目中运行 CI/CD 作业的权限

The parsed YAML is too big 消息

当 YAML 配置过大或嵌套过深时会显示此消息。具有大量包含项和数千行的 YAML 文件更容易达到内存限制。例如,200 kb 的 YAML 文件可能会达到默认内存限制。

为了减少配置大小,你可以:

  • 在流水线编辑器的完整配置标签中检查扩展的 CI/CD 配置的长度。查找可以删除或简化的重复配置。
  • 将长或重复的 script 部分移到项目中的独立脚本中。
  • 使用父子流水线将一些工作移到独立的子流水线中的作业中。

在极狐GitLab 私有化部署中,你可以增加大小限制

编辑 .gitlab-ci.yml 文件时出现 500 错误

包含配置文件的循环导致 500 错误,当使用网页编辑器编辑 .gitlab-ci.yml 文件时发生。

确保包含的配置文件不会相互引用形成循环。

Failed to pull image 消息

{{< history >}}

  • 在极狐GitLab 16.3 中,允许使用 CI_JOB_TOKEN 访问此项目 设置已重命名为 限制访问 此项目

{{< /history >}}

当尝试在 CI/CD 作业中拉取容器镜像时,runner 可能返回 Failed to pull image 消息。

runner 使用CI/CD 作业令牌进行身份验证,当从另一个项目的容器注册表中获取由 image 定义的容器镜像时。

如果作业令牌设置阻止访问另一个项目的容器注册表,runner 会返回错误消息。

例如:

  • WARNING: Failed to pull image with policy "always": Error response from daemon: pull access denied for registry.example.com/path/to/project, repository does not exist or may require 'docker login': denied: requested access to the resource is denied
    
  • WARNING: Failed to pull image with policy "": image pull failed: rpc error: code = Unknown desc = failed to pull and unpack image "registry.example.com/path/to/project/image:v1.2.3": failed to resolve reference "registry.example.com/path/to/project/image:v1.2.3": pull access denied, repository does not exist or may require authorization: server message: insufficient_scope: authorization failed
    

这些错误可能发生在以下情况下:

  • 在托管镜像的私有项目中启用了 限制访问 此项目 选项。
  • 尝试获取镜像的作业在未列入私有项目允许列表的项目中运行。

要解决此问题,将任何具有 CI/CD 作业的项目添加到目标项目的作业令牌允许列表,以从容器注册表中获取镜像。

这些错误也可能发生在尝试使用项目访问令牌访问另一个项目中的镜像时。项目访问令牌的范围仅限于一个项目,因此无法访问其他项目中的镜像。你必须使用具有更广泛范围的其他令牌类型

在运行流水线时 Something went wrong on our end 消息或 500 错误

你可能会收到以下流水线错误:

  • 在推送或创建合并请求时出现 Something went wrong on our end 消息。
  • 使用 API 触发流水线时出现 500 错误。

这些错误可能发生在导入项目后内部 ID 记录不同步时。

config should be an array of hashes 错误消息

当使用 parallel:matrix 关键字!reference 标签 时,你可能会看到类似以下的错误:

This GitLab CI configuration is invalid: jobs:my_job_name:parallel:matrix config should be an array of hashes.

parallel:matrix 关键字不支持同时使用多个 !reference 标签。尝试使用 YAML 锚点 来代替。