如何在Jenkinsfile(Pipeline)中获取所有并发构建作业信息并执行操作?
根据并发运行作业的Display Name执行预处理操作的实践方案
我之前在Jenkins和GitHub Actions的项目里都实现过类似需求——在启动流水线新实例前,先检查当前所有并发运行的同流水线作业的displayName,再执行对应的操作(比如终止同名实例、统计运行数量、触发告警等)。分享几个落地性强的方案:
一、Jenkins流水线实现
Jenkins可以通过Groovy脚本直接调用内置API来获取运行中的构建实例,核心思路是在流水线开头加入检查逻辑:
pipeline { agent any stages { stage('Pre-check: Handle Concurrent Jobs by DisplayName') { steps { script { // 获取当前流水线的所有运行中构建 def currentJob = Jenkins.instance.getItemByFullName(env.JOB_NAME) def runningBuilds = currentJob.getBuilds().findAll { it.isBuilding() } // 定义要匹配的displayName规则(这里示例是完全匹配"Release Build v2.x") def targetDisplayName = "Release Build v2.x" // 遍历运行中的构建,执行操作 runningBuilds.each { build -> if (build.getDisplayName() == targetDisplayName) { echo "Found running build with target displayName: #${build.number}" // 示例操作1:终止该运行中的构建 build.doStop() echo "Stopped build #${build.number}" // 示例操作2:记录日志或触发告警 // slackSend channel: '#ci-alerts', message: "Terminated old build #${build.number} to start new one" } } } } } // 后续业务阶段 stage('Build') { steps { echo 'Starting new build...' } } } }
注意事项:
- 需要确保Jenkins开启了允许脚本访问Jenkins内部API(在全局安全配置里调整)
- 如果需要模糊匹配
displayName,可以把==换成contains()或者正则匹配,比如build.getDisplayName() =~ /Release Build v\d+\.\d+/ - 避免并发竞争:如果多个新实例同时启动,可能出现检查完后又有新实例启动的情况,可以结合Jenkins的
Lockable Resources插件加锁,确保检查和操作的原子性
二、GitHub Actions实现
GitHub Actions可以通过actions/github-script调用GitHub REST API,获取当前工作流的运行实例:
name: My Pipeline on: [push] jobs: pre-check: runs-on: ubuntu-latest steps: - name: Cancel running jobs with target displayName uses: actions/github-script@v6 with: script: | // 获取当前工作流的所有运行中实例 const runs = await github.rest.actions.listWorkflowRuns({ owner: context.repo.owner, repo: context.repo.repo, workflow_id: context.workflow, status: 'in_progress' }) // 定义目标displayName(这里示例是模糊匹配包含"Production Deploy") const targetDisplayNamePattern = /Production Deploy/ // 遍历并处理匹配的运行实例 for (const run of runs.data.workflow_runs) { // 排除当前正在启动的这个实例 if (run.id !== context.runId && targetDisplayNamePattern.test(run.name)) { console.log(`Found running job with target displayName: #${run.run_number}`) // 执行取消操作 await github.rest.actions.cancelWorkflowRun({ owner: context.repo.owner, repo: context.repo.repo, run_id: run.id }) console.log(`Cancelled job #${run.run_number}`) } } # 后续业务Job build-and-deploy: needs: pre-check runs-on: ubuntu-latest steps: - name: Build run: echo "Starting build..."
注意事项:
GITHUB_TOKEN需要有actions:write权限(默认的token已经包含这个权限)- 如果需要更复杂的操作(比如统计数量、发送通知),可以在脚本里扩展逻辑
- 同样要注意并发竞争,可以结合
concurrency关键字配合group来限制同一组的并发数,但如果是基于displayName的动态判断,还是需要脚本检查
三、通用思路总结
不管用什么CI/CD工具,核心步骤都是一致的:
- 获取实例列表:调用工具的API获取当前流水线所有处于运行状态的实例
- 过滤匹配:根据
displayName的规则(完全匹配、模糊匹配、正则匹配)筛选目标实例 - 执行操作:对筛选出的实例执行预设操作(终止、通知、统计等)
- 原子性保障:如果需要避免并发冲突,要通过锁机制或工具自带的并发控制功能确保检查和操作的连续性
内容的提问来源于stack exchange,提问作者Dillip Kumar Behera




