GitLab CI/CD 完全指南

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/repositorynode_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 触发来源 pushmerge_request_eventschedule
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: alwaysallow_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 卡住不动怎么办?

常见原因:

  1. 没有可用的 Runner --- 检查 tags 是否匹配已注册的 Runner
  2. Runner 离线 --- 在 Settings → CI/CD → Runners 查看状态
  3. 并发限制 --- 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 失败

更安全的替代方案:

  1. 把脚本放到专门的 Git 仓库,通过 include 引用
  2. 在项目中本地维护检查脚本
  3. 使用私有镜像仓库中预装了工具的 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 自动帮你执行。

相关推荐
不会C语言的男孩1 小时前
Linux 系统编程 · 第 8 章:进程基础
linux·c语言
古城小栈2 小时前
Unix 与 Linux 异同小叙
linux·服务器·unix
凡人叶枫3 小时前
Effective C++ 条款42:了解 typename 的双重意义
java·linux·服务器·c++
2601_961875243 小时前
决战申论100题2026|最新|范文
linux·容器·centos·debian·ssh·fabric·vagrant
java_cj3 小时前
深入kube-apiserver认证机制:从Bearer Token到mTLS的完整认证链解析
linux·运维·服务器·云原生·容器·kubernetes
lsyeei4 小时前
linux 系统目录详解
linux·运维·服务器
森G4 小时前
75、服务器源码解析---------云视频服务项目
linux·服务器·网络·c++·qt
阿米亚波4 小时前
【Windows】QEMU 启动 openEuler aarch64/arm64 架构系统 + 离线软件源
linux·windows·经验分享·笔记·架构·arm
张飞飞飞飞飞4 小时前
Tmux命令使用教程
linux·服务器·ubuntu
Fcy6484 小时前
Linux下 可重入函数、volatile关键字和SIGCHLD信号
linux·可重入函数·volatile关键字·sigchld