前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【GitLab CI/CD】:条件、分支(rules)

【GitLab CI/CD】:条件、分支(rules)

作者头像
WEBJ2EE
发布2021-01-04 14:53:00
21.6K5
发布2021-01-04 14:53:00
举报
文章被收录于专栏:WebJ2EE
代码语言:javascript
复制
目录
1. 用途
2. 机制
    2.1. Rules attributes
    2.2. Rules clauses
    2.3. rules:if
      2.3.1. Common if clauses for rules
    2.4. rules:changes
    2.5. rules:exists
3. 综合示例    
    3.1. 示例1:根据 commit meesage 触发
    3.2. 示例2:根据 Tag 触发

1. 用途?

.gitlab-ci.yml 的 rules 配置,能让我们根据自定义的筛选条件,控制 job 是否执行:

  • 这段脚本我只想在 dev 分支执行,另一段只想在 master 分支执行;
  • 这段脚本我只想在 master 分支上打 tag 的时候触发,其他情况不触发;
  • 这段脚本我只想在 这些文件产生变更时触发,其他情况不触发;
  • 这段脚本我只想在 commit message 中包含某些特定关键字时才触发;
  • ....

一个例子:

代码语言:javascript
复制
job:
  script: echo "Hello, Rules!"
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
      when: manual
      allow_failure: true
    - if: '$CI_PIPELINE_SOURCE == "schedule"'

2. 机制

The rules keyword can be used to include or exclude jobs in pipelines.

Rules are evaluated in order until the first match. When matched, the job is either included or excluded from the pipeline, depending on the configuration. If included, the job also has certain attributes added to it.

2.1. Rules attributes

The job attributes you can use with rules are:

  • when: If not defined, defaults to when: on_success.
    • If used as when: delayed, start_in is also required.
  • allow_failure: If not defined, defaults to allow_failure: false.
  • variables: If not defined, uses the variables defined elsewhere.

If a rule evaluates to true, and when has any value except never, the job is included in the pipeline.

For example:

代码语言:javascript
复制
docker build:
  script: docker build -t my-image:$CI_COMMIT_REF_SLUG .
  rules:
    - if: '$CI_COMMIT_BRANCH == "master"'
      when: delayed
      start_in: '3 hours'
      allow_failure: true

2.2. Rules clauses

Available rule clauses are:

  • if:Add or exclude jobs from a pipeline by evaluating an if statement.
  • changes:Add or exclude jobs from a pipeline based on what files are changed.
  • exists:Add or exclude jobs from a pipeline based on the presence of specific files.

Rules are evaluated in order until a match is found. If a match is found, the attributes are checked to see if the job should be added to the pipeline. If no attributes are defined, the defaults are:

  • when: on_success
  • allow_failure: false

The job is added to the pipeline:

  • If a rule matches and has when: on_success, when: delayed or when: always.
  • If no rules match, but the last clause is when: on_success, when: delayed or when: always (with no rule).

The job is not added to the pipeline:

  • If no rules match, and there is no standalone when: on_success, when: delayed or when: always.
  • If a rule matches, and has when: never as the attribute.

For example, using if clauses to strictly limit when jobs run:

代码语言:javascript
复制
job:
  script: echo "Hello, Rules!"
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
      when: manual
      allow_failure: true
    - if: '$CI_PIPELINE_SOURCE == "schedule"'

In this example:

  • If the pipeline is for a merge request, the first rule matches, and the job is added to the merge request pipeline with attributes of:
    • when: manual (manual job)
    • allow_failure: true (the pipeline continues running even if the manual job is not run)
  • If the pipeline is not for a merge request, the first rule doesn’t match, and the second rule is evaluated.
  • If the pipeline is a scheduled pipeline, the second rule matches, and the job is added to the scheduled pipeline. No attributes were defined, so it is added with:
    • when: on_success (default)
    • allow_failure: false (default)
  • In all other cases, no rules match, so the job is not added to any other pipeline.

Alternatively, you can define a set of rules to exclude jobs in a few cases, but run them in all other cases:

代码语言:javascript
复制
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
  • If the pipeline is for a merge request, the job is not be added to the pipeline.
  • If the pipeline is a scheduled pipeline, the job is not be added to the pipeline.
  • In all other cases, the job is added to the pipeline, with when: on_success.

2.3. rules:if

rules:if clauses determine whether or not jobs are added to a pipeline by evaluating an if statement. If the if statement is true, the job is either included or excluded from a pipeline. In plain English, if rules can be interpreted as one of:

  • “If this rule evaluates to true, add the job” (default).
  • “If this rule evaluates to true, do not add the job” (by adding when: never).

Any set of expressions to be evaluated can be conjoined into a single expression by using && or ||, and the variable matching operators (==, !=, =~ and !~).

Unlike variables in script sections, variables in rules expressions are always formatted as $VARIABLE.

For example:

代码语言:javascript
复制
job:
  script: echo "Hello, Rules!"
  rules:
    - if: '$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME =~ /^feature/ && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "master"'
      when: always
    - if: '$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME =~ /^feature/'
      when: manual
      allow_failure: true
    - if: '$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME'  # Checking for the presence of a variable is possible

Some details regarding the logic that determines the when for the job:

  • If none of the provided rules match, the job is set to when: never and is not included in the pipeline.
  • A rule without any conditional clause, such as a when or allow_failure rule without if or changes, always matches, and is always used if reached.
  • If a rule matches and has no when defined, the rule uses the when defined for the job, which defaults to on_success if not defined.
  • You can define when once per rule, or once at the job-level, which applies to all rules. You can’t mix when at the job-level with when in rules.

2.3.1. Common if clauses for rules

You can check the value of the $CI_PIPELINE_SOURCE variable:

For example:

代码语言:javascript
复制
job:
  script: echo "Hello, Rules!"
  rules:
    - if: '$CI_PIPELINE_SOURCE == "schedule"'
      when: manual
      allow_failure: true
    - if: '$CI_PIPELINE_SOURCE == "push"'
  • This example runs the job as a manual job in scheduled pipelines or in push pipelines (to branches or tags), with when: on_success (default). It does not add the job to any other pipeline type.

Another example:

代码语言:javascript
复制
job:
  script: echo "Hello, Rules!"
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
    - if: '$CI_PIPELINE_SOURCE == "schedule"'
  • This example runs the job as a when: on_success job in merge request pipelines and scheduled pipelines. It does not run in any other pipeline type.

Other commonly used variables for if clauses:

  • if: $CI_COMMIT_TAG: If changes are pushed for a tag.
  • if: $CI_COMMIT_BRANCH: If changes are pushed to any branch.
  • if: '$CI_COMMIT_BRANCH == "master"': If changes are pushed to master.
  • if: 'CI_COMMIT_BRANCH == CI_DEFAULT_BRANCH': If changes are pushed to the default branch (usually master). Use when you want to have the same configuration in multiple projects with different default branches.
  • if: '$CI_COMMIT_BRANCH =~ /regex-expression/': If the commit branch matches a regular expression.
  • if: '$CUSTOM_VARIABLE !~ /regex-expression/': If the custom variable CUSTOM_VARIABLE does not match a regular expression.
  • if: '$CUSTOM_VARIABLE == "value1"': If the custom variable CUSTOM_VARIABLE is exactly value1.

2.4. rules:changes

rules:changes determines whether or not to add jobs to a pipeline by checking for changes to specific files.

It’s recommended to only use rules: changes with branch pipelines or merge request pipelines. For example, it’s common to use rules: changes with merge request pipelines:

代码语言:javascript
复制
docker build:
  script: docker build -t my-image:$CI_COMMIT_REF_SLUG .
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
      changes:
        - Dockerfile
      when: manual
      allow_failure: true

In this example:

  • If the pipeline is a merge request pipeline, check Dockerfile for changes.
  • If Dockerfile has changed, add the job to the pipeline as a manual job, and the pipeline continues running even if the job is not triggered (allow_failure: true).
  • If Dockerfile has not changed, do not add job to any pipeline (same as when: never).

To use rules: changes with branch pipelines instead of merge request pipelines, change the if: clause in the example above to:

代码语言:javascript
复制
rules:
  - if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH

To implement a rule similar to except:changes, use when: never.

  • You can use rules: changes with other pipeline types, but it is not recommended because rules: changes always evaluates to true when there is no Git push event. Tag pipelines, scheduled pipelines, and so on do not have a Git push event associated with them. A rules: changes job is always added to those pipeline if there is no if: statement that limits the job to branch or merge request pipelines.

2.5. rules:exists

exists accepts an array of paths and matches if any of these paths exist as files in the repository:

代码语言:javascript
复制
job:
  script: docker build -t my-image:$CI_COMMIT_REF_SLUG .
  rules:
    - exists:
        - Dockerfile

You can also use glob patterns to match multiple files in any directory in the repository:

代码语言:javascript
复制
job:
  script: bundle exec rspec
  rules:
    - exists:
        - spec/**.rb

For performance reasons, using exists with patterns is limited to 10,000 checks. After the 10,000th check, rules with patterned globs always match.

3. 综合示例

3.1. 示例1:根据 commit meesage 触发

代码语言:javascript
复制
publish-modern-docs:
  stage: build
  trigger:
    include: sef/sef_docs_modern/.gitlab-ci.yml
  rules:
    - if: '$CI_COMMIT_MESSAGE =~ /^docs/'
      changes:
        - sef/sef_docs_modern/**/*

3.2. 示例2:根据 Tag 触发

代码语言:javascript
复制
build_sef:
  stage: build
  trigger:
    include: sef/.gitlab-ci_sef.yml
  rules:
    - if: $CI_COMMIT_TAG

参考:

rules: https://docs.gitlab.com/ee/ci/yaml/README.html#rules


本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-12-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 WebJ2EE 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档