Skip to content

Instantly share code, notes, and snippets.

@sturman
Created November 23, 2020 21:02
Show Gist options
  • Save sturman/ce445c13a741fb3a0d4c0bf9bb940580 to your computer and use it in GitHub Desktop.
Save sturman/ce445c13a741fb3a0d4c0bf9bb940580 to your computer and use it in GitHub Desktop.
Jenkins pipeline that demonstrates how to abort previous pull request build when new changes are pushed
@NonCPS
def cancelPreviousBuilds() {
def jobName = env.JOB_NAME
def buildNumber = env.BUILD_NUMBER.toInteger()
def ghPrId = env.ghprbPullId.toInteger()
/* Get job name */
def currentJob = Jenkins.instance.getItemByFullName(jobName)
/* Iterating over the builds for specific job */
for (def build : currentJob.builds) {
def listener = build.getListener()
def ghprbPullId = build.getEnvironment(listener).get('ghprbPullId').toInteger()
def exec = build.getExecutor()
/* If there is a build that is currently running and it's not current build */
if (build.isBuilding() && build.number.toInteger() < buildNumber && exec != null && ghprbPullId == ghPrId) {
/* Then stop it */
exec.interrupt(
Result.ABORTED,
new CauseOfInterruption.UserInterruption("Aborted by #${currentBuild.number}")
)
println("Aborted previously running build #${build.number}")
}
}
}
pipeline {
agent any
stages {
stage('Init') {
agent { label 'master' }
steps {
script {
cancelPreviousBuilds()
}
}
}
stage('Test') {
agent { label 'agent' }
steps {
//...
}
}
}
}
@LeeU1911
Copy link

Thanks for this! My working version is below. I removed the commit id check as my project only builds on branches and not PRs, therefore, ghprbPullId seemed to be null.

I also needed to approve a bunch of methods to be executed in the script, simply check if your log has something like "administrator needs to approve blah blah", follow that link and click approve

@NonCPS
def cancelPreviousBuilds() {
    def jobName = env.JOB_NAME
    def buildNumber = env.BUILD_NUMBER.toInteger()

    /* Get job name */
    def currentJob = Jenkins.instance.getItemByFullName(jobName)

    /* Iterating over the builds for specific job */
    for (def build : currentJob.builds) {
        def listener = build.getListener()
        def exec = build.getExecutor()
        /* If there is a build that is currently running and it's not current build */
        if (build.isBuilding() && build.number.toInteger() < buildNumber && exec != null) {
            /* Then stop it */
            exec.interrupt(
                    Result.ABORTED,
                    new CauseOfInterruption.UserInterruption("Aborted by #${currentBuild.number}")
                )
            println("Aborted previously running build #${build.number}")
        }
    }
}

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