Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jenkins pipeline milestone not cancelling previous ongoing build

I am experimenting with Jenkins pipeline and milestones and cannot figure out why Jenkins is not cancelling the previous build when a new build crosses the milestone.

Example Jenkinsfile

pipeline {
    agent any

    parameters {
        booleanParam(defaultValue: true, description: '', name: 'userFlag')
    }

    stages {
        stage("foo") {
            steps {
                milestone(ordinal: 1, label: "BUILD_START_MILESTONE")
                sh 'sleep 1000'
            }
        }
    } 
}

Triggering this pipeline twice does not cancel the 1st job

like image 907
puneeth Avatar asked Sep 04 '17 17:09

puneeth


People also ask

How can I abort a running pipeline build if a new one is started?

While build #1 is running, if build #2 is started, it will create milestone1 and milestone2 in the project. Build #2 will immediately pass milestone1 and will therefore cause Build #1 to abort.

How do I force abort Jenkins?

Abort the job by clicking the red X next to the build progress bar. Click on "Pause/resume" on the build to pause. Click on "Pause/resume" again to resume the build.


4 Answers

I have a simple work around with milestone plugin, according to the document:

  • Builds pass milestones in order (taking the build number as sorter field).
  • Older builds will not proceed (they are aborted) if a newer one already passed the milestone.
  • When a build passes a milestone, any older build that passed the previous milestone but not this one is aborted.
  • Once a build passes the milestone, it will never be aborted by a newer build that didn't pass the milestone yet.

you can try something like this:

pipeline {
    agent any
    stages {
        stage('Stop Old Build') {
            steps {
                milestone label: '', ordinal:  Integer.parseInt(env.BUILD_ID) - 1
                milestone label: '', ordinal:  Integer.parseInt(env.BUILD_ID)
            }
        }
    }
}

you can put this at the start of any pipeline.

Assume you just start a new build, #5. The first milestone, will be used to passes #4's second milestone, and the second milestone(of #5) will be used to kill #4's process, if it's currently running.

like image 104
D.W Avatar answered Oct 17 '22 22:10

D.W


I don't think the behavior is "If I'm a newer build that crosses this milestone, then all older build that crossed this milestone will be cancelled"

The actual behavior of the milestone step is that when a more recent pipeline crosses it first, then it prevents older pipeline from crossing that milestone.

like image 23
warhod Avatar answered Oct 17 '22 22:10

warhod


Try this:

/* This method should be added to your Jenkinsfile and called at the very beginning of the build*/
@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) {
        /* If there is a build that is currently running and it's not current build */
        if (build.isBuilding() && build.number.toInteger() != buildNumber) {
            /* Than stopping it */
            build.doStop()
        }
    }
}
like image 14
sshepel Avatar answered Oct 17 '22 21:10

sshepel


The disableConcurrentBuilds property has been added to Pipeline. The Pipeline syntax snippet generator offers the following syntax hint:

properties([disableConcurrentBuilds(abortPrevious: true)])

That property is used on ci.jenkins.io to cancel older plugin build jobs when newer plugin build jobs start.

Declarative Pipeline also includes the disableConcurrentBuilds option that is documented in the Pipeline syntax page.

The declarative directive generator suggests the following:

options {
  disableConcurrentBuilds abortPrevious: true
}
like image 1
Mark Waite Avatar answered Oct 17 '22 22:10

Mark Waite