You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在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

火山引擎 最新活动