.gitlab-ci.yml 基础结构:定义阶段、作业、脚本、全局配置
GitLab CI 使用项目根目录下的 .gitlab-ci.yml 文件描述整个持续集成流水线。该文件采用 YAML 格式,核心要素包括:阶段(stages)、作业(jobs)、脚本(script) 以及 全局配置。理解这四个元素的组织关系,是编写可靠流水线的第一步。
原理:流水线由多个顺序执行的阶段组成,每个阶段包含一个或多个并行运行的作业,作业通过脚本执行具体命令。全局配置为所有作业提供共享环境与行为。
1. 核心元素一览
| 元素 | 关键字 | 作用 | 是否必填 |
|---|---|---|---|
| 阶段列表 | stages | 定义流水线的执行顺序 | 否(默认有 build、test、deploy) |
| 作业 | 自定义名称(如 build-job) | 定义一组任务及其所属阶段 | 是(至少一个) |
| 脚本 | script | 作业要执行的命令序列 | 是 |
| 全局变量 | variables | 设置所有作业共享的环境变量 | 否 |
| 前置脚本 | before_script | 每个作业执行前运行的脚本 | 否 |
| 后置脚本 | after_script | 每个作业执行后运行的脚本 | 否 |
| 缓存 | cache | 跨作业和流水线共享文件 | 否 |
2. 阶段(stages)
阶段决定了作业的执行顺序。默认阶段顺序为 build → test → deploy,可通过 stages 关键字自定义并调整顺序。同一阶段的作业并行执行,只有所有作业成功,流水线才进入下一阶段。
stages:
- build
- test
- deploy
如果
stages 未定义,所有作业会被放入默认的 test 阶段并并行执行,这可能导致非预期的依赖失败。3. 作业(jobs)
每个作业必须包含 script,并可指定 stage(默认 test)、only/except、when 等控制属性。作业名称不能包含特殊字符,推荐使用连字符连接。
build-job:
stage: build
script:
- echo "Building project..."
- make
test-job:
stage: test
script:
- echo "Running tests..."
- make test
4. 脚本(script)
script 是作业的核心,可以包含一条或多条命令。每条命令在独立的 shell 中执行(除非使用 | 多行块)。GitLab Runner 会依次执行,若某条命令返回非零退出码,作业即标记为失败。
lint-job:
stage: test
script:
- npm install
- npm run lint
常见错误:脚本中使用了交互式命令(如
read、vim)或未设置非零退出码处理,导致作业挂起或误报成功。5. 全局配置
全局配置作用于所有作业,常见的有:
variables— 全局环境变量before_script— 每个作业前执行(可被作业内同名覆盖)after_script— 每个作业后执行(即使作业失败也会运行)cache— 缓存依赖以加速后续作业default— 为所有作业设置默认值(如image、tags)
variables:
APP_ENV: "ci"
NODE_ENV: "test"
before_script:
- echo "Starting job for ${APP_ENV}"
after_script:
- echo "Job finished"
cache:
paths:
- node_modules/
default:
image: node:18-alpine
6. 完整示例
stages:
- build
- test
- deploy
variables:
COMMON_VAR: "shared"
before_script:
- echo "Preparing environment"
build:
stage: build
script:
- npm install
- npm run build
test:
stage: test
script:
- npm test
after_script:
- echo "Cleaning test artefacts"
deploy:
stage: deploy
script:
- npm run deploy
only:
- main
7. 调试与验证
编写 .gitlab-ci.yml 后,务必使用 GitLab CI Lint 工具验证语法:在项目页面左侧菜单进入 CI/CD → Pipelines → CI Lint,或通过 API 调用。常见调试手段:
- 对复杂脚本使用
echo输出中间变量值。 - 使用
jobs:output查看作业日志中的退出码。 - 在全局或作业内设置
FF_功能标志。
# 通过 API 验证
curl --header "PRIVATE-: " \
"https://gitlab.example.com/api/v4/ci/lint" \
--data '{"content": "stages:\n - build\n - test\n..."}'
8. 常见错误与解决方案
| 错误现象 | 原因 | 解决方案 |
|---|---|---|
流水线一直处于 pending | Runner 不匹配 tag 或未在线 | 检查作业是否设置了 tags,且对应 Runner 存在 |
YAML 解析错误:mapping values are not allowed here | 缩进使用了 Tab 或冒号后缺少空格 | 强制使用空格缩进,冒号后加一个空格 |
| 作业名称冲突 | 存在两个同名作业 | 使用唯一名称或集成 parallel 属性 |
| 变量未生效 | 变量定义在作业内但作用域错误 | 全局变量放在顶层,作业变量放在作业内 |
下面通过一张结构图直观展示 .gitlab-ci.yml 各元素的层级关系: