〇、前言

.gitlab-ci.yml 文件主要用于项目的自动化部署配置,自动化可以大大提升团队效率,但同时这个文件的内容也比较复杂,弄清楚也并非易事,本文将对此文件的内容进行简单介绍,供参考。

另外,.gitlab-ci.yml 文件一般存放在项目的根目录中,可以参考以往项目的配置文件来理解。

关于 CI/CD 的概念可参考博主过往文章:https://www.cnblogs.com/hnzhengfy/p/18806480/CI_CD1

一、.gitlab-ci.yml 可以做什么

1.1 简介

.gitlab-ci.yml 是 GitLab 中用于定义持续集成(CI)和持续交付/部署(CD)流程的配置文件。

它告诉 GitLab Runner 如何执行自动化任务,例如构建代码、运行测试、打包应用程序以及将应用程序部署到生产环境。

通过统一的自动化的流程,减少手动操作,从而避免诸多的人为错误;还可以快速发现和修复问题(例如通过自动化测试);也可以实现持续交付和持续部署,缩短从代码提交到上线的时间。

.gitlab-ci.yml 还可以与代码一起存入版本控制系统(如 Git),便于跟踪配置变更。

1.2 关于 Pipelines(管道)

Popelines 代表了一系列用于构建、测试和部署代码的任务或步骤的集合。这些任务按照预定的顺序执行,以确保软件的质量和稳定性,并且能够高效地将新功能或修复推送到生产环境中。

配置文件完成后,就可以触发 CI,启动 Pipelines,成功的状态为 passed,失败为 failed,如下图。

每个 Pipeline 通常由多个 Job 组成,这些 Job 根据 stages 配置,同一阶段默认并行执行,不同阶段串行执行。

1.3 Job:一个基本执行单元

Job 是 CI/CD 流程中的基本执行单元,代表了一个独立的任务或操作。

每个 Job 通常负责完成某一特定的工作,例如编译代码、运行测试、打包应用程序或部署到生产环境。

在 .gitlab-ci.yml 文件中,Job 是通过 YAML 格式定义的。每个 Job 都有一个唯一的名称,并包含一组配置选项来描述它的行为。

点击 Pipelines 可以查看 Job 详情,如下图。

每个 Job 包含多个配置选项,如 stage、script、artifacts、cache 等,后文将详细介绍。

1.4 Runners

Runners 是执行 CI/CD 任务的核心组件。它们是实际运行 .gitlab-ci.yml 中定义的 Jobs 的代理或服务。

Runners 是需要单独安装注册的教程可以参考:https://juejin.cn/post/6963927908444274718

Runners 是执行 CI/CD 任务的一个独立的核心组件。它负责从 GitLab 接收指令并执行 Pipeline 中定义的任务(Jobs)。每个 Runner 可以被分配到一个或多个项目,并根据需要执行不同的 Jobs。

Runners 的主要类型有:

Shared Runners:由 GitLab.com 提供,所有用户都可以使用,适合小型项目或不需要定制化环境的项目,特点是资源共享,但可能会导致排队等待。

Group Runners:可以被分配给某个 GitLab Group 下的所有项目。它提供了一种在组内共享资源的方式,同时保持一定程度的隔离。

Specific Runners:专为特定项目配置的 Runner。它提供了最大的灵活性和控制力,允许针对项目的特殊需求进行定制。适用于需要特定环境或高安全性的场景。

当一个项目的代码发生变化(如提交、合并请求等),GitLab 会根据 .gitlab-ci.yml 文件创建一个新的 Pipeline。Pipeline 包含多个阶段(stages),每个阶段包含一个或多个 Jobs。GitLab 将这些 Jobs 分配给可用的 Runner 来执行。

执行的流程大概为:

注册 Runner:首先需要将 Runner 注册到 GitLab 实例上,这样它才能接收到来自 GitLab 的任务。

获取任务:一旦有新的 Pipeline 触发,GitLab 会将相应的 Jobs 分配给符合条件的 Runner。

执行脚本:Runner 执行 .gitlab-ci.yml 中定义的 script 命令。

报告结果:完成 Job 后,Runner 会将结果(成功或失败)以及任何生成的产物(artifacts)返回给 GitLab。

二、示例配置

一个简单的示例配置,可以大概浏览下有哪些配置节点,结合后文继续理解。

include:
- remote: "http://www.baidu.com/data/prod.yml" variables:
- buildImage: "http://hub.com/nginx" workflow:
rules:
- if: '$CI-PIPELINE_SOURCE' == "push"'
when: never
- when: always stages:
- build
- nextStep
- testStep1 build-job:
stage: build
script:
- echo "Hello, $GITLAB_USER_LOGIN!" test-job1:
stage: nextStep
script:
- echo "This job tests something" test-job2:
stage: nextStep
script:
- echo "This job tests something, but takes more time than test-job1."
- echo "After the echo commands complete, it runs the sleep command for 20 seconds" deploy-prod:
stage: testStep1
script:
- echo "This job deploys something from the $CI_COMMIT_BRANCH branch."

这份文件包含了四个可执行的 Jobs,通过 stages 定义执行的顺序,test-job1、test-job2 的 stage 名字相同都是 nextStep,此时这两个任务将并列执行。

三、全局关键字

.gitlab-ci.yml 可以分为几个层级,首先最外层的变量包括四个,如下:

关键字 释义 值例举 说明
stages 阶段,类型数组 分别为自定义的 jobs 规定各个任务的执行顺序,任务名称相同,则同时执行
include 引用的 yml 或 yaml 配置文件 key: 包括,local、remote、file、template local 一般是本地文件,remote 可以是远程其他可访问的地址,filter 一般是其他项目下的文件路径,template 是官方提供的模版
variables 变量 预定义或自定义 根据变量位置不同,优先级不样,相同的变量会根据优先级进行覆盖
workflow 工作流 rules 用来定义 CI/CD 何时触发,和 jobs 中的 rules、only 相似

3.1 stages 阶段(每个阶段可包含多个 Job)

stages 用于定义 CI/CD Pipeline 的执行阶段顺序

每个阶段(stage)包含一组任务(Jobs,并行或串行),并且这些任务会按照 stages 中定义的顺序依次执行。

各个阶段是控制依赖关系(串行),即前一个阶段的所有 Jobs 必须成功完成后,才会进入下一个阶段。如果某个阶段中的某个 Job 失败,后续阶段通常不会执行(除非配置了允许失败)。如果某个阶段没有定义任何 Jobs,则该阶段会被跳过。

如果没有显式定义 stages,GitLab 会使用默认的三个阶段:build-构建代码或准备环境;test-运行测试;deploy-部署到目标环境。

在一个阶段中,所有 Jobs 默认是并行执行的。例如:

stages:
- test unit_tests:
stage: test
script:
- echo "Running unit tests..." integration_tests:
stage: test
script:
- echo "Running integration tests..."

在这个例子中,unit_tests 和 integration_tests 会同时运行。

在一个阶段中,也可以通过 needs 配置来实现串行执行,从而强制某些 Jobs 按顺序执行,即使它们属于同一个 stage。例如:

stages:
- build job1:
stage: build
script:
- echo "Running job1..."
- sleep 5
tags:
- shared job2:
stage: build
script:
- echo "Running job2 after job1..."
needs:
- job1

在 job2 中添加了 needs: -job1 配置,意思就是在执行 job2 之前,需要等 job1 先执行完成。

常见的阶段列举:

阶段名称 描述
prepare 准备工作,如安装依赖、设置环境变量等
build 构建代码或生成构建产物,如编译代码、打包应用程序等
test 运行单元测试、集成测试、端到端测试等
deploy 将应用程序部署到目标环境,如测试、生产环境等
release 发布版本,例如生成发布包、推送镜像到容器仓库等
cleanup 清理临时文件、释放资源等

配置的注意事项:

为每个阶段分配明确的任务,避免混杂。例如:build 阶段只负责构建;test 阶段只负责测试;deploy 阶段只负责部署。

根据项目需求定义清晰的阶段名称,例如 prepare、package、publish 等。

过多的阶段可能导致 Pipeline 变得复杂且难以维护,要根据实际需求合理划分阶段。

如果某些阶段的失败不影响整体流程,可以通过 allow_failure: true 来允许失败。

optional_stage:
stage: optional
script:
- echo "This stage can fail without affecting the pipeline."
allow_failure: true

3.2 include 引入外部配置文件

3.2.1 简介

include 配置,用于将外部的配置文件引入到当前的 CI/CD 配置中。可以实现配置的模块化和复用,从而简化复杂的管道配置文件。

即:拆分复杂的配置文件;在多个项目中共享通用的 CI/CD 配置;维护更加清晰和模块化的管道定义。

include 等基本类型:

include:
# 1)引入本地文件
# 路径是相对于项目根目录
- local: path/to/file.yml
# 2)引入外部 URL 提供的配置文件
# 文件必须可通过 HTTP 或 HTTPS 访问,并且支持 CORS(Cross-Origin Resource Sharing:跨源资源共享)
- remote: https://example.com/config.yml
# 3)使用 GitLab 提供的内置模板(如 Auto DevOps)
# 内置模板可以直接使用,无需额外配置
- template: Auto-DevOps.gitlab-ci.yml
# 4)引入其他项目的文件
# 需要指定项目路径(project)和文件路径(file)
- project: 'group/project'
file: '/path/to/file.yml'

当使用 include 引入外部文件时,GitLab 会将所有文件的内容合并为一个完整的 .gitlab-ci.yml 文件。

注意事项:

  1. 访问权限:如果使用 project 类型引用其他项目的文件,需要确保当前项目有权限访问目标项目。如果使用 remote 类型,目标文件必须公开或有适当的访问权限。
  2. 不允许存在循环依赖:例如 A 包含 B,B 又包含 A。
  3. 合理拆分文件:单个大文件和过多的 include 都会增加 Pipeline 配置加载的时间。
  4. 提前验证配置内容:使用 GitLab 的 CI Lint 工具可以验证最终合并的配置是否正确。

通过灵活运用 include,可以构建出高效且可扩展的 CI/CD 流程。

3.2.2 合并规则

如果有重复的键值对,后定义的内容会覆盖先定义的内容(后来居上)

所有的 stages、jobs 和全局变量都会被合并。如果某个 Job 定义了相同的名称,则后定义的 Job 会覆盖前一个(后来居上)

  • stages 的合并规则

主文件优先:如果主 .gitlab-ci.yml 文件中定义了 stages,那么它会完全覆盖外部文件中的 stages 定义。

外部文件补充:如果主文件中没有定义 stages,则会使用外部文件中的 stages。

例如:

# 主文件
include:
- local: included.yml stages:
- build
- test
# 外部文件:included.yml
stages:
- deploy
# 最终合并结果
stages:
- build
- test
# 即:主文件中的 stages 完全覆盖了外部文件中的 stages
  • jobs 的合并规则

不冲突时合并:如果主文件和外部文件中的 jobs 名称不同,则它们会被合并到最终的配置中。

冲突时主文件优先:如果主文件和外部文件中有同名的 job,则主文件中的定义会完全覆盖外部文件中的定义。

# 主文件:.gitlab-ci.yml
include:
- local: included.yml build_job:
script:
- echo "Building from main file"
# 外部文件:included.yml
build_job:
script:
- echo "Building from included file" test_job:
script:
- echo "Testing from included file"
# 合并结果:
build_job:
script:
- echo "Building from main file" test_job:
script:
- echo "Testing from included file"
# build_job 被主文件覆盖
# test_job 被保留,因为它没有冲突
  • 全局变量的合并规则

主文件优先:如果主文件和外部文件中都定义了相同的全局变量,则主文件中的值会覆盖外部文件中的值。

非冲突变量合并:如果主文件和外部文件中的变量名称不同,则它们会被合并。

3.2.3 include 实现配置文件的动态包含

通过结合 rules 或 only/except,可以根据条件动态地引入不同的配置文件。

当一个管道触发时,GitLab 会根据当前的环境变量(如 $CI_COMMIT_BRANCH)评估 rules 条件。只有满足条件的 include 块会被执行,对应的外部文件内容会被加载并合并到主配置中。

例如:

include:
- local: .gitlab/ci/build-dev.yml
rules:
- if: '$CI_COMMIT_BRANCH == "dev"' # 如果当前提交的分支是 dev,则加载 .gitlab/ci/build-dev.yml 文件
- local: .gitlab/ci/build-prod.yml
rules:
- if: '$CI_COMMIT_BRANCH == "main"' # 如果当前提交的分支是 main,则加载 .gitlab/ci/build-prod.yml 文件

3.2.4 include 允许嵌套包含

外部文件本身也可以包含其他文件,从而实现嵌套的模块化配置。

例如:

# 主文件
include:
- local: .gitlab/ci/main-config.yml
# 外部文件:.gitlab/ci/main-config.yml
include:
- local: .gitlab/ci/build.yml
- local: .gitlab/ci/test.yml

3.2.5 include 可以结合锚点(&)和别名(*)

结合 YAML 的锚点和别名,可以在多个地方复用相同的配置。

例如:

# 主文件
include:
- local: .gitlab/ci/common.yml
# 外部文件:.gitlab/ci/common.yml
.common-template: &common-template # 定义了一个 YAML 锚点 .common-template,它包含了通用的配置(如 image 和 before_script)
image: alpine
before_script:
- echo "Preparing environment..." build_job:
<<: *common-template # 使用 <<: *common-template 将锚点的内容合并到 build_job 中,并添加特定的任务脚本(如 script)
script:
- echo "Building the application..."
# 最终合并结果
# 合并后的完整配置
image: alpine
before_script:
- echo "Preparing environment..." build_job:
image: alpine
before_script:
- echo "Preparing environment..."
script:
- echo "Building the application..."

3.3 Variables(变量)

3.3.1 简介

Variables 用于存储配置信息、敏感数据或任何需要动态改变的值,并且可以在 .gitlab-ci.yml 文件、Pipeline Jobs 的脚本中使用。合理地使用变量可以提高 Pipeline 的灵活性和安全性。

主要作用为:

配置管理:通过变量来配置不同的环境(如开发、测试、生产),使得同一套 CI/CD 配置能够适应多种环境。

动态流程控制:通过变量控制任务的行为(如分支名称、环境类型)。

安全性:保护敏感信息(例如 API 密钥、数据库密码等),避免直接硬编码到脚本或配置文件中。

灵活性:允许根据不同的条件动态调整 Pipeline 行为,例如分支名称、标签等。

3.3.2 Variables 有哪些类型

  • 预定义变量

.gitlab-ci.yml 自动提供了一些预定义的环境变量,这些变量包含了关于当前项目、提交、分支、标签等信息。如下是常用的预定义变量列举:

# 当前触发流水线的【分支或标签名称】,示例:在 main 分支触发的流水线中,该值为 main
CI_COMMIT_REF_NAME
# 【当前提交(commit)的完整 SHA 值】,常用于构建 Docker 镜像或其他需要唯一标识符的场景
CI_COMMIT_SHA
# 当前触发流水线的【分支名称】,用于基于分支的条件逻辑判断。注意:对于由标签触发的流水线,此变量为空
CI_COMMIT_BRANCH
# 【当前流水线的唯一 ID】,可用于追踪特定流水线实例
CI_PIPELINE_ID
# 【当前任务(job)的唯一 ID】,可用于日志记录或调试
CI_JOB_ID
# 【项目根目录路径】,用于指定文件路径或工作目录
CI_PROJECT_DIR
# 【项目名称】,可用于生成报告、文档等
CI_PROJECT_NAME
# 项目【主页的 URL 地址】,可用于发送通知或链接到项目主页
CI_PROJECT_URL
# 默认情况下,这是【GitLab 容器注册表的基础地址】,结合项目路径和名称构成完整的镜像名,通常与 CI_COMMIT_SHA 结合使用来标记 Docker 镜像
CI_REGISTRY_IMAGE
# 如果流水线是由一个标签(tag)触发,则此变量包含该【标签的名字】否则为空,用于版本发布流程中
CI_COMMIT_TAG
# 【执行当前任务的 Runner 的 ID】,有助于了解哪个 Runner 执行了任务
CI_RUNNER_ID
# 提供服务的 GitLab 实例名称,可用于区分不同的 GitLab 实例,
CI_SERVER_NAME
# 【临时的 API 令牌】,允许任务访问 GitLab API 资源,可用于自动化脚本调用 GitLab API
CI_JOB_TOKEN
# 当前【部署环境的名称】,在多环境部署策略中很有用
CI_ENVIRONMENT_NAME
# 【部署密码】,当启用保护变量时可用,用于安全地存储和传递敏感信息如密码
CI_DEPLOY_PASSWORD
  • 自定义变量

用户自己可以在 .gitlab-ci.yml 文件中或者通过 GitLab UI 添加自定义变量。自定义变量可以分为两类:全局变量(适用于整个 Pipeline 中的所有 Jobs)、Job 特定变量(仅适用于某个具体的 Job)。

variables: # 全局变量
ENV: "production"
DB_HOST: "db.example.com" build_job1:
script:
- echo "Deploying to $ENV"
- echo "Connecting to $DB_HOST" build_job2:
variables: # 局部变量
BUILD_TYPE: "debug"
script:
- echo "Building with type $BUILD_TYPE"

Runner 配置变量:在 GitLab Runner 的配置文件中定义(如 config.toml),作用于特定 Runner。

[[runners]]
environment = ["CUSTOM_VAR=value"]
  • 保护变量

对于包含敏感信息的变量(如密码、API密钥),可以将其设置为“保护”状态。这意味着该变量只能被用于受保护的分支或标签上的 Pipelines。

3.3.3 变量的优先级

当多个来源的变量发生冲突时,GitLab 会根据以下优先级决定最终值(从高到低)

  1. Job 任务级别的变量(局部变量)
  2. GitLab UI 配置的变量
  3. 全局变量(.gitlab-ci.yml 文件中定义的 variables)
  4. Runner 配置的变量
  5. 系统预定义变量

3.3.4 应用场景

  • 通过变量控制任务的执行逻辑
deploy_job:
script:
- if [ "$DEPLOY_ENV" == "production" ]; then
echo "Deploying to production";
else
echo "Deploying to staging";
fi
  • 将敏感信息存储为变量,避免直接暴露在代码中
deploy_job:
script:
- echo "Using API key: $API_KEY"

可以在 GitLab UI 中定义 API_KEY,并将其标记为“屏蔽”,防止日志泄露。

  • 跨任务共享数据

通过 artifacts:reports 或 artifacts 将变量传递给后续任务。

build_job:
script:
- echo "BUILD_VERSION=1.0.0" > build.env
artifacts:
reports:
dotenv: build.env deploy_job:
script:
- echo "Deploying version $BUILD_VERSION"
  • 控制触发条件

结合 rules 或 only/except 使用变量控制任务的触发

deploy_job:
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
when: always
script:
- echo "Deploying to main branch"
  • 设置默认值
script:
- echo "${ENV:-staging}" # 如果 ENV 未定义,则使用 "staging"
  • 变量之间支持多层嵌套
variables:
BASE_URL: "https://example.com"
API_URL: "${BASE_URL}/api"
  • 多行变量

对于较长的变量值,可以使用 YAML 的多行语法。

variables:
LONG_TEXT: |
This is a multi-line variable.
It can span multiple lines.

3.4 workflow

3.4.1 简介

workflow 用于定义管道的触发规则,决定了管道是否应该被创建。

然后根据分支、标签、事件类型等条件动态调整管道的行为,配合 rules 或 only/except 使用,提供更细粒度的控制。

workflow 定义在 .gitlab-ci.yml 文件的顶层,与 stages 和 jobs 并列。

workflow:
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
when: always
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
when: manual

3.4.2 配置项:rules

rules 是 GitLab CI/CD 推荐的条件控制机制,用于决定管道是否应该被创建。

以下是 rules 的关键字:

if:基于条件表达式判断是否创建管道。

when:指定管道的行为:

  always:总是创建管道。
  on_success:仅当之前的任务成功时创建。
  on_failure:仅当之前的任务失败时创建。
  manual:手动触发管道。
  never:不创建管道。

changes:根据文件变更路径判断是否创建管道。

exists:根据文件是否存在判断是否创建管道。

3.4.3 配置项:only/except 这两个都是旧语法

only 和 except 是早期版本的 GitLab 提供的条件控制机制,虽然仍然支持,但推荐使用 rules 替代。

only:指定管道仅在某些条件下创建

except:指定管道在某些条件下不创建

workflow:
only: # 管道仅在 main 分支或合并请求事件 merge_requests 时创建
- main
- merge_requests
except: # 不在计划管道(schedules)中创建
- schedules

3.4.4 workflow 的典型用法

  • 按分支触发管道

只在特定分支上创建流水线。

workflow:
rules:
- if: '$CI_COMMIT_BRANCH == "main"' # 如果分支是 main,则始终创建管道
when: always
- if: '$CI_COMMIT_BRANCH =~ /^feature\//' # 如果分支以 feature/ 开头,则需要手动触发管道
when: manual
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"' # 如果是合并请求事件,则 manual 需要手动触发管道
when: manual
- when: never # 其他分支不创建管道
  • 按事件类型触发管道

根据管道来源(如推送、合并请求、计划流水线)控制。

workflow:
rules:
- if: '$CI_PIPELINE_SOURCE == "push"' # 如果是代码推送事件,则始终创建管道
when: always
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"' # 如果是合并请求事件,则需要手动触发管道
when: manual
- if: '$CI_PIPELINE_SOURCE == "schedule"' # 如果是计划管道,则不创建管道
when: never
  • 按文件变更触发管道

根据文件变更路径决定是否创建流水线。

workflow:
rules: # 如果在 main 分支上修改了 src 目录下的文件,则创建管道
- if: '$CI_COMMIT_REF_NAME == "main" && $CI_COMMIT_CHANGED_FILES =~ /src/'
when: always
- when: never # 其他情况不创建管道

按时间触发管道

结合计划流水线(Schedules)使用。

workflow:
rules:
- if: '$CI_PIPELINE_SOURCE == "schedule"' # 如果是计划管道,则始终创建管道
when: always
- when: never # 其他情况不创建管道

3.4.5 workflow 优先级

workflow 的规则会覆盖任务级别的 rules 或 only/except。如果 workflow 规则阻止了管道的创建,则所有任务都不会运行。

workflow:
rules: # 如果分支不是 main,则不会创建管道,即使 build_job 存在也不会运行
- if: '$CI_COMMIT_BRANCH != "main"'
when: never build_job:
script:
- echo "Building..."

四、Jobs 相关的关键字

4.1 script:定义任务执行的具体命令

每个任务必须包含 script,且可以执行多个命令行。

# 语法:
job_name:
script:
- command1
- command2
# 示例:
build_job:
script:
- echo "Building the project..."
- npm install
- npm run build

4.2 before_script / after_script:在 Job开始之前/之后执行的脚本

可以是全局配置,也可以局部配置。

# 语法:
before_script:
- apt-get update job_name:
before_script:
- echo "Overriding global before_script"
# 示例:
before_script: # 全局 before_script 配置,会应用到全部的任务中,除非在任务中重新配置过
- echo "Global setup" build_job:
before_script: # 局部的 before_script,会覆盖全局配置 before_script
- echo "Local setup"
script: echo "Building..."
# 如果希望全局配置 before_script 保留,则需要用到 extends 关键字:
.before_template:
before_script:
- echo "Global setup" build_job:
extends: .before_template # extends 引入全局的 before_template 配置
before_script:
- echo "Local setup"
script:
- echo "Building..."

4.3 stage:指定任务所属的阶段

stage 的内容需要与全局的 stages 中内容对应。

# 语法
job_name:
stage: stage_name
# 示例
stages: # 全局 stages 配置
- build
- test
- deploy build_job:
stage: build
script: echo "Building"

4.4 image:指定任务运行的 Docker 镜像

# 语法
job_name:
image: image_name[:tag]
# 示例
build_job:
image: node:18
script: npm install && npm run build

4.5 tags:指定任务运行的 Runner 标签,确保任务由特定 Runner 执行

# 语法
job_name:
tags:
- tag1
- tag2
# 示例
deploy_job:
tags:
- production
- docker
script: echo "Deploying to prod"

4.6 rules:定义任务是否运行的条件规则(推荐使用,来替代 only/except)

# 语法:
job_name:
rules:
- if: <条件表达式>
when: <执行时机> # 执行时机枚举:always(总是), on_success(成功时), on_failure(失败时), manual(手动触发), never(从不)
[changes: <文件路径>] # 示例
test_job:
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
when: always
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
when: manual
- when: never # only:指定管道仅在某些条件下创建
# except:指定管道在某些条件下不创建
# 语法
job_name:
only:
- branches # 分支
- tags # 标签
- pipelines # 流水线类型
# 示例
build_job:
only:
- main
- /^feature-.*/ # 正则匹配分支

4.7 variables:定义任务的环境变量

# 语法
job_name:
variables:
VAR_NAME: "value"
# 示例
test_job:
variables:
DB_HOST: "localhost"
DB_PORT: "5432"
script: echo "Connecting to $DB_HOST:$DB_PORT"

4.8 cache:定义任务的缓存路径,加速后续任务

cache 是 GitLab CI/CD 中优化流水线性能的重要工具,尤其适用于频繁安装依赖的任务。

通过合理使用 paths 和 key,可以有效减少重复操作,提高构建和测试的速度。

同时,需要注意缓存的作用范围和清理策略,确保流水线的稳定性和可靠性。

# 语法
job_name:
cache:
paths:
- path/to/cache/
key: $CI_COMMIT_REF_SLUG # 缓存键
# 示例
stages:
- build build_job:
stage: build
cache: # 缓存 Node.js 依赖,到 node_modules 目录,避免每次运行时都重新安装依赖
key: "$CI_COMMIT_REF_SLUG"
paths:
- node_modules/
script:
- npm install
- npm run build
# 示例:多个缓存条目
job_name:
cache:
- key: "npm-cache"
paths:
- node_modules/
- key: "gradle-cache"
paths:
- .gradle/
# 示例:动态缓存键
# 通过环境变量动态生成缓存键,避免不同分支或任务之间的缓存冲突
stages:
- deploy deploy_job:
stage: deploy
cache: # 根据分支名称生成不同的缓存键,避免不同分支之间的缓存冲突
key: "cache-$CI_COMMIT_REF_SLUG"
paths:
- dist/
script:
- echo "Deploying..."
# $CI_COMMIT_REF_SLUG 是 GitLab 提供的预定义变量,表示分支或标签名称的规范化版本

GitLab CI/CD 不会自动清理旧的缓存,但可以通过以下两种方式手动清理:

  1. 在项目的 Settings > CI/CD > Cache 页面中删除缓存。
  2. 修改 key 的值以强制生成新的缓存。

缓存的作用域:

  跨任务共享:如果多个任务使用相同的 key,它们将共享同一个缓存。
  跨管道共享:缓存不仅限于当前管道,还可以在后续管道中复用。
  Runner 级别隔离:缓存存储在 Runner 上,因此只有使用相同 Runner 的任务才能访问缓存。

注意,Cache 和 Artifacts 的区别:

Cache:用于在任务之间共享文件,适合存储依赖项或其他临时文件。
Artifacts:用于保存任务的输出结果,可供后续任务或用户下载。

cache 缓存可能会丢失(例如,当 Runner 清理磁盘空间时),因此,不要将关键数据仅依赖于缓存,确保任务能够重新生成所需文件。

GitLab 默认保留最近 7 天的缓存。如果缓存占用过多空间,可以手动清理或调整 key 强制生成新缓存

如果项目使用了多个 Runner,建议使用共享存储(如 S3)来存储缓存,以确保一致性。

4.9 artifacts:定义任务的输出结果

用于定义任务的输出结果(如文件、目录等),并使其可供后续任务使用或供用户下载。

与 cache 不同,artifacts 主要用于保存任务的构建产物,而不是依赖项

# 语法
job_name:
artifacts:
paths: # 指定需要保存的文件或目录路径
- path/to/artifact
expire_in: 1 week # 定义过期时间,缺省默认为 30 天
untracked: true # 是否包含未被 Git 跟踪的文件(即未提交到仓库的文件),缺省默认为 false
# 示例:保存构建产物
stages:
- build build_job:
stage: build
script:
- mkdir dist
- echo "Build output" > dist/output.txt
artifacts:
paths:
- dist/
expire_in: 1 week
# 示例:传递测试报告
# 将 JUnit 测试报告上传到 GitLab,管道页面会显示测试结果
stages:
- test test_job:
stage: test
script:
- mvn test
artifacts:
reports:
junit: target/surefire-reports/TEST-*.xml
# 示例:根据根据分支名称生成不同的保存路径
stages:
- deploy deploy_job:
stage: deploy
script:
- mkdir -p "build/$CI_COMMIT_REF_SLUG"
- echo "Deployed to $CI_COMMIT_REF_SLUG" > "build/$CI_COMMIT_REF_SLUG/output.txt"
artifacts:
paths:
- "build/$CI_COMMIT_REF_SLUG/"

GitLab 对制品大小有限制,具体取决于实例配置(通常为 1GB 或更高)。如果制品过大,可以考虑压缩后再上传。

制品会在 expire_in 时间后自动删除。如果需要永久保存某些制品,可以手动调整过期时间或将其存储到外部系统(如 S3)。

如果项目使用了多个 Runner,确保 Runner 有权限上传和下载制品。

4.10 allow_failure:允许任务失败而不影响整体流水线

用于控制任务失败时是否会影响管道的整体状态。

默认情况下,如果某个任务失败,整个管道会被标记为失败。而通过设置 allow_failure: true,即使该任务失败,流水线仍然可以继续运行。

# 语法
job_name:
allow_failure: true
# 示例
unstable_test:
allow_failure: true
script: ./run-unstable-tests.sh

如果 allow_failure: true 的任务失败,管道的状态不会被标记为失败,但仍会显示为“部分成功”或“有警告”。如果所有任务都成功,则管道状态为“成功”。

有哪些使用场景:

  • 非关键任务,例如实验性功能的测试、非核心部署等。
  • 手动触发任务,允许用户手动触发的任务失败不影响整体流程。
  • 延迟任务,某些延迟任务即使失败也不影响主要流程。

4.11 when:控制任务的执行时机

when 需结合 rules 或 trigger 使用。

常用的值:

on_success:描述:任务仅在所有前置任务成功完成时运行(默认行为)。
on_failure:任务仅在至少一个前置任务失败时运行。通常用于清理环境或发送通知。
always:无论前置任务是否成功或失败,任务都会运行。通常用于生成报告或记录日志。
manual:任务需要手动触发,不会自动运行。适用于需要人工干预的任务,例如部署到生产环境。
delayed:任务会在指定的时间延迟后运行。适用于定时任务或延迟触发的场景(需配合 start_in)。

# 基本用法
job_name:
script:
- echo "Running job"
when: on_success # 默认值,任务仅在所有前置任务成功完成时运行
# 示例:结合 rules 使用,实现更复杂的逻辑
deploy_job:
script:
- echo "Deploying..."
rules: # 如果分支是 main,则任务需要手动触发;否则不运行
- if: '$CI_COMMIT_BRANCH == "main"'
when: manual
- when: never
# 示例:通过环境变量动态调整 when 的值
deploy_job:
script:
- echo "Deploying..."
when: $DEPLOY_WHEN # 根据 $DEPLOY_WHEN 的值决定任务的执行时机
# 示例:清理任务
stages:
- build
- cleanup build_job:
stage: build
script:
- echo "Building..."
when: on_success cleanup_job:
stage: cleanup
script:
- echo "Cleaning up..."
when: on_failure # 如果构建失败,则运行清理任务
# 示例:部署任务需要手动触发
stages:
- deploy deploy_job:
stage: deploy
script:
- echo "Deploying to production..."
when: manual
# 示例:延迟任务
stages:
- notify notify_job:
stage: notify
script:
- echo "Sending notification..."
when: delayed # 通知任务会在 10 分钟后运行
start_in: "10 minutes"

注意:手动任务不会影响流水线的整体状态,即使未触发也不会导致流水线失败。

when: delayed 的限制 start_in 的最小延迟时间为 1 分钟。如果流水线被取消或超时,延迟任务不会运行。

4.12 extends:继承其他任务或模板的配置

extends 用于实现任务配置的复用和继承。

通过 extends,可以将通用的配置提取到一个模板中,避免重复定义,提高配置文件的可维护性和可读性。

# 语法
.base_template:
script:
- echo "Base script" job1:
extends: .base_template
script:
- echo "Extended script" # 示例:允许多层嵌套
.base-template:
image: alpine .common-template:
extends: .base-template
before_script:
- echo "Preparing environment..." build_job:
extends: .common-template
script:
- echo "Building the application..."
# 示例:合并配置
# 当任务继承模板时,GitLab 会合并模板和任务的配置。如果存在冲突,任务中的配置优先于模板中的配置
.common-template: &common-template
image: alpine
variables:
ENV: "production" build_job:
extends: .common-template
variables:
ENV: "development" # 覆盖模板中的变量
script:
- echo "Building with $ENV"
# 示例:继承多个模板
.base-image:
image: alpine .base-script:
before_script:
- echo "Preparing environment..." build_job:
extends:
- .base-image
- .base-script
script:
- echo "Building the application..."

模板名称通常以 . 开头(如 .common-template),表示它是一个隐藏的任务,不会被实际执行

如果模板和任务中有同名的配置项,任务中的配置优先级更高

extends 只能在同一个文件中使用。如果需要跨文件复用配置,可以结合 include 使用。

应避免在 extends 中形成循环依赖,否则会导致配置解析失败。

4.13 services:附加容器服务(如数据库、代理)

services 用于定义与任务关联的服务容器。这些服务容器通常用来运行数据库、缓存系统或其他依赖服务(如 Redis、PostgreSQL、MySQL 等),以便在 CI/CD 流水线中模拟真实的应用环境。

# 基本用法
job_name:
services:
- name: redis:6
alias: cache # 通过 alias 为服务指定一个自定义的主机名,方便任务访问
script:
- echo "Connecting to Redis at cache:6379"
# 示例:通过 variables 向服务容器传递环境变量,用于配置服务的行为
job_name:
services:
- name: mysql:8
alias: db
variables: # 设置 MySQL 的初始密码和数据库名称
MYSQL_ROOT_PASSWORD: "rootpassword"
MYSQL_DATABASE: "testdb"
script:
- echo "Connecting to MySQL at db:3306"
# 示例:启动 Redis 服务并测试连接
stages:
- build build_job:
stage: build
services:
- name: redis:6
alias: cache
script:
- apt-get update && apt-get install -y redis-tools
- redis-cli -h cache ping
# 示例:启动 MySQL 服务并列出数据库
stages:
- deploy deploy_job:
stage: deploy
services:
- name: mysql:8
alias: db
variables:
MYSQL_ROOT_PASSWORD: "rootpassword"
MYSQL_DATABASE: "testdb"
script:
- apt-get update && apt-get install -y mysql-client
- mysql -h db -uroot -prootpassword -e "SHOW DATABASES;"

注意:

服务容器会在任务开始时启动,并在任务结束时停止。如果任务失败,服务容器也会被销毁。

服务容器和任务容器共享同一个 Docker 网络,任务可以通过服务的主机名(或别名)访问服务。

某些服务需要特定的环境变量才能正常运行(如 MySQL 的 MYSQL_ROOT_PASSWORD),因此需要确保正确配置这些变量。

服务容器可能会占用额外的资源(CPU、内存等)。如果资源不足,流水线可能会失败。

services 主要适用于基于 Docker 的 Runner。如果使用其他类型的 Runner(如 Shell Runner),可能无法使用 services。

4.14 dependencies:控制任务之间依赖关系

dependencies 主要用于指定当前任务需要从哪些前置任务中下载 artifacts(制品)

默认情况下,GitLab 会自动下载所有前置任务的制品,但通过 dependencies,可以显式地定义需要下载哪些任务的制品,或者完全禁用制品下载。

# 语法
job_name:
dependencies:
- job1
- job2
# 示例:默认情况
build_job:
script:
- echo "Building..."
artifacts: # 由于未指定 dependencies,test_job 会自动下载 build_job 的制品(dist/)
paths:
- dist/ test_job:
script:
- echo "Testing..."
# 示例:使用 dependencies 显式指定需要下载制品的任务
build_job:
script:
- echo "Building..."
artifacts:
paths:
- dist/ another_job:
script:
- echo "Another job..." test_job:
dependencies: # test_job 只会下载 build_job 的制品,而不会下载 another_job 的制品
- build_job
script:
- echo "Testing with artifacts from build_job..."
# 示例:将 dependencies 设置为空数组表示,不下载任何制品
build_job:
script:
- echo "Building..."
artifacts:
paths:
- dist/ test_job: # test_job 不会下载任何制品
dependencies: []
script:
- echo "Testing without artifacts..."
# 示例:允许跨阶段引用其他任务的制品
stages:
- build
- test build_job:
stage: build
script:
- echo "Building..."
- mkdir dist && echo "Artifact" > dist/file.txt
artifacts:
paths:
- dist/ test_job:
stage: test
dependencies: # test_job 从 build_job 下载制品并读取内容
- build_job
script:
- cat dist/file.txt

注意:

制品只能从前置任务中下载,不能跨流水线或从后续任务中下载。

使用 dependencies 可以减少不必要的制品下载,从而提高流水线的执行效率。

dependencies 通常与 artifacts 和 stages 结合使用,实现更精细的依赖管理。

如果指定的任务没有生成制品,GitLab 会抛出错误。确保依赖的任务正确生成了制品。

参考:https://juejin.cn/post/6971013569986953223

GitLab CI/CD 的配置文件 .gitlab-ci.yml 简介的更多相关文章

  1. Gitlab+Gitlab-CI+Docker实现持续集成(CI)与持续部署(CD)

    写在前面 记录一下,一个自动化开发部署项目的构建过程与简单使用,实现真正的DevOps gitlab安装 步骤一:安装依赖 yum -y install git gcc glibc-static te ...

  2. 官网GitLab CI/CD英文文档翻译

    在查阅GitLab官网的CI/CD功能说明时,全是英文看起来不方便,通过翻译软件自动翻译后"内容失真",看起来很变扭.查阅了百度上的资料发现很多翻译很老旧,有些甚至是挂羊头卖狗肉. ...

  3. [转]gitlab ci/cd 发布

    转自 https://meigit.readthedocs.io/en/latest/configure_gitlab_i18n_and_create_gitlab_ci_with_gitlab_ru ...

  4. GitLab私有化部署 - CI/CD - 持续集成/交付/部署 - 源代码托管 & 自动化部署

    预期目标 源代码管理 借助GitLab实现源代码托管,私有化部署版本,创建项目,创建用户组,分配权限,项目的签入/牵出等. 自动化部署 源代码产生变更时(如签入),自动化编译并发布到指定服务器中部署, ...

  5. [转]GitLab Continuous Integration (GitLab CI/CD)

    本文转自:https://docs.gitlab.com/ee/ci/README.html GitLab Continuous Integration (GitLab CI/CD) The bene ...

  6. 前端初探 Gitlab CI/CD

    前言 纵观人类历史的发展以及三次工业革命,你会发现利用机器来替代部分人力劳动,将重复的工作自动化从而解放生产力都是发展的必然趋势,在软件工程领域也不例外,其中 CI/CD 就是其中一项,那么什么是 C ...

  7. Gitlab CI/CD

    Gitlab CI/CD 前言 纵观人类历史的发展以及三次工业革命,你会发现利用机器来替代部分人力劳动,将重复的工作自动化从而解放生产力都是发展的必然趋势,在软件工程领域也不例外,其中 CI/CD 就 ...

  8. 使用Gitlab的CI/CD功能自动化推送docker镜像到Nexus仓库出现的问题

    在服务器中可以直接使用命令行登录,推送docker镜像等 但是在使用Gitlab的CI/CD功能中,gitlab-ci.yml文件执行过程中出现如下错误: 原因分析: 服务器上之前使用命令行登陆过Ne ...

  9. Jenkins CI&CD 自动化发布项目实战(上篇)

    Jenkins CI&CD 自动化发布项目实战(上篇) 作者 刘畅 时间 2020-11-28 实验环境 centos7.5 主机名 ip 服务配置 软件 gitlab 172.16.1.71 ...

  10. 构建之法与CI/CD

    项目 内容 这个作业属于哪个课程 2021春季软件工程(罗杰 任健) 这个作业的要求在哪里 个人阅读作业2 我在这个课程的目标是 认识软工,拥抱软工,提升相关能力以便日后与其朝夕相伴 这个作业在哪个具 ...

随机推荐

  1. [大模型/AI/GPT] Chatbox:大模型可视化终端应用

    序 概述:Chatbox AI Chatbox AI 是一款 AI 客户端应用和智能助手,支持众多先进的 AI 模型和 API,可在 Windows.MacOS.Android.iOS.Linux 和 ...

  2. CentOS7安装RabbitMQ (安装包安装)

    环境: CentOS7 需要安装:erlang 22.2  rabbitmq 3.8.3 参考: rabbit官网地址:http://www.rabbitmq.com/which-erlang.htm ...

  3. TypeScript 中的 type 和 interface:你真的了解它们的不同吗?

    如果你有写过 Vue3 的项目,那么对 TypeScript 肯定不会陌生.不管是公司新项目技术选型还是个人学习开发新的前端项目,Vue3 + TypeScript 已经成为首选技术方案之一 在 Ty ...

  4. Ansible - [11] Roles

    前言 Q1:什么是Roles 在实际生产环境中,会编写大量的playbook文件来实现不同的功能.而且,每个playbook还可能会调用其他文件(变量文件),对于海量的.无规律的文件,管理是个问题.A ...

  5. 分布式锁—2.Redisson的可重入锁

    大纲 1.Redisson可重入锁RedissonLock概述 2.可重入锁源码之创建RedissonClient实例 3.可重入锁源码之lua脚本加锁逻辑 4.可重入锁源码之WatchDog维持加锁 ...

  6. 通过 C# 打印Word文档

    Word文档是日常办公和学习中不可或缺的一部分.比如在商务往来中,经常需要打印 Word 文档用于撰写和传递正式的商务信函.合作协议.项目提案等.打印出来的文档便于双方签字盖章,具有法律效力和正式性. ...

  7. 关闭 ReportCrash 进程防止CPU占用率过高 [MacBook]

    关闭 ReportCrash 的原因 自己 MacBook Pro 总是过载,机器很热.结果通过看进程 top 命令,看到 ReportCrash 占用了了过高的 CPU,而且好像我用不上.于是乎,得 ...

  8. 【Azure Fabric Service】分享使用Visual Studio 2022发布中国区Service Fabric服务应用的办法

    问题描述 使用Visual Studio 2022如何发布Service Fabric到中国区云服务呢? 因为使用VS2022中的插件无法创建Service Fabric Cluster服务. 那么, ...

  9. Docker swarm集群增加节点

    docker swarm初始化 docker swarm init docker swarm 增加节点 在已经初始化的机器上执行:# docker swarm join-token manager T ...

  10. verilog实现32位有符号流水乘法器

    verilog实现32位有符号流水乘法器 1.4bit乘法流程 1.无符号X无符号二进制乘法器 以下为4bit乘法器流程(2X6) 0 0 0 0 0 0 1 0 (2) X 0 0 0 0 0 1 ...