有没有一份Jenkins Pipeline脚本可以将自上一个成功构建以来的所有更改放入变量中?我正在使用git和多分支管道作业。
有没有一份Jenkins Pipeline脚本可以将自上一个成功构建以来的所有更改放入变量中?我正在使用git和多分支管道作业。
好的,我设法拼凑出了一些东西。我相信你可以更好地迭代数组,但目前这就是我所拥有的:
node('Android') {
passedBuilds = []
lastSuccessfulBuild(passedBuilds, currentBuild);
def changeLog = getChangeLog(passedBuilds)
echo "changeLog ${changeLog}"
}
def lastSuccessfulBuild(passedBuilds, build) {
if ((build != null) && (build.result != 'SUCCESS')) {
passedBuilds.add(build)
lastSuccessfulBuild(passedBuilds, build.getPreviousBuild())
}
}
@NonCPS
def getChangeLog(passedBuilds) {
def log = ""
for (int x = 0; x < passedBuilds.size(); x++) {
def currentBuild = passedBuilds[x];
def changeLogSets = currentBuild.rawBuild.changeSets
for (int i = 0; i < changeLogSets.size(); i++) {
def entries = changeLogSets[i].items
for (int j = 0; j < entries.length; j++) {
def entry = entries[j]
log += "* ${entry.msg} by ${entry.author} \n"
}
}
}
return log;
}
根据CaptRespect的回答,我编写了以下用于声明式流水线的脚本:
def changes = "Changes:\n"
build = currentBuild
while(build != null && build.result != 'SUCCESS') {
changes += "In ${build.id}:\n"
for (changeLog in build.changeSets) {
for(entry in changeLog.items) {
for(file in entry.affectedFiles) {
changes += "* ${file.path}\n"
}
}
}
build = build.previousBuild
}
echo changes
在 stage->when->expression
部分中,这非常有用,可以在某些文件发生更改时仅运行一个阶段。尽管我还没有涉及到这一部分,但我希望从中创建一个共享库,并使其能够传递一些 globbing 模式以进行检查。
编辑:顺便查看文档,如果您想深入了解的话。您应该能够将所有的 object.getSomeProperty()
调用转换为只使用 entry.someProperty
。
def getChangesSinceLastSuccessfulBuild() {
def changes = []
def build = currentBuild
while (build != null && build.result != 'SUCCESS') {
changes += (build.changeSets.collect { changeSet ->
(changeSet.items.collect { item ->
(item.affectedFiles.collect { affectedFile ->
affectedFile.path
}).flatten()
}).flatten()
}).flatten()
build = build.previousBuild
}
return changes.unique()
}
def listFilesForBuild(build) {
def files = []
currentBuild.changeSets.each {
it.items.each {
it.affectedFiles.each {
files << it.path
}
}
}
files
}
def filesSinceLastPass() {
def files = []
def build = currentBuild
while(build.result != 'SUCCESS') {
files += listFilesForBuild(build)
build = build.getPreviousBuild()
}
return files.unique()
}
def files = filesSinceLastPass()
currentBuild
需要声明性流水线吗?当我在我的脚本流水线中尝试时,我得到了java.lang.NullPointerException: Cannot get property 'result' on null object
的错误,这可能是因为currentBuild
为空。 - Shane BishoplistFilesForBuild()
中的 build
参数未被使用(你在该函数中使用了currentBuild
代替它)。 - Shane Bishop对于使用 Accurev 的任何人,这里是 andsens 答案的一种适应方式。由于 Accurev 插件没有实现 getAffectedFiles,因此无法使用 andsens 的答案。可以在扩展 ChangeLogSet.Entry 类的 AccurevTransaction 的文档中找到更多信息,链接在这里。
import hudson.plugins.accurev.*
def changes = "Changes: \n"
build = currentBuild
// Go through the previous builds and get changes until the
// last successful build is found.
while (build != null && build.result != 'SUCCESS') {
changes += "Build ${build.id}:\n"
for (changeLog in build.changeSets) {
for (AccurevTransaction entry in changeLog.items) {
changes += "\n Issue: " + entry.getIssueNum()
changes += "\n Change Type: " + entry.getAction()
changes += "\n Change Message: " + entry.getMsg()
changes += "\n Author: " + entry.getAuthor()
changes += "\n Date: " + entry.getDate()
changes += "\n Files: "
for (path in entry.getAffectedPaths()) {
changes += "\n " + path;
}
changes += "\n"
}
}
build = build.previousBuild
}
echo changes
writeFile file: "changeLog.txt", text: changes
lastSuccessfulBuild()
函数中,为什么if()
语句是build.result != SUCCESS
? - Chris FcurrentBuild.rawBuild.changeSets
是在调用checkout scm
时初始化的。如果你的调用在这条指令之前进行,你将得不到任何东西。 - Maxif ((build != null) && (build.getResult().toString() == 'SUCCESS'))
。build.result将返回类hudson.model.Result,而不是一个字符串。 - Biju