当前位置: 首页 > news >正文

Jenkins Pipeline 多job依赖、触发多Job、并行执行及制品下载

以下是关于 Jenkins Pipeline 触发多平台Job、并行执行及制品下载 的详细攻略,涵盖核心概念、关键配置和完整示例。

一、核心场景与目标

假设我们需要在一个主Pipeline中:

  1. 自动识别当前代码分支(如 wip/jenkins);
  2. 对分支名中的特殊字符(如 /)进行转义,适配Jenkins的Job命名规则;
  3. 并发触发3个平台的子Job(MacOSX、Windows、Linux),等待它们执行完成(!!!还有一种方式值直接下载其他job最后一次成功的制品,但是每个job的制品可能版本就不一样,就比如可能不是最新一次提交而生成的制品,有可能这次提交,其他job还没有执行完成,又或者执行失败了!!!);
  4. 从每个子Job中下载构建好的制品(如可执行文件,下载制品也可以通过Jenkins自带的插件下载,直接通过URL下载是由于一直有一个权限问题,目前不知道为什么);
  5. 聚合所有平台的制品,打包存档。

二、关键概念与细节

1. 分支名转义:为什么需要处理 /

Jenkins中,多分支Pipeline的Job名称会自动将分支名中的 / 编码为 %2F(URL编码规则)。例如:

  • 原始分支名:wip/jenkins
  • 对应的Jenkins Job名称:wip%2Fjenkins

处理方式:用 sed 命令将 / 替换为 %2F,确保后续拼接Job路径时匹配Jenkins实际名称。

2. 触发Job的URL vs 下载制品的URL

Jenkins中,“触发Job”和“下载制品”的路径格式不同,这是最容易出错的点:

场景路径格式说明示例(基于分支 wip/jenkins
触发Job用「Jenkins项目全称」,层级用 / 分隔,无 job/ 前缀(Jenkins内部识别格式)。Middleware/Whiteboard/WhiteboardTools/WbresOnMacOSX/wip%2Fjenkins
下载制品用「浏览器URL格式」,每个层级需加 job/ 前缀(HTTP请求路径格式)。http://jenkins-url/job/Middleware/job/Whiteboard/job/WhiteboardTools/job/WbresOnMacOSX/job/wip%2Fjenkins/3/artifact/...

核心区别:触发Job时Jenkins接受“项目全称”(无 job/),而下载制品时的HTTP URL必须用 job/ 分隔层级。

3. 并行触发Job:为什么需要并行?

如果3个平台的子Job无依赖关系(可独立执行),并行触发能大幅缩短总构建时间:

  • 顺序执行:总时间 = t1 + t2 + t3
  • 并行执行:总时间 ≈ max(t1, t2, t3)

Jenkins通过 parallel 块实现并行,需注意语法(子阶段用键值对定义,支持 failFast 快速失败)。

三、详细步骤与配置

步骤1:定义分支名并转义

在Pipeline开始阶段,获取当前分支名并转义 /%2F,确保后续路径正确。

stage('Set BRANCH_CODING') {steps {script {// 获取当前分支名(Jenkins内置变量 BRANCH_NAME,如 wip/jenkins)// 转义 / 为 %2F,适配Jenkins Job名称格式env.BRANCH_CODING = sh(script: '''echo "${BRANCH_NAME}" | sed 's/\\//%2F/g' ''',  // 关键:用sed替换 / 为 %2FreturnStdout: true).trim()echo "转义后的分支名(适配Jenkins):${env.BRANCH_CODING}"  // 输出:wip%2Fjenkins}}
}
步骤2:并行触发多平台子Job

parallel 块并发触发3个平台的子Job,每个子Job包含“触发→等待完成→下载制品”逻辑。

关键配置

  • triggerJobPath:触发Job用的“项目全称”(无 job/);
  • dependJobPath:下载制品用的“URL路径”(含 job/);
  • build 步骤:wait: true 等待Job完成,propagate: true 子Job失败时主Job也失败;
  • failFast: true:可选,一个子Job失败则立即终止所有并行任务。
步骤3:下载制品并验证

子Job执行完成后,通过构建编号(buildNumber)精准定位最新制品,用 curl 下载并验证文件是否存在。

步骤4:聚合制品并存档

所有平台制品下载完成后,打包为zip并存档到Jenkins。

四、完整Pipeline脚本(带详细注释)

pipeline {agent {node {label 'UBUNTU'  // 运行主Pipeline的节点标签}}// 可选:手动指定测试分支(实际场景用Jenkins内置的BRANCH_NAME)environment {// BRANCH_NAME = 'wip/jenkins'  // 测试时可手动设置,正式环境注释掉}stages {// 步骤1:处理分支名,转义 / 为 %2Fstage('Set BRANCH_CODING') {steps {script {// 从Jenkins内置变量获取当前分支名(如 git 分支)// 用sed将 / 替换为 %2F(适配Jenkins Job名称)env.BRANCH_CODING = sh(script: '''echo "${BRANCH_NAME}" | sed 's/\\//%2F/g' ''',returnStdout: true).trim()echo "✅ 转义后的分支名:${env.BRANCH_CODING}"  // 示例输出:wip%2Fjenkins}}}// 步骤2:并行触发3个平台的子Job并下载制品stage('并行触发子Job并下载制品') {steps {script {// 并行执行3个子阶段(MacOSX/Windows/Linux)parallel(failFast: true,  // 快速失败:一个子Job失败,所有并行任务终止// 子阶段1:MacOSX平台"MacOSX": {// 1. 定义路径(触发Job和下载制品的路径分开)def jenkinsUrl = env.JENKINS_URL.trim().replaceAll(/\/$/, '')  // 去除URL末尾的 /// 触发Job用的项目全称(无 job/)def triggerJobPath = "Middleware/Whiteboard/WhiteboardTools/WbresOnMacOSX/${env.BRANCH_CODING}"// 下载制品用的URL路径(含 job/)def dependJobPath = "Middleware/job/Whiteboard/job/WhiteboardTools/job/WbresOnMacOSX/job/${env.BRANCH_CODING}"def artifactSourcePath = 'tools/wbres/bin/macos/wbres'  // 子Job中制品的相对路径def artifactTargetDir = 'bin/macos/'  // 本地保存路径// 2. 触发子Job并等待完成echo "=== [MacOSX] 触发子Job:${triggerJobPath} ==="def buildResult = build(job: triggerJobPath,  // 传入项目全称(无 job/)wait: true,           // 等待子Job执行完成propagate: true,      // 子Job失败时,主Job也失败quietPeriod: 0        // 立即触发,不延迟)def buildNumber = buildResult.getNumber()  // 获取子Job的构建编号(如 3)echo "=== [MacOSX] 子Job执行完成,构建编号:${buildNumber} ==="// 3. 构建下载URL并下载制品def downloadUrl = "${jenkinsUrl}/job/${dependJobPath}/${buildNumber}/artifact/${artifactSourcePath}"sh "mkdir -p ${artifactTargetDir}"  // 创建本地目录echo "=== [MacOSX] 下载URL:${downloadUrl} ==="// 用Jenkins凭证下载(避免明文密码)withCredentials([usernamePassword(credentialsId: '2c66b483-ef17-436e-a0d2-114d00bdf090',  // 你的凭证IDusernameVariable: 'JENKINS_USER',passwordVariable: 'JENKINS_PWD')]) {sh """# 用curl下载制品,-f确保失败时返回非0状态码curl -f -L -v \-u "${JENKINS_USER}:${JENKINS_PWD}" \"${downloadUrl}" \-o "${artifactTargetDir}/wbres"# 验证下载结果echo "=== [MacOSX] 验证制品 ==="ls -l "${artifactTargetDir}"if [ -f "${artifactTargetDir}/wbres" ]; thenecho "✅ [MacOSX] 制品下载成功"elseecho "❌ [MacOSX] 制品下载失败"exit 1  # 失败时终止Pipelinefi"""}},// 子阶段2:Windows x64平台(逻辑与MacOSX一致,仅路径不同)"Windows x64": {def jenkinsUrl = env.JENKINS_URL.trim().replaceAll(/\/$/, '')def triggerJobPath = "Middleware/Whiteboard/WhiteboardTools/WbresX64OnWindows/${env.BRANCH_CODING}"def dependJobPath = "Middleware/job/Whiteboard/job/WhiteboardTools/job/WbresX64OnWindows/job/${env.BRANCH_CODING}"def artifactSourcePath = 'tools/wbres/bin/win32/wbres.exe'def artifactTargetDir = 'bin/win32/'echo "=== [Windows] 触发子Job:${triggerJobPath} ==="def buildResult = build(job: triggerJobPath, wait: true, propagate: true, quietPeriod: 0)def buildNumber = buildResult.getNumber()echo "=== [Windows] 子Job执行完成,构建编号:${buildNumber} ==="def downloadUrl = "${jenkinsUrl}/job/${dependJobPath}/${buildNumber}/artifact/${artifactSourcePath}"sh "mkdir -p ${artifactTargetDir}"echo "=== [Windows] 下载URL:${downloadUrl} ==="withCredentials([usernamePassword(credentialsId: '2c66b483-ef17-436e-a0d2-114d00bdf090', usernameVariable: 'JENKINS_USER', passwordVariable: 'JENKINS_PWD')]) {sh """curl -f -L -v -u "${JENKINS_USER}:${JENKINS_PWD}" "${downloadUrl}" -o "${artifactTargetDir}/wbres.exe"echo "=== [Windows] 验证制品 ==="ls -l "${artifactTargetDir}"if [ -f "${artifactTargetDir}/wbres.exe" ]; thenecho "✅ [Windows] 制品下载成功"elseecho "❌ [Windows] 制品下载失败"exit 1fi"""}},// 子阶段3:Linux (Docker)平台"Linux (Docker)": {def jenkinsUrl = env.JENKINS_URL.trim().replaceAll(/\/$/, '')def triggerJobPath = "Middleware/Whiteboard/WhiteboardTools/WbresGccLinuxDocker/${env.BRANCH_CODING}"def dependJobPath = "Middleware/job/Whiteboard/job/WhiteboardTools/job/WbresGccLinuxDocker/job/${env.BRANCH_CODING}"def artifactSourcePath = 'tools/wbres/bin/linux/wbres'def artifactTargetDir = 'bin/linux/'echo "=== [Linux] 触发子Job:${triggerJobPath} ==="def buildResult = build(job: triggerJobPath, wait: true, propagate: true, quietPeriod: 0)def buildNumber = buildResult.getNumber()echo "=== [Linux] 子Job执行完成,构建编号:${buildNumber} ==="def downloadUrl = "${jenkinsUrl}/job/${dependJobPath}/${buildNumber}/artifact/${artifactSourcePath}"sh "mkdir -p ${artifactTargetDir}"echo "=== [Linux] 下载URL:${downloadUrl} ==="withCredentials([usernamePassword(credentialsId: '2c66b483-ef17-436e-a0d2-114d00bdf090', usernameVariable: 'JENKINS_USER', passwordVariable: 'JENKINS_PWD')]) {sh """curl -f -L -v -u "${JENKINS_USER}:${JENKINS_PWD}" "${downloadUrl}" -o "${artifactTargetDir}/wbres"echo "=== [Linux] 验证制品 ==="ls -l "${artifactTargetDir}"if [ -f "${artifactTargetDir}/wbres" ]; thenecho "✅ [Linux] 制品下载成功"elseecho "❌ [Linux] 制品下载失败"exit 1fi"""}})}}}// 步骤3:聚合所有平台的制品并存档stage('聚合制品并存档') {steps {script {// 将所有平台的制品打包为zipsh 'mkdir -p bin && zip -r wbres_all_platforms.zip bin/'}// 存档到Jenkins(仅当所有步骤成功时)archiveArtifacts(artifacts: 'wbres_all_platforms.zip',fingerprint: true,onlyIfSuccessful: true)echo "✅ 所有平台制品已聚合并存档:wbres_all_platforms.zip"}}}// 构建结束后通知(可选)post {success {echo "🎉 主Pipeline执行成功!所有制品已就绪。"// 可添加邮件/企业微信通知:emailext to: 'xxx@example.com', subject: '构建成功', body: '...'}failure {echo "❌ 主Pipeline执行失败,请查看日志。"// 失败通知:emailext to: 'xxx@example.com', subject: '构建失败', body: '...'}}
}

五、调试与验证技巧

  1. 验证分支名转义
    查看 Set BRANCH_CODING 阶段的输出,确认 BRANCH_CODING 正确转义(如 wip/jenkinswip%2Fjenkins)。

  2. 检查触发Job的路径
    在Jenkins网页端导航到子Job,查看浏览器URL中的“项目全称”(如 Middleware/Whiteboard/.../wip%2Fjenkins),与脚本中的 triggerJobPath 对比是否一致。

  3. 验证下载URL
    下载阶段输出的 downloadUrl 可直接复制到浏览器,用Jenkins账号密码访问,确认能否下载制品(排除URL格式错误)。

  4. 并行执行日志
    在Jenkins Pipeline页面,并行阶段会显示为“分支”,可点击单个分支查看详细日志(如MacOSX子阶段的触发和下载过程)。

六、常见问题与解决

  1. “No item named … found”
    原因:triggerJobPath 与Jenkins实际项目全称不匹配(如未转义 / 或多了 job/)。
    解决:按“触发Job的URL格式”修正 triggerJobPath,确保无 job// 已转义为 %2F

  2. 并行阶段语法错误
    原因:parallel 块内用 stage(...) { ... } 定义子阶段,或 failFast 位置错误。
    解决:子阶段用键值对 “名称”: { ... } 定义,failFast 作为 parallel 函数的参数(如 parallel(failFast: true, "子阶段1": { ... }))。

  3. 制品下载404
    原因:downloadUrl 中的 dependJobPath 未加 job/ 层级,或构建编号错误。
    解决:确保 dependJobPath 每个层级都有 job/,并通过 buildResult.getNumber() 获取正确的构建编号。

通过以上步骤,你可以实现“并行触发多平台Job→等待完成→下载制品→聚合存档”的完整流程,大幅提升构建效率并确保制品版本一致性。

http://www.dtcms.com/a/536426.html

相关文章:

  • 静态网站 服务器男女做暖暖到网站
  • PortableApps_U 便携式软件_Software
  • Map Set
  • 云渲染技术高效创作的三大核心支撑
  • Linux小课堂: HTTPS协议原理与Apache服务器配置实战
  • 51c大模型~合集37
  • 03-Machine-4-fft.py K230进行快速傅里叶变换、频率计算及幅值计算功能演示
  • 医院系统接口对接实战:从 WSDL 到 HTTP 的全流程解析
  • 【C++学习】对象特性--构造函数
  • 装修公司前十强郑州做网站优化
  • 绿色网站欣赏站点查询
  • 插件:@vitejs/plugin-basic-ssl
  • Docker使用详解:在ARM64嵌入式环境部署Python应用
  • 【微知】MAC笔记本如何重启tourchbar?(sudo pkill TouchBarServer)
  • Smartproxy API 代理 IP 提取指南——JSON-first 架构与参数化最佳实践
  • 统计过程能力指数在齿轮制造中的应用学习分享
  • 河北地矿建设集团官方网站昆山市网站建设
  • __金仓数据库平替MongoDB实战:制造业生产进度管理的国产化升级之路__
  • 电商设计就是网站设计吗乐清本地生活服务平台
  • html css js网页制作成品——似锦HTML+CSS网页设计(5页)附源码
  • 某教育大厂面试题解析:MySQL索引、Redis缓存、Dubbo负载均衡等
  • wordpress怎么加菜单阿里网站怎样做seo
  • 2025年损坏Excel文件修复工具推荐:一键恢复表格内容
  • 网站一直百度上搜不到是怎么回事素马杭州网站设计介绍
  • 基于 STM32 的智能水表流量计设计与实现 —— 数据采集与远程传输
  • 深度学习核心概念拆解:张量、模型、训练、推理
  • C++初阶 -- 模拟实现list
  • 开源Outline系统基础知识要点及避坑要点
  • 淘宝客云建站官网模板网pi
  • 中国糕点网页设计网站查工程建设不良记录免费的网站