.gitlab-ci.yml是 GitLab CI/CD 的核心配置文件,它告诉 GitLab Runner 具体要执行什么操作。
.gitlab-ci.yml 简介
.gitlab-ci.yml 是一个使用 YAML 语法编写的文件,通常存放在项目的根目录下。
- 作用:定义自动化的流水线(Pipeline)。
- 触发机制:当你推送代码(push)、创建合并请求(Merge Request)或打标签(Tag)时,GitLab 会自动检测该文件并触发流水线。
- 结构:由一系列的 Jobs(作业)组成,这些 Job 被分配到不同的 Stages(阶段)中按顺序或并发执行。
核心关键字速查表
下表总结了最常用和关键的配置项:
| 关键字 | 说明 | 典型用途 |
|---|---|---|
stages |
定义流水线的阶段顺序 | [build, test, deploy],决定了 Job 的执行大顺序。 |
stage |
定义当前 Job 属于哪个阶段 | 将 Job 归类,如 stage: build。 |
script |
(必填) Job 真正执行的 Shell 命令 | npm install、docker build、pytest 等。 |
image |
指定执行环境的 Docker 镜像 | node:16-alpine、python:3.9。 |
default |
设置全局默认值 | 如果大部分 Job 都用同一个 image 或 tag,可在此统一定义。 |
variables |
定义环境变量 | 数据库连接串、版本号等(避免硬编码)。 |
rules |
现代化的条件判断逻辑 (替代 only/except) |
决定 Job 何时运行(如:只在 Tag 时、只在 MR 时)。 |
extends |
继承模版(复用配置) | 减少重复代码,继承隐藏作业 (.hidden-job) 的配置。 |
artifacts |
定义产物(Job 跑完后保留的文件) | 保存编译后的二进制文件、测试报告,供后续 Stage 下载。 |
dependencies |
限制下载哪些 Job 的产物 | 默认后续 Stage 会下载前面所有产物,用此可指定只下载特定的。 |
needs |
定义依赖关系(DAG 模式) | 高级:允许跨 Stage 并行,不按严格顺序,只等待特定的 Job 完成。 |
allow_failure |
是否允许失败 | 设为 true 时,即使该 Job 报错,流水线也会继续(常用于非阻塞的测试)。 |
before_script |
脚本执行前的准备命令 | 安装依赖、打印环境信息等。 |
cache |
定义缓存 | 缓存 node_modules 等,加速下一次构建。 |
environment |
定义部署环境 | 用于 GitLab UI 记录部署历史(如 Production, Staging)。 |
tags |
指定由哪个 Runner 执行 | 对应 GitLab Runner 配置的 tag(如 gpu, linux)。 |
环境变量解释
- CI_JOB_TOKEN 权限主要是查看API相关的
GIT_STRATEGY
- 环境变量 GIT_STRATEGY 用于控制 GitLab Runner 如何获取(拉取)源代码,它决定了在作业(Job)开始执行脚本之前,Runner 是应该重用之前的代码、重新克隆整个仓库,还是根本不需要代码。
| 策略值 | 行为描述 | 速度 | 纯净度 | 推荐场景 |
|---|---|---|---|---|
| fetch (默认) | 复用本地目录,拉取更新 | 快 🚀 | 低 (可能有残留) | 日常开发、测试、CI 流程 |
| clone | 删除目录,重新克隆 | 慢 🐢 | 高 (完全纯净) | 正式发布、排查环境问题 |
| none | 不拉取代码 | 最快 ⚡️ | - | 仅依赖 Artifacts 的部署、通知任务 |
GIT_DEPTH
当使用 fetch 或 clone 时,为了进一步加快速度,通常会配合 GIT_DEPTH 变量使用(浅克隆):
variables:
GIT_STRATEGY: fetch
GIT_DEPTH: "1" # 只下载最近的一次 commit,不下载历史记录,速度极快
## 深度解析:复杂流程完整实例
**场景假设**:
我们要构建一个 Node.js 应用。
1. **全局配置**:默认使用 Node 镜像,设置重试机制。
2. **Lint 阶段**:代码风格检查,允许失败(不阻塞流程)。
3. **Build 阶段**:编译代码,生成 `dist/` 目录作为产物。
4. **Test 阶段**:
- 单元测试:需要 `dist/` 文件。
- 安全扫描:使用特定 Docker 镜像,耗时较长。
5. **Deploy 阶段**:
- **Staging**:当合并到 `main` 分支时自动部署。
- **Production**:只有打 `v*` 格式的 Tag 时才部署,且需要人工点击确认。
### 完整的 `.gitlab-ci.yml` 内容
```yaml
# 1. 定义整个流水线的阶段顺序
stages:
- check # 代码检查
- build # 构建
- test # 测试
- deploy # 部署
# 2. 全局默认配置 (Default)
# 所有 Job 如果没有单独指定,都会继承这里的配置
default:
image: node:16-alpine # 默认使用 Node 16 镜像
retry: 1 # 如果 Job 失败,自动重试 1 次
tags: # 指定默认由带 'docker' 标签的 Runner 执行
- docker
# 全局变量
variables:
NPM_CONFIG_CACHE: '$CI_PROJECT_DIR/.npm'
# 3. 缓存配置:在 Job 之间共享 node_modules,加快速度
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- node_modules/
- .npm/
# 4. 模版作业 (Hidden Job / Template)
# 以 '.' 开头,不会直接运行,专门用于被 extends 继承
.deploy_template:
stage: deploy
script:
- echo "Deploying to $DEPLOY_ENV..."
- echo "Simulate deployment script here"
# 假设这里有真实部署命令,如 scp 或 kubectl
dependencies:
- build_app # 明确只下载 build_app 的产物
# =======================
# Stage: CHECK
# =======================
lint_code:
stage: check
script:
- npm ci
- npm run lint
# 关键字: allow_failure
# 即使代码风格检查失败,流水线也会显示橙色警告,但继续执行后续 Build
allow_failure: true
# =======================
# Stage: BUILD
# =======================
build_app:
stage: build
script:
- npm ci
- npm run build
# 关键字: artifacts
# 定义产物,build 完成后,GitLab 会把 dist 目录压缩保存
artifacts:
name: 'dist-$CI_COMMIT_REF_NAME'
expire_in: 1 week # 产物保留1周
paths:
- dist/ # 指定要保留的文件夹
# =======================
# Stage: TEST
# =======================
unit_test:
stage: test
script:
- npm run test
# 关键字: dependencies
# 显式声明依赖 build_app,GitLab 会自动把 build_app 的 artifacts 下载并解压到当前目录
dependencies:
- build_app
security_scan:
stage: test
# 关键字: image (覆盖全局 default)
# 这个 Job 需要特殊的安全工具镜像,不使用默认的 Node 镜像
image: aquasec/trivy:latest
script:
- trivy filesystem .
# 关键字: rules (逻辑控制)
# 仅在 main 分支 或 Tag 时运行,Merge Request 中不运行以节省资源
rules:
- if: $CI_COMMIT_BRANCH == "main"
- if: $CI_COMMIT_TAG
# =======================
# Stage: DEPLOY
# =======================
# 部署到测试环境
deploy_staging:
# 关键字: extends
# 继承上面定义的 .deploy_template,复用 script 和 dependencies
extends: .deploy_template
variables:
DEPLOY_ENV: 'Staging'
environment:
name: staging
url: https://staging.example.com
# 规则:只有当推送到 main 分支时执行
rules:
- if: $CI_COMMIT_BRANCH == "main"
# 部署到生产环境
deploy_production:
extends: .deploy_template
variables:
DEPLOY_ENV: 'Production'
environment:
name: production
url: https://example.com
# 规则:只有打 Tag (例如 v1.0.0) 时才执行
rules:
- if: $CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/
when: manual # 关键:手动触发。流水线会暂停,等待人工点击`播放`按钮
# 生产环境通常不允许失败
allow_failure: false详细代码解读
让我们把上面例子中体现的关键技术点拆解一下:
stages (流程编排)
GitLab CI 默认有 .pre, build, test, deploy, .post 这几个阶段
stages:
- check
- build
- test
- deployGitLab 会按照这个顺序执行。如果 check 阶段的所有 Job 没成功(除非 allow_failure: true),就不会进入 build。同一个 Stage 下的 Job(如 unit_test 和 security_scan)是并行运行的。
extends (继承/复用)
.deploy_template:
script: ...
deploy_staging:
extends: .deploy_template这是保持 YAML 简洁的最佳实践。.deploy_template 就像父类,定义了通用的部署脚本。deploy_staging 和 deploy_production 继承它,只需要修改变量 (variables) 和规则 (rules)。
artifacts 与 dependencies (文件传递)
- Build 阶段:
artifacts告诉 GitLab:“我生成了dist/目录,请打包上传到服务器”。 - Test/Deploy 阶段:默认情况下,后续阶段会自动下载所有前序阶段的 artifacts。
- Dependencies:在
deploy_staging中,如果我们只想下载build_app的产物(不想下载unit_test可能产生的测试报告),使用dependencies: ["build_app"]可以显式指定,既安全又加快下载速度。
rules (强大的逻辑控制)
这是现代 GitLab CI 最核心的部分,取代了老旧的 only/except。
rules:
- if: $CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/
when: manual这段逻辑表示:
- IF: 当前提交是一个 Tag,且 Tag 名字匹配版本号正则(如
v1.0.0)。 - THEN: 将 Job 状态设为
manual(手动)。在 UI 界面上,这个 Job 会显示一个播放按钮,只有点击后才会真正部署。这对生产环境至关重要。
allow_failure (容错)
在 lint_code 中设置了 true。这意味着,如果 ESLint 发现代码格式有问题报错了,Pipeline 会显示一个黄色的感叹号(Warning),但不会通过红色的 X(Error)来停止流水线,后续的 build 依然会继续。
default 与 image
- 我们在顶部
default里定义了node:16-alpine。大部分 Job 不需要写 image,直接用这个。 - 但是在
security_scan中,我们需要运行安全扫描工具trivy,所以用image: aquasec/trivy:latest覆盖了默认值。
这个例子涵盖了你在实际工作中 90% 会用到的场景,从基础构建到复杂的生产环境门禁控制。