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

Jenkins多分支Pipeline修改changeSet展示上次成功构建以来变更问题

多分支Pipeline场景下自定义变更集范围的可行方案

多分支Pipeline完全可以实现「仅展示上次成功构建以来所有提交」的需求,替换默认取上一次构建(无论成功失败)变更的逻辑。

原有代码失效的核心原因

直接给currentBuild.rawBuild.changeSets赋值git命令输出的纯字符串数组是错误写法:

  • Jenkins内部changeSets属性仅接受hudson.scm.ChangeLogSet类型的实例集合,纯字符串列表不符合类型要求
  • 页面渲染、Jira插件等逻辑读取changeSets时,会按照ChangeLogSet的结构解析提交信息,传入字符串会直接触发解析异常,导致UI展示故障、插件无法识别提交

正确实现代码

实现核心思路是通过Git插件自带的变更日志解析器,生成符合Jenkins内部规范的ChangeLogSet实例,再写入构建对象,完全兼容所有依赖原生变更集的功能。

import hudson.plugins.git.GitChangeLogParser
import hudson.plugins.git.GitSCM
import org.jenkinsci.plugins.workflow.job.WorkflowRun

@NonCPS
String getBuildCommitHash(WorkflowRun build) {
    def scmRevisionAction = build?.actions.find { action ->
        action instanceof jenkins.scm.api.SCMRevisionAction
    }
    return scmRevisionAction?.revision?.hash
}

@NonCPS
WorkflowRun getLastSuccessfulBuild(WorkflowRun currentRun) {
    return currentRun.getPreviousSuccessfulBuild()
}

def call(Map config = [:]) {
    WorkflowRun currentRun = currentBuild.rawBuild
    String currentCommit = getBuildCommitHash(currentRun)
    WorkflowRun lastSuccessBuild = getLastSuccessfulBuild(currentRun)
    String fromCommit

    if (lastSuccessBuild) {
        fromCommit = getBuildCommitHash(lastSuccessBuild)
    } else {
        // 首次构建无历史成功记录时,取仓库初始根提交作为起点
        fromCommit = sh(script: "git rev-list --max-parents=0 HEAD", returnStdout: true).trim()
    }

    // 生成符合GitChangeLogParser要求格式的临时变更日志文件
    sh """
        git log ${fromCommit}..${currentCommit} \
        --pretty=format:'<commit><h>%H</h><an>%an</an><ae>%ae</ae><ai>%ai</ai><s>%s</s><b>%b</b></commit>' \
        > ${WORKSPACE}/.tmp_git_changelog.xml
    """

    // 解析日志写入标准变更集
    @NonCPS
    def applyNewChangeSet() {
        File changelogFile = new File("${WORKSPACE}/.tmp_git_changelog.xml")
        GitSCM scm = currentRun.getParent().getScm() as GitSCM
        GitChangeLogParser parser = scm.createChangeLogParser()
        // 清空原有默认生成的变更集
        currentRun.changeSets.clear()
        // 写入新计算的变更集
        currentRun.changeSets.add(parser.parse(currentRun, changelogFile))
        changelogFile.delete()
    }

    applyNewChangeSet()
    sh "rm -f ${WORKSPACE}/.tmp_git_changelog.xml"
}

多分支场景适配说明

  • 多分支Pipeline下每个分支的构建历史完全独立,getPreviousSuccessfulBuild()方法会自动匹配当前分支的历史成功构建,不会跨分支拉取其他分支的提交,符合分支独立变更统计的要求
  • 生成的变更集结构和Jenkins原生生成的完全一致,Jira插件、构建变更页、其他依赖变更集的插件都可以正常读取识别
  • 脚本需要在受信任的共享库或者通过管理员脚本权限审批后运行,因为操作rawBuild内部属性需要执行权限
  • 如果存在合并提交场景,可以给git log命令加--no-merges参数过滤合并提交,按需调整即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 23:15:11