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

Jenkins跳过Checkout阶段时自定义工作区Git轮询失效问题咨询

问题描述
  • 基于Jenkins搭建软件编译部署流水线,对接Bitbucket Cloud时使用Bitbucket插件实现代码轮询与流水线自动触发,初始checkout配置如下:
checkout(poll: true, scm:[$class: 'GitSCM',  
         branches: [[name: "my_branch"]], 
         extensions: [[$class: 'RelativeTargetDirectory', relativeTargetDir: "my_dir"]], 
         userRemoteConfigs: [[credentialsId: "$credentialsId", url: "my_repo"]]
])
  • 该流水线的Jenkinsfile存放在软件代码仓库外部,在stage层级定义了自定义目录用于代码拉取操作,流水线包含Checkout、Build、Deploy1、Deploy2多个支持跳过配置的阶段。
  • 异常表现:流水线全量执行时所有功能运行正常,但如果Checkout阶段被跳过,Git轮询逻辑就会异常:轮询会忽略配置的自定义目录,转而在Jenkins任务默认工作区路径下检测代码变更。

可复现该问题的最小化流水线代码如下:

properties([pipelineTriggers([pollSCM("* * * * *")])])

pipeline {
    parameters {
        booleanParam(name: 'UPDATE_SOURCES', defaultValue: True)
    }
    stages {
        stage('Checkout') {
            agent {
                label 'agent_name'
            }
            when {
                expression { return params.UPDATE_SOURCES }
            }
            steps {
                dir("some_full_path_dir") {
                    script {
                        checkout(poll: true, scm:[$class: 'GitSCM', branches: [name: "branch_name"], 
                            userRemoteConfigs: [[credentialsId: "whatever", url: "repo_url"]]
                        ])
                    }
                }
            }
        }
    }
}

当Checkout阶段被跳过时,后续构建的轮询逻辑会忽略配置的some_full_path_dir自定义路径,仅在C:\Jenkins\etc\etc这类默认工作区路径下检测代码变更;只有Checkout阶段正常执行时,Git轮询功能才可正常运行。该问题目前无官方解决方案,以下为经过验证的可行变通方案。

变通实现方案

方案1:将SCM轮询配置注册逻辑抽离到不可跳过的全局步骤

Jenkins内置的SCM轮询逻辑依赖每次构建成功执行checkout步骤时记录的SCM元数据(包含仓库地址、分支、目标工作目录等信息),如果带poll: true的checkout步骤所在阶段被跳过,Jenkins就会丢失自定义目录配置,回退到默认工作区路径做检测。

  • 不要把带轮询标记的checkout步骤放在带when判断的可跳过阶段中,将SCM配置定义为全局变量,在流水线最外层、所有业务阶段之前的固定执行块(比如初始化步骤、全局pre步骤)中,执行一次轻量checkout,仅用于让Jenkins正确记录SCM轮询需要的配置信息。
  • 轻量checkout可配置浅克隆参数降低开销,执行完可直接清理临时拉取的文件,不会影响后续正式拉代码的逻辑,示例配置:
// 全局定义SCM配置
def scmConfig = [$class: 'GitSCM', 
    branches: [[name: "branch_name"]],
    extensions: [[$class: 'RelativeTargetDirectory', relativeTargetDir: "some_full_path_dir"]],
    userRemoteConfigs: [[credentialsId: "whatever", url: "repo_url"]]
]
pipeline {
    agent any
    triggers { pollSCM('* * * * *') }
    stages {
        stage('InitScmPollMeta') {
            // 该阶段不设置任何when判断,永远执行
            steps {
                script {
                    // 浅克隆拉取,仅用于注册轮询元数据
                    checkout(poll: true, changelog: false, scm: scmConfig, depth: 1, noTags: true)
                    // 可选:清理临时拉取的文件,不影响后续流程
                    dir("some_full_path_dir") {
                        deleteDir()
                    }
                }
            }
        }
        stage('Checkout') {
            agent { label 'agent_name' }
            when { expression { return params.UPDATE_SOURCES } }
            steps {
                dir("some_full_path_dir") {
                    script {
                        // 正式拉取代码,这里不需要再设置poll:true
                        checkout(scm: scmConfig)
                    }
                }
            }
        }
        // 其余Build、Deploy阶段保持原有逻辑不变
    }
}

方案2:弃用定时轮询,改用Webhook主动触发

Jenkins内置的SCM轮询本身存在实时性差、依赖本地工作区状态的问题,生产环境更推荐直接通过Bitbucket Cloud的Webhook触发流水线:

  • 移除流水线中配置的pollSCM触发器,在Bitbucket仓库的Webhook配置中,添加代码推送事件对应的Jenkins触发地址,指定分支有代码提交时Bitbucket会主动发起请求触发构建,完全绕开Jenkins本地的目录轮询逻辑,不会再出现路径不匹配的问题。
  • 触发时可在Webhook中携带最新commit信息、提交人等参数,流水线直接根据参数判断是否需要执行代码拉取、后续构建部署步骤,稳定性远高于定时轮询。

方案3:自定义代码变更检测逻辑

如果必须保留轮询能力,可以完全弃用Jenkins内置的pollSCM逻辑,自行实现固定目录下的变更检测:

  • 移除内置pollSCM触发器,在流水线不可跳过的初始化阶段,直接进入自定义代码目录执行Git命令对比commit哈希判断是否有新变更,根据检测结果设置标记位,再决定是否执行后续的Checkout、Build等阶段。核心检测逻辑示例:
def hasCodeChange = false
dir("some_full_path_dir") {
    if (fileExists(".git")) {
        def localCommit = sh(script: "git rev-parse HEAD", returnStdout: true).trim()
        sh "git fetch --depth=1 origin branch_name"
        def remoteCommit = sh(script: "git rev-parse FETCH_HEAD", returnStdout: true).trim()
        hasCodeChange = localCommit != remoteCommit
    } else {
        // 目录不存在时判定需要拉取代码
        hasCodeChange = true
    }
}
// 将hasCodeChange存入全局变量,供后续阶段的when判断使用

内容的提问来源于stack exchange,提问作者IonutS

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 00:24:44