GitLab CI/CD 完全指南
一、什么是 CI/CD?
| 概念 | 全称 | 含义 |
|---|---|---|
| CI | Continuous Integration(持续集成) | 代码提交后自动编译、测试、检查,快速发现问题 |
| CD | Continuous Delivery / Deployment(持续交付/部署) | 通过验证后自动打包、部署到测试/生产环境 |
核心思想:每次代码变更都自动经过一条"流水线"(Pipeline),确保代码始终处于可发布状态。
开发者 push 代码
↓
GitLab 检测到变更,自动触发 Pipeline
↓
┌─────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ build │ → │ test │ → │ quality │ → │ deploy │
│ 编译 │ │ 测试 │ │ 质量检查 │ │ 部署 │
└─────────┘ └──────────┘ └──────────┘ └──────────┘
二、GitLab CI 核心概念
2.1 概念关系图
Pipeline(流水线)------ 一次完整的 CI/CD 执行
│
├── Stage 1: build(阶段)
│ └── Job: compile(任务)
│
├── Stage 2: test
│ ├── Job: unit-test
│ └── Job: integration-test(同一 stage 内的 job 并行执行)
│
├── Stage 3: quality
│ ├── Job: checkstyle
│ └── Job: sonar
│
└── Stage 4: deploy
└── Job: deploy-to-staging
2.2 核心术语
| 术语 | 含义 | 类比 |
|---|---|---|
| Pipeline | 一次完整的流水线执行 | 工厂的一条生产线 |
| Stage | 流水线中的一个阶段 | 生产线上的一个工序(如:焊接、喷漆、组装) |
| Job | 阶段中的一个具体任务 | 工序中的一个具体操作 |
| Runner | 执行 Job 的机器/容器 | 工人/机器人 |
| Artifact | Job 产出的文件(传递给下游) | 半成品(传给下一个工序) |
| Cache | 跨 Pipeline 复用的文件(加速构建) | 工具箱(每次都能用) |
2.3 执行规则
| 规则 | 说明 |
|---|---|
| Stage 间串行 | 前一个 Stage 的所有 Job 完成后才进入下一个 Stage |
| Stage 内并行 | 同一个 Stage 里的多个 Job 同时执行 |
| 失败即停止 | 某个 Job 失败,默认后续 Stage 不再执行(除非设了 when: always) |
| 手动触发 | 可以设 when: manual,需要在 Web UI 上手动点击 |
三、配置文件 .gitlab-ci.yml
3.1 文件位置
放在项目根目录,文件名必须是 .gitlab-ci.yml。GitLab 检测到 push 后会自动读取这个文件并执行。
3.2 基本结构
yaml
# 1. 定义所有阶段(按执行顺序)
stages:
- build
- test
- quality
- deploy
# 2. 定义全局变量(所有 Job 可用)
variables:
MAVEN_OPTS: "-Dmaven.repo.local=.m2/repository"
# 3. 定义各个 Job
build_job: # Job 名称(自定义)
stage: build # 属于哪个阶段
script: # 执行的命令
- mvn clean compile
四、配置项逐一详解
4.1 stages --- 阶段定义
yaml
stages:
- build # 第1步:编译
- test # 第2步:测试
- quality # 第3步:质量检查
- deploy # 第4步:部署
阶段按数组顺序依次执行。
4.2 Job 的完整配置项
yaml
my_job:
# === 基础配置 ===
stage: build # 所属阶段
# === 执行环境 ===
image: maven:3.9-eclipse-temurin-17 # Docker 镜像(运行环境)
tags:
- docker # 指定使用哪个 Runner 执行
# === 执行条件 ===
only: # 仅在这些条件下执行
- main
- develop
- /^feature\/.*$/ # 正则匹配分支名
except: # 排除这些条件
- tags
rules: # 更灵活的条件规则(替代 only/except)
- if: '$CI_COMMIT_BRANCH == "main"'
when: always
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
when: always
- when: never
# === 执行控制 ===
when: on_success # 执行时机:on_success | on_failure | always | manual | delayed
allow_failure: false # 是否允许失败(不阻断后续 Stage)
timeout: 30m # 超时时间
retry: 2 # 失败重试次数
# === 命令 ===
before_script: # 前置命令(每个 Job 都会先执行)
- echo "准备环境"
script: # 主命令(必填)
- mvn clean compile
- echo "编译完成"
after_script: # 后置命令(无论成功失败都会执行)
- echo "清理临时文件"
# === 产物 ===
artifacts:
name: "$CI_JOB_NAME-$CI_COMMIT_REF_NAME" # 产物文件名
paths: # 保存哪些文件
- target/
reports: # 特殊报告类型
junit: target/surefire-reports/*.xml # 测试报告
coverage_report:
coverage_format: cobertura
path: target/site/jacoco/jacoco.xml # 覆盖率报告
expire_in: 7 days # 产物保留时间
when: always # 何时保存:on_success | on_failure | always
# === 缓存 ===
cache:
key: ${CI_COMMIT_REF_SLUG} # 缓存 key(通常按分支区分)
paths:
- .m2/repository/ # 缓存 Maven 依赖
- node_modules/ # 缓存 npm 依赖
policy: pull-push # pull | push | pull-push
# === 依赖 ===
needs: # 跨 Stage 依赖(跳过等待,加速执行)
- build_job
dependencies: # 从哪些 Job 下载 artifacts
- build_job
# === 环境变量 ===
variables:
APP_ENV: "staging"
DEBUG: "true"
# === 服务(如数据库) ===
services:
- name: mysql:8.0
alias: db
- name: redis:7
alias: cache
4.3 关键配置项详解
image --- 运行环境
yaml
# 全局默认镜像
image: maven:3.9-eclipse-temurin-17
# 单个 Job 覆盖
deploy_job:
image: docker:24.0
Job 运行在一个 Docker 容器中,image 指定容器的基础镜像。
tags --- 指定 Runner
yaml
build_job:
tags:
- runner-xx.xx.xx.133 # 使用这台机器上的 Runner
Runner 是真正执行 Job 的机器。tags 用于匹配注册 Runner 时设定的标签。
when --- 执行时机
| 值 | 含义 |
|---|---|
on_success |
前面所有 Job 成功才执行(默认) |
on_failure |
前面有 Job 失败才执行(适合发通知) |
always |
无论成败都执行 |
manual |
需要手动在 Web UI 点击触发 |
delayed |
延迟执行,配合 start_in: 30 minutes |
artifacts vs cache
| artifacts(产物) | cache(缓存) | |
|---|---|---|
| 用途 | 传递给下游 Job 或供下载 | 加速后续 Pipeline(复用依赖) |
| 生命周期 | 跟随 Pipeline,到期自动删除 | 跨 Pipeline 存在 |
| 典型内容 | target/*.jar、测试报告 |
.m2/repository、node_modules |
| 可靠性 | 保证可用 | 可能被清除(不保证) |
rules --- 高级条件控制
yaml
deploy_job:
rules:
# 只有 main 分支才部署
- if: '$CI_COMMIT_BRANCH == "main"'
when: always
# MR 合并时部署到预发布
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
when: manual
# 其他情况不执行
- when: never
五、内置环境变量
GitLab 自动注入大量环境变量,常用的有:
| 变量 | 含义 | 示例值 |
|---|---|---|
CI_COMMIT_BRANCH |
当前分支名 | main |
CI_COMMIT_SHA |
完整的 commit hash | a1b2c3d4... |
CI_COMMIT_SHORT_SHA |
短 hash | a1b2c3d4 |
CI_COMMIT_REF_NAME |
分支或 tag 名 | feature/login |
CI_COMMIT_REF_SLUG |
URL 安全的分支名 | feature-login |
CI_COMMIT_MESSAGE |
commit 消息 | fix: 修复登录Bug |
CI_PROJECT_NAME |
项目名 | my-order-service |
CI_PROJECT_PATH |
项目路径 | team/my-order-service |
CI_PIPELINE_ID |
Pipeline ID | 12345 |
CI_JOB_NAME |
当前 Job 名 | build_job |
CI_JOB_STAGE |
当前阶段名 | build |
CI_PIPELINE_SOURCE |
触发来源 | push、merge_request_event、schedule |
CI_REGISTRY |
容器镜像仓库地址 | registry.gitlab.com |
CI_REGISTRY_IMAGE |
项目的镜像路径 | registry.gitlab.com/team/app |
使用方式:
yaml
script:
- echo "构建分支:$CI_COMMIT_BRANCH"
- echo "Commit:$CI_COMMIT_SHORT_SHA"
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA .
六、完整通用示例
6.1 Java Maven 项目(Spring Boot)
yaml
# ===========================================================
# GitLab CI/CD 配置 - Java Maven Spring Boot 项目
# ===========================================================
# 阶段定义(按顺序执行)
stages:
- build
- test
- quality
- package
- deploy
# 全局变量
variables:
MAVEN_OPTS: >-
-Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository
-Dorg.slf4j.simpleLogger.showDateTime=true
JAVA_HOME: /opt/java/openjdk
# 全局缓存(Maven 依赖)
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- .m2/repository/
# 默认镜像
image: maven:3.9-eclipse-temurin-17
# -----------------------------------------------------------
# Stage 1: 编译
# -----------------------------------------------------------
compile:
stage: build
script:
- mvn clean compile -DskipTests
artifacts:
paths:
- target/
expire_in: 1 hour
# -----------------------------------------------------------
# Stage 2: 测试
# -----------------------------------------------------------
unit-test:
stage: test
script:
- mvn test
artifacts:
paths:
- target/surefire-reports/
- target/site/jacoco/
reports:
junit: target/surefire-reports/TEST-*.xml
expire_in: 7 days
# 即使测试失败也保存报告
when: always
# -----------------------------------------------------------
# Stage 3: 质量检查(并行执行)
# -----------------------------------------------------------
checkstyle:
stage: quality
script:
- mvn checkstyle:check
artifacts:
paths:
- target/checkstyle-result.xml
expire_in: 7 days
allow_failure: false # 风格违规则阻断流水线
sonarqube:
stage: quality
script:
- mvn sonar:sonar
-Dsonar.host.url=$SONAR_HOST_URL
-Dsonar.token=$SONAR_TOKEN
-Dsonar.qualitygate.wait=true
variables:
SONAR_HOST_URL: "http://sonar.xxxx.com:9000"
# SONAR_TOKEN 在 GitLab Settings → CI/CD → Variables 中配置
allow_failure: false # 质量门禁不通过则阻断
# -----------------------------------------------------------
# Stage 4: 打包
# -----------------------------------------------------------
package:
stage: package
script:
- mvn package -DskipTests
artifacts:
name: "$CI_PROJECT_NAME-$CI_COMMIT_SHORT_SHA"
paths:
- target/*.jar
expire_in: 30 days
rules:
- if: '$CI_COMMIT_BRANCH == "main" || $CI_COMMIT_BRANCH == "develop"'
# -----------------------------------------------------------
# Stage 5: 部署
# -----------------------------------------------------------
deploy-staging:
stage: deploy
image: docker:24.0
services:
- docker:24.0-dind
script:
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA .
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
- echo "部署到 staging 环境..."
environment:
name: staging
url: https://staging.xxx.com
rules:
- if: '$CI_COMMIT_BRANCH == "develop"'
when: always
deploy-production:
stage: deploy
image: docker:24.0
services:
- docker:24.0-dind
script:
- docker build -t $CI_REGISTRY_IMAGE:latest .
- docker push $CI_REGISTRY_IMAGE:latest
- echo "部署到生产环境..."
environment:
name: production
url: https://app.xxxx.com
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
when: manual # 生产部署需要手动确认
6.2 执行流程可视化
push 到 develop 分支时:
┌──────────┐ ┌──────────────┐ ┌─────────────────────┐ ┌─────────┐ ┌─────────────┐
│ compile │ → │ unit-test │ → │ checkstyle │ sonar │ → │ package │ → │deploy-staging│
│ (编译) │ │ (单元测试) │ │ (并行质量检查) │ │ (打包) │ │ (部署预发布) │
└──────────┘ └──────────────┘ └─────────────────────┘ └─────────┘ └─────────────┘
push 到 main 分支时:
┌──────────┐ ┌──────────────┐ ┌─────────────────────┐ ┌─────────┐ ┌──────────────────┐
│ compile │ → │ unit-test │ → │ checkstyle │ sonar │ → │ package │ → │deploy-production │
│ (编译) │ │ (单元测试) │ │ (并行质量检查) │ │ (打包) │ │ (手动点击才部署) │
└──────────┘ └──────────────┘ └─────────────────────┘ └─────────┘ └──────────────────┘
6.3 Node.js 项目示例
yaml
stages:
- install
- build
- test
- deploy
image: node:20-alpine
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- node_modules/
install:
stage: install
script:
- npm ci
artifacts:
paths:
- node_modules/
expire_in: 1 hour
build:
stage: build
script:
- npm run build
artifacts:
paths:
- dist/
expire_in: 1 day
lint:
stage: test
script:
- npm run lint
unit-test:
stage: test
script:
- npm run test:ci
artifacts:
reports:
junit: junit.xml
coverage_report:
coverage_format: cobertura
path: coverage/cobertura-coverage.xml
deploy:
stage: deploy
script:
- npm run deploy
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
when: manual
七、高级特性
7.1 模板复用(extends)
避免重复配置:
yaml
# 定义模板(以 . 开头不会被当做 Job 执行)
.maven_base:
image: maven:3.9-eclipse-temurin-17
cache:
key: maven-${CI_COMMIT_REF_SLUG}
paths:
- .m2/repository/
variables:
MAVEN_OPTS: "-Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository"
# 继承模板
compile:
extends: .maven_base
stage: build
script:
- mvn clean compile
test:
extends: .maven_base
stage: test
script:
- mvn test
7.2 并行矩阵(parallel:matrix)
同一个 Job 在多种环境下运行:
yaml
test:
stage: test
parallel:
matrix:
- JAVA_VERSION: ["11", "17", "21"]
DB: ["mysql", "postgres"]
image: maven:3.9-eclipse-temurin-${JAVA_VERSION}
services:
- name: ${DB}:latest
script:
- mvn test
这会生成 3×2=6 个并行 Job。
7.3 条件包含(include)
拆分大配置文件:
yaml
# 主文件 .gitlab-ci.yml
include:
# 引用本仓库其他文件
- local: ci/build.yml
- local: ci/test.yml
- local: ci/deploy.yml
# 引用其他仓库的模板
- project: 'devops/ci-templates'
ref: main
file: '/templates/java-maven.yml'
# 引用远程文件
- remote: 'https://example.com/ci/shared-template.yml'
stages:
- build
- test
- deploy
7.4 环境(environments)
跟踪部署状态:
yaml
deploy-staging:
stage: deploy
script:
- deploy.sh staging
environment:
name: staging
url: https://staging.xxx.com
on_stop: stop-staging # 关联的停止 Job
auto_stop_in: 1 week # 1 周后自动停止
stop-staging:
stage: deploy
script:
- destroy.sh staging
environment:
name: staging
action: stop
when: manual
7.5 定时触发(Schedules)
除了 push 触发,还可以定时执行(在 GitLab Web UI → CI/CD → Schedules 配置):
yaml
nightly-build:
stage: build
script:
- mvn clean verify
rules:
- if: '$CI_PIPELINE_SOURCE == "schedule"' # 只在定时触发时执行
7.6 安全变量管理
敏感信息不要写在 .gitlab-ci.yml 中,而是在 GitLab Web UI 中配置:
Settings → CI/CD → Variables
| 变量名 | 值 | 属性 |
|---|---|---|
SONAR_TOKEN |
sqp_xxx... |
Masked + Protected |
DEPLOY_KEY |
-----BEGIN RSA... |
Masked + Protected + File |
DB_PASSWORD |
xxxx |
Masked |
在 YAML 中直接引用:
yaml
script:
- echo $SONAR_TOKEN # 日志中会显示 [MASKED]
- deploy --key $DEPLOY_KEY
| 属性 | 含义 |
|---|---|
| Protected | 只在受保护分支(如 main)上可用 |
| Masked | 日志中自动替换为 [MASKED] |
| File | 变量值写入临时文件,变量内容是文件路径 |
八、Runner 详解
8.1 什么是 Runner?
Runner 是实际执行 Job 命令的程序。GitLab Server 负责调度,Runner 负责干活。
GitLab Server(调度中心)
│
│ 分配 Job
↓
┌──────────────┐
│ Runner 1 │ ← tags: [docker, linux]
│ (Docker 执行) │
└──────────────┘
┌──────────────┐
│ Runner 2 │ ← tags: [shell, build-server]
│ (本机 Shell) │
└──────────────┘
┌──────────────┐
│ Runner 3 │ ← tags: [k8s, prod]
│ (Kubernetes) │
└──────────────┘
8.2 Runner 类型
| 类型 | 说明 | 适用场景 |
|---|---|---|
| Shared Runner | GitLab 平台提供的公共 Runner | 小项目、开源项目 |
| Group Runner | 注册到某个 Group,组内项目共享 | 团队共用 |
| Specific Runner | 注册到特定项目 | 有特殊环境要求的项目 |
8.3 Runner 执行器(Executor)
| 执行器 | 工作方式 | 优缺点 |
|---|---|---|
| docker | 每个 Job 启动新容器 | 隔离性好,环境干净,推荐 |
| shell | 直接在 Runner 机器上执行命令 | 简单直接,但环境可能被污染 |
| kubernetes | 每个 Job 创建 Pod | 弹性伸缩,适合大规模 |
| docker+machine | 按需创建虚拟机 | 成本优化,适合突发负载 |
8.4 注册 Runner
bash
# 安装 gitlab-runner
sudo apt-get install gitlab-runner
# 注册
sudo gitlab-runner register \
--url https://gitlab.example.com/ \
--registration-token YOUR_TOKEN \
--description "Build Runner" \
--tag-list "docker,linux,java17" \
--executor docker \
--docker-image maven:3.9-eclipse-temurin-17
通过 tags 匹配 Job:
yaml
build_job:
tags:
- docker # 只有带 "docker" 标签的 Runner 会接这个 Job
- java17
九、调试技巧
9.1 本地验证配置语法
bash
# 使用 GitLab CI Lint 工具
# 在 GitLab Web UI → CI/CD → Pipelines → CI Lint
# 或使用命令行工具
gitlab-ci-lint .gitlab-ci.yml
9.2 查看 Job 日志
Pipeline 执行中/后,在 GitLab Web UI:
CI/CD → Pipelines → 点击 Pipeline → 点击具体 Job → 查看日志
9.3 调试变量
yaml
debug_job:
stage: build
script:
- echo "分支:$CI_COMMIT_BRANCH"
- echo "来源:$CI_PIPELINE_SOURCE"
- echo "项目:$CI_PROJECT_NAME"
- env | sort # 打印所有环境变量
9.4 手动重试失败 Job
在 Web UI 中点击失败 Job 旁的「重试」按钮,或:
bash
# 通过 API 重试
curl --request POST \
--header "PRIVATE-TOKEN: your-token" \
"https://gitlab.example.com/api/v4/projects/1/jobs/123/retry"
十、常见问题 FAQ
Q1: when: always 和 allow_failure: true 有什么区别?
| 配置 | 效果 |
|---|---|
when: always |
无论前面 Stage 是否失败,该 Job 都会执行 |
allow_failure: true |
该 Job 失败不会阻断后续 Stage(Pipeline 整体仍标记为"通过") |
两者经常组合使用:
yaml
# 代码质量检查:始终执行,失败也不阻断部署
quality_check:
stage: quality
when: always
allow_failure: true
script:
- mvn sonar:sonar
Q2: artifacts 和 cache 到底用哪个?
| 场景 | 用 artifacts | 用 cache |
|---|---|---|
| 编译产物(jar/dist)传给下游 Job | ✅ | ❌ |
| Maven/npm 依赖加速下载 | ❌ | ✅ |
| 测试报告、覆盖率报告 | ✅ | ❌ |
| 供用户下载的构建包 | ✅ | ❌ |
简单记:artifacts 传产物,cache 存依赖。
Q3: 如何让两个 Job 并行执行?
把它们放在同一个 Stage 中:
yaml
stages:
- quality
# 这两个 Job 同属 quality Stage,会并行执行
checkstyle:
stage: quality
script: mvn checkstyle:check
sonar:
stage: quality
script: mvn sonar:sonar
Q4: 如何只在特定分支上触发?
yaml
# 方式一:only(简单场景)
deploy:
only:
- main
- develop
# 方式二:rules(推荐,更灵活)
deploy:
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
when: manual
- if: '$CI_COMMIT_BRANCH == "develop"'
when: always
- when: never
Q5: 如何在 MR(Merge Request)时触发?
yaml
mr-check:
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
script:
- mvn verify
Q6: Pipeline 卡住不动怎么办?
常见原因:
- 没有可用的 Runner --- 检查
tags是否匹配已注册的 Runner - Runner 离线 --- 在 Settings → CI/CD → Runners 查看状态
- 并发限制 --- Runner 的
concurrent设置太小,排队等待
Q7: 如何跳过 CI?
在 commit message 中加入关键词:
bash
git commit -m "docs: 更新 README [skip ci]"
# 或
git commit -m "docs: 更新 README [ci skip]"
Q8: Job 之间如何传递数据?
通过 artifacts:
yaml
build:
stage: build
script:
- mvn package -DskipTests
- echo "1.0.0-$CI_COMMIT_SHORT_SHA" > version.txt
artifacts:
paths:
- target/*.jar
- version.txt
deploy:
stage: deploy
script:
- VERSION=$(cat version.txt)
- echo "部署版本:$VERSION"
- deploy.sh target/*.jar
dependencies:
- build # 声明从 build Job 下载 artifacts
Q9: 如何设置超时防止 Job 卡死?
yaml
long_running_test:
timeout: 30m # Job 级别超时
script:
- mvn verify -Pintegration-test
全局默认超时在 Settings → CI/CD → General pipelines → Timeout 中配置。
Q10: curl ... | bash 安全吗?
这种方式把检查逻辑集中管理(一处修改,所有项目生效),但有安全风险:
- 远程脚本被篡改会影响所有项目
- 网络不可用时 Pipeline 失败
更安全的替代方案:
- 把脚本放到专门的 Git 仓库,通过
include引用 - 在项目中本地维护检查脚本
- 使用私有镜像仓库中预装了工具的 Docker 镜像
十一、最佳实践总结
Pipeline 设计原则
| 原则 | 说明 |
|---|---|
| 快速反馈 | 编译和基本测试放前面,耗时操作放后面 |
| 失败即停 | 编译失败就没必要继续测试和部署 |
| 并行加速 | 互不依赖的 Job 放同一 Stage 并行执行 |
| 产物精简 | 只保存下游需要的文件,设合理的过期时间 |
| 缓存加速 | Maven/npm 依赖用 cache 加速下载 |
| 环境隔离 | 用 Docker 镜像确保环境一致性 |
| 安全变量 | 密码、Token 放 CI Variables,不写进 YAML |
推荐的 Stage 编排
yaml
stages:
- build # 编译(1-2 分钟)
- test # 单元测试(2-5 分钟)
- quality # 质量检查:CheckStyle + SonarQube(并行,3-10 分钟)
- package # 打包 Docker 镜像(2-3 分钟)
- deploy-dev # 部署到开发环境(自动)
- deploy-stg # 部署到预发布环境(自动,仅 develop 分支)
- deploy-prod # 部署到生产环境(手动确认,仅 main 分支)
分支策略与 CI 配合
| 分支 | 触发行为 |
|---|---|
feature/* |
build → test → quality |
develop |
build → test → quality → package → deploy-dev |
main |
build → test → quality → package → deploy-prod(手动) |
| MR | build → test → quality(作为合入门禁) |
十二、完整配置模板(可直接复用)
yaml
# ============================================================
# 通用 Java Maven 项目 GitLab CI/CD 模板
# 使用方式:复制到项目根目录命名为 .gitlab-ci.yml
# ============================================================
stages:
- build
- test
- quality
- package
- deploy
variables:
MAVEN_OPTS: "-Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository"
image: maven:3.9-eclipse-temurin-17
cache:
key: maven-${CI_COMMIT_REF_SLUG}
paths:
- .m2/repository/
# ---------- 编译 ----------
compile:
stage: build
script:
- mvn clean compile -DskipTests
artifacts:
paths:
- target/
expire_in: 2 hours
# ---------- 单元测试 ----------
unit-test:
stage: test
script:
- mvn test jacoco:report
artifacts:
paths:
- target/site/jacoco/
- target/surefire-reports/
reports:
junit: target/surefire-reports/TEST-*.xml
expire_in: 7 days
# ---------- CheckStyle ----------
checkstyle:
stage: quality
script:
- mvn checkstyle:check
artifacts:
paths:
- target/checkstyle-result.xml
expire_in: 7 days
allow_failure: false
# ---------- SonarQube ----------
sonarqube:
stage: quality
script:
- >
mvn sonar:sonar
-Dsonar.host.url=$SONAR_HOST_URL
-Dsonar.token=$SONAR_TOKEN
-Dsonar.qualitygate.wait=true
allow_failure: false
# ---------- 打包 ----------
package:
stage: package
script:
- mvn package -DskipTests
artifacts:
name: "${CI_PROJECT_NAME}-${CI_COMMIT_SHORT_SHA}"
paths:
- target/*.jar
expire_in: 30 days
rules:
- if: '$CI_COMMIT_BRANCH == "main" || $CI_COMMIT_BRANCH == "develop"'
# ---------- 部署开发环境 ----------
deploy-dev:
stage: deploy
script:
- echo "Deploy to development..."
# - kubectl apply -f k8s/dev/
environment:
name: development
url: https://dev.example.com
rules:
- if: '$CI_COMMIT_BRANCH == "develop"'
when: always
# ---------- 部署生产环境 ----------
deploy-prod:
stage: deploy
script:
- echo "Deploy to production..."
# - kubectl apply -f k8s/prod/
environment:
name: production
url: https://app.example.com
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
when: manual
十三、总结
| 你需要记住的 | 说明 |
|---|---|
.gitlab-ci.yml |
配置文件,放项目根目录 |
stages |
定义阶段顺序 |
script |
Job 要执行的命令 |
artifacts |
产物,传给下游或供下载 |
cache |
缓存依赖加速构建 |
tags |
匹配 Runner |
rules / only |
控制何时执行 |
when |
执行时机(always/manual/on_success) |
allow_failure |
失败是否阻断流水线 |
| CI Variables | 管理密码和 Token |
一句话总结 GitLab CI:用 YAML 文件声明"代码推上来后要做什么",GitLab 自动帮你执行。