带人工确认的生产部署流水线

.gitlab-ci.yml

# ============================================
# 1. 定义流水线阶段,按顺序执行
# ============================================
stages:
  - build              # 第1阶段:编译 + 打包(install 会下载依赖并打包成 jar/war)
  - test               # 第2阶段:单元测试 + 集成测试(并行执行)
  - deploy             # 第3阶段:部署到各环境

# ============================================
# 2. 全局变量,所有 job 都可以引用
# ============================================
variables:
  APP_NAME: "my-app"                                             # 应用名称
  DOCKER_IMAGE: "registry.example.com/${APP_NAME}:${CI_COMMIT_SHA}"  # Docker 镜像地址(带提交SHA唯一标识)
  MAVEN_OPTS: "-Dmaven.repo.local=.m2/repository"               # Maven 本地仓库路径(利用 CI cache 加速)
  DOCKER_DRIVER: overlay2                                        # Docker 存储驱动(Runner 机器配置)

# ============================================
# 3. Build 阶段 - 编译 + 打包 + 构建 Docker 镜像
# ============================================
build:
  stage: build                                                   # 属于 build 阶段
  image: maven:3.9-openjdk-17                                     # Maven + JDK 17 运行环境  

 services:                                                     # 关联 Docker 服务(让 Maven 能够运行 Docker 命令)
    - docker:24-dind                                             # Docker-in-Docker,Runner 内运行 Docker
  script:                                                       # 核心执行命令
    # ---------- 编译打包 ----------
    - mvn clean package -DskipTests                             # 编译代码 + 跳过测试打包 jar(Dockerfile 需要)
    - ls -la target/*.jar                                        # 确认 jar 包生成成功(调试用)
    # ---------- Docker 登录 ----------
    - echo "$CI_REGISTRY_PASSWORD" | docker login -u "$CI_REGISTRY_USER" --password-stdin $CI_REGISTRY  # 登录镜像仓库
    # ---------- 构建镜像 ----------
    - docker build -t ${DOCKER_IMAGE} .                          # 根据 Dockerfile 构建镜像,标签为本次提交SHA    # ---------- 推送镜像 ----------
    - docker push ${DOCKER_IMAGE}                               # 推送到镜像仓库,供 K8s 部署使用
  artifacts:                                                    # 产物:下游 job 可以使用
    paths:
      - target/*.jar                                            # 打包产物(如果需要传递给其他 job)
    expire_in: 1 hour                                          # 产物过期时间
    # reports:                                                   # 可选:SonarQube 代码质量报告
    #   junit: target/surefire-reports/*.xml
  cache:                                                        # 缓存 Maven 依赖,加速下次构建
    key: "${CI_COMMIT_REF_SLUG}"                                 # 按分支缓存,避免分支间互相覆盖
    paths:
      - .m2/repository                                          # Maven 本地仓库(下载一次后复用)
  only:                                                         # 触发条件
    - main                                                      # 仅 main 分支 push 时执行# ============================================
# 4. Test 阶段 - 单元测试
# ============================================
test_unit:
  stage: test                                                   # 属于 test 阶段
  image: maven:3.9-openjdk-17                                   # Maven + JDK 17 运行环境
  script:                                                       # 执行命令
    - mvn test                                                  # 运行 src/test/java 下的单元测试
  artifacts:                                                    # 产物:测试报告(GitLab UI 直接查看)
    when: always                                               # 即使失败也生成报告
    paths:
      - target/surefire-reports/                               # Maven Surefire 测试报告(XML 格式)
    reports:                                                    # 解析为标准格式,供 GitLab 展示
      junit: target/surefire-reports/TEST-*.xml                 # GitLab 自动解析,显示测试通过/失败数
      # coverage_report:                                       # 可选:JaCoCo 覆盖率报告
      #   coverage_format: cobertura
      #   path: target/site/jacoco/jacoco.xml
  coverage: '/Total.*?([0-9]{1,3})%/'                           # 从日志中提取覆盖率百分比
  needs: [build]                                               # 等待 build job 完成后才执行(从 build 的 artifacts 继承)
  cache:
    key: "${CI_COMMIT_REF_SLUG}"
    paths:
      - .m2/repository
  only:
    - main

# ============================================
# 5. Test 阶段 - 集成测试
# ============================================
test_integration:
  stage: test                                                   # 属于 test 阶段(与 test_unit 并行)
  image: maven:3.9-openjdk-17                                   # Maven + JDK 17 运行环境
  services:                                                     # 集成测试需要依赖真实中间件
    - postgres:13                                              # PostgreSQL 数据库容器(测试时连接)
    # - redis:7                                                 # Redis 缓存容器(如果项目用到)
  variables:                                                    # Job 局部变量,覆盖全局变量
    # ---------- Spring Boot 测试配置(通过系统属性注入) ----------
    SPRING_DATASOURCE_URL: "jdbc:postgresql://postgres:5432/testdb"  # 数据库连接地址(postgres 是 service 名称)
    SPRING_DATASOURCE_USERNAME: "test"                         # 数据库用户名
    SPRING_DATASOURCE_PASSWORD: "test"                         # 数据库密码
  script:
    # ---------- 集成测试(使用 Spring Boot Test) ----------
    - mvn verify -Dspring.profiles.active=ci                   # 运行集成测试(激活 ci 配置,排除本地文件依赖)
    # ---------- 可选:运行指定集成测试类 ----------
    # - mvn test -Dtest=OrderServiceIntegrationTest
  artifacts:
    when: always
    paths:
      - target/surefire-reports/                               # Maven Surefire 报告
      - target/failsafe-reports/                              # Maven Failsafe 集成测试报告(如果用 failsafe 插件)
  reports:
    junit: target/surefire-reports/TEST-*.xml                  # GitLab 解析测试结果
  needs: [build]                                               # 等待 build 完成
  cache:
    key: "${CI_COMMIT_REF_SLUG}"
    paths:
      - .m2/repository
  allow_failure: true                                         # ⚠️ 允许失败,不阻塞后续流程(根据业务决定)
  only:
    - main

# ============================================
# 6. Deploy 阶段 - 部署到测试环境(自动化,无需人工确认)
# ============================================
deploy_test:
  stage: deploy                                                 # 属于 deploy 阶段
  image: bitnami/kubectl:latest                                # kubectl 操作 K8s
  before_script:                                               # 执行 script 前的准备工作
    - kubectl config use-context test-cluster                  # 切换到测试集群上下文
  script:
    # ---------- 替换镜像版本 ----------
    - kubectl set image deployment/${APP_NAME} app=${DOCKER_IMAGE}  # 更新 K8s Deployment 的镜像版本
    # ---------- 等待滚动更新 ----------
    - kubectl rollout status deployment/${APP_NAME} --timeout=300s  # 等待滚动更新完成,超时5分钟
    # ---------- 确认版本 ----------
    - kubectl rollout history deployment/${APP_NAME}           # 查看滚动历史(调试用)
    - kubectl get pods -l app=${APP_NAME}                      # 查看 pod 状态(确认启动成功)
  environment:                                                  # 声明环境,GitLab UI 追踪部署历史
    name: test                                                 # 环境名称
    url: https://test.example.com                              # 测试环境访问地址
  needs: [test_unit, test_integration]                        # 等待两个测试 job 都完成
  only:
    - main

# ============================================
# 7. Deploy 阶段 - 部署到预发布环境(自动化)
# ============================================
deploy_staging:
  stage: deploy                                                 # 属于 deploy 阶段
  image: bitnami/kubectl:latest                                # kubectl 操作 K8s
  before_script:
    - kubectl config use-context staging-cluster                # 切换到预发布集群
  script:
    - kubectl set image deployment/${APP_NAME} app=${DOCKER_IMAGE}  # 更新镜像版本
    - kubectl rollout status deployment/${APP_NAME} --timeout=300s  # 等待滚动更新完成
    - kubectl get pods -l app=${APP_NAME}                      # 确认 Pod 运行正常
  environment:
    name: staging                                              # 环境名称
    url: https://staging.example.com                           # 预发布环境地址
    on_stop: rollback_staging                                 # 🔑 环境停止时触发回滚 job
  needs: [test_unit, test_integration]                        # 等待测试完成
  only:
    - main

# ============================================
# 8. 预发布环境人工审批(关键卡点:确保验收通过后再上生产)
# ============================================
approve_staging:                                                # job 名称(纯人工审批节点)
  stage: deploy                                                 # 同一 deploy 阶段(不占 Runner 资源)
  script:
    # ---------- 无实际命令,GitLab UI 会显示 Play 按钮 ----------
    - echo "✅ 预发布环境验收通过,等待生产部署审批"              # GitLab 日志中显示提示信息
  environment:
    name: staging                                               # 关联到 staging 环境
    action: prepare                                            # 🔑 暂停预发布环境,等待后续操作
  needs: [deploy_staging]                                     # 必须等预发布部署完成
  when: manual                                                 # 🔑 核心:人工手动点击才触发,不自动执行
  allow_failure: false                                         # 不允许失败
  only:
    - main

# ============================================
# 9. 生产环境部署(最高风险:人工确认 + 前置审批通过)
# ============================================
deploy_production:                                             # job 名称
  stage: deploy                                                 # 属于 deploy 阶段
  image: bitnami/kubectl:latest                                # kubectl 操作生产 K8s 集群
  before_script:
    - kubectl config use-context prod-cluster                  # 切换到生产集群(⚠️ 操作需谨慎)
  script:
    # ---------- 正式部署 ----------
    - kubectl set image deployment/${APP_NAME} app=${DOCKER_IMAGE}  # 更新生产镜像版本
    - kubectl rollout status deployment/${APP_NAME} --timeout=600s  # 等待滚动更新完成(生产超时可设更长)
    # ---------- 健康检查确认 ----------
    - kubectl get pods -l app=${APP_NAME}                      # 确认所有 Pod 运行成功
    - kubectl describe deployment ${APP_NAME} | grep -A5 "RollingUpdateStrategy:"  # 查看滚动策略
    # ---------- 记录部署信息 ----------
    - echo "🚀 生产环境部署完成!镜像:${DOCKER_IMAGE},提交:${CI_COMMIT_SHA}"
  environment:
    name: production                                           # 环境名称
    url: https://www.example.com                               # 生产环境地址
    on_stop: rollback_production                              # 🔑 环境停止时触发回滚 job
  needs: [approve_staging]                                    # 🔑 关键:必须等预发布审批通过
  when: manual                                                 # 🔑 核心:必须人工点击,不自动执行
  allow_failure: false                                         # 不允许失败,失败则阻塞流水线
  only:
    - main
  # resource_group: production                                 # 🔑 可选:生产环境加锁,防止多人同时触发

# ============================================
# 10. 生产环境回滚(快速回退到上一稳定版本)
# ============================================
rollback_production:                                           # job 名称
  stage: deploy                                                 # 同一 deploy 阶段
  image: bitnami/kubectl:latest                                # kubectl 操作 K8s
  before_script:
    - kubectl config use-context prod-cluster                  # 切换到生产集群
  script:
    # ---------- 回滚到上一版本 ----------
    - kubectl rollout undo deployment/${APP_NAME}             # 🔑 kubectl 内置回滚命令,秒级回退    - kubectl rollout status deployment/${APP_NAME} --timeout=300s  # 等待回滚完成
    # ---------- 确认回滚成功 ----------
    - kubectl rollout history deployment/${APP_NAME}          # 查看当前版本历史
    - kubectl get pods -l app=${APP_NAME}                      # 确认 Pod 恢复
    - echo "⏪ 生产环境已回滚到上一版本"
  environment:
    name: production                                           # 关联生产环境
    action: stop                                               # 🔑 标记环境为停止状态
  when: manual                                                 # 🔑 手动触发,不自动执行
  only:
    - main

# ============================================
# 11. 预发布环境回滚
# ============================================
rollback_staging:                                              # job 名称
  stage: deploy
  image: bitnami/kubectl:latest
  before_script:
    - kubectl config use-context staging-cluster               # 切换到预发布集群
  script:
    - kubectl rollout undo deployment/${APP_NAME}              # 回滚到上一版本
    - kubectl rollout status deployment/${APP_NAME} --timeout=300s  # 等待回滚完成
    - kubectl get pods -l app=${APP_NAME}                      # 确认 Pod 恢复
    - echo "⏪ 预发布环境已回滚"
  environment:
    name: staging    action: stop                                               # 停止预发布环境
  when: manual                                                 # 手动触发
  only:
    - main
 

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐