3. CI/CD 流水线基础:Jenkins/GitLab CI 核心概念、Pipeline 即代码、Stage 与 Job 定义

在多租户 SaaS 鉴权拦截链路中,每一次代码提交都可能影响租户隔离、Token 校验或拦截规则。为了在每次变更后自动验证这些关键路径,必须建立标准化的 CI/CD 流水线。本章聚焦 Jenkins 与 GitLab CI 的核心概念,重点讲解 Pipeline 即代码的实现方式,以及 Stage 与 Job 的定义规则。

3.1 CI/CD 流水线核心概念

CI/CD 流水线将代码从提交到部署的过程拆解为多个自动化阶段。在多租户 SaaS 项目中,流水线需要额外处理租户上下文、多环境配置以及鉴权拦截的专项测试。

概念 说明 多租户 SaaS 场景要点
持续集成 (CI) 代码合并后自动构建、静态分析、单元测试 需注入不同租户的测试 Token,验证隔离性
持续交付 (CD) 通过自动化测试后,自动部署到预发布环境 预发布环境需模拟多租户数据源与拦截规则
Pipeline 定义整个自动化流程的配置文件 Pipeline 即代码,与鉴权测试脚本一同版本管理
Stage 流水线中的逻辑阶段,如构建、测试、部署 鉴权拦截测试应作为独立 Stage,避免阻塞其他流程
Job Stage 内的具体执行任务,可并行或串行 不同租户的鉴权测试可拆分为多个并行 Job
实践建议: 在多租户 SaaS 项目中,建议将“鉴权拦截测试”定义为流水线中的 门禁 Stage。只有该 Stage 全部 Job 通过,才允许合并到主分支或触发后续部署。

3.2 Pipeline 即代码 (Pipeline as Code)

Pipeline 即代码将流水线配置以文本文件形式存储在代码仓库中,与源代码一同进行版本控制、代码审查和分支管理。这种方式保证了流水线的可追溯性和可重复性。

3.2.1 Jenkins Pipeline 即代码

Jenkins 支持两种 Pipeline 语法:声明式 (Declarative) 和 脚本式 (Scripted)。声明式语法结构清晰,适合大多数 SaaS 项目;脚本式更灵活,适合复杂定制场景。

// Jenkinsfile - 声明式 Pipeline 示例
pipeline {
    agent any

    stages {
        stage('Checkout') {
            steps {
                checkout scm
            }
        }
        stage('Build & Unit Test') {
            steps {
                sh 'mvn clean compile'
                sh 'mvn test'
            }
        }
        stage('Multi-Tenant Auth Intercept Test') {
            parallel {
                stage('Tenant-A') {
                    steps {
                        sh 'mvn test -Dtest=AuthInterceptTest -Dtenant.id=tenant-a'
                    }
                }
                stage('Tenant-B') {
                    steps {
                        sh 'mvn test -Dtest=AuthInterceptTest -Dtenant.id=tenant-b'
                    }
                }
                stage('Tenant-C') {
                    steps {
                        sh 'mvn test -Dtest=AuthInterceptTest -Dtenant.id=tenant-c'
                    }
                }
            }
        }
        stage('Deploy to Staging') {
            steps {
                sh 'kubectl apply -f k8s/staging/'
            }
        }
    }

    post {
        failure {
            emailext (
                subject: "Pipeline Failed: ${env.JOB_NAME} - ${env.BUILD_NUMBER}",
                body: "鉴权拦截测试失败,请检查日志。",
                to: "team@saas.com"
            )
        }
    }
}

3.2.2 GitLab CI 即代码

GitLab CI 使用 .gitlab-ci.yml 文件定义流水线。其核心概念包括 stages、jobs、runner 和 artifacts。GitLab CI 天然支持并行 Job 和依赖传递。

# .gitlab-ci.yml - 多租户鉴权测试流水线
stages:
  - build
  - unit_test
  - auth_intercept_test
  - deploy_staging

variables:
  MAVEN_OPTS: "-Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository"

build_job:
  stage: build
  script:
    - mvn clean compile
  artifacts:
    paths:
      - target/

unit_test_job:
  stage: unit_test
  script:
    - mvn test
  dependencies:
    - build_job

auth_intercept_test:
  stage: auth_intercept_test
  parallel:
    matrix:
      - TENANT_ID: ["tenant-a", "tenant-b", "tenant-c"]
  script:
    - mvn test -Dtest=AuthInterceptTest -Dtenant.id=$TENANT_ID
  artifacts:
    when: always
    reports:
      junit: target/surefire-reports/TEST-*.xml

deploy_staging_job:
  stage: deploy_staging
  script:
    - kubectl apply -f k8s/staging/
  only:
    - main
  dependencies:
    - auth_intercept_test
关键差异对比:
  • Jenkins:Pipeline 文件名为 Jenkinsfile,语法更丰富,支持复杂的脚本逻辑和共享库。
  • GitLab CI:配置文件为 .gitlab-ci.yml,语法简洁,与 GitLab 平台深度集成,天然支持矩阵并行测试。
  • 共同点:都支持 Stage 串行、Job 并行、环境变量注入、制品传递和失败通知。

3.3 Stage 与 Job 定义规则

Stage 和 Job 是流水线的核心构建块。合理的 Stage 划分和 Job 定义直接影响流水线的执行效率与可维护性。

3.3.1 Stage 定义原则

  • 逻辑独立:每个 Stage 完成一个独立的功能阶段,如构建、单元测试、鉴权测试、部署。
  • 串行依赖:Stage 之间默认串行执行,后一个 Stage 依赖前一个 Stage 的成功状态。
  • 门禁设置:将关键验证(如鉴权拦截测试)设为门禁 Stage,失败即阻断后续流程。
  • 最小化粒度:避免 Stage 过多导致流水线过长,通常 4~6 个 Stage 即可覆盖 SaaS 项目的核心流程。

3.3.2 Job 定义原则

  • 单一职责:每个 Job 只做一件事,如“运行租户 A 的鉴权测试”或“构建 Docker 镜像”。
  • 并行执行:同一 Stage 内的 Job 可以并行执行,适合多租户并发测试场景。
  • 资源标签:为 Job 指定运行环境标签(如 agent { label 'docker' }),确保测试环境一致性。
  • 超时与重试:为 Job 设置超时时间(如 timeout 10)和重试策略(如 retry 2),避免流水线卡死。
常见陷阱:
  • 将多个租户的鉴权测试写在同一个 Job 中,导致失败时无法快速定位是哪个租户的问题。
  • Stage 划分过细(如将编译和打包拆成两个 Stage),增加流水线总耗时且无实际收益。
  • 忽略 Job 之间的资源竞争,例如多个并行 Job 同时写入同一个数据库或文件。

3.4 多租户鉴权测试流水线架构图

下图展示了针对多租户 SaaS 鉴权拦截链路的 CI/CD 流水线架构。流水线从代码提交触发,经过构建、单元测试、多租户并行鉴权测试,最终部署到预发布环境。

多租户鉴权测试 CI/CD 流水线架构 多租户鉴权测试 CI/CD 流水线架构 代码提交 (Git Push) 构建 (Build) 单元测试 (Unit Test) 鉴权拦截测试 (门禁) Job: 租户 A 鉴权测试 Job: 租户 B 鉴权测试 Job: 租户 C 鉴权测试 部署预发布环境 失败时触发邮件/钉钉通知 门禁 Stage:所有租户 Job 通过 才允许合并或部署

3.5 多租户并行测试 Job 执行流程

下图展示了鉴权拦截测试 Stage 内部,多个租户 Job 的并行执行流程。每个 Job 独立运行,互不干扰,最终汇总测试报告。

多租户并行测试 Job 执行流程 多租户并行测试 Job 执行流程 鉴权拦截测试 Stage 启动 Job: 租户 A 注入 Token-A,执行测试 Job: 租户 B 注入 Token-B,执行测试 Job: 租户 C 注入 Token-C,执行测试 汇总测试报告,判断门禁结果

3.6 最佳实践总结

实践项 说明 推荐工具/方法
Pipeline 即代码 流水线配置与源代码一同版本管理 Jenkinsfile / .gitlab-ci.yml
门禁 Stage 鉴权拦截测试作为强制门禁 Stage 失败阻断后续流程
并行 Job 不同租户的测试并行执行 Jenkins parallel / GitLab CI parallel:matrix
环境隔离 每个 Job 使用独立的测试环境或数据 Docker 容器 / Kubernetes Pod
失败通知 门禁失败时及时通知团队 邮件 / 钉钉 / Slack Webhook
测试报告 收集并展示测试结果,便于追溯 JUnit 报告 / Allure 报告
核心要点:
  • Pipeline 即代码是 CI/CD 现代化的基础,确保流水线可追溯、可复用。
  • Stage 定义逻辑阶段,Job 定义具体任务;Stage 串行,Job 可并行。
  • 多租户鉴权测试应作为门禁 Stage,利用并行 Job 提升测试效率。
  • Jenkins 和 GitLab CI 都支持 Pipeline 即代码,选择取决于团队技术栈和平台偏好。