Skip to content

Instantly share code, notes, and snippets.

@ftclausen
Created April 13, 2017 05:36
Show Gist options
  • Star 44 You must be signed in to star a gist
  • Fork 10 You must be signed in to fork a gist
  • Save ftclausen/8c46195ee56e48e4d01cbfab19c41fc0 to your computer and use it in GitHub Desktop.
Save ftclausen/8c46195ee56e48e4d01cbfab19c41fc0 to your computer and use it in GitHub Desktop.
Jenkins pipeline - An approach to get all commits since the last successful build.
// -*- mode: groovy -*-
// vim: set filetype=groovy :
node( 'some_node' ) {
stage( "Phase 1" ) {
sshagent( credentials: [ 'some_creds' ] ) {
checkout scm
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"
}
}
}
}
def getLastSuccessfulCommit() {
def lastSuccessfulHash = null
def lastSuccessfulBuild = currentBuild.rawBuild.getPreviousSuccessfulBuild()
if ( lastSuccessfulBuild ) {
lastSuccessfulHash = commitHashForBuild( lastSuccessfulBuild )
}
return lastSuccessfulHash
}
/**
* Gets the commit hash from a Jenkins build object, if any
*/
@NonCPS
def commitHashForBuild( build ) {
def scmAction = build?.actions.find { action -> action instanceof jenkins.scm.api.SCMRevisionAction }
return scmAction?.revision?.hash
}
@Hobbit71
Copy link

Thanks - that was useful

@rmpestano
Copy link

Hi, another option (as described on the SO question) is to use Last Changes plugin, following is a (scripted) pipeline 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.

@belsander
Copy link

maybe not completely related, but useful nevertheless. I needed to obtain the branch name without using the env.

@NonCPS
def branchForBuild( build ) {
  def scmAction = build?.actions.find { action -> action instanceof jenkins.scm.api.SCMRevisionAction }
  return scmAction?.revision?.head?.getName()
}

@ababushk
Copy link

@belsander thank you! I've used this to retrieve commit hash from which Jenkinsfile was cloned to execute inside GitHub Organization Folder https://gist.github.com/oxygenxo/930980d79ab09c74da34be459563f760

@roman-acumen
Copy link

roman-acumen commented Nov 22, 2019

Solution using jenkins changelogsets

@NonCPS
def getAllChangeResults() {
	def result = getChangeStringForBuild(currentBuild)

	def buildToCheck = currentBuild.getPreviousBuild()
	while (buildToCheck != null && buildToCheck.result != 'SUCCESS') {
		result += "\nBuild #${buildToCheck.number} [${buildToCheck.result}]\n"
		result += getChangeStringForBuild(buildToCheck)

		buildToCheck = buildToCheck.previousBuild
	}

	return result
}

@NonCPS
def getChangeStringForBuild(build) {
    MAX_MSG_LEN = 60

    echo "Gathering SCM changes"
    def changeLogSets = build.changeSets
	def changeString = ""

    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]
            def truncated_msg = entry.msg.take(MAX_MSG_LEN)
			if (entry.msg.length() > MAX_MSG_LEN) {
				truncated_msg += "..."
			}

            changeString += "-[@${entry.author.getFullName().toLowerCase()}][${entry.commitId.take(6)}]: ${truncated_msg}\n"
        }
    }

    if (!changeString) {
        changeString = " - No new changes"
    }

    return "${changeString}"
}

@jrowinski3d
Copy link

Has anyone else having trouble with getRevisionList() ?

I keep receiving the following

[ERROR: getRevisionList]: org.jenkinsci.plugins.workflow.job.WorkflowRun

I believe its due to the git rev-list shell command as my multi-branch pipeline jobs are being merged before any building occurs. Seems to be comparing the same commit and erroring out. Testing the git rev-list on my local machine seems to output a bunch of git sha's out.

@Xydrel
Copy link

Xydrel commented Mar 5, 2021

roman-acumen commented on Nov 22, 2019

Thank you!

@vart123
Copy link

vart123 commented Sep 14, 2021

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

Does this only works with multibranch pipeline jobs and doesnot work with regular jobs? This doesnot seem to work for me for regular jobs..

@nwsparks
Copy link

nwsparks commented Jan 19, 2022

in a multi branch pipeline there is a env var exposed GIT_PREVIOUS_COMMIT. This seems to be the commit of the last build however regardless of pass fail.

@spun1525
Copy link

spun1525 commented Apr 8, 2022

Is there a way i can get the getLastSuccessfulCommit in a Declarative Pipeline ?

@rgarg-quotient
Copy link

rgarg-quotient commented Mar 4, 2023

GIT_PREVIOUS_SUCCESSFUL_COMMIT is the environment variable exposed by jenkins build and provides the last successful build git commit.

@yjsun1
Copy link

yjsun1 commented Mar 20, 2023

GIT_PREVIOUS_SUCCESSFUL_COMMIT is the environment variable exposed by jenkins build and provides the last successful build git commit.

simple variable! it works.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment