You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jenkins配置:单作业成功触发下游构建,避免重复执行

解决Jenkins作业A/B触发1-4避免重复执行的方案

嘿,这个场景我之前帮团队处理过,刚好有几个实用的方案,你可以根据现有作业的结构来选:

方法一:用标记作业+条件触发(适合传统自由风格作业,改动小)

这个思路是给作业1-4加个“已执行”的标记,不管是A还是B触发,先看标记状态,没执行过才跑,跑过就跳过。

  • 步骤1:建一个极简的标记作业
    新建一个叫Flag_Jobs_1-4的作业,加一个字符串参数FLAG_ACTION(可选值SET或RESET),然后加个Shell步骤:

    # 假设我们在Jenkins服务器上存一个标记文件,路径可自行调整
    FLAG_FILE="/var/jenkins_home/flags/jobs_1-4_flag"
    if [ "$FLAG_ACTION" = "SET" ]; then
        echo "true" > $FLAG_FILE
    elif [ "$FLAG_ACTION" = "RESET" ]; then
        echo "false" > $FLAG_FILE
    fi
    

    这个作业的作用就是切换标记状态。

  • 步骤2:修改A和B的触发逻辑
    别直接在A/B的构建后操作里触发1-4了,换成「Conditional BuildStep」(需要先安装这个插件):

    1. 先加一个“执行Shell”的条件步骤,检查标记文件的值:
      FLAG_FILE="/var/jenkins_home/flags/jobs_1-4_flag"
      # 如果文件不存在,默认标记为未执行
      if [ ! -f $FLAG_FILE ]; then echo "false" > $FLAG_FILE; fi
      CURRENT_FLAG=$(cat $FLAG_FILE)
      if [ "$CURRENT_FLAG" = "false" ]; then exit 0; else exit 1; fi
      
    2. 条件满足(标记为未执行)时,同时触发两个操作:
      • 触发作业1、2、3、4(并行或串行都可以)
      • 触发标记作业Flag_Jobs_1-4,传入参数FLAG_ACTION=SET
    3. 条件不满足时,直接跳过触发逻辑即可。
  • 步骤3:添加标记重置逻辑(可选)
    如果需要每天重置标记(比如每天凌晨),给标记作业加个定时触发器,设置H 0 * * *,并传入参数FLAG_ACTION=RESET。


方法二:用Pipeline重构(灵活度拉满,适合长期维护)

如果能把作业改成Pipeline,逻辑会更清晰,也不用依赖太多插件:

方案1:做一个统一的触发调度Pipeline

新建一个Pipeline作业,设置为当A或B成功后触发,然后在脚本里控制:

pipeline {
    agent any
    stages {
        stage('Check if Jobs 1-4 need to run') {
            steps {
                script {
                    // 以作业1为例,检查最近一次构建是否是A/B触发且在24小时内
                    def job1 = Jenkins.instance.getItemByFullName('Job1')
                    def lastValidBuild = job1.getBuilds().find { build ->
                        // 判断是否是A或B触发的
                        def isTriggeredByAorB = build.causes.any { cause ->
                            cause instanceof hudson.model.Cause.UpstreamCause &&
                            (cause.upstreamProject == 'JobA' || cause.upstreamProject == 'JobB')
                        }
                        // 判断是否在最近24小时内
                        def isRecent = build.timestamp.time > (System.currentTimeMillis() - 24*60*60*1000)
                        isTriggeredByAorB && isRecent
                    }

                    if (!lastValidBuild) {
                        echo 'Jobs 1-4 haven\'t been triggered by A/B recently, starting them...'
                        // 并行触发四个作业
                        parallel(
                            "Job1": { build job: 'Job1', wait: false },
                            "Job2": { build job: 'Job2', wait: false },
                            "Job3": { build job: 'Job3', wait: false },
                            "Job4": { build job: 'Job4', wait: false }
                        )
                    } else {
                        echo "Jobs 1-4 were already triggered at ${lastValidBuild.timestamp}, skip."
                    }
                }
            }
        }
    }
}

这样不管A还是B先完成,只要1-4没被触发过,就跑一次,之后再触发就直接跳过。

方案2:给每个作业1-4加自我判断逻辑

如果不想改A/B,直接给作业1-4改成Pipeline,在开头加判断:

pipeline {
    agent any
    stages {
        stage('Pre-check: Avoid duplicate run') {
            steps {
                script {
                    def lastBuild = currentBuild.previousBuild
                    if (lastBuild) {
                        // 检查上一次构建是否是A或B触发的,且在有效期内
                        def isTriggeredByAorB = lastBuild.causes.any { cause ->
                            cause instanceof hudson.model.Cause.UpstreamCause &&
                            (cause.upstreamProject == 'JobA' || cause.upstreamProject == 'JobB')
                        }
                        def isWithinValidPeriod = lastBuild.timestamp.time > (System.currentTimeMillis() - 24*60*60*1000)
                        
                        if (isTriggeredByAorB && isWithinValidPeriod) {
                            error "Abort: This job was already triggered by A/B at ${lastBuild.timestamp}, no need to run again."
                        }
                    }
                }
            }
        }
        // 原来的构建步骤
        stage('Build & Deploy') {
            steps {
                // 你的原有构建逻辑,比如拉代码、打包、打标签等
            }
        }
    }
}

这样不管A还是B触发这个作业,它都会先自检,符合重复条件就直接终止,避免重复打标签的问题。


方法三:用节流插件快速限制(适合简单场景)

如果只是想让作业1-4在指定时间内只跑一次,装个Throttle Concurrent Builds Plugin就行:

  • 给作业1-4分别配置插件:
    1. 勾选「Throttle this project」
    2. 设置「Maximum total concurrent builds」为1
    3. 勾选「Throttle all builds」,然后设置「Cool down period」(比如填1440,代表24小时)
      这样不管A还是B触发,作业在冷却期内只会执行一次,后续的触发请求都会被插件拦截。

内容的提问来源于stack exchange,提问作者50th Mersenne Prime

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:17:18