.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. 常见错误与解决方案

错误现象原因解决方案
流水线一直处于 pendingRunner 不匹配 tag 或未在线检查作业是否设置了 tags,且对应 Runner 存在
YAML 解析错误:mapping values are not allowed here缩进使用了 Tab 或冒号后缺少空格强制使用空格缩进,冒号后加一个空格
作业名称冲突存在两个同名作业使用唯一名称或集成 parallel 属性
变量未生效变量定义在作业内但作用域错误全局变量放在顶层,作业变量放在作业内

下面通过一张结构图直观展示 .gitlab-ci.yml 各元素的层级关系:

GitLab CI YAML 结构图 .gitlab-ci.yml stages(阶段) job(作业) 全局配置 build test build-job script(脚本) variables before_script cache / default 说明:每个作业必须关联一个阶段(默认 test),阶段顺序由stages列表决定。 全局配置作用于所有作业,作业内同名配置会覆盖全局配置。