配置 runners

如果您已经安装了自己的 runner,则可以在极狐GitLab 中配置和保护它们。

设置作业的最大超时

您可以为每个 runner 指定最大作业超时,以防止具有更长作业超时的项目使用 runner。如果最大作业超时短于项目中定义的作业超时,则使用最大作业超时。

要设置 runner 的最大超时,请在 REST API 端点 PUT /runners/:id 中设置 maximum_timeout 参数。

针对实例 runner

先决条件:

  • 您必须是管理员。

您可以在极狐GitLab 私有化部署实例上覆盖实例 runner 的作业超时时间。

在 JihuLab.com 上,您不能覆盖 JihuLab.com 托管的实例 runner 的作业超时时间,而必须使用项目定义的超时

要设置最大的作业超时:

  1. 在左侧边栏中,底部,选择 管理员
  2. 选择 CI/CD > Runners
  3. 在 runner 右侧,选择 编辑 ( )。
  4. 最大作业超时 字段中,输入以秒为单位的值。最小值为 600 秒(10 分钟)。
  5. 选择 保存更改

针对群组 runner

先决条件:

  • 您必须具有群组的所有者角色。

要设置最大作业超时:

  1. 在左侧边栏中,选择 搜索或转到,并找到您的群组。
  2. 选择 构建 > Runners
  3. 在 runner 右侧,选择 编辑 ( )。
  4. 最大作业超时 字段中,输入以秒为单位的值。最小值为 600 秒(10 分钟)。
  5. 选择 保存更改

针对项目 runner

先决条件:

  • 您必须具有项目的所有者角色。

要设置最大作业超时:

  1. 在左侧边栏中,选择 搜索或转到,并找到您的项目。
  2. 选择 设置 > CI/CD
  3. 展开 Runners 部分。
  4. 在您要编辑的 runner 右侧,选择 编辑 ( )
  5. 最大作业超时 字段中,输入以秒为单位的值。最小值为 600 秒(10 分钟)。如果未定义,则使用项目的作业超时设置
  6. 选择 保存更改

最大作业超时如何工作

示例 1 - Runner 超时大于项目超时

  1. 您将 runner 的 最大作业超时 设置为 24 小时。
  2. 你将项目的 CI/CD 超时 设置为 2 小时
  3. 您启动作业。
  4. 如果运行时间较长,作业会在 2 小时后超时

示例 2 - 未配置 runner 超时

  1. 您从 runner 中移除 最大作业超时 配置。
  2. 你将项目的 CI/CD 超时 设置为 2 小时。
  3. 您启动一个作业。
  4. 如果运行时间较长,作业会在 2 小时后超时

示例 3 - Runner 超时小于项目超时

  1. 您将 runner 的 最大作业超时 设置为 30 分钟
  2. 您将项目的 CI/CD 超时 设置为 2 小时。
  3. 您启动一个作业。
  4. 如果运行时间较长,作业会在 30 分钟 后超时。

设置 scriptafter_script 超时

  • 引入于极狐GitLab Runner 16.4。

要控制 scriptafter_script 运行的时间长度,可以在 .gitlab-ci.yml 文件中指定一个超时值。

比如,您可以指定一个超时值来提前终止一个长时间运行的 script。这可以确保在作业超时之前,产物和缓存仍然可以上传。scriptafter_script 的超时值必须小于作业超时值。

  • 要为 script 设置超时,使用作业变量 RUNNER_SCRIPT_TIMEOUT
  • 要为 after_script 设置超时,并覆盖默认值 5 分钟,请使用作业变量 RUNNER_AFTER_SCRIPT_TIMEOUT

这些变量都接受 Go 的持续时间格式(例如,40s1h20m2h 4h30m30s)。

比如:

job-with-script-timeouts:
  variables:
    RUNNER_SCRIPT_TIMEOUT: 15m
    RUNNER_AFTER_SCRIPT_TIMEOUT: 10m
  script:
    - "I am allowed to run for min(15m, remaining job timeout)."
  after_script:
    - "I am allowed to run for min(10m, remaining job timeout)."

job-artifact-upload-on-timeout:
  timeout: 1h                           # set job timeout to 1 hour
  variables:
     RUNNER_SCRIPT_TIMEOUT: 50m         # only allow script to run for 50 minutes
  script:
    - long-running-process > output.txt # will be terminated after 50m

  artifacts: # artifacts will have roughly ~10m to upload
    paths:
      - output.txt
    when: on_failure # on_failure because script termination after a timeout is treated as a failure

保护敏感信息

使用示例 runner 时存在安全风险,因为默认情况下实例中所有的群组和项目都能使用它们。runner 执行器和文件系统配置会影响安全。具有访问 runner 宿主机环境的用户可以查看 runner 执行和认证的代码。比如,具有访问 runner 认证令牌的用户可以克隆 runner 并在向量攻击中提交虚假作业。更多信息请参见安全注意事项

配置长轮询

为了减少作业队列超时并加载到您的极狐GitLab 服务器上,可配置长轮询

在派生的项目中使用实例 runner

当项目是派生的,与作业相关的设置会被拷贝。如果您的项目配置了实例 runner,并且用户派生了该项目,则实例 runner 会为该项目服务。

如果派生项目的 runner 设置和新项目命名空间不匹配,就会展示信息:An error occurred while forking the project. Please try again..

为了解决此问题,确保实例 runner 的配置和派生项目以及新的命名空间保持一致。

  • 如果实例 runner 在派生项目中 启用,则它也应该在新的命名空间中 启用
  • 如果实例 runner 在派生项目中 禁用,则它也应该在新的命名空间中 禁用

认证令牌安全

  • 引入于极狐GitLab 15.3,使用名为 enforce_runner_token_expires_at 的功能标志。默认禁用。
  • 在极狐GitLab 15.5 中 GA。功能标志 enforce_runner_token_expires_at 被移除。

每个runner 都使用一个runner 认证令牌来跟极狐GitLab 实例进行连接和认证。

为了防止令牌被泄露,您可以设置令牌在指定的时间间隔内自动轮换。当令牌被轮换时,每个 runner 的令牌都会被更新,无论 runner 的状态如何(onlineoffline)。

不需要手动干预,并且不会影响正在运行的作业。关于令牌轮换的更多详情,请参见runner 认证令牌未在轮换时更新

如果您需要手动更新 runner 认证令牌,您可以运行命令来重置令牌

重置 runner 配置认证令牌

如果 runner 的认证令牌发生了泄露,攻击者就可以使用它来克隆 runner

要重置 runner 配置认证令牌:

  1. 删除 runner:
  2. 创建一个新的 runner,这样它就会被分配一个新的 runner 认证令牌:
  3. 可选。要验证以前的 runner 认证令牌已被撤销,请使用 Runners API

自动轮换 runner 认证令牌

您可以指定轮换 runner 认证令牌的间隔。经常轮换 runner 认证令牌有诸如减少安全风险,避免通过利用泄露令牌来对您的实例进行未授权访问。

先决条件:

  • runner 必须使用 GitLab Runner 15.3 或更高版本。
  • 您必须是管理员。

要自动轮换 runner 认证令牌:

  1. 在左侧边栏中,在底部选择 管理员
  2. 选择 设置 > CI/CD
  3. 展开 持续集成和部署
  4. 为 runner 设置一个 Runners 过期时间,留空表示不过期。
  5. 选择 保存更改

在间隔过期之前,runner 会自动请求新的 runner 认证令牌。关于令牌轮换的更多信息,可以查看Runner 认证令牌在轮换时没有更新

防止 runner 泄露敏感信息

为了确保 runner 不泄露敏感信息,您可以配置它们仅在受保护分支上运行作业,或仅在具有受保护标签的作业上运行。

配置受保护的 runner 可以防止它们在合并请求流水线中运行作业。

对于实例 runner

先决条件:

  • 您必须是管理员。
  1. 在左侧边栏中,在底部选择 管理员
  2. 选择 CI/CD > Runners
  3. 在您要保护的 runner 的右侧,选择 编辑 ( )。
  4. 选择 受保护的复选框。
  5. 选择 保存更改

对于群组 runner

先决条件:

  • 您必须具有项目的所有者角色。
  1. 在左侧边栏中,选择 搜索或前往,找到您的群组。
  2. 选择 构建 > Runners
  3. 在您想要保护的 runner 的右侧,编辑 ( )。
  4. 选择 受保护的复选框。
  5. 选择 保存更改

对于项目 runner

先决条件:

  • 您必须具有项目的所有者角色。
  1. 在左侧边栏中,选择 搜索或前往,找到您的项目。
  2. 选择 设置 > CI/CD
  3. 展开 Runners
  4. 在您要编辑的 runner 右侧,选择 编辑 ( )。
  5. 选择 受保护的复选框。
  6. 选择 保存更改

控制 runner 可以运行的作业

您可以使用标签来控制 runner 可以运行的作业。例如,您可以为具有运行 Rails 测试套件所需依赖项的 runner 指定 rails 标签。

极狐GitLab CI/CD 标签与 Git 标签不同。极狐GitLab CI/CD 标签与 runner 相关联。Git 标签与提交相关联。

对于实例 runner

先决条件:

  • 您必须是管理员。

要控制实例 runner 可以运行的作业:

  1. 在左侧边栏中,在底部选择 管理员
  2. 选择 CI/CD > Runners
  3. 在您要编辑的 runner 的右侧,选择 编辑 ( )。
  4. 设置 runner 运行标记或未标记的作业:
    • 要运行标记的作业,在 标签字段中,输入用逗号分隔的作业标签。例如,macosrails
    • 要运行未标记的作业,选择 运行未标记的作业复选框。
  5. 选择 保存更改

对于群组 runner

先决条件:

  • 您必须具有群组的所有者角色。

要控制群组 runner 可以运行的作业:

  1. 在左侧边栏中,选择 搜索或前往,找到您的群组。
  2. 选择 构建 > Runners
  3. 在您要编辑的 runner 右侧,选择 编辑 ( )。
  4. 设置 runner 运行标记或未标记的作业:
    • 要运行标记的作业,在 标签字段中,输入用逗号分隔的作业标签。例如,macosruby
    • 要运行未标记的作业,选择 运行未标记的作业复选框。
  5. 选择 保存更改

对于项目 runner

先决条件:

  • 您必须具有项目的所有者角色。

要控制项目 runner 可以运行的作业:

  1. 在左侧边栏中,选择 搜索或前往,找到您的项目。
  2. 选择 设置 > CI/CD
  3. 展开 Runners
  4. 在您要编辑的 runner 右侧,选择 编辑 ( )。
  5. 设置 runner 运行标记或未标记的作业:
    • 要运行标记的作业,在 标签字段中,输入用逗号分隔的作业标签。例如,macosruby
    • 要运行未标记的作业,选择 运行未标记的作业复选框。
  6. 选择 保存更改

Runner 如何使用标签

Runner 只运行有标签作业

以下示例说明了将 runner 设置为仅运行有标签作业的潜在影响。

示例 1:

  1. Runner 被配置为仅运行有标签的作业并具有 docker 标签。
  2. 一个带有 hello 标签的作业被执行并卡住。

示例 2:

  1. Runner 被配置为仅运行有标签的作业并具有 docker 标签。
  2. 执行并运行具有 docker 标签的作业。

示例 3:

  1. Runner 被配置为仅运行有标签的作业并具有 docker 标签。
  2. 未定义标签的作业被执行并卡住。

Runner 被允许运行未标记的作业

以下示例说明了将 runner 设置为运行有标签和未标记作业的潜在影响。

示例 1:

  1. Runner 被配置为运行未标记的作业并具有 docker 标记。
  2. 执行并运行未定义标签的作业。
  3. 执行并运行定义了 docker 标签的第二个作业。

示例 2:

  1. Runner 被配置为运行未标记的作业并且没有定义任何标记。
  2. 执行并运行未定义标签的作业。
  3. 定义了 docker 标签的第二个作业卡住了。

runner 和作业有多个标签

匹配作业和 runner 的选择逻辑基于作业中定义的 tags 列表。

以下示例说明了 runner 和具有多个标签的作业的影响。对于要选择的 runner 来运行作业,它必须具有作业脚本块中定义的所有标签。

示例 1:

  1. runner 配置了标签 [docker, shell, gpu]
  2. 拥有标签 [docker, shell, gpu] 的作业执行。

示例 2:

  1. runner 配置了标签 [docker, shell, gpu]
  2. 拥有标签 [docker, shell,] 的作业执行。

示例 3:

  1. runner 配置了标签 [docker, shell]
  2. 拥有标签 [docker, shell, gpu] 的作业没有被执行。

使用标签在不同平台上运行作业

您可以使用标签在不同的平台上运行不同的作业。例如,您有一个带有标签 osx 的 OS X runner 和一个带有标签 windows 的 Windows runner,您可以在每个平台上运行一个作业:

.gitlab-ci.yml 中更新 tags 字段:

windows job:
  stage: build
  tags:
    - windows
  script:
    - echo Hello, %USERNAME%!

osx job:
  stage: build
  tags:
    - osx
  script:
    - echo "Hello, $USER!"

在标签中使用 CI/CD 变量

您可以使用带有 tagsCI/CD 变量 进行动态 runner 选择:

variables:
  KUBERNETES_RUNNER: kubernetes

  job:
    tags:
      - docker
      - $KUBERNETES_RUNNER
    script:
      - echo "Hello runner selector feature"

使用变量配置 runner 行为

您可以使用 CI/CD 变量 全局或为单个作业配置 runner Git 行为:

您还可以使用变量来配置 runner 尝试某些作业执行阶段的次数。

当使用 Kubernetes executor 时,您可以使用变量来覆盖 Kubernetes CPU 和内存分配请求和限制

Git strategy

您可以在全局或每个作业 variables 部分中设置用于获取仓库内容的 GIT_STRATEGY

variables:
  GIT_STRATEGY: clone

有三个可能的值:clonefetchnone。如果未指定,作业将使用项目的流水线设置。

clone 是最慢的选项。它为每个作业从头开始克隆仓库,确保本地工作副本始终是原始的。如果找到现有工作树,则在克隆之前将其删除。

fetch 更快,因为它重新使用本地工作副本(如果它不存在则回退到 clone)。git clean 用于撤消上一个作业所做的任何更改,而 git fetch 用于检索上一个作业运行后所做的提交。

然而,fetch 确实需要访问前一个工作树。这在使用 shelldocker executor 时效果很好,因为它们会尝试保留工作树并尝试在默认情况下重用它们。

none 的 Git 策略也会重用本地工作副本,但会跳过通常由极狐GitLab 完成的所有 Git 操作。GitLab Runner 预克隆脚本也会被跳过(如果存在)。这种策略可能意味着您需要将 fetchcheckout 命令添加到您的 .gitlab-ci.yml 脚本

none 的 Git 策略也复用本地工作副本,但会跳过极狐GitLab 完成的所有 Git 操作。极狐GitLab 预克隆脚本也会被跳过(如果存在)。这种策略可能意味着您需要将 fetchcheckout 命令添加到您的 .gitlab-ci.yml 脚本

它可以被用于仅操作工件的作业,例如部署作业。Git 存储库数据可能在,但可能过时。您应该只依赖从缓存或工件中引入到本地工作副本的文件。请注意,来自以前流水线的缓存和工件文件可能仍然存在。

none 不同,empty Git 策略删除并重新创建专用构建目录,然后下载缓存或工件文件。使用此策略时,仍然会运行极狐GitLab Runner 钩子脚本(如果提供),以允许进一步的行为自定义。在以下情况下使用 empty Git 策略:

  • 您不需要仓库数据存在。
  • 您希望每次作业运行时都有一个干净的、受控的或自定义的起始状态。

Git submodule strategy

GIT_SUBMODULE_STRATEGY 变量用于控制在构建之前获取代码时是否/如何包含 Git 子模块。您可以在 variables 部分中全局或按作业设置它们。

有三个可能的值:nonenormalrecursive

  • none 表示在获取项目代码时不包含子模块。这是默认值,与 v1.10 之前的行为相匹配。

  • normal 表示只包含顶级子模块。相当于:

    git submodule sync
    git submodule update --init
    
  • recursive 表示包含所有子模块(包括子模块的子模块)。此功能需要 Git v1.8.1 及更高版本。将 GitLab Runner 与不基于 Docker 的 executor 一起使用时,请确保 Git 版本满足该要求。相当于:

    git submodule sync --recursive
    git submodule update --init --recursive
    

要使此功能正常工作,必须使用以下任一方式配置子模块(在 .gitmodules 中):

  • 可公开访问的仓库的 HTTP(S) URL,或
  • 同一 GitLab 服务器上另一个仓库的相对路径。 请参阅 Git 子模块 文档。

您可以使用 GIT_SUBMODULE_UPDATE_FLAGS 提供额外的标志来控制高级行为。

Git checkout

GIT_STRATEGY 设置为 clonefetch 来指定是否应该运行 git checkout 时,可以使用 GIT_CHECKOUT 变量。如果未指定,则默认为 true。您可以在 variables 部分中全局或按作业设置它们。

如果设置为 false,则 runner:

  • 在执行 fetch 时 - 更新仓库并将工作副本保留在当前修订版上,
  • 在执行 clone 时 - 克隆仓库并将工作副本保留在默认分支上。

如果 GIT_CHECKOUT 设置为 true,则 clonefetch 的工作方式相同。 Runner 检查与 CI 流水线相关的修订的工作副本:

variables:
  GIT_STRATEGY: clone
  GIT_CHECKOUT: "false"
script:
  - git checkout -B master origin/master
  - git merge $CI_COMMIT_SHA

Git clean flags

GIT_CLEAN_FLAGS 变量用于在检查源代码后控制 git clean 的默认行为。您可以在 variables 部分中全局或按作业设置它。

GIT_CLEAN_FLAGS 接受 git clean 命令的所有可能选项。

如果指定了 GIT_CHECKOUT: "false",则禁用 git clean

如果 GIT_CLEAN_FLAGS

  • 未指定,git clean 标志默认为 -ffdx
  • 给定值 none,不执行 git clean

例如:

variables:
  GIT_CLEAN_FLAGS: -ffdx -e cache/
script:
  - ls -al cache/

Git fetch extra flags

使用 GIT_FETCH_EXTRA_FLAGS 变量来控制 git fetch 的行为。您可以在 variables 部分中全局或按作业设置它。

GIT_FETCH_EXTRA_FLAGS 接受 git fetch 命令的所有选项。 但是,GIT_FETCH_EXTRA_FLAGS 标志附加在无法修改的默认标志之后。

默认标志是:

如果 GIT_FETCH_EXTRA_FLAGS

  • 未指定,git fetch 标志默认为 --prune --quiet 以及默认标志。
  • 给定值 nonegit fetch 仅使用默认标志执行。

例如,默认标志是 --prune --quiet,因此您可以通过仅使用 --prune 覆盖它来使 git fetch 更详细:

variables:
  GIT_FETCH_EXTRA_FLAGS: --prune
script:
  - ls -al cache/

上面的配置导致 git fetch 被这样调用:

git fetch origin $REFSPECS --depth 50  --prune

其中 $REFSPECS 是极狐GitLab 在内部提供给 runner 的值。

从 CI 作业中同步或排除特定 submodules

  • 引入于极狐GitLab Runner 14.0。

使用 GIT_SUBMODULE_PATHS 变量来控制必须同步或更新哪些子模块。您可以在 variables 部分中全局或按作业设置它。

路径语法同 git submodule

  • 同步和更新特定路径:

     variables:
        GIT_SUBMODULE_PATHS: submoduleA submoduleB
    
  • 要排除特定路径:

     variables:
        GIT_SUBMODULE_PATHS: :(exclude)submoduleA :(exclude)submoduleB
    
caution Git 忽略嵌套路径。要忽略嵌套 submodule,请排除 submodule,然后在作业脚本中手动克隆它。例如,git clone <repo> --recurse-submodules=':(exclude)nested-submodule'。确保将字符串用单引号引起来,以便可以成功解析 YAML。

Git submodule 更新标志

GIT_SUBMODULE_STRATEGY 设置为 normalrecursive 时,使用GIT_SUBMODULE_UPDATE_FLAGS 变量来控制 git submodule update 的行为。您可以在 variables 部分中全局或按作业设置它。

GIT_SUBMODULE_UPDATE_FLAGS 接受 git submodule update 的所有选项子命令。但是,请注意 GIT_SUBMODULE_UPDATE_FLAGS 标志附加在几个默认标志之后:

Git 尊重参数列表中最后一次出现的标志,因此在 GIT_SUBMODULE_UPDATE_FLAGS 中手动提供它们也将覆盖这些默认标志。

您可以使用此变量在仓库中获取最新的远端 HEAD 而不是跟踪的提交,或者通过在多个并行作业中获取子模块来加速检出:

variables:
  GIT_SUBMODULE_STRATEGY: recursive
  GIT_SUBMODULE_UPDATE_FLAGS: --remote --jobs 4
script:
  - ls -al .git/modules/

上面的配置导致 git submodule update 被这样调用:

git submodule update --init --depth 50 --recursive --remote --jobs 4
caution 使用 --remote 标志时,您应该注意对构建的安全性、稳定性和可重复性的影响。在大多数情况下,最好按照设计显式跟踪子模块提交,并使用自动修复/依赖机器人更新它们。

将子模块 URL 重写为 HTTPS

  • 引入于极狐GitLab Runner 15.11 版本。

使用 GIT_SUBMODULE_FORCE_HTTPS 变量强制将所有 Git 和 SSH 子模块 URL 重写为 HTTPS,系统允许您在使用绝对 URL 的同一极狐GitLab 实例上克隆子模块,即使它们是使用 Git 或 SSH 协议配置的。

variables:
  GIT_SUBMODULE_STRATEGY: recursive
  GIT_SUBMODULE_FORCE_HTTPS: "true"

启用后,极狐GitLab Runner 使用 CI/CD 作业令牌来执行作业的用户权限克隆子模块,并且不需要 SSH 凭据。

影子克隆

您可以使用 GIT_DEPTH 指定获取和克隆的深度。GIT_DEPTH 对仓库进行浅层克隆,可以显著加快克隆速度。它对于具有大量提交或旧的大型二进制文件的仓库很有帮助。此值被传递给 git fetchgit clone

在 12.0 及更高版本中,新创建的项目自动具有 git depth50

如果您使用 1 的深度并且有一个作业队列或重试作业,作业可能会失败。

Git 获取和克隆基于 ref,例如分支名称,因此 runner 无法克隆特定的提交 SHA。如果队列中有多个作业,或者您正在重试旧作业,则要测试的提交必须在克隆的 Git 历史记录中。将 GIT_DEPTH 的值设置得太小会导致无法运行这些旧提交,并且在作业日志中会显示 unresolved reference。然后,您应该重新考虑将 GIT_DEPTH 更改为更高的值。

当设置了 GIT_DEPTH 时,依赖 git describe 的作业可能无法正常工作,因为只有部分 Git 历史存在。

仅获取或克隆最后 3 个提交:

variables:
  GIT_DEPTH: "3"

您可以在 variables 部分中全局或按作业设置它。

Git submodule depth

  • 引入于极狐GitLab Runner 15.5。

使用 GIT_SUBMODULE_DEPTH 变量来指定获取和克隆子模块的深度,当 GIT_SUBMODULE_STRATEGY 设置为 normalrecursive 时。您可以在 variables 部分中全局或按作业设置它。

当您设置 GIT_SUBMODULE_DEPTH 变量时,它会仅为子模块覆盖 GIT_DEPTH 设置。

要拉取或仅克隆最后 3 个提交:

variables:
  GIT_SUBMODULE_DEPTH: 3

自定义构建目录

默认情况下,GitLab Runner 将仓库克隆到 $CI_BUILDS_DIR 目录的唯一子路径中。但是,您的项目可能需要特定目录中的代码(例如 Go 项目)。 在这种情况下,您可以指定 GIT_CLONE_PATH 变量来告诉 runner 克隆仓库的目录:

variables:
  GIT_CLONE_PATH: $CI_BUILDS_DIR/project-name

test:
  script:
    - pwd

GIT_CLONE_PATH 必须始终位于 $CI_BUILDS_DIR 内。$CI_BUILDS_DIR 中设置的目录取决于 executor 和 runners.builds_dir 设置的配置。

只能在 runner 配置中启用 custom_build_dir 时使用。

处理兵法

使用大于 1 的并发 executor 可能会导致失败。如果 builds_dir 在作业之间共享,则多个作业可能在同一个目录上工作。

Runner 不会试图阻止这种情况。是否符合 runner 配置的要求取决于管理员和开发人员。

为避免这种情况,您可以在 $CI_BUILDS_DIR 中使用唯一路径,因为 runner 公开了两个额外的变量,它们提供了唯一的并发 ID

  • $CI_CONCURRENT_ID:在特定 runner 中运行的所有作业的唯一 ID。
  • $CI_CONCURRENT_PROJECT_ID:在特定 runner 和项目中运行的所有作业的唯一 ID。

在任何场景和任何 executor 上都能正常工作的最稳定配置是在 GIT_CLONE_PATH 中使用 $CI_CONCURRENT_ID。例如:

variables:
  GIT_CLONE_PATH: $CI_BUILDS_DIR/$CI_CONCURRENT_ID/project-name

test:
  script:
    - pwd -P

$CI_CONCURRENT_PROJECT_ID 应与 $CI_PROJECT_PATH 一起使用,因为 $CI_PROJECT_PATH 提供了仓库的路径。 即 group/subgroup/project。例如:

variables:
  GIT_CLONE_PATH: $CI_BUILDS_DIR/$CI_CONCURRENT_ID/$CI_PROJECT_PATH

test:
  script:
    - pwd -P

嵌套路径

GIT_CLONE_PATH 的值被扩展一次,不支持嵌套变量。

例如,您在 .gitlab-ci.yml 文件中定义以下两个变量:

variables:
  GOPATH: $CI_BUILDS_DIR/go
  GIT_CLONE_PATH: $GOPATH/src/namespace/project

GIT_CLONE_PATH 的值被展开一次到 $CI_BUILDS_DIR/go/src/namespace/project,由于 $CI_BUILDS_DIR 没有展开而导致失败。

忽略 after_script 中的错误

您可以在作业中使用 after_script 定义一个命令数组,这些命令应该在作业的 before_scriptscript 部分之后运行。无论脚本终止状态如何(失败或成功),after_script 命令都会运行。

默认情况下,极狐GitLab 会忽略 after_script 运行时发生的任何错误。要立即在 after_script 运行时出现错误时设置作业失败,请将 AFTER_SCRIPT_IGNORE_ERRORS CI/CD 变量设置为 false。例如:

variables:
  AFTER_SCRIPT_IGNORE_ERRORS: false

作业阶段重试

您可以设置正在运行的作业尝试执行以下阶段的尝试次数:

变量 描述
ARTIFACT_DOWNLOAD_ATTEMPTS 尝试下载运行作业的产物的次数
EXECUTOR_JOB_SECTION_ATTEMPTS 在 12.10 及更高版本中,在 No Such Container 错误(仅限 Docker executor)后尝试运行作业中的部分的次数。
GET_SOURCES_ATTEMPTS 尝试获取运行作业的源的次数
RESTORE_CACHE_ATTEMPTS 尝试恢复运行作业的缓存的次数

默认是一次尝试。

示例:

variables:
  GET_SOURCES_ATTEMPTS: 3

您可以在 variables 部分中全局或按作业设置它们。

产物和缓存设置

产物和缓存设置控制产物和缓存的压缩率。 使用这些设置来指定作业生成的存档的大小。

  • 在慢速网络上,对于较小的存档,上传速度可能会更快。
  • 在不考虑带宽和存储的快速网络上,使用最快的压缩比上传可能会更快,尽管生成的存档更大。

可以启用 meter 来提供上传和下载的传输速率。

您可以使用 CACHE_REQUEST_TIMEOUT 设置来设置缓存上传和下载的最长时间。当缓慢的缓存上传显著增加作业的持续时间时,此设置可能很有用。

variables:
  # output upload and download progress every 2 seconds
  TRANSFER_METER_FREQUENCY: "2s"

  # Use fast compression for artifacts, resulting in larger archives
  ARTIFACT_COMPRESSION_LEVEL: "fast"

  # Use no compression for caches
  CACHE_COMPRESSION_LEVEL: "fastest"

  # Set maximum duration of cache upload and download
  CACHE_REQUEST_TIMEOUT: 5
变量 描述
TRANSFER_METER_FREQUENCY 指定打印 meter 传输率的频率,可以设置为持续时间(例如,1s1m30s)。0 的持续时间表示禁用 meter(默认)。设置值后,流水线会显示产物和缓存上传和下载的进度。
ARTIFACT_COMPRESSION_LEVEL 要调整压缩率,请设置为 fastestfastdefaultslowslowest。此设置仅适用于 Fastzip archiver,因此还必须启用 GitLab Runner 功能标志 FF_USE_FASTZIP
CACHE_COMPRESSION_LEVEL 要调整压缩率,请设置为 fastestfastdefaultslowslowest。此设置仅适用于 Fastzip archiver,因此还必须启用 GitLab Runner 功能标志 FF_USE_FASTZIP
CACHE_REQUEST_TIMEOUT 配置单个作业的缓存上传和下载操作的最大持续时间(以分钟为单位)。默认为 10 分钟。

产物治理元数据

  • 引入于极狐GitLab Runner 15.1。

Runner 可以为所有构建产物生成治理元数据。

为了确保产物治理数据,您可以将 RUNNER_GENERATE_ARTIFACTS_METADATA 环境变量设置为 true。您可以将变量设置为全局或单个作业:

variables:
  RUNNER_GENERATE_ARTIFACTS_METADATA: "true"

job1:
  variables:
    RUNNER_GENERATE_ARTIFACTS_METADATA: "true"

元数据呈现在与产物一起存储的纯文本 .json 文件中。 文件名如下:{ARTIFACT_NAME}-metadata.json,其中 ARTIFACT_NAME 是 CI 文件中产物名称的定义。但是,如果没有为构建产物指定名称,则文件名默认为 artifacts-metadata.json

治理元数据格式

证明元数据以规范版本 v0.1in-toto 证明格式生成。默认填充以下字段:

字段
_type https://in-toto.io/Statement/v0.1
subject.name 产物的文件名
subject.digest.sha256 产物的 sha256 校验和
predicateType https://slsa.dev/provenance/v0.2
predicate.buildType https://gitlab.com/gitlab-org/gitlab-runner/-/blob/{GITLAB_RUNNER_VERSION}/PROVENANCE.md。例如 v15.0.0
predicate.builder.id 指向 runner 详细信息页面的 URI,例如 https://gitlab.com/gitlab-com/www-gitlab-com/-/runners/3785264
predicate.invocation.configSource.uri https://gitlab.example.com/.../{PROJECT_NAME}
predicate.invocation.configSource.digest.sha256 代码仓库的 sha256 校验和
predicate.invocation.configSource.entryPoint 触发构建的 CI 作业的名称
predicate.invocation.environment.name Runner 的名称
predicate.invocation.environment.executor Runner 执行器
predicate.invocation.environment.architecture 运行 CI 作业的架构
predicate.invocation.parameters 运行构建命令时存在的任何 CI/CD 或环境变量的名称。该值始终表示为空字符串,以避免泄露任何 secrets
metadata.buildStartedOn 构建开始的时间。RFC3339 格式
metadata.buildEndedOn 构建结束的时间。由于元数据生成是在构建过程中发生的,因此这一时刻比极狐GitLab 中报告的时间稍早。RFC3339 格式
metadata.reproducible 通过收集所有生成的元数据,构建是否可重现。始终为 false
metadata.completeness.parameters 是否提供参数。始终为 true
metadata.completeness.environment 是否报告 builder 的环境。始终为 true
metadata.completeness.materials 是否报告构建材料。始终为 false

极狐GitLab Runner 可能生成的证明示例如下:

{
 "_type": "https://in-toto.io/Statement/v0.1",
 "predicateType": "https://slsa.dev/provenance/v1",
 "subject": [
  {
   "name": "build/pico_w/wifi/blink/picow_blink.uf2",
   "digest": {
    "sha256": "f5a381a3fdf095a88fb928094f0e38cf269d226b07414369e8906d749634c090"
   }
  },
  {
   "name": "build/pico_w/wifi/blink/picow_blink.0.1.148-2-new-feature49.cosign.bundle",
   "digest": {
    "sha256": "f8762bf0b3ea1b88550b755323bf04417c2bbe9e50010cfcefc1fa877e2b52a6"
   }
  },
  {
   "name": "build/pico_w/wifi/blink/pico-examples-3a.0.1.148-2-new-feature49.tar.gz",
   "digest": {
    "sha256": "104674887da894443ab55918d81b0151dc7abb2472e5dafcdd78e7be71098af1"
   }
  },
  {
   "name": "build/pico_w/wifi/blink/pico-examples-3a.0.1.148-2-new-feature49.tar.gz.cosign.bundle",
   "digest": {
    "sha256": "33f3f7a19779a2d189dc03b420eb0be199a38404e8c1a24b2c8731bdfa3a30fb"
   }
  }
 ],
 "predicate": {
  "buildDefinition": {
   "buildType": "https://gitlab.com/gitlab-org/gitlab-runner/-/blob/761ae5dd/PROVENANCE.md",
   // All other CI variable names are listed here. Values are always represented as empty strings to avoid leaking secrets and to comply with SLSA.
   "externalParameters": {
    "CI": "",
    "CI_API_GRAPHQL_URL": "",
    "CI_API_V4_URL": "",
    "CI_COMMIT_AUTHOR": "",
    "CI_COMMIT_BEFORE_SHA": "",
    "CI_COMMIT_BRANCH": "",
    "CI_COMMIT_DESCRIPTION": "",
    "CI_COMMIT_MESSAGE": "",
    "CI_COMMIT_REF_NAME": "",
    "CI_COMMIT_REF_PROTECTED": "",
    "CI_COMMIT_REF_SLUG": "",
    "CI_COMMIT_SHA": "",
    "CI_COMMIT_SHORT_SHA": "",
    "CI_COMMIT_TIMESTAMP": "",
    "CI_COMMIT_TITLE": "",
    "CI_CONFIG_PATH": "",
    "CI_DEFAULT_BRANCH": "",
    "CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX": "",
    "CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX": "",
    "CI_DEPENDENCY_PROXY_PASSWORD": "",
    "CI_DEPENDENCY_PROXY_SERVER": "",
    "CI_DEPENDENCY_PROXY_USER": "",
    "CI_JOB_ID": "",
    "CI_JOB_NAME": "",
    "CI_JOB_NAME_SLUG": "",
    "CI_JOB_STAGE": "",
    "CI_JOB_STARTED_AT": "",
    "CI_JOB_TOKEN": "",
    "CI_JOB_URL": "",
    "CI_NODE_TOTAL": "",
    "CI_OPEN_MERGE_REQUESTS": "",
    "CI_PAGES_DOMAIN": "",
    "CI_PAGES_URL": "",
    "CI_PIPELINE_CREATED_AT": "",
    "CI_PIPELINE_ID": "",
    "CI_PIPELINE_IID": "",
    "CI_PIPELINE_NAME": "",
    "CI_PIPELINE_SOURCE": "",
    "CI_PIPELINE_URL": "",
    "CI_PROJECT_CLASSIFICATION_LABEL": "",
    "CI_PROJECT_DESCRIPTION": "",
    "CI_PROJECT_ID": "",
    "CI_PROJECT_NAME": "",
    "CI_PROJECT_NAMESPACE": "",
    "CI_PROJECT_NAMESPACE_ID": "",
    "CI_PROJECT_PATH": "",
    "CI_PROJECT_PATH_SLUG": "",
    "CI_PROJECT_REPOSITORY_LANGUAGES": "",
    "CI_PROJECT_ROOT_NAMESPACE": "",
    "CI_PROJECT_TITLE": "",
    "CI_PROJECT_URL": "",
    "CI_PROJECT_VISIBILITY": "",
    "CI_REGISTRY": "",
    "CI_REGISTRY_IMAGE": "",
    "CI_REGISTRY_PASSWORD": "",
    "CI_REGISTRY_USER": "",
    "CI_REPOSITORY_URL": "",
    "CI_RUNNER_DESCRIPTION": "",
    "CI_RUNNER_ID": "",
    "CI_RUNNER_TAGS": "",
    "CI_SERVER_FQDN": "",
    "CI_SERVER_HOST": "",
    "CI_SERVER_NAME": "",
    "CI_SERVER_PORT": "",
    "CI_SERVER_PROTOCOL": "",
    "CI_SERVER_REVISION": "",
    "CI_SERVER_SHELL_SSH_HOST": "",
    "CI_SERVER_SHELL_SSH_PORT": "",
    "CI_SERVER_URL": "",
    "CI_SERVER_VERSION": "",
    "CI_SERVER_VERSION_MAJOR": "",
    "CI_SERVER_VERSION_MINOR": "",
    "CI_SERVER_VERSION_PATCH": "",
    "CI_TEMPLATE_REGISTRY_HOST": "",
    "COSIGN_YES": "",
    "DS_EXCLUDED_ANALYZERS": "",
    "DS_EXCLUDED_PATHS": "",
    "DS_MAJOR_VERSION": "",
    "DS_SCHEMA_MODEL": "",
    "GITLAB_CI": "",
    "GITLAB_FEATURES": "",
    "GITLAB_USER_EMAIL": "",
    "GITLAB_USER_ID": "",
    "GITLAB_USER_LOGIN": "",
    "GITLAB_USER_NAME": "",
    "GitVersion_FullSemVer": "",
    "GitVersion_LegacySemVer": "",
    "GitVersion_Major": "",
    "GitVersion_MajorMinorPatch": "",
    "GitVersion_Minor": "",
    "GitVersion_Patch": "",
    "GitVersion_SemVer": "",
    "RUNNER_GENERATE_ARTIFACTS_METADATA": "",
    "SAST_EXCLUDED_ANALYZERS": "",
    "SAST_EXCLUDED_PATHS": "",
    "SAST_IMAGE_SUFFIX": "",
    "SCAN_KUBERNETES_MANIFESTS": "",
    "SECRETS_ANALYZER_VERSION": "",
    "SECRET_DETECTION_EXCLUDED_PATHS": "",
    "SECRET_DETECTION_IMAGE_SUFFIX": "",
    "SECURE_ANALYZERS_PREFIX": "",
    "SIGSTORE_ID_TOKEN": "",
    "entryPoint": "create_generic_package",
    "source": "https://gitlab.com/dsanoy-demo/experiments/pico-examples-3a"
   },
   "internalParameters": {
    "architecture": "amd64",
    "executor": "docker+machine",
    "job": "7211908025",
    "name": "green-6.saas-linux-small-amd64.runners-manager.gitlab.com/default"
   },
   "resolvedDependencies": [
    {
     "uri": "https://gitlab.com/dsanoy-demo/experiments/pico-examples-3a",
     "digest": {
      "sha256": "7e1aeac4e6c07138769b638d4926f429692d0124"
     }
    }
   ]
  },
  "runDetails": {
   "builder": {
    "id": "https://gitlab.com/dsanoy-demo/experiments/pico-examples-3a/-/runners/32976645",
    "version": {
     "gitlab-runner": "761ae5dd"
    }
   },
   "metadata": {
    "invocationID": "7211908025",
    "startedOn": "2024-06-28T09:56:44Z",
    "finishedOn": "2024-06-28T09:56:58Z"
   }
  }
 }
}

暂存目录

  • 引入于极狐GitLab Runner 15.0 版本。

如果您不想在系统的默认临时目录中归档缓存和产物,您可以指定一个不同的目录。

如果系统的默认临时路径有限制,您可能需要更改目录。如果您使用快速磁盘作为目录位置,也可以提高性能。

要更改目录,请将 ARCHIVER_STAGING_DIR 设置为 CI 作业中的变量,或者在注册 runner 时使用 runner 变量(gitlab register --env ARCHIVER_STAGING_DIR=<dir>)。

您指定的目录用作在提取之前下载产物的位置。如果使用 fastzip 归档器,这个位置在归档时也用作暂存空间。

配置 fastzip 提高性能

  • 引入于极狐GitLab Runner 15.0 版本。

要调整 fastzip,请确保启用 FF_USE_FASTZIP 功能标志。 然后使用以下任何环境变量。

变量 描述
FASTZIP_ARCHIVER_CONCURRENCY 要同时压缩的文件数。默认值是可用的 CPU 数。
FASTZIP_ARCHIVER_BUFFER_SIZE 每个文件的每个并发分配的缓冲区大小。超过此数量的数据将移至暂存空间。默认值为 2 MiB。
FASTZIP_EXTRACTOR_CONCURRENCY 要并发解压缩的文件数。默认值是可用的 CPU 数。

zip 存档中的文件按顺序附加,这使得并发压缩具有挑战性。fastzip 通过先同时将文件压缩到磁盘,然后按顺序将结果复制回 zip 存档来解决此限制。

为了避免写入磁盘并读回较小文件的内容,每个并发使用一个小缓冲区。此设置可以通过 FASTZIP_ARCHIVER_BUFFER_SIZE 进行控制,此缓冲区的默认大小为 2 MiB,因此,16 的并发分配 32 MiB。超过缓冲区大小的数据将写入磁盘并从磁盘读回。 因此,不使用缓冲区,FASTZIP_ARCHIVER_BUFFER_SIZE: 0,并且只使用暂存空间是一个有效的选项。

FASTZIP_ARCHIVER_CONCURRENCY 控制有多少文件被并发压缩。如上所述,此设置因此可以增加正在使用的内存量,但也可以增加写入暂存空间的临时数据量。 默认值是可用 CPU 的数量,但考虑到内存影响,可能并不是最佳设置。

FASTZIP_EXTRACTOR_CONCURRENCY 控制一次解压多少文件。来自 zip 存档的文件可以从本地并发读取,因此除了解压缩器需要的内存之外,不会分配额外的内存,默认为可用的 CPU 数。