GitLab CI/CD 基础:.gitlab-ci.yml 流水线实践
FreeGuideOnline
最新
2026-06-13
GitLab CI/CD 基础:.gitlab-ci.yml 流水线实践
什么是 GitLab CI/CD
GitLab CI/CD 是 GitLab 内置的持续集成、持续交付与部署工具。只需在仓库根目录创建一个名为 .gitlab-ci.yml 的文件,GitLab 就会自动检测并运行其中定义的流水线(Pipeline)。不需要安装第三方插件或服务,配置即用,适合从个人项目到企业级应用的各种场景。
流水线的核心概念:
- Pipeline(流水线):由阶段和作业组成的自动化过程。
- Stage(阶段):流水线中的一个逻辑分组,例如
build、test、deploy。 - Job(作业):具体执行的任务,每个作业属于某一个阶段,可以运行脚本、编译代码、运行测试等。
- Runner(运行器):实际执行作业的代理,可以是 GitLab 共享的 Runner,或是自行部署的专用 Runner。
.gitlab-ci.yml 文件结构与基础关键字
.gitlab-ci.yml 使用 YAML 格式编写,必须放在仓库根目录。一个最小化的流水线文件如下:
stages:
- build
- test
build-job:
stage: build
script:
- echo "Compiling the code..."
- gcc hello.c -o hello
test-job:
stage: test
script:
- echo "Running tests..."
- ./hello
核心关键字解释
| 关键字 | 说明 |
|---|---|
stages |
定义流水线中的阶段列表,按顺序执行。同一阶段的作业可并行运行,前一个阶段全部成功后才会开始下一阶段。 |
stage |
指定当前作业属于哪个阶段。 |
script |
作业要执行的命令,可以是一系列 shell 命令。这是作业的必填项(除 trigger 等特殊作业外)。 |
before_script |
在 script 之前运行的命令,通常用于安装依赖或设置环境。可定义在全局或单个作业中。 |
after_script |
在 script 之后运行的命令,即使 script 失败也会执行。 |
variables |
定义环境变量,可在全局或作业内声明。 |
only / except |
控制作业在何时触发(基于分支名、标签等)。新版推荐用 rules 替代。 |
rules |
更灵活的条件控制,可基于分支、变量、文件变化等决定是否执行作业。 |
tags |
指定运行该作业的 Runner 标签,用于匹配特定 Runner。 |
image |
用于作业的 Docker 镜像,例如 image: node:18。 |
services |
启用的额外服务容器,如数据库。 |
artifacts |
定义要保留并传递给后续作业的文件或目录。 |
dependencies |
控制当前作业只依赖哪些上游作业的产物。 |
needs |
定义作业之间的依赖关系,可创建跨阶段的并行依赖结构(DAG 流水线)。 |
cache |
缓存依赖或编译结果,加快后续流水线速度。 |
when |
控制作业何时运行:on_success(默认)、on_failure、always、manual、delayed 等。 |
environment |
关联部署环境名称和 URL,用于监控和回滚。 |
include |
引用外部 YAML 文件,实现配置复用。 |
从零开始:构建一个多阶段流水线
下面以一个 Node.js 项目为例,展示从安装依赖、测试、构建到部署到测试环境的完整流程。
1. 项目结构假设
my-app/
.gitlab-ci.yml
package.json
src/
tests/
2. 编写 .gitlab-ci.yml
# 全局默认镜像
image: node:18-alpine
# 定义阶段
stages:
- install
- test
- build
- deploy
# 全局缓存配置:缓存 node_modules
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- node_modules/
# 安装依赖作业
install-deps:
stage: install
script:
- npm ci
artifacts:
paths:
- node_modules/
expire_in: 1 hour
# 代码质量检查(并行于测试)
lint:
stage: test
script:
- npm run lint
needs:
- install-deps
# 单元测试作业
unit-test:
stage: test
script:
- npm run test
coverage: '/All files[^|]*\|[^|]*\s+([\d\.]+)/'
artifacts:
when: always
reports:
junit: test-results.xml
coverage_report:
coverage_format: cobertura
path: coverage/cobertura-coverage.xml
needs:
- install-deps
# 构建作业
build-app:
stage: build
script:
- npm run build
artifacts:
paths:
- dist/
expire_in: 1 week
needs:
- install-deps
# 部署到测试环境(手动触发)
deploy-staging:
stage: deploy
script:
- echo "Deploying to staging server..."
- rsync -av dist/ user@staging-server:/var/www/app
environment:
name: staging
url: https://staging.my-app.com
when: manual
only:
- main
needs:
- build-app
3. 配置解读
image: node:18-alpine指定所有作业默认使用的轻量 Docker 镜像。cache通过分支名缓存node_modules,避免每次重新下载依赖,但缓存不会跨分支污染。install-deps使用npm ci严格依照 lock 文件安装依赖,并将node_modules设为制品供后续作业使用。needs关键字让lint和unit-test不必等待整个阶段完成,只要依赖的作业完成即可开始,实现更快的并行。unit-test中的coverage使用正则从测试输出中提取覆盖率并展示在合并请求中。artifacts将测试报告上传为 GitLab 可解析的格式,用于合并请求中的测试和覆盖率视图。deploy-staging作业设置为when: manual,需要手动点击触发;environment设置使其在“环境”页面中可跟踪部署历史和回滚。
条件控制与最佳实践
使用 rules 精确控制作业触发
推荐用 rules 代替旧的 only/except。例如,仅在合并请求或主分支上运行部署:
deploy-production:
stage: deploy
script: ./deploy-prod.sh
rules:
- if: $CI_COMMIT_BRANCH == "main"
when: manual
- when: never
更复杂的规则可以结合变量、文件变化等:
run-e2e-tests:
stage: test
script: npm run e2e
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- changes:
- tests/**/*
when: on_success
环境变量管理
敏感信息(如密码、密钥)应在 GitLab 项目的 Settings > CI/CD > Variables 中设置,然后在 .gitlab-ci.yml 中通过 $VARIABLE_NAME 引用。将变量标记为 Masked 和 Protected 以增强安全性。
示例:
deploy:
script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
缓存与制品的区别
| 特性 | Cache(缓存) | Artifacts(制品) |
|---|---|---|
| 目的 | 加速后续流水线,存储依赖或中间文件 | 传递构建结果给后续作业或下载 |
| 持久性 | 非保证,可能被清理 | 保证在设定时间内可用 |
| 跨流水线 | 是,通过 key 复用 |
否(默认只在当前流水线内传递) |
| 上传到 GitLab | 否(存在 Runner 本地) | 是 |
合理使用缓存(如 node_modules、vendor)和制品(如编译后的二进制、测试报告)可以大幅优化流水线效率。
定义可复用的配置模板
使用 include 和 YAML 锚点(& 与 *)减少重复。例如,定义通用的部署设置:
.deploy_template: &deploy_template
stage: deploy
script:
- echo "Deploying to ${DEPLOY_ENV}"
- ./deploy.sh
deploy-staging:
<<: *deploy_template
environment:
name: staging
variables:
DEPLOY_ENV: staging
only:
- develop
deploy-production:
<<: *deploy_template
environment:
name: production
variables:
DEPLOY_ENV: production
only:
- main
when: manual
常见问题与调试技巧
- 作业一直处于 pending 状态:没有匹配的 Runner,检查
tags是否正确,或共享 Runner 是否启用。 - 脚本执行失败但日志不清晰:在
script中开启详细输出,如set -x,或分段输出。 - 缓存未生效:确保
cache:key稳定,作业使用相同的 Runner 且路径正确。 - 无法下载制品:使用
needs或dependencies必须明确定义依赖关系,否则默认会下载前序所有作业的制品(可能导致下载无关制品)。 - YAML 语法错误:在 GitLab CI/CD 编辑器(Pipeline Editor)中可直接验证语法。
完整的进阶流水线示例
以下流水线集成了代码检测、多版本测试、容器化构建与自动发布:
include:
- template: Security/SAST.gitlab-ci.yml
stages:
- prepare
- test
- build
- release
- deploy
variables:
DOCKER_DRIVER: overlay2
IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- node_modules/
prepare:
stage: prepare
image: node:18
script: npm ci
artifacts:
paths:
- node_modules/
unit-test:
stage: test
image: node:18
script: npm test
needs: ["prepare"]
build-docker:
stage: build
image: docker:20.10
services:
- docker:20.10-dind
before_script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
script:
- docker build -t $IMAGE_TAG .
- docker push $IMAGE_TAG
needs: ["unit-test"]
release:
stage: release
image: registry.gitlab.com/gitlab-org/release-cli:latest
script:
- echo "Creating release $CI_COMMIT_TAG"
release:
name: 'Release $CI_COMMIT_TAG'
description: 'Auto-generated release from tag.'
rules:
- if: $CI_COMMIT_TAG
deploy-staging:
stage: deploy
script:
- kubectl set image deployment/my-app app=$IMAGE_TAG -n staging
environment:
name: staging
rules:
- if: $CI_COMMIT_BRANCH == "main"
通过以上从基础到进阶的讲解,你已经可以上手编写自己的 .gitlab-ci.yml 流水线。记住,GitLab CI/CD 的强大在于其灵活性与内置集成,反复在 CI/CD > Pipelines 页面查看执行结果,并结合合并请求的 Pipeline 状态,可以快速优化交付流程。