How to cancel redundant builds on branches/pulls, but not master

I’m using jenkins pipelines, and have this disableConcurrentBuilds set - which right now if someone pushes a commit to a branch or pull request that is building, jenkins will cancel the existing build and start on the latest commit.

This is great for branches and pull requests, but I don’t want this to happen to master

How do I alter disableConcurrentBuilds s.t. that it doesn’t apply to master?

pipeline {
  agent any
  options {
    disableConcurrentBuilds(abortPrevious: true)
  }
1 Like

It can be done in a script step

if (env.CHANGE_ID != null) {
    properties([disableConcurrentBuilds(abortPrevious: true)])
}

but place that before anything that allocates an agent, so that it can be executed while all agents are busy.

Related discussion in https://issues.jenkins.io/browse/JENKINS-41392?focusedCommentId=344397&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-344397.

Thanks for pointing out that logic can be done like this. In my case I want to apply this to pull requests and branches – would env.BRANCH_ID != 'master' be more appropriate in this case?

Also - where do I stick this thing?

I currently have:

pipeline {
  agent any
  options {
    disableConcurrentBuilds(abortPrevious: true)
  }

Doesn’t seem to like it if I stick if statements inside the options block

1 Like

I did this in a convoluted way. The pipeline block has agent none and two stages:

  • stage('Options') inherits agent none and just uses a script step to run the if statement.
  • stage('Agent') specifies an actual agent and then contains nested stages that run on the agent.

This works, but the stage view looks a bit strange, as the time in spent the queue waiting for an agent to become available is accounted to stage('Agent').

Possibly the if statement could come before pipeline, but I did not try.

Using the guidance in this thread, I was able to get the following to work:

pipeline {
    agent none
    environment {
        ALLOW_CONCURRENT_BUILDS = allowConcurrentBuilds()
    }
def allowConcurrentBuilds() {
    // Disable concurrent builds on PRs and abort previous.
    if (env.CHANGE_ID != null) {
        properties([disableConcurrentBuilds(abortPrevious: true)])
        return false
    } else {
        properties([])
        return true
    }
}

I clear the properties in the else case because when testing on a Pull Request the properties seem to be sticky as seen on the Configure page view/change-requests/job/PR-XXXX/configure.

Screenshot 2024-05-15 at 11.18.45 AM

I couldn’t get the stage('Options') suggestion to work, but it’s likely due to my lack of knowledge about the declarative pipeline.