.gitlab-ci.yml 语法参考

配置文件放在仓库根目录(也可在 Settings → CI/CD → General pipelines 指定其他路径)。每次提交都会解析,语法问题用 Pipeline editor 在线校验。

顶层关键字

关键字作用
stages定义阶段及顺序
default所有 Job 的默认值(image/services/before_script/retry 等)
variables全局变量
workflow流水线级控制(是否创建 pipeline、全局名称)
include引入本地/跨项目/远程/官方模板/Component

Job 关键字速查

关键字作用
script必填,Job 执行的命令(数组逐行执行,任一非零退出即失败)
before_script / after_script前置/后置脚本;after_script 即使主脚本失败也会执行
image / servicesdocker executor 下的运行镜像与伴随服务(如 postgres)
stage所属阶段,默认 test
tags只由带这些 tag 的 Runner 执行
rules条件控制(推荐,取代 only/except)
needsDAG 依赖,可跨 stage 提前执行
dependencies控制下载哪些 Job 的 artifacts([] 表示不下载)
artifacts产物:paths/expire_in/reports/when
cache缓存:key/paths/policy
when执行时机:on_success(默认)/on_failure/always/manual/delayed
allow_failure失败不阻断流水线(MR 页显示橙色警告)
retry失败自动重试,可配 when: [runner_system_failure] 等条件
timeoutJob 级超时
parallel:matrix变量矩阵,一个 Job 展开为多个并行实例
environment部署目标环境(配合 Environments 审计与回滚)
trigger触发子流水线/多项目流水线
interruptible新提交到来时可被自动取消
resource_group互斥锁,保证同环境部署串行
id_tokens / secretsOIDC JWT / 外部密钥管理(Vault)集成

rules:条件控制

按顺序匹配,第一条命中即生效:

deploy-prod:
  script: ./deploy.sh
  rules:
    - if: $CI_COMMIT_TAG                    # tag 推送才部署
    - if: $CI_COMMIT_BRANCH == "main"
      when: manual                          # main 分支手动触发
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
      when: never                           # MR 流水线里不跑
    - changes:
        - "src/**/*.go"                     # 仅这些文件变化时
    - exists:
        - Dockerfile                        # 仓库存在该文件时
  • if 支持变量表达式、&& / ||、=~ 正则匹配
  • when: never 常用于排除场景
  • allow_failure、variables 可在单条 rule 内覆盖

workflow:rules:控制是否生成流水线

经典配方——避免「分支 pipeline + MR pipeline」重复跑:

workflow:
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
    - if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS
      when: never
    - if: $CI_COMMIT_BRANCH

needs 与 dependencies

stages: [build, test, deploy]
 
build-app:
  stage: build
  script: make build
  artifacts:
    paths: [dist/]
 
integration-test:
  stage: test
  needs:
    - job: build-app
      artifacts: true        # 只依赖 build-app,test 阶段一开始就能跑
 
deploy:
  stage: deploy
  needs: [build-app]
  dependencies: []           # 只要执行顺序,不下载产物
  script: ./deploy.sh
  • needs 决定执行顺序(DAG),可跨 stage 生效
  • dependencies 决定下载谁的 artifacts,不影响顺序

include 与复用

include:
  - local: '/ci/docker-build.yml'                       # 本仓库文件
  - project: mygroup/ci-templates                       # 跨项目
    file: '/ci/templates/deploy.yml'
    ref: main
  - remote: 'https://example.com/ci/common.yml'
  - template: Security/SAST.gitlab-ci.yml               # 官方模板
  - component: gitlab.com/myorg/components/build@1.0.0  # CI/CD Component,可带 inputs

extends 做 Job 级继承:

.base-test:
  image: golang:1.24
  before_script:
    - go mod download
 
unit-test:
  extends: .base-test
  script: go test ./...

以 . 开头的 Job 名是隐藏 Job,不会执行,适合当模板基类。

parallel:matrix

test:
  script: ./run-tests.sh $DB $VERSION
  parallel:
    matrix:
      - DB: [mysql, postgres]
        VERSION: ["15", "16"]

展开为 2×2 = 4 个并行 Job。

完整注释示例

stages: [lint, test, build, deploy]
 
default:
  image: golang:1.24
  interruptible: true
 
variables:
  GOPROXY: https://goproxy.cn,direct
 
lint:
  stage: lint
  script: golangci-lint run
 
test:
  stage: test
  script: go test -coverprofile=cover.out ./...
  artifacts:
    reports:
      coverage_report:
        coverage_format: cobertura
        path: coverage.xml
  coverage: '/total:\s+\(statements\)\s+(\d+.\d+)%/'
 
build:
  stage: build
  needs: [test]
  script: go build -o app ./cmd/app
  artifacts:
    paths: [app]
    expire_in: 1 day
 
deploy-staging:
  stage: deploy
  image: bitnami/kubectl:latest
  needs: [build]
  environment:
    name: staging
    url: https://staging.example.com
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
  script:
    - kubectl apply -k deploy/staging/

相关