'Jenkinsfile - get all changes between builds
With reference to this question is there a way to get the equivalent information from when using the mult-branch pipeline? Specifically - the list of commits since the last successful build.
Currently we use the following
def scmAction = build?.actions.find { action ->
action instanceof jenkins.scm.api.SCMRevisionAction
}
return scmAction?.revision?.hash
but this only returns the last commit that triggered the build if multiple commits were pushed. I accept that the very first build of a new branch might be ambiguious but getting a list of commits that triggered the build when possible would be very useful.
Solution 1:[1]
I have found a solution that seems to work for us. It revolves around getting the currentBuild
commit hash and then the lastSuccessfulBuild
commit hash. First we wrote a utility method for getting a commit hash of a given Jenkins build object:
def commitHashForBuild(build) {
def scmAction = build?.actions.find { action -> action instanceof jenkins.scm.api.SCMRevisionAction }
return scmAction?.revision?.hash
}
then use that to get the lastSuccessfulBuild
's hash:
def getLastSuccessfulCommit() {
def lastSuccessfulHash = null
def lastSuccessfulBuild = currentBuild.rawBuild.getPreviousSuccessfulBuild()
if ( lastSuccessfulBuild ) {
lastSuccessfulHash = commitHashForBuild(lastSuccessfulBuild)
}
return lastSuccessfulHash
}
finally combine those two in a sh
function to get the list of commits
def lastSuccessfulCommit = getLastSuccessfulCommit()
def currentCommit = commitHashForBuild(currentBuild.rawBuild)
if (lastSuccessfulCommit) {
commits = sh(
script: "git rev-list $currentCommit \"^$lastSuccessfulCommit\"",
returnStdout: true
).split('\n')
println "Commits are: $commits"
}
you can then use the commits
array to query various things in Git as your build requires. E.g. you can use this data to get a list of all changed files since the last successful build.
I have put this into a complete example Jenkinsfile Gist to show how it fits together in context.
A possible improvement would be to use a Java/Groovy native Git library instead of shelling out to a sh
step.
Solution 2:[2]
I think Jenkins Last changes plugin can provide the information you need, take a look here: https://plugins.jenkins.io/last-changes, following is an example:
node {
stage("checkout") {
git url: 'https://github.com/jenkinsci/last-changes-plugin.git'
}
stage("last-changes") {
def publisher = LastChanges.getLastChangesPublisher "LAST_SUCCESSFUL_BUILD", "SIDE", "LINE", true, true, "", "", "", "", ""
publisher.publishLastChanges()
def changes = publisher.getLastChanges()
println(changes.getEscapedDiff())
for (commit in changes.getCommits()) {
println(commit)
def commitInfo = commit.getCommitInfo()
println(commitInfo)
println(commitInfo.getCommitMessage())
println(commit.getChanges())
}
}
}
Note that by default (without the need for groovy scripting) the plugin makes the list of commits available for browsing on the jenkins UI, see here.
I hope it helps.
Solution 3:[3]
I was looking for how to get the git hash of the last successful build to do some git diff-tree change detection. I was following Friedrich's answer to programmatically get the SCM actions and revision hash out of the build returned from currentBuild.rawBuild.getPreviousSuccessfulBuild().
I was struggling to get this working with the current Jenkins API, and then realized that the git Jenkins plugin now exports the env var GIT_PREVIOUS_SUCCESSFUL_COMMIT. I now just refer to ${env.GIT_COMMIT} and ${env.GIT_PREVIOUS_SUCCESSFUL_COMMIT} to do a git diff-tree in my pipelines.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | |
Solution 3 | sporkthrower |