选择何时运行作业

当新流水线启动时,极狐GitLab 检查流水线配置以确定应在该流水线中运行哪些作业。您可以根据变量的状态、流水线类型等配置要运行的作业。

要将作业配置为包含或排除在某些流水线中,您可以使用 rules

使用 needs 将作业配置为在其依赖的较早作业完成运行后立即运行。

指定作业何时使用 rules 运行

使用 rules 在流水线中包含或排除作业。

规则按顺序评估,直到第一次匹配。找到匹配项后,该作业将包含在流水线中或从流水线中排除,具体取决于配置。 有关更多详细信息,请参阅 rules 参考。

rules 示例

以下示例使用 if 来定义作业仅在两种特定情况下运行:

job:
  script: echo "Hello, Rules!"
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
      when: manual
      allow_failure: true
    - if: $CI_PIPELINE_SOURCE == "schedule"
  • 如果流水线用于合并请求,则第一个规则匹配,并将作业添加到合并请求流水线并具有以下属性:
    • when: manual(手工作业)
    • allow_failure: true(即使没有运行手动作业,流水线也会继续运行)
  • 如果流水线不是合并请求触发,则第一条规则不匹配,并评估第二条规则。
  • 如果流水线是计划流水线,则第二条规则匹配,并将作业添加到计划流水线。没有定义属性,因此添加了:
    • when: on_success(默认)
    • allow_failure: false(默认)
  • 所有其他情况,没有规则匹配,因此作业添加到任何其他流水线。

或者,您可以定义一组规则以在少数情况下排除作业,但在所有其他情况下运行它们:

job:
  script: echo "Hello, Rules!"
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
      when: never
    - if: $CI_PIPELINE_SOURCE == "schedule"
      when: never
    - when: on_success
  • 如果流水线用于合并请求,则作业添加到流水线中。
  • 如果流水线是计划流水线,则作业添加到流水线中。
  • 所有其他情况,作业被添加到流水线中,使用 when: on_success
caution如果您使用 when 子句作为最终规则(不包括 when: never),则可能会同时启动两个流水线。推送流水线和合并请求流水线都可以由同一事件触发(推送到源分支以获取开放合并请求)。 有关更多详细信息,请参阅如何防止重复流水线

为计划流水线运行作业

要将作业配置为仅为计划流水线时执行,请使用 rules 关键字。

在此示例中,make world 在计划流水线中运行,而 make build 在分支和标签流水线中运行:

job:on-schedule:
  rules:
    - if: $CI_PIPELINE_SOURCE == "schedule"
  script:
    - make world

job:
  rules:
    - if: $CI_PIPELINE_SOURCE == "push"
  script:
    - make build

如果分支为空则跳过作业

使用 rules:changes:compare_to 避免在分支为空时运行作业,从而节省 CI/CD 资源。将分支与默认分支进行比较,如果分支:

  • 没有更改的文件,作业不运行。
  • 已更改文件,作业运行。

例如,在以 main 作为默认分支的项目中:

job:
  script:
    - echo "This job only runs for branches that are not empty"
  rules:
    - if: $CI_COMMIT_BRANCH
      changes:
        compare_to: 'refs/heads/main'
        paths:
          - '*'

此作业的规则将当前分支中的所有文件和路径 (*) 与默认分支 main 进行比较。只有当分支中的文件发生更改时,规则才匹配并且作业运行。

复杂规则

您可以在同一规则中使用所有 rules 关键字,例如 ifchangesexists。 仅当所有包含的关键字评估为 true 时,规则才会评估为 true。

例如:

docker build:
  script: docker build -t my-image:$CI_COMMIT_REF_SLUG .
  rules:
    - if: $VAR == "string value"
      changes:  # Include the job and set to when:manual if any of the follow paths match a modified file.
        - Dockerfile
        - docker/scripts/*
      when: manual
      allow_failure: true

如果 Dockerfile 文件或 /docker/scripts 中的任何文件发生了变化 $VAR == “string value”`,则该作业手动运行并允许失败。

您可以使用括号&&|| 来构建更复杂的变量表达式。 引入于 13.3 版本:

job1:
  script:
    - echo This rule uses parentheses.
  rules:
    - if: ($CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_COMMIT_BRANCH == "develop") && $MY_VARIABLE
caution在 13.3 版本之前,同时使用 ||&& 的规则可能会以意外的操作顺序进行评估。

防止重复流水线

如果作业使用 rules,则单个操作(例如将提交推送到分支)可以触发多个流水线。您不必为多种类型的流水线显式配置规则来意外触发它们。

一些可能导致重复流水线的配置,会导致显示流水线警告。 引入于 13.3 版本。

示例:

job:
  script: echo "This job creates double pipelines!"
  rules:
    - if: $CUSTOM_VARIABLE == "false"
      when: never
    - when: always

$CUSTOM_VARIABLE 为 false 时,此作业不会运行,但它确实所有 其他流水线中运行,包括推送(分支)和合并请求流水线。使用此配置,每次推送到开放合并请求的源分支都会导致重复的流水线。

为避免重复流水线,您可以:

  • 使用 workflow 指定可以运行的流水线类型。
  • 重写规则以仅在非常特定的情况下运行作业,并避免最终的 when 规则:

    job:
      script: echo "This job does NOT create double pipelines!"
      rules:
        - if: '$CUSTOM_VARIABLE == "true" && $CI_PIPELINE_SOURCE == "merge_request_event"'
    

您还可以通过更改作业规则来避免重复流水线,以避免推送(分支)流水线或合并请求流水线。但是,如果您使用没有 workflow: rules- when: always 规则,系统仍会显示流水线警告。

例如,以下不会触发双流水线,但不建议在没有 workflow: rules 的情况下使用:

job:
  script: echo "This job does NOT create double pipelines!"
  rules:
    - if: $CI_PIPELINE_SOURCE == "push"
      when: never
    - when: always

如果没有 workflow:rules 防止重复流水线:

job:
  script: echo "This job creates double pipelines!"
  rules:
    - if: $CI_PIPELINE_SOURCE == "push"
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"

此外,不要在同一流水线中将 only/except 作业与 rules 作业混合。 它可能不会导致 YAML 错误,但是 only/exceptrules 的不同默认行为可能会导致难以解决的问题:

job-with-no-rules:
  script: echo "This job runs in branch pipelines."

job-with-rules:
  script: echo "This job runs in merge request pipelines."
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"

对于推送到分支的每个更改,都会运行重复的流水线。一个分支流水线运行单个作业(job-with-no-rules),一个合并请求流水线运行另一个作业(job-with-rules)。没有规则的作业默认为 except: merge_requests,所以 job-with-no-rules 在所有情况下都会运行,除了合并请求。

rules 的常见 if 子句

类似于 only/except 关键字,您可以检查 $CI_PIPELINE_SOURCE 变量的值:

描述
api 对于由 pipelines API 触发的流水线。
chat 对于使用极狐GitLab ChatOps 命令创建的流水线。
external 当您使用极狐GitLab 以外的 CI 服务时。
external_pull_request_event 在 GitHub 上创建或更新外部拉取请求时。
merge_request_event 对于在创建或更新合并请求时创建的流水线。需要启用合并请求流水线合并结果流水线合并队列
parent_pipeline 对于由带有 rules父/子流水线 触发的流水线。在子流水线配置中使用此流水线源,以便它可以由父流水线触发。
pipeline 对于通过[使用带有 CI_JOB_TOKEN 的 API 创建的多项目流水线trigger 关键字。
push 对于由 git push 事件触发的流水线,包括分支和标签。
schedule 对于计划流水线
trigger 对于使用触发器令牌–>创建的流水线。
web 对于使用极狐GitLab UI 中的 运行流水线 按钮创建的流水线,来自项目的 构建 > 流水线 部分。
webide 对于使用 WebIDE 创建的流水线。

以下示例在计划流水线或推送流水线(到分支或标签)中将作业作为手动作业运行,使用 when: on_success(默认)。它不会将作业添加到任何其他流水线类型。

job:
  script: echo "Hello, Rules!"
  rules:
    - if: $CI_PIPELINE_SOURCE == "schedule"
      when: manual
      allow_failure: true
    - if: $CI_PIPELINE_SOURCE == "push"

以下示例在合并请求流水线和计划流水线中将作业作为 when: on_success 作业运行。 它不会在任何其他流水线类型中运行。

job:
  script: echo "Hello, Rules!"
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
    - if: $CI_PIPELINE_SOURCE == "schedule"

if 子句的其他常用变量:

  • if: $CI_COMMIT_TAG:如果为标签推送更改。
  • if: $CI_COMMIT_BRANCH:如果更改被推送到任何分支。
  • if: $CI_COMMIT_BRANCH == "main":如果更改被推送到 main
  • if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH:如果更改被推送到默认分支。当您希望在具有不同默认分支的多个项目中具有相同配置时使用。
  • if: $CI_COMMIT_BRANCH =~ /regex-expression/:如果提交分支匹配正则表达式。
  • if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_COMMIT_TITLE =~ /Merge branch.*/: 如果提交分支是默认分支并且提交消息标题匹配正则表达式。例如,合并提交的默认提交消息以 Merge branch 开头。
  • if: $CUSTOM_VARIABLE !~ /regex-expression/:如果自定义变量 CUSTOM_VARIABLE 匹配一个正则表达式。
  • if: $CUSTOM_VARIABLE == "value1":如果自定义变量 CUSTOM_VARIABLE 正好是 value1

rules:changes 中的变量

您可以在 rules:changes 表达式中使用 CI/CD 变量来确定何时向流水线添加作业:

docker build:
  variables:
    DOCKERFILES_DIR: 'path/to/files/'
  script: docker build -t my-image:$CI_COMMIT_REF_SLUG .
  rules:
    - changes:
        - $DOCKERFILES_DIR/*

您可以将 $ 字符用于变量和路径。例如,如果存在 $DOCKERFILES_DIR 变量,则使用其值。 如果它不存在,$ 被解释为路径的一部分。

在不同的作业中重用规则

引入于 14.3 版本。

使用 !reference 标签 在不同的作业中重用规则。您可以将 !reference 规则与常规作业定义的规则结合起来:

.default_rules:
  rules:
    - if: $CI_PIPELINE_SOURCE == "schedule"
      when: never
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

job1:
  rules:
    - !reference [.default_rules, rules]
  script:
    - echo "This job runs for the default branch, but not schedules."

job2:
  rules:
    - !reference [.default_rules, rules]
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
  script:
    - echo "This job runs for the default branch, but not schedules."
    - echo "It also runs for merge requests."

指定作业何时以 onlyexcept 运行

您可以使用 onlyexcept 来控制何时添加作业到流水线。

  • 使用 only 来定义作业何时运行。
  • 使用 except 定义作业 运行的时间。

only:refs / except:refs 示例

不使用 refs 时,使用的 onlyexceptonly:refs / except/refs 相同。

在以下示例中,job 仅针对以下情况运行:

job:
  # use special keywords
  only:
    - tags
    - triggers
    - schedules

要仅为父仓库而不是派生仓库执行作业:

job:
  only:
    - branches@gitlab-org/gitlab
  except:
    - main@gitlab-org/gitlab
    - /^release/.*$/@gitlab-org/gitlab

此示例为 gitlab-org/gitlab 上的所有分支运行 job,除了 main 和以 release/ 开头的分支。

only: variables / except: variables 示例

您可以使用 except:variables 根据提交消息排除作业:

end-to-end:
  script: rake test:end-to-end
  except:
    variables:
      - $CI_COMMIT_MESSAGE =~ /skip-end-to-end-tests/

您可以使用括号&&|| 来构建更复杂的变量表达式:

job1:
  script:
    - echo This rule uses parentheses.
  only:
    variables:
      - ($CI_COMMIT_BRANCH == "main" || $CI_COMMIT_BRANCH == "develop") && $MY_VARIABLE

当在 only:variables 中指定了多个条目时,作业会在其中至少一个评估为 true 时运行。 当必须同时满足多个条件时,您可以在单个条目中使用 &&

only:changes / except:changes 示例

如果在仓库根目录中带有.md 扩展名的任何文件中检测到更改,您可以跳过作业:

build:
  script: npm run build
  except:
    changes:
      - "*.md"

如果您更改了多个文件,但只有一个文件以 .md 结尾,则仍会跳过 build 作业。该作业不会为任何文件运行。

对于一些使用 changes 的配置,作业或流水线可能会意外运行

only:changes 与流水线一起用于合并请求

使用合并请求流水线,可以根据合并请求中修改的文件定义要创建的作业。

将此关键字与 only: [merge_requests] 一起使用,以便系统可以找到源分支的正确基础 SHA。从任何进一步的提交中正确计算文件差异,并且在流水线中正确测试合并请求中的所有更改。

例如:

docker build service one:
  script: docker build -t my-service-one-image:$CI_COMMIT_REF_SLUG .
  only:
    refs:
      - merge_requests
    changes:
      - Dockerfile
      - service-one/**/*

在这种情况下,如果合并请求更改了 service-one 目录或 Dockerfile 中的文件,系统会创建 docker build service one 作业。

例如:

docker build service one:
  script: docker build -t my-service-one-image:$CI_COMMIT_REF_SLUG .
  only:
    changes:
      - Dockerfile
      - service-one/**/*

在此示例中,流水线可能会因更改 service-one/**/* 中的文件而失败。

稍后提交在 service-one/**/* 中没有更改,但确实对 Dockerfile 进行了更改的提交可以通过。该作业仅测试对 Dockerfile 的更改。

系统检查通过最新流水线。如果合并请求是可合并的,那么早先的流水线由于未更正的更改而失败并不重要。

当您使用此配置时,请确保最近的流水线正确地纠正了先前流水线中的任何故障。

将多个关键字与 onlyexcept 组合

如果您将多个关键字与 onlyexcept 一起使用,则这些关键字将被评估为单个连接表达式:

  • only 包含作业,如果 all 的键至少有一个匹配的条件。
  • except 如果 any 的键至少有一个匹配的条件,则排除作业。

使用 only,单个键由 AND 逻辑连接。如果满足以下条件,则将作业添加到流水线中:

  • (any listed refs are true) AND (any listed variables are true) AND (any listed changes are true) AND (any chosen Kubernetes status matches)

在以下示例中,仅当以下 all 为 true 时才会创建 test 作业:

  • 流水线是计划的运行 main
  • variables 关键字匹配。
  • kubernetes 服务在项目中处于活动状态。
test:
  script: npm run test
  only:
    refs:
      - main
      - schedules
    variables:
      - $CI_COMMIT_MESSAGE =~ /run-end-to-end-tests/
    kubernetes: active

使用except,各个键由 OR 逻辑连接。如果满足以下条件,则添加作业:

  • (any listed refs are true) OR (any listed variables are true) OR (any listed changes are true) OR (a chosen Kubernetes status matches)

在以下示例中,当以下 任何 为 true 时,创建 test 作业:

  • 流水线为 main 分支运行。
  • 对仓库根目录中的 README.md 文件进行了更改。
test:
  script: npm run test
  except:
    refs:
      - main
    changes:
      - "README.md"

创建必须手动运行的作业

您可以要求作业在用户启动之前不运行。这称为手工作业。 您可能希望使用手动作业来进行部署到生产之类的工作。

要将作业指定为手动,请将 when: manual 添加到 .gitlab-ci.yml 文件中的作业。

默认情况下,手动作业在流水线启动时显示为已跳过。

您可以使用受保护的分支来更严格地保护手动部署不被未经授权的用户运行。

手动作业类型

手动作业可以是可选的或阻塞的。

可选的手动作业:

  • allow_failuretrue,这是具有 when:manual 且没有 rules 的作业的默认设置,或当在 rules 之外定义了 when:manual 时的设置。
  • 该状态不影响整体流水线状态。即使所有手动作业都失败,流水线也可以成功。

阻塞的手动作业:

  • allow_failurefalse,这是在 rules 中定义了 when:manual 的作业的默认设置。
  • 流水线在定义作业的阶段停止。要让流水线继续运行,请运行手动作业
  • 启用了流水线成功时合并的项目中的合并请求,不能在存在已阻塞的流水线时合并。
  • 流水线显示状态为已阻塞

运行手动作业

要运行手动作业,您必须具有合并到指定分支的权限:

  1. 转到流水线、作业、环境 或部署视图。
  2. 在手动作业旁边,选择 运行 ()。

您还可以在运行手动作业时添加自定义 CI/CD 变量

保护手动作业

使用受保护的环境 定义授权运行手动作业的用户列表。您只能授权与受保护环境关联的用户触发手动作业,这可以:

  • 更精确地限制可以部署到环境的人员。
  • 阻止流水线,直到合资格的用户“批准”它。

要保护手动作业:

  1. 为作业添加一个 environment。 例如:

    deploy_prod:
      stage: deploy
      script:
        - echo "Deploy to production server"
      environment:
        name: production
        url: https://example.com
      when: manual
      rules:
        - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
    
  2. 在受保护环境设置中,选择环境(本例中为 production),添加授权触发手动作业的用户、角色或群组,到 允许部署 列表。只有此列表中的人,以及始终能够使用受保护环境的 GitLab 管理员,才能触发此手动作业。

您可以使用具有阻止手动作业的受保护环境来获得允许批准后期流水线阶段的用户列表。将 allow_failure: false 添加到受保护的手动作业,流水线的下一阶段仅在手动作业由授权用户触发后运行。

延迟后运行作业

使用 when: delay 在等待期后执行脚本,或者如果您想避免作业立即进入 pending 状态。

您可以使用 start_in 关键字设置时间段。start_in 的值是以秒为单位的经过时间,除非提供了单位。最短为一秒,最长为一星期。 有效值的示例包括:

  • '5'(没有单位的值必须用单引号括起来)
  • 5 seconds
  • 30 minutes
  • 1 day
  • 1 week

当阶段包含延迟作业时,流水线在延迟作业完成之前不会进行。 您可以使用此关键字在不同阶段之间插入延迟。

延迟作业的计时器在前一阶段完成后立即启动。 与其他类型的作业类似,除非前一阶段通过,否则延迟作业的计时器不会启动。

以下示例创建了一个名为 timed rollout 10% 的作业,该作业在前一阶段完成 30 分钟后执行:

timed rollout 10%:
  stage: deploy
  script: echo 'Rolling out 10% ...'
  when: delayed
  start_in: 30 minutes
  environment: production

要停止延迟作业的活动计时器,请选择 (取消计划) 按钮。 无法再安排此作业自动运行。但是,您可以手动执行作业。

要手动启动延迟作业,请选择 取消计划 () 来停止延迟计时器,然后选择 运行 ()。 很快,GitLab Runner 开始工作。

并行化大型作业

要将大型作业拆分为多个并行运行的较小作业,请在您的 .gitlab-ci.yml 文件中使用 parallel 关键字。

不同的语言和测试套件有不同的方法来实现并行化。 例如,使用 Semaphore Test Boosters 和 RSpec 并行运行 Ruby 测试:

# Gemfile
source 'https://rubygems.org'

gem 'rspec'
gem 'semaphore_test_boosters'
test:
  parallel: 3
  script:
    - bundle
    - bundle exec rspec_booster --job $CI_NODE_INDEX/$CI_NODE_TOTAL

然后,您可以导航到新流水线构建的 作业 选项卡,并查看您的 RSpec 作业分为三个独立的作业。

cautionTest Boosters 向作者报告使用统计数据。

运行并行作业的一维矩阵

引入于 13.5 版本。

您可以创建并行作业的一维矩阵:

deploystacks:
  stage: deploy
  script:
    - bin/deploy
  parallel:
    matrix:
      - PROVIDER: [aws, ovh, gcp, vultr]
  environment: production/$PROVIDER

您还可以创建多维矩阵

运行并行触发作业矩阵

引入于 13.10 版本。

您可以在单个流水线中多次并行运行 trigger 作业,但对于作业的每个实例使用不同的变量值。

deploystacks:
  stage: deploy
  trigger:
    include: path/to/child-pipeline.yml
  parallel:
    matrix:
      - PROVIDER: aws
        STACK: [monitoring, app1]
      - PROVIDER: ovh
        STACK: [monitoring, backup]
      - PROVIDER: [gcp, vultr]
        STACK: [data]

此示例生成 6 个并行的 deploystacks 触发器作业,每个具有不同的 PROVIDERSTACK 值,并且它们使用这些变量创建 6 个不同的子流水线。

deploystacks: [aws, monitoring]
deploystacks: [aws, app1]
deploystacks: [ovh, monitoring]
deploystacks: [ovh, backup]
deploystacks: [gcp, data]
deploystacks: [vultr, data]

为每个并行矩阵作业选择不同的 runner 标签

引入于 14.1 版本。

您可以将 parallel: matrix 中定义的变量与 tags 关键字一起用于动态 runner 选择:

deploystacks:
  stage: deploy
  parallel:
    matrix:
      - PROVIDER: aws
        STACK: [monitoring, app1]
      - PROVIDER: gcp
        STACK: [data]
  tags:
    - ${PROVIDER}-${STACK}
  environment: $PROVIDER/$STACK

parallel:matrix 作业中获取产物

您可以使用 dependencies 关键字从使用 parallel:matrix 创建的作业中获取产物。使用作业名称作为 dependencies 的值,格式如下:

<job_name> [<matrix argument 1>, <matrix argument 2>, ... <matrix argument N>]

例如,要从具有 2.7RUBY_VERSIONawsPROVIDER 的作业中获取产物:

ruby:
  image: ruby:${RUBY_VERSION}
  parallel:
    matrix:
      - RUBY_VERSION: ["2.5", "2.6", "2.7", "3.0", "3.1"]
        PROVIDER: [aws, gcp]
  script: bundle install

deploy:
  image: ruby:2.7
  stage: deploy
  dependencies:
    - "ruby: [2.7, aws]"
  script: echo hello
  environment: production

dependencies 条目周围的引号是必需的。

通过多个并行作业的需求指定并行作业

引入于极狐GitLab 16.3。

您可以将 needs:parallel:matrix 中定义的变量与多个并行作业一起使用。

例如:

linux:build:
  stage: build
  script: echo "Building linux..."
  parallel:
    matrix:
      - PROVIDER: aws
        STACK:
          - monitoring
          - app1
          - app2

mac:build:
  stage: build
  script: echo "Building mac..."
  parallel:
    matrix:
      - PROVIDER: [gcp, vultr]
        STACK: [data, processing]

linux:rspec:
  stage: test
  needs:
    - job: linux:build
      parallel:
        matrix:
          - PROVIDER: aws
            STACK: app1
  script: echo "Running rspec on linux..."

mac:rspec:
  stage: test
  needs:
    - job: mac:build
      parallel:
        matrix:
          - PROVIDER: [gcp, vultr]
            STACK: [data]
  script: echo "Running rspec on mac..."

production:
  stage: deploy
  script: echo "Running production..."
  environment: production

此示例生成多个作业。每个并行作业都有不同的 PROVIDERSTACK 值。

  • 3 个并行 linux:build 作业:
    • linux:build: [aws, monitoring]
    • linux:build: [aws, app1]
    • linux:build: [aws, app2]
  • 4 个并行 mac:build 作业:
    • mac:build: [gcp, data]
    • mac:build: [gcp, processing]
    • mac:build: [vultr, data]
    • mac:build: [vultr, processing]
  • 1 个 linux:rspec 作业:
  • 1 个 production 作业:

这些作业具有三种执行路径:

  • Linux 路径:linux:rspec 作业在 linux:build: [aws, app1] 作业运行后立即运行,无需等待 mac:build 完成。
  • macOS 路径:mac:rspec 作业在 mac:build: [gcp, data]mac:build: [vultr, data] 作业完成后立即运行,无需等待 linux:build 完成。
  • 之前的作业全部完成后,production 作业就会运行。

使用预定义的 CI/CD 变量仅在特定流水线类型中运行作业

您可以使用预定义 CI/CD 变量来选择运行的管道类型作业,其中:

下表列出了一些您可以使用的变量,以及这些变量可以控制的流水线类型:

  • 为 Git push 事件运行到分支的分支流水线,例如新的提交或标签。
  • 仅在将新 Git 标签推送到分支时运行的标签流水线。
  • 合并请求流水线 运行以更改合并请求,例如新提交或在合并请求的流水线选项卡中选择 运行流水线 按钮。
  • 预定流水线
变量 分支 标签 合并请求 计划流水线
CI_COMMIT_BRANCH Yes     Yes
CI_COMMIT_TAG   Yes   Yes,如果计划的流水线配置为在标签上运行。
CI_PIPELINE_SOURCE = push Yes Yes    
CI_PIPELINE_SOURCE = scheduled       Yes
CI_PIPELINE_SOURCE = merge_request_event     Yes  
CI_MERGE_REQUEST_IID     Yes  

例如,要将作业配置为针对合并请求流水线和计划流水线运行,但不针对分支或标签流水线运行:

job1:
  script:
    - echo
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
    - if: $CI_PIPELINE_SOURCE == "schedule"
    - if: $CI_PIPELINE_SOURCE == "push"
      when: never

常用表达

@ 符号表示引用的仓库路径的开头。 要匹配正则表达式中包含 @ 字符的引用名称,您必须使用十六进制字符代码匹配 \x40

正则表达式只能匹配标签或分支名称。 仓库路径(如果给定)始终按字面匹配。

要匹配标签或分支名称,pattern 的整个 ref 名称部分必须是一个正则表达式,用 / 包围。 例如,您不能使用 issue-/.*/ 来匹配所有以 issue- 开头的标签名称或分支名称,但您可以使用 /issue-.*/

正则表达式标志必须附加在结束的 / 之后。默认情况下,模式匹配区分大小写。使用 i 标志修饰符,如 /pattern/i,使模式不区分大小写:

job:
  # use regexp
  only:
    - /^issue-.*$/i
  # use special keyword
  except:
    - branches

使用锚点^$ 来避免正则表达式只匹配标签名称或分支名称的子字符串。 例如,/^issue-.*$/ 等价于 /^issue-/,而仅仅 /issue/ 也会匹配名为 severe-issues 的分支。

CI/CD 变量表达

使用变量表达式来控制在将更改推送到极狐GitLab 后,在流水线中创建哪些作业。您可以将变量表达式用于:

例如,使用 rules:if

job1:
  variables:
    VAR1: "variable1"
  script:
    - echo "Test variable comparison
  rules:
    - if: $VAR1 == "variable1"

将变量与字符串进行比较

您可以使用相等运算符 ==!= 将变量与字符串进行比较。单引号和双引号都有效。顺序无关紧要,因此变量可以是第一个,也可以是字符串的第一个。例如:

  • if: $VARIABLE == "some value"
  • if: $VARIABLE != "some value"
  • if: "some value" == $VARIABLE

比较两个变量

您可以比较两个变量的值。 例如:

  • if: $VARIABLE_1 == $VARIABLE_2
  • if: $VARIABLE_1 != $VARIABLE_2

检查变量是否未定义

您可以将变量与 null 关键字进行比较,以查看它是否已定义。例如:

  • if: $VARIABLE == null
  • if: $VARIABLE != null

检查变量是否为空

您可以检查变量是否已定义但为空。例如:

  • if: $VARIABLE == ""
  • if: $VARIABLE != ""

检查变量是否存在

您可以仅使用表达式中的变量名称来检查变量是否存在。变量不能为空。例如:

  • if: $VARIABLE

将变量与正则表达式 pattern 进行比较

您可以使用 =~!~ 运算符对变量值进行正则表达式模式匹配。 与正则表达式的变量模式匹配使用 RE2 正则表达式语法

表达式在以下情况下评估为true

  • 使用 =~ 时会找到匹配项。
  • 使用!~找不到匹配。

例如:

  • if: $VARIABLE =~ /^content.*/
  • if: $VARIABLE !~ /^content.*/

不支持单字符正则表达式,如 /./,会产生 invalid expression syntax 错误。

默认情况下,pattern 匹配区分大小写。使用 i 标志修饰符使 pattern 不区分大小写。例如:/pattern/i

将正则表达式样式存储在变量中

  • 引入于 15.0 版本,功能标志ci_fix_rules_if_comparison_with_regexp_variable,默认禁用。
  • 功能标志 ci_fix_rules_if_comparison_with_regexp_variable 删除于 15.1 版本。

=~!~ 表达式右侧的变量被评估为正则表达式。 正则表达式必须用正斜杠 (/) 括起来。例如:

variables:
  pattern: '/^ab.*/'

regex-job1:
  variables:
    teststring: 'abcde'
  script: echo "This job will run, because 'abcde' matches the /^ab.*/ pattern."
  rules:
    - if: '$teststring =~ $pattern'

regex-job2:
  variables:
    teststring: 'fghij'
  script: echo "This job will not run, because 'fghi' does not match the /^ab.*/ pattern."
  rules:
    - if: '$teststring =~ $pattern'

&&|| 连接变量表达式

您可以使用&&(和)或||(或)连接多个表达式,例如:

  • $VARIABLE1 =~ /^content.*/ && $VARIABLE2 == "something"
  • $VARIABLE1 =~ /^content.*/ && $VARIABLE2 =~ /thing$/ && $VARIABLE3
  • $VARIABLE1 =~ /^content.*/ || $VARIABLE2 =~ /thing$/ && $VARIABLE3

运算符的优先级遵循 Ruby 2.5 标准,因此 &&|| 之前评估。

将变量表达式与括号一起分组

您可以使用括号将表达式组合在一起。 括号优先于&&||,所以括号中的表达式首先被计算,结果用于表达式的其余部分。

您可以嵌套括号以创建复杂条件,并首先计算括号中最内层的表达式。

例如:

  • ($VARIABLE1 =~ /^content.*/ || $VARIABLE2) && ($VARIABLE3 =~ /thing$/ || $VARIABLE4)
  • ($VARIABLE1 =~ /^content.*/ || $VARIABLE2 =~ /thing$/) && $VARIABLE3
  • $CI_COMMIT_BRANCH == "my-branch" || (($VARIABLE1 == "thing" || $VARIABLE2 == "thing") && $VARIABLE3)

故障排查

使用 changes: 时,作业或流水线意外运行

当使用 rules: changesonly: changes 没有用于合并请求流水线时,您的作业或流水线可能会意外运行。

与合并请求没有显式关联的分支或标签上的流水线使用以前的 SHA 来计算差异。此计算等效于 git diff HEAD~ 并可能导致意外,包括:

  • 将新分支或新标签推送到极狐GitLab 时,changes 规则始终评估为 true。
  • 当推送一个新的提交时,更改的文件是通过使用以前的提交作为基本 SHA 计算的。

此外,在计划流水线中,带有 changes 的规则始终评估为 true。 当计划流水线运行时,所有文件都被认为已更改,因此作业可能始终添加到使用 changes 的计划流水线中。

You are not allowed to download code from this project. 错误消息

当极狐GitLab 管理员在私有项目中运行受保护的手动作业时,您可能会看到流水线失败。

CI/CD 作业通常在作业启动时克隆项目,使用运行作业的用户的权限。所有用户(包括管理员)都必须是私有项目的直接成员才能克隆该项目的源。

要运行受保护的手动作业:

  • 将管理员添加为私有项目的直接成员(任何角色)
  • 模拟作为项目直接成员的用户。