.gitlab-ci.yml 结构详解:全局关键字、默认段、预定义变量、include 和 trigger
.gitlab-ci.yml 是 GitLab CI/CD 的单一配置入口,决定了后台任务集成测试从触发、编译、模拟到测试报告归档的完整流程。本章从顶层结构出发,拆解全局关键字、默认段、预定义变量、include 和 trigger 这 5 个核心模块,并建立它们在多项目、多环境场景下的协作关系。只有准确理解这一骨架,后续章节的阶段、作业、artifacts 和测试编排才可能可靠运行。
1. 全局关键字与配置骨架
全局关键字位于 .gitlab-ci.yml 的根层级,直接控制管道的全局行为。下表列出后台任务集成测试中最常用的全局关键字:
| 关键字 | 作用 | 集成测试常用值 |
|---|---|---|
stages | 定义流水线阶段及其执行顺序 | |
variables | 设置所有作业可见的全局变量 | |
cache | 缓存依赖(如 Maven .m2、npm node_modules) | |
before_script | 每个作业执行前运行的公共命令 | |
after_script | 每个作业执行后运行的清理命令 | |
default | 为作业设置默认值 | 见下一节 |
stages 应严格遵循 build → test → test-report ↔ deploy 的顺序。全局 variables 用于定义数据库连接串、测试超时阈值等环境常量,避免在每个作业中重复。2. default 段:统一作业默认行为
default 关键字允许为所有作业指定共享默认值,降低重复配置。单个作业可通过同名关键字覆盖这些默认值。
default:
before_script:
- echo "Running CI for project $CI_PROJECT_NAME"
after_script:
- echo "Cleaning up temporary files"
image: registry.example.com/base-test-image:latest
tags:
- docker-runner
timeout: 30 minutes
覆盖规则:作业内定义的同名关键字(如 before_script)会完全替换 default 段的值,而非合并。若希望追加默认命令,需在作业内显式引用默认值(目前不直接支持,推荐使用 YAML 锚点)。
default 中定义 variables 会被作业级变量覆盖,但若作业未定义同名变量,则使用 default 值。然而,variables 的优先级:作业级 > default > 全局变量 > 预定义变量。3. 预定义变量:CI/CD 环境自省
GitLab 自动注入约 80 个预定义变量,在集成测试中可用于区分环境、传递凭证、控制分支行为。以下为必知变量:
| 变量名 | 含义 | 集成测试应用 |
|---|---|---|
CI_PIPELINE_ID | 当前流水线唯一 ID | 测试报告命名、数据库 schema 隔离 |
CI_COMMIT_SHA | 当前构建的 commit SHA | 测试覆盖率快照标识 |
CI_COMMIT_REF_NAME | 分支或标签名 | 仅在 master 分支执行完整回归测试 |
CI_JOB_ID | 当前作业 ID | 并行测试产物隔离 |
CI_API_V4_URL | GitLab API V4 地址 | 通过 API 上传测试结果 |
CI_REGISTRY_IMAGE | 项目容器镜像 registry 路径 | 推测试容器镜像 |
在 variables 中可直接引用预定义变量:
variables:
REPORT_PATH: "test-reports/${CI_PIPELINE_ID}/"
DATABASE_NAME: "test_${CI_JOB_ID}"
script 中添加 env | grep CI_ 可输出所有 CI 预定义变量,便于排查变量未定义或取值错误。4. include 关键字:模块化与模板复用
include 允许将一个或多个外部 YAML 文件合并到主配置中,是实现跨项目模板和阶段拆分的核心手段。支持 4 种源:
| 类型 | 示例 | 适用场景 |
|---|---|---|
local | | 同一仓库内拆分多文件 |
file | | 跨项目共享通用阶段 |
remote | | 引用第三方维护的模板 |
template | | 使用 GitLab 官方预置模板 |
合并规则:多个 include 按数组中出现的顺序依次合并,后包含的文件会覆盖前文件的同名键。但作业内定义的键始终高于 include 引入的值。
# .gitlab-ci.yml
include:
- local: '/ci/base-env.yml' # 定义全局变量、default
- file: 'templates/integration-test.yml' # 定义集成测试作业
project: 'shared/qa-tools'
- template: Jobs/Code-Quality.gitlab-ci.yml
stages:
- build
- test
- quality
my-build:
stage: build
script:
- make build
include 文件路径写错时,管道在启动阶段即报错 Included file ... does not have a valid YAML syntax。可先在本地用 gitlab-ci-validate 验证。另外,include 不支持循环引用。5. trigger:跨管道集成测试
trigger 关键字用于在当前管道中触发下游管道,是实现多项目集成测试的利器。典型场景:微服务 A 变更后,自动触发服务 B 和 C 的测试管道。
trigger-service-b:
stage: integration
trigger:
project: team-b/service-b
branch: main
strategy: depend # 等待下游管道完成
trigger-service-c:
stage: integration
trigger:
project: team-c/service-c
branch: feature/${CI_COMMIT_REF_NAME}
forward:
pipeline_variables: true # 将当前管道变量传递给下游
传递变量:可通过 variables 关键字显式传给下游,或使用 forward:pipeline_variables 全局传递。
trigger-service-b:
trigger:
project: team-b/service-b
variables:
PARENT_CI_JOB_ID: $CI_JOB_ID
TEST_TAG: regression
下游管道成功/失败状态会被反映到当前作业。集成测试场景中,常将 trigger 作业与 needs 结合,实现事件驱动的并行测试。
6. 结构关系概览:全局关键字、default、预定义变量、include、trigger 的协作
7. 调试与常见错误
| 错误现象 | 可能原因 | 排查方法 |
|---|---|---|
Included file is empty or invalid | include 路径错误、远程 URL 不可达 | 本地用 curl -o- {url} 测试;使用 CI/CD > Pipelines > CI Lint 校验 |
作业未继承 default 中的 before_script | 作业内显式定义了 before_script(完全覆盖) | 检查作业内是否出现 before_script 关键字 |
触发下游管道失败:404 | 下游项目不存在或当前用户无访问权限 | 确认 project 路径正确, 或 CI_JOB_ 有该项目的访问权限 |
| 预定义变量取值为空 | 变量名拼写错误或访问时未处于对应上下文 | 在作业内添加 echo "CI_JOB_STAGE: $CI_JOB_STAGE" 检查 |
全局 cache 不生效 | runner 配置中 GIT_STRATEGY: none 或使用了 ephemeral 卷 | 检查 runner 日志;确认作业中未覆盖 cache: {} |
# 本地验证(需要 gitlab-ctl 或 CI lint API)
curl --header "PRIVATE-: $YOUR_" \
--header "Content-Type: application/json" \
--data '{"content": "'"$(cat .gitlab-ci.yml | base64 -w 0)"'"}' \
"https://gitlab.example.com/api/v4/ci/lint?include_merged_yaml=true" | jq .
8. 性能与稳定性优化建议
- 精简
include数量:每增加一个远程include文件,管道初始化时间约增加 200~500ms。将频繁使用的公共配置合并为 2~3 个大模板。 - 善用
default而非在每个作业重复:减少 YAML 解析体积,也降低人为漏写风险。 - 预定义变量替代硬编码:在
before_script中引用CI_JOB_进行 API 调用,避免明文 泄露。 - 条件触发下游管道:结合
rules或only/except,仅在非 WIP、特定目录变更时执行trigger,减少不必要的跨项目测试。 - 启用
parallel与needs:多个include引入的测试作业若相互独立,可并行执行,加速集成反馈。