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
相关产品推荐
相关产品推荐

