Jenkins 多分支流水线配置教程

Jenkins 多分支流水线配置教程

一、多分支流水线概述

1.1 什么是多分支流水线

多分支流水线(Multibranch Pipeline)是 Jenkins 针对多分支项目设计的自动化构建方案,能够自动发现代码仓库中的所有分支(如 maindevfeature/* 等),并为每个分支自动创建独立的流水线实例,分支新增/删除时会自动同步,无需手动配置单个分支任务。

1.2 为什么使用多分支流水线

适用于以下场景:

  • 项目存在多个开发分支(如主分支、开发分支、功能分支),需要对每个分支独立构建、测试;
  • 团队协作开发,需确保每个分支的代码提交后能快速验证稳定性;
  • 需实现分支级别的差异化配置(如主分支定时构建、功能分支仅提交触发)。

1.3 相对于自由风格/普通流水线的优势

对比维度 多分支流水线 自由风格项目 普通流水线(单分支)
分支管理 自动发现、同步所有分支 需手动为每个分支创建独立项目 仅支持单个分支,多分支需重复配置
配置维护 统一配置,分支共享核心逻辑 每个分支独立配置,维护成本高 多分支需复制多个流水线,配置冗余
灵活性 支持分支级差异化配置(定时、触发规则) 配置分散,差异化需手动调整 不支持分支差异化,需额外编写逻辑
自动化程度 提交/合并自动触发对应分支构建 需手动绑定分支与触发规则 仅能触发单个分支,多分支需额外配置
版本控制 流水线脚本(Jenkinsfile)纳入代码管理 配置存储在 Jenkins 服务器,无版本控制 脚本可版本控制,但仅对应单个分支

二、前置准备:GitHub PAT 凭证配置

多分支流水线需通过 GitHub 个人访问令牌(PAT)访问私有仓库,步骤如下:

2.1 创建 GitHub PAT(个人访问令牌)

  1. 登录 GitHub → 右上角头像 → SettingsDeveloper settingsPersonal access tokensGenerate new token
  2. 配置令牌信息:
    • 填写 Note(如 Jenkins 多分支流水线访问);
    • 勾选权限:repo(所有子权限,用于访问私有仓库)、read:org(可选,组织仓库需勾选);
  3. 点击 Generate token,生成后立即复制保存(仅显示一次)。

2.2 在 Jenkins 中添加 PAT 凭证

  1. 进入 Jenkins → Manage JenkinsManage Credentials全局添加凭证
  2. 选择凭证类型:Username with password
  3. 填写配置:
    • Username:你的 GitHub 用户名;
    • Password:步骤 2.1 生成的 PAT;
    • ID:自定义凭证 ID(如 github-pat),方便后续引用;
  4. 点击 OK 保存,凭证将用于仓库代码拉取和分支发现。

三、核心配置:分支源(Branch Source)选项详解

分支源是多分支流水线的核心配置,用于连接代码仓库、筛选分支、配置拉取规则。进入多分支流水线 → 配置分支源添加源GitHub,展开配置后,重点选项说明如下:

3.1 Within repository(仓库内分支/标签发现)

3.1.1 Discover branches(发现分支)
  • 作用:自动发现仓库中的所有分支,为有 Jenkinsfile 的分支创建流水线;
  • 用法
    • 勾选后默认发现所有分支;
    • 可选择 Exclude branches that do not contain the Jenkinsfile(仅发现包含流水线脚本的分支,推荐);
  • 场景:避免为无构建需求的分支(如废弃分支)创建流水线实例。
3.1.2 Discover pull requests from forks(发现 Fork 仓库的 PR)
  • 作用:自动发现来自 Fork 仓库的 Pull Request(PR),并创建临时构建实例;
  • 用法:勾选后可配置 PR 构建规则(如仅构建已审核的 PR);
  • 场景:开源项目或跨团队协作,需验证 Fork 仓库的 PR 稳定性。
3.1.3 Discover pull requests from origin(发现本仓库的 PR)
  • 作用:自动发现仓库内的 PR,支持 PR 合并前的预构建验证;
  • 用法 :勾选后可选择构建策略(如 Merge PR head with base branch,将 PR 分支与目标分支合并后构建);
  • 场景:团队内部协作,确保 PR 合并后不影响目标分支稳定性。
3.1.4 Discover tags(发现标签)
  • 作用 :自动发现仓库中的标签(如 v1.0.0),为标签创建构建实例;
  • 用法:勾选后可配置标签筛选规则;
  • 场景:版本发布时,标签提交后自动触发构建、打包。
3.1.5 Filter by name (with regular expression)(按正则筛选分支/标签)
  • 作用:通过正则表达式筛选需要构建的分支/标签,仅匹配的分支会被发现;
  • 用法
    • Include:填写正则表达式(如 ^(main|dev|feature/.*)$,仅保留 main、dev 和 feature 前缀分支);
    • Exclude:填写需排除的正则(如 ^feature/old-.*$,排除 old- 前缀的 feature 分支);
  • 注意 :正则匹配区分大小写,需准确编写表达式(如 ^Dev$ 不匹配 dev)。
3.1.6 Filter by name (with wildcards)(按通配符筛选分支/标签)
  • 作用:通过通配符快速筛选分支/标签,比正则更简单易用;
  • 用法
    • Include:用 * 匹配任意字符(如 main,dev,feature/*,保留 main、dev 和所有 feature 分支);
    • Exclude:排除不需要的分支(如 release/*,排除所有 release 分支);
  • 场景:快速筛选特定前缀的分支,无需编写复杂正则。
3.1.7 Ignore pull requests marked as drafts(忽略草稿 PR)
  • 作用:跳过标记为「草稿」的 PR,不触发构建;
  • 用法:直接勾选;
  • 场景:避免 PR 未完成时频繁触发无效构建。

3.2 General(通用拉取/构建配置)

3.2.1 Advanced checkout behaviours(高级检出行为)
  • 作用:配置代码检出后的额外操作(如检出到指定目录、设置超时);
  • 常用选项
    • Check out to matching local branch:检出到与远程分支同名的本地分支(默认检出到 detached HEAD 状态);
    • Timeout:设置检出超时时间(如 10 分钟,避免网络卡顿导致卡死);
  • 用法 :点击 添加 选择对应行为,按需配置。
3.2.2 Advanced clone behaviours(高级克隆行为)
  • 作用:优化 Git 克隆逻辑(加速克隆、缓存复用、大文件处理),详细配置见「第四章」;
  • 核心选项:浅克隆、参考仓库、克隆超时等。
3.2.3 Advanced sub-modules behaviours(高级子模块行为)
  • 作用:若仓库包含 Git 子模块(submodule),配置子模块的拉取规则;
  • 常用选项
    • Recursively update submodules:递归拉取所有子模块;
    • Use credentials for submodules:为子模块单独配置访问凭证;
  • 场景:项目依赖子模块(如公共组件库),需同步拉取子模块代码。
3.2.4 Check out to matching local branch(检出到匹配的本地分支)
  • 作用:将远程分支检出为本地同名分支(默认检出为「分离头指针」状态);
  • 用法:直接勾选;
  • 场景 :需在构建中执行 git push 等操作(分离头指针状态不支持提交)。
3.2.5 Checkout over SSH(通过 SSH 检出)
  • 作用:强制使用 SSH 协议拉取代码(默认根据仓库 URL 自动选择协议);
  • 用法:勾选后需配置 SSH 凭证(需提前在 Jenkins 中添加 SSH 私钥凭证);
  • 场景:仓库仅支持 SSH 访问,或需避免 HTTPS 协议的 SSL 问题。
3.2.6 Clean after checkout(检出后清理)
  • 作用:代码检出后,清理工作空间中的未跟踪文件(如构建产物、临时文件);
  • 用法:直接勾选;
  • 场景:避免旧构建产物影响新构建(如测试报告、日志文件残留)。
3.2.7 Clean before checkout(检出前清理)
  • 作用:检出代码前,清空整个工作空间(比「检出后清理」更彻底);
  • 用法:直接勾选;
  • 场景:需确保工作空间完全干净(如依赖包缓存冲突、配置文件篡改),但会增加构建时间。
3.2.8 Custom user name/e-mail address(自定义用户名/邮箱)
  • 作用:覆盖 Git 提交的用户名和邮箱(默认使用 Jenkins 节点的 Git 配置);
  • 用法 :勾选后填写自定义的 NameE-mail
  • 场景:构建过程中需提交代码(如自动更新版本号),需指定提交人身份。
3.2.9 First Build Changelog(首次构建变更日志)
  • 作用:首次构建时生成完整的变更日志(默认首次构建无变更记录);
  • 用法 :勾选后选择日志生成规则(如 Include all commits);
  • 场景:需追溯首次构建的代码基线。
3.2.10 Git LFS pull after checkout(克隆后拉取 LFS 大文件)
  • 作用:若仓库使用 Git LFS(大文件存储,如安装包、测试资源),自动拉取 LFS 跟踪的大文件;
  • 用法:直接勾选(需 Jenkins 节点已安装 Git LFS 工具);
  • 场景:项目包含超过 100MB 的大文件(Git 原生不适合存储大文件)。
3.2.11 Job display name strategy(任务显示名称策略)
  • 作用:自定义分支流水线实例的显示名称(默认显示分支名);
  • 用法 :选择策略(如 Branch name 直接显示分支名,Repository name - Branch name 显示仓库+分支名);
  • 场景:多仓库多分支场景,避免任务名称重复。
3.2.12 Prune stale remote-tracking branches(清理过期远程跟踪分支)
  • 作用:构建时清理本地已不存在的远程分支(如远程分支已删除,本地残留的跟踪分支);
  • 用法:直接勾选;
  • 场景:避免过期分支占用工作空间,保持本地分支与远程同步。
3.2.13 Prune stale tags(清理过期标签)
  • 作用:清理本地已不存在的远程标签(如远程标签已删除,本地残留标签);
  • 用法:直接勾选;
  • 场景:版本发布后删除旧标签,避免本地标签冗余。
3.2.14 Sparse Checkout paths(稀疏检出路径)
  • 作用:仅拉取仓库中的指定目录/文件(无需克隆整个仓库),加速拉取;
  • 用法
    • 勾选后点击 添加,填写需要检出的路径(如 src/jenkins/);
  • 场景:仓库体积大,但构建仅依赖部分目录(如仅需拉取源代码目录,无需文档、资源文件)。
3.2.15 Use commit author in changelog(变更日志中使用提交作者)
  • 作用:构建日志的「变更记录」中显示代码提交者的姓名和邮箱(默认显示 Jenkins 凭证用户);
  • 用法:直接勾选;
  • 场景:需追溯代码变更的实际提交人,方便问题定位。
3.2.16 Wipe out repository & force clone(清空仓库并强制克隆)
  • 作用:每次构建前删除本地仓库,重新强制克隆(解决本地仓库缓存冲突);
  • 用法:直接勾选;
  • 注意 :会大幅增加构建时间,仅在本地仓库损坏(如 git 操作失败)时临时启用。
3.2.17 Configure remote name(配置远程仓库名称)
  • 作用 :自定义远程仓库的名称(默认远程名称为 origin);
  • 用法 :填写自定义名称(如 upstream);
  • 场景:仓库需关联多个远程仓库(如上游开源仓库+本地私有仓库)。
3.2.18 Specify ref specs(指定引用规范)
  • 作用:自定义 Git 拉取的引用范围(如仅拉取特定分支、标签的提交);
  • 用法 :填写 ref spec 格式(如 +refs/heads/*:refs/remotes/origin/*,默认拉取所有分支;+refs/tags/*:refs/tags/* 拉取所有标签);
  • 场景:需限制拉取的分支/标签范围,减少数据传输量。

四、Advanced clone behaviours 详细配置

高级克隆行为用于优化代码拉取效率,尤其适合大仓库或网络不稳定场景,配置步骤:

进入多分支流水线 → 配置分支源AdvancedBehaviours添加Advanced clone behaviours,展开后配置如下:

4.1 常用配置项(按优先级排序)

配置项 作用 用法/推荐值 适用场景
Shallow clone(浅克隆) 仅拉取最新提交,不下载完整历史 勾选,配合「Shallow clone depth」使用 测试、构建无需历史记录(如冒烟测试)
Shallow clone depth 浅克隆深度(拉取最近 N 个提交) 1-50(推荐 1,仅最新提交) 加速克隆,减少数据传输
Reference repository 复用本地缓存仓库,仅拉取差异数据 勾选,填写本地镜像路径(如 D:\Jenkins\reference\SuuntoTest.git 同一节点多次拉取同一仓库
Clone timeout 克隆超时时间(避免无限等待) 勾选,设置 10-30 分钟 网络不稳定(如跨国访问 GitHub)
Fetch only the reference branch 仅拉取当前分支,不拉取其他分支引用 勾选 多分支流水线,无需其他分支数据
Use credentials for every fetch 每次拉取都使用凭证 勾选 私有仓库,避免凭证缓存失效
Skip SSL verification 忽略 HTTPS SSL 证书验证 仅 SSL 报错时勾选(测试环境) 内网节点无法获取公开 SSL 证书
LFS pull after clone 克隆后自动拉取 Git LFS 大文件 仓库有 LFS 大文件时勾选 项目包含安装包、测试资源等大文件

4.2 关键配置说明

4.2.1 浅克隆(Shallow clone)
  • 优势:拉取速度提升 50%-90%,尤其适合大仓库;
  • 注意:浅克隆无法执行 git log --oneline(查看早期提交)、git diff(跨历史版本对比),若构建需依赖历史,请勿启用。
4.2.2 参考仓库(Reference repository)
  1. 需提前在 Jenkins 节点创建本地镜像(仅执行 1 次):

    bash 复制代码
    # Windows 节点(Git Bash 执行)
    git clone --mirror https://github.com/YourTest.git  D:\Jenkins\reference\YourTest.git
  2. 配置路径时使用 Windows 反斜杠(\)或双斜杠(\\),确保 Jenkins 有读写权限。

4.2.3 克隆超时(Clone timeout)
  • 单位:分钟,推荐 10 分钟(小仓库)或 30 分钟(大仓库);
  • 超时后构建会失败,避免因网络卡顿占用 Jenkins 资源。

4.3 推荐配置组合(适配你的场景)

复制代码
Shallow clone: ✅
Shallow clone depth: 1
Reference repository: ✅ → 路径:D:\Jenkins\reference\SuuntoTest.git
Clone timeout: ✅ → 10 分钟
Fetch only the reference branch: ✅
Use credentials for every fetch: ✅

五、流水线脚本:节点标签筛选(单个/多个标签)

多分支流水线通过 agent 配置指定执行节点,支持单个标签、多个标签(且/或关系)筛选,语法如下:

5.1 核心语法

Jenkins 标签筛选支持逻辑运算:

  • 「且」关系:标签A && 标签B(节点必须同时具备两个标签);
  • 「或」关系:标签A 标签B(空格分隔,节点具备任一标签);
  • 「非」关系:标签A && !标签B(节点有 A 标签但无 B 标签)。

5.2 配置示例(写入 Jenkinsfile)

groovy 复制代码
pipeline {
    // 节点标签筛选核心配置
    agent {
        // 方案 1:多个标签「且」关系(必须同时有 Android 和 Ng 标签)
        label 'Android && Ng'
        
        // 方案 2:单个标签(节点有 master 标签即可)
        // label 'master'
        
        // 方案 3:「或」关系(节点有 Android 或 iOS 标签)
        // label 'Android iOS'
        
        // 方案 4:参数化标签(优先使用用户输入,默认 Android && Ng)
        // label params.NODE_LABEL ?: 'Android && Ng'
    }

    parameters {
        // 可选:参数化标签,支持用户手动指定
        string(name: 'NODE_LABEL', defaultValue: '', description: '执行节点标签(如 Android && Ng)')
    }

    stages {
        stage('Test') {
            steps {
                echo "当前执行节点:${env.NODE_NAME}"
                echo "节点标签:${env.NODE_LABELS}"
            }
        }
    }
}

5.3 注意事项

  • 标签大小写敏感:AndroidandroidNgNG,需与节点配置的标签完全一致;
  • 节点配置标签:进入 Jenkins → Manage Jenkins节点 → 目标节点 → 配置Labels,填写标签(如 master Android Ng)。

六、流水线脚本:定时任务配置

无需额外插件,直接在 Jenkinsfile 中通过 triggers 块配置定时构建,支持分支级差异化定时。

6.1 核心语法(Cron 表达式)

格式:分 时 日 月 周(空格分隔),支持通配符和逻辑运算:

  • *:任意值(如 * 表示每分钟/每小时);
  • */N:每 N 个单位(如 */5 表示每 5 分钟);
  • N-M:范围(如 1-5 表示周一至周五);
  • N,M:多个值(如 8,18 表示 8 点和 18 点)。

6.2 常用 Cron 示例

需求 Cron 表达式 说明
每天早上 8:00 执行 0 8 * * * 分=0,时=8,日/月/周=任意
每周一至周五 9:30 执行 30 9 * * 1-5 周=1(周一)至 5(周五)
每 6 小时执行一次 0 */6 * * * 时=每 6 小时(0、6、12、18 点)
每天 8:00、18:00 执行 0 8,18 * * * 时=8 和 18 点(逗号分隔)

6.3 配置示例(写入 Jenkinsfile)

groovy 复制代码
pipeline {
    agent { label 'Android && Ng' }
    triggers {
        // 方案 1:固定定时(每天 8 点执行)
        cron('0 8 * * *')
        
        // 方案 2:分支差异化定时(仅 main 分支定时,其他分支不定时)
        // cron(env.BRANCH_NAME == 'main' ? '0 8 * * *' : '')
    }

    parameters {
        // 定时执行时自动使用默认参数
        string(name: 'TEST_MARKER', defaultValue: 'SMOKE and not NG')
        string(name: 'UPGRADE', defaultValue: 'True')
    }

    stages {
        stage('定时构建测试') {
            steps {
                echo "定时构建触发,分支:${env.BRANCH_NAME}"
                echo "测试标签:${params.TEST_MARKER}"
            }
        }
    }
}

6.4 验证定时生效

  1. 提交 Jenkinsfile 到代码仓库,多分支流水线自动扫描更新;
  2. 进入分支的流水线实例 → 配置构建触发器,可看到自动生成的定时规则;
  3. 临时测试:将 Cron 改为 */5 * * * *(每 5 分钟执行),观察构建历史是否自动触发。

七、Poll SCM 实现代码 Push 触发构建

当 Jenkins 部署在内网(GitHub 无法通过 WebHook 访问)时,使用 Poll SCM 轮询方案(安装Poll SCM插件):Jenkins 定时检查代码仓库是否有新提交,有变更则自动触发对应分支构建。

7.1 配置步骤

  1. 进入多分支流水线 → 配置分支源Behaviours添加Poll SCM
  2. 填写 Schedule(轮询频率),示例:
    • */5 * * * *:每 5 分钟检查一次(实时性高,适合测试环境);
    • */15 * * * *:每 15 分钟检查一次(平衡实时性和服务器压力);
  3. 保存配置,Jenkins 会按频率扫描所有分支,有新提交则触发对应分支构建。

7.2 优势与注意事项

  • 优势:无需外网访问,配置简单,适配内网 Jenkins 场景;
  • 注意:
    • 轮询频率越短,实时性越高,但会增加 Jenkins 和 GitHub 的 API 调用压力;
    • 若仓库分支较多,建议配合「分支过滤」(如仅轮询 main、dev 分支),减少无效扫描。

7.3 补充:WebHook 实时触发(外网可访问场景)

若 Jenkins 可被 GitHub 访问,推荐使用 WebHook 实现实时触发(替代 Poll SCM):

  1. Jenkins 配置:进入多分支流水线 → 配置构建触发器 → 勾选 GitHub Hook Trigger for GITScm polling
  2. GitHub WebHook 配置:
    • 仓库 → SettingsWebhooksAdd webhook
    • Payload URLhttp://Jenkins地址:端口/github-webhook/(末尾 / 必须保留);
    • Content typeapplication/json
    • Which events:选择 Just the push event
  3. 提交代码后,GitHub 会立即通知 Jenkins,触发对应分支构建(延迟 < 10 秒)。

八、jenkinsFile示例

groovy 复制代码
pipeline {
   agent {
       label params.NODE_LABEL ?: 'Android'
   }

   environment {
       // 统一工作空间目录
       WORKSPACE_DIR = "${env.WORKSPACE}\\SuuntoTest"
       // 实时打印 Python 输出
       PYTHONUNBUFFERED = true
       // Windows 命令行 UTF-8 编码
       CMD_ENCODING = "chcp 65001 > nul 2>&1"
   }

   parameters {
       string(name: 'GIT_REPO_URL', defaultValue: 'git@github.com:Test.git', description: 'Git SSH 地址')
       string(name: 'PLATFORM', defaultValue: 'android', description: '测试平台 (android/android+ng/android+dilu)')
       string(name: 'TESTCASE', defaultValue: 'testcase_android/app/', description: '测试用例目录')
       string(name: 'TEST_MARKER', defaultValue: 'SMOKE and not NG', description: '''
       根据mark标签选择测试 适配-m 参数:
       示例:
         SMOKE
         SMOKE and not NG
       ''')
       string(name: 'TEST_NAME_EXPR', defaultValue: '', description: '''
       根据测试函数/类名匹配选择测试 适配-k 参数:
       示例:
         test_week_tab
         TestCalendar
       ''')
       string(name: 'RERUNS', defaultValue: '1', description: '重试次数')
       credentials(name: 'GIT_SSH_CRED', credentialType: 'ssh', defaultValue: 'github-ssh', description: 'SSH凭证用于拉取代码-私钥Jenkins配置的凭据ID')
       string(name: 'SEND_METHOD', defaultValue: 'test', description: '新钉钉群需要配置')
       string(name: 'UPGRADE', defaultValue: 'True', description: '是否升级,True or False')
       string(name: 'NODE_LABEL', defaultValue: 'Android', description: '执行构建的节点标签(需配置 android_devices_id 环境变量)')
       string(name: 'TITLE', defaultValue: 'Android每日冒烟', description: '测试任务标题')
   }

   stages {
       stage('参数校验') {
           steps {
               script {
                   echo "======================================"
                   echo "📋 开始参数校验"
                   echo "======================================"
                   if (!env.android_devices_id) {
                       error "❌ 选中的节点(标签:${params.NODE_LABEL})未配置 android_devices_id 环境变量!\n请在 Jenkins 节点配置 → 节点属性 → 环境变量 中添加。"
                   }
                   echo "✅ 从节点环境变量获取 DEVICE_ID:${env.android_devices_id}"
               }
           }
       }

       stage('Checkout Code') {
           steps {
               script {
                   echo "======================================"
                   echo "📥 准备拉取代码到目录: ${env.WORKSPACE_DIR}"
                   echo "======================================"

                   withCredentials([sshUserPrivateKey(credentialsId: params.GIT_SSH_CRED, keyFileVariable: 'GIT_KEY')]) {
                       dir("${env.WORKSPACE_DIR}") {
                           // 判断是否为首次拉取(.git文件夹是否存在)
                           def isFirstCheckout = !fileExists(".git")

                           if (isFirstCheckout) {
                               echo "首次拉取代码,执行初始克隆..."
                               // 首次拉取:直接用原生git步骤克隆代码
                               git(
                                   url: params.GIT_REPO_URL,
                                   branch: env.BRANCH_NAME,
                                   credentialsId: params.GIT_SSH_CRED,
                                   changelog: true,
                                   poll: false
                               )
                               bat """
                                   @echo on
                                   ${env.CMD_ENCODING}
                                   cd /d "${env.WORKSPACE_DIR}"
                                   echo "首次拉取:设置 skip-worktree 防止后续操作覆盖"
                                   git update-index --skip-worktree jenkins/jenkins_config.json
                                   git update-index --skip-worktree jenkins/result.json
                               """
                           } else {
                               try {
                                   bat """
                                       @echo on
                                       set GIT_SSH_COMMAND=ssh -i "%GIT_KEY%"
                                       cd /d "${env.WORKSPACE_DIR}"
                                       echo "设置 skip-worktree 防止后续操作覆盖"
                                       git update-index --skip-worktree jenkins/jenkins_config.json
                                       git update-index --skip-worktree jenkins/result.json
                                       echo "切换分支到 ${env.BRANCH_NAME}"
                                       git checkout ${env.BRANCH_NAME}
                                       echo "强制同步远程最新提交"
                                       git fetch origin ${env.BRANCH_NAME}
                                       git reset --hard origin/${env.BRANCH_NAME}
                                       echo "清理未跟踪文件"
                                       git clean -fd
                                       echo "拉取最新代码"
                                       git pull origin ${env.BRANCH_NAME}
                                   """
                               } catch (Exception e) {
                                   echo "⚠️ 警告:git 操作失败,但继续执行后续步骤: ${e.getMessage()}"
                               }
                           }
                       }
                   }
               }
           }
       }

       stage('Initialize Config') {
           steps {
               script {
                   echo "======================================"
                   echo "⚙️  初始化配置并写入 jenkins_config.json"
                   echo "======================================"

                   // 整合所有配置参数(DEVICE_ID 从节点环境变量获取)
                   def JENKINS_CONFIG = [
                       GIT_REPO_URL: params.GIT_REPO_URL,
                       BRANCH: env.BRANCH_NAME,
                       WORKSPACE_DIR: env.WORKSPACE_DIR,
                       PLATFORM: params.PLATFORM,
                       DEVICE_ID: env.android_devices_id,
                       TESTCASE: params.TESTCASE,
                       TEST_MARKER: params.TEST_MARKER,
                       TEST_NAME_EXPR: params.TEST_NAME_EXPR,
                       RERUNS: params.RERUNS,
                       JENKINS_BUILD_URL: env.BUILD_URL,
                       NOTIFY_EMAIL: params.NOTIFY_EMAIL,
                       JOB_URL: env.JOB_URL,
                       SEND_METHOD: params.SEND_METHOD,
                       BUILD_URL: env.BUILD_URL,
                       BUILD_NUMBER: env.BUILD_NUMBER,
                       JOB_NAME: env.JOB_NAME,
                       NODE_LABELS: env.NODE_LABELS,
                       NODE_NAME: env.NODE_NAME,
                       UPGRADE: params.UPGRADE,
                       TITLE: params.TITLE
                   ]

                   def CONFIG_PATH = "${env.WORKSPACE_DIR}\\jenkins\\jenkins_config.json"
                   // 确保jenkins目录存在
                   writeJSON file: CONFIG_PATH, json: JENKINS_CONFIG
                   echo "✅ 配置文件已写入:${CONFIG_PATH}"
               }
               bat 'set'
           }
       }

       stage('Setup Virtual Environment') {
           steps {
               script {
                   echo "======================================"
                   echo "🐍 设置虚拟环境并安装依赖"
                   echo "======================================"

                   dir("${env.WORKSPACE_DIR}") {
                       bat """
                           @echo on
                           ${env.CMD_ENCODING}
                           set PYTHONIOENCODING=utf-8
                           set PYTHONPATH=${env.WORKSPACE_DIR}

                           echo "创建Python虚拟环境"
                           python -m venv .venv

                           echo "升级pip并安装pipenv"
                           .venv\\Scripts\\python.exe -m pip install --upgrade pip
                           .venv\\Scripts\\python.exe -m pip install pipenv

                           echo "通过pipenv安装项目依赖"
                           .venv\\Scripts\\python.exe -m pipenv install
                       """
                   }
               }
           }
       }

       stage('Update Config') {
           steps {
               script {
                   echo "======================================"
                   echo "🔄 执行配置更新"
                   echo "======================================"

                   dir("${env.WORKSPACE_DIR}") {
                       bat """
                           @echo on
                           ${env.CMD_ENCODING}
                           set PYTHONIOENCODING=utf-8
                           set PYTHONPATH=${env.WORKSPACE_DIR}

                           .venv\\Scripts\\python.exe jenkins\\config_manager.py
                       """
                   }
               }
           }
       }

       stage('Generate Commit Report') {
           steps {
               script {
                   echo "======================================"
                   echo "📊 生成Git Commit历史报告"
                   echo "======================================"

                   dir("${env.WORKSPACE_DIR}") {
                       bat """
                           @echo on
                           ${env.CMD_ENCODING}
                           set PYTHONIOENCODING=utf-8
                           set PYTHONPATH=${env.WORKSPACE_DIR}

                           .venv\\Scripts\\python.exe jenkins\\git_commit_report.py . commit_history.html
                       """
                       // 归档报告(可选,在Jenkins界面查看)
                       archiveArtifacts artifacts: 'commit_history.html', allowEmptyArchive: true
                       echo "✅ Commit报告已生成并归档"
                   }
               }
           }
       }

       stage('Run Tests') {
           steps {
               script {
                   echo "======================================"
                   echo "🧪 开始执行测试用例"
                   echo "======================================"
                   echo "测试平台:${params.PLATFORM}"
                   echo "设备ID:${env.android_devices_id}"
                   echo "测试用例:${params.TESTCASE}"
                   echo "测试标签:${params.TEST_MARKER}"

                   try {
                       dir("${env.WORKSPACE_DIR}") {
                           bat """
                               @echo on
                               ${env.CMD_ENCODING}
                               set PYTHONIOENCODING=utf-8
                               set PYTHONPATH=${env.WORKSPACE_DIR}

                               .venv\\Scripts\\python.exe jenkins\\executor.py
                           """
                       }
                       echo "✅ 测试执行完成"
                   } catch (Exception e) {
                       currentBuild.result = 'FAILURE'
                       echo "❌ 测试执行失败:${e.getMessage()}"
                       throw e // 抛出异常,让Pipeline标记为失败
                   }
               }
           }
       }
   }

   post {
       success {
           echo "======================================"
           echo "✅ 流水线执行成功!"
           echo "构建地址:${env.BUILD_URL}"
           echo "======================================"
       }
       failure {
           echo "======================================"
           echo "❌ 流水线执行失败!"
           echo "构建地址:${env.BUILD_URL}"
           echo "======================================"

           // 发送失败通知
           dir("${env.WORKSPACE_DIR}") {
               bat """
                   @echo on
                   ${env.CMD_ENCODING}
                   set PYTHONIOENCODING=utf-8
                   set PYTHONPATH=${env.WORKSPACE_DIR}

                   .venv\\Scripts\\python.exe jenkins\\notification_sender.py --status failed
               """
           }
       }
   }
}
相关推荐
企鹅侠客9 小时前
Linux性能调优 详解磁盘工作流程及性能指标
linux·运维·服务器·性能调优
企鹅侠客9 小时前
Linux性能调优 再谈磁盘性能指标和进程级IO
linux·运维·服务器·性能调优
不过普通话一乙不改名10 小时前
Linux 网络收包的进阶之路:从普通 socket 到 AF_XDP 零拷贝
linux·运维·网络
在路上@Amos10 小时前
Linux 命令行查看 串口hex数据
linux·运维·服务器
人工智能训练10 小时前
Linux 系统核心快捷键表(可打印版)
linux·运维·服务器·人工智能·ubuntu·容器·openeuler
dualven_in_csdn12 小时前
【疑难问题】某些win11机器 网卡统计也会引起dns client 占用cpu问题
运维·服务器·网络
sanduo11212 小时前
docker 构建编排过程中常见问题
运维·docker·容器
翼龙云_cloud12 小时前
亚马逊云渠道商:如何快速开始使用Amazon RDS?
运维·服务器·云计算·aws
0思必得012 小时前
[Web自动化] 开发者工具元素(Elements)面板
运维·前端·自动化·web自动化·开发者工具