GitLab CI/CD学习教程(第四章gitlab-ci.yml)
🚀从零开始,结合具体场景和示例,让你彻底掌握 GitLab CI/CD 的配置!

目录
1 定义
⭐ 什么是.gitlab-ci.yml
在上一章节中,我们详细讲述了Pipeline的定义,本章节将重点讲解如何对Pipeline进行精细化的控制。
.gitlab-ci.yml
文件是 GitLab CI/CD 管道的配置文件。它以 YAML 格式定义了流水线(Pipeline)的各个阶段(stages)和任务(jobs)。每当你向 GitLab 仓库提交代码时,GitLab 会根据 .gitlab-ci.yml
文件自动执行预定的任务。
2 基础语法
.gitlab-ci.yml
配置文件使用的是 YAML语法,规则十分简单,是一种简洁的数据序列化语言,主要特点是可读性强,并且支持层级结构。
- 🧤 缩进
用
空格
(不能用 Tab),通常用 2 个空格缩进。 - 🎎 键值对
配置项是由键
key
和值value
组成的。例如:stages: [build, test, deploy] - 📊 列表
用
-
表示列表项 - ⚙ 多行脚本
用
|
或>
(保留换行/折叠换行) - 💬 注释
以
#
开头的行表示注释,GitLab CI/CD 会忽略这些行。
3 关键配置项
项目 | 类型 | 作用 | 示例 |
---|---|---|---|
workflow | Object | 用于控制整个 CI/CD 流水线的行为。 (定义全局规则,比如是否启用流水线、如何调度流水线的执行等) (通常与rules结合使用) |
workflow: rules: - if: '$CI_COMMIT_TAG #仅当打标签时触发整个流水线 |
variables | 键值对 key-value |
定义了在 CI/CD 流水线中使用的环境变量。 | variables: version: 1.0.0.0 description: xxx |
stages | Array | 定义了流水线的所有阶段,并指定这些阶段的执行顺序 | stages: - build - test - deploy |
jobs | Object | 具体执行的任务,每个任务定义了一个独立的操作。 任务通常包括以下配置项:
|
job1: stage: build script: - echo “Running job1” |
stage | String | 指定任务属于哪个阶段。 (必须在 stages 中定义) |
job1: stage: build # 该作业属于build阶段 |
script | Array 或 String |
定义任务执行的实际命令。 (比如打印一句话) |
script: - echo “Running tests…” |
before_script | Array 或 String |
定义在每个任务之前执行的脚本。 (常用于设置公共的执行步骤,安装依赖等) |
before_script: - $scriptPath = " $env:CI_PROJECT_DIR\test.py" if (-not (Test-Path $scriptPath)) { Write-Error “错误:Python脚本不存在于 $scriptPath” exit 1 } python $scriptPath |
after_script | Array 或 String |
定义在每个任务之后执行的脚本。 (常用于清理操作、记录日志等) |
after_script: - echo “运行结束” |
artifacts | Object | 用于指定在job执行完成后需要保存的文件或目录。 (这些文件将在后续作业或流水线运行中可用。) |
artifacts: paths: - build/ expire_in: 30 minute # 30分钟后过期 |
timeout | String | 设置作业的超时时间。 (超出这个时间作业会被强制终止。) |
job1: timeout: 60 minutes |
interruptible | Boolean | 是否允许中断当前作业。 (通常用于节省资源。) |
job1: interruptible: true |
allow_failure | Boolean | 是否允许任务失败。 (如果设置为 true,即使任务失败,流水线会继续执行) |
job1: interruptible: true |
needs | Array | 每个阶段内的作业默认是并行执行的,除非使用 needs 显式声明依赖关系。 | job1: script: - eho “Running job1” job2: script: - eho “Running job2” needs: job1 |
only except |
Array | only 定义job应该在哪些分支或事件下执行 except 定义job不应该在哪些情况下执行 (控制任务的触发条件) |
job1: only: - main # main分支才会触发 |
when | Object | 定义作业的执行时机。 常用的值包括:
|
job1: when: manual |
rules | Array 或 Object |
替代 only 和 except 的更灵活的条件控制方法。 常用选项:
|
rules: - if: ‘$ CI_COMMIT_BRANCH’==main when: manual - if: ‘$CI_COMMIT_TAG’ |
image | String | 用于指定一个 Docker 镜像,镜像将在执行作业时被拉取和使用。 | image: node:14 |
services | Array | 用于定义与作业一起运行的其他 Docker 容器(服务)。 (这些服务通常是数据库、缓存或其他依赖服务。) |
services: - mysql:5.7 |
这里需要对only和when区别作一个详细的解释。(PS: 建议使用rules,它更强大和灵活)
- 意图:only 更侧重于指定作业应该在哪种类型的变更(如特定分支或标签)上运行;而 when 则关注于作业在整个管道流程中的执行策略。
- 灵活性:虽然两者都能影响作业是否执行,但是 when 提供了关于作业执行时机的更多选项,并且可以结合其他条件(例如通过 rules)来实现更为复杂的逻辑。
4 预定义变量
预定义变量在流水线执行的三个不同阶段可用:
- 预流水线:预流水线变量在创建流水线之前可用。这些变量是仅使用 include:rules 来控制在创建流水线时要使用哪些配置文件。
- 流水线:这些变量在流水线创建时可用。除了预流水线变量外,流水线- 变量还可以用于配置在作业中定义的 rules ,以确定要添加到流水线中的哪些作业。
- 仅作业:这些变量仅在 runner 选择作业并运行作业时为每个作业可用。
常用的预定义变量: (更多其他变量请查阅官方文档)
🎎 变量 | 🎨 描述 |
---|---|
CI_COMMIT_AUTHOR | Name 格式的提交作者。 |
CI_COMMIT_BEFORE_SHA | 出现在分支或标签上的上一个最新提交。在合并请求的流水线中总是 0000000000000000000000000000000000000000。 |
CI_COMMIT_BRANCH | 提交分支名称。在分支流水线中可用,包括默认分支的流水线。在合并请求流水线或标签流水线中不可用。 |
CI_COMMIT_DESCRIPTION | 提交的描述。如果标题短于 100 个字符,则消息没有第一行。 |
CI_COMMIT_MESSAGE | 完整的提交消息。 |
CI_COMMIT_REF_NAME | 为其构建项目的分支或标签名称。 |
CI_COMMIT_SHORT_SHA | CI_COMMIT_SHA 的前八个字符。 |
CI_COMMIT_TAG | 提交标签名称。仅在标签流水线中可用。 |
CI_COMMIT_TAG_MESSAGE | 提交标签消息。仅在标签流水线中可用。 |
CI_COMMIT_TIMESTAMP | ISO 8601 格式的提交时间戳。 |
CI_COMMIT_TITLE | 提交的标题。消息的完整第一行。 |
CI_CONFIG_PATH | CI/CD 配置文件的路径。默认为.gitlab-ci.yml。在正在运行的流水线中只读。 |
CI_RELEASE_DESCRIPTION | 发布的描述。仅在标签流水线上可用。描述长度限制为前 1024 个字符。 |
CI_JOB_IMAGE | 运行作业的 Docker 镜像的名称。 |
CI_JOB_NAME | 作业名称 |
CI_JOB_STAGE | 作业阶段名称。 |
CI_JOB_STATUS | 执行每个 runner 阶段时的作业状态。与 after_script 一起使用。可以是 success、failed 或 canceled。 |
CI_PIPELINE_SOURCE | 流水线是如何触发的。可以是 push、web、schedule、api、external、chat、webide、merge_request_event、external_pull_request_event、parent_pipeline、trigger 或 pipeline 。 |
CI_PIPELINE_NAME | workflow:name 中定义的名称。 |
CI_PROJECT_ID | 当前项目的 ID。该 ID 在实例上的所有项目中都是唯一的。 |
CI_PROJECT_NAME | 项目目录的名称。例如,如果项目 URL 是 gitlab.example.com/group-name/project-1,则 CI_PROJECT_NAME 是 project-1。 |
CI_PROJECT_NAMESPACE | 作业的项目命名空间(用户名或群组名)。 |
CI_PROJECT_NAMESPACE_ID | 作业的项目命名空间 ID。 |
CI_PROJECT_PATH | 包含项目名称的项目命名空间。 |
CI_PROJECT_ROOT_NAMESPACE | 作业的根项目命名空间(用户名或群组名)。例如,如果 CI_PROJECT_NAMESPACE 是 root-group/child-group/grandchild-group,则 CI_PROJECT_ROOT_NAMESPACE 是 root-group。 |
CI_PROJECT_TITLE | Web 界面中显示的人类可读的项目名称。 |
CI_PROJECT_DESCRIPTION | Web 界面中显示的项目描述。 |
CI_PROJECT_URL | 项目的 HTTP(S) 地址。 |
CI_PROJECT_VISIBILITY | 项目可见性。可以是 internal、private 或 public。 |
CI_REPOSITORY_URL | 克隆 Git 仓库的 URL。 |
GITLAB_USER_EMAIL | 启动流水线的用户的电子邮件,除非作业是手动作业。在手动作业中,该值是启动作业的用户的电子邮件。 |
GITLAB_USER_ID | 启动流水线的用户的 ID,除非作业是手动作业。在手动作业中,该值是启动作业的用户的 ID。 |
GITLAB_USER_LOGIN | 启动流水线的用户的用户名,除非作业是手动作业。在手动作业中,该值是启动作业的用户的用户名。 |
GITLAB_USER_NAME | 启动流水线的用户的姓名,除非作业是手动作业。在手动作业中,该值是启动作业的用户的姓名。 |
5 简单示例
5.1 Vue.js 项目
image: node:18
stages:
- install
- build
- deploy
cache:
key: $CI_COMMIT_REF_SLUG
paths:
- node_modules/
install-deps:
stage: install
script:
- npm ci
only:
- main
build-prod:
stage: build
script:
- npm run build
artifacts:
paths:
- dist/
deploy-s3:
stage: deploy
image: amazon/aws-cli:latest
script:
- aws s3 sync dist/ s3://my-bucket/ --delete
only:
- main
5.2 Python Django 项目
image: python:3.10
stages:
- test
services:
- postgres:13
variables:
POSTGRES_DB: mydb
POSTGRES_USER: runner
POSTGRES_PASSWORD: ""
DATABASE_URL: "postgres://runner:@postgres:5432/mydb"
test:
stage: test
before_script:
- pip install -r requirements.txt
- python manage.py migrate
script:
- pytest --cov=.
coverage: '/^TOTAL.+?(\d+\%)$/'
5.3 Qt/C++ 项目(Windows + shell环境)
# 包含共享配置
include:
- local: '/.ci-templates/variables.yml' # 共享变量定义
# 定义工作流规则
workflow:
rules:
- if: '$CI_COMMIT_TAG' # 标签提交触发完整流水线
variables:
DEPLOY_ENV: "production"
- if: '$CI_COMMIT_BRANCH == "main"' # main分支触发构建、测试、打包
variables:
DEPLOY_ENV: "staging"
- when: manual # 允许手动触发
# 全局配置
variables:
QT_ROOT: "C:\\Qt"
QIFW_BIN: "C:\\Qt\\Tools\\QtInstallerFramework\\4.6\\bin"
BUILD_SCRIPT: "scripts/build.py"
PACKAGE_SCRIPT: "scripts/package.py"
RELEASE_SCRIPT: "scripts/release.py"
# 阶段定义
stages:
- prepare
- build
- test
- package
- release
# 公共before_script
before_script:
- echo "Running on $CI_RUNNER_DESCRIPTION"
- python --version
- pip install -r requirements-ci.txt
- export ARTIFACTS_DIR="$CI_PROJECT_DIR/artifacts"
- mkdir -p $ARTIFACTS_DIR
# 公共after_script
after_script:
- echo "Cleaning temporary files..."
- rm -rf tmp_build
# 准备阶段
prepare-env:
stage: prepare
rules:
- if: '$DEPLOY_ENV == "production" || $DEPLOY_ENV == "staging"'
script:
- python $BUILD_SCRIPT prepare
--qt-version 5.15.2
--platform win64
--output-dir $ARTIFACTS_DIR
artifacts:
paths:
- $ARTIFACTS_DIR/qt_env.bat
expire_in: 1h
# 并行构建任务
build-windows:
stage: build
needs: ["prepare-env"] # 显式声明依赖
parallel: 2 # 并行构建两个配置
rules:
- if: '$DEPLOY_ENV == "production"'
variables:
BUILD_TYPE: "release"
- if: '$DEPLOY_ENV == "staging"'
variables:
BUILD_TYPE: "debug"
script:
- call $ARTIFACTS_DIR/qt_env.bat
- python $BUILD_SCRIPT compile
--type $BUILD_TYPE
--jobs 4
--output $ARTIFACTS_DIR/$BUILD_TYPE
artifacts:
paths:
- $ARTIFACTS_DIR/$BUILD_TYPE/**
reports:
dotenv: $ARTIFACTS_DIR/build_info.env
# 测试阶段
run-tests:
stage: test
needs:
- job: build-windows
artifacts: true
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
script:
- python -m pytest tests/ -v --junitxml=test-results.xml
- python $BUILD_SCRIPT analyze-coverage
--input build/coverage
--output $ARTIFACTS_DIR/coverage_report.html
artifacts:
paths:
- test-results.xml
- $ARTIFACTS_DIR/coverage_report.html
reports:
junit: test-results.xml
# 打包阶段
create-installer:
stage: package
needs:
- build-windows
- run-tests
rules:
- if: '$DEPLOY_ENV == "production"'
script:
- python $PACKAGE_SCRIPT
--config installer/windows/config.xml
--source $ARTIFACTS_DIR/release
--output $ARTIFACTS_DIR/installer
--tool-path $QIFW_BIN
artifacts:
paths:
- $ARTIFACTS_DIR/installer/*.exe
expire_in: 1 week
# 发布阶段
deploy-release:
stage: release
needs: ["create-installer"]
rules:
- if: '$CI_COMMIT_TAG != null'
script:
- python $RELEASE_SCRIPT
--tag $CI_COMMIT_TAG
--artifact $ARTIFACTS_DIR/installer/*.exe
--changelog changelog.md
environment:
name: production
url: https://downloads.example.com
# 安全扫描(动态包含)
include:
- template: Security/SAST.gitlab-ci.yml
上一篇:《GitLab CI/CD学习教程 第三章Pipeline》
下一篇:《GitLab CI/CD学习教程 第五章高级示例》正在编写中…