sickgemini
sickgemini

Reputation: 551

How to syncronise Jenkins stages on different nodes to single changeset?

I have a Jenkins pipeline that runs two jobs on different slaves as follows

node('node-1') {
    stage ('Checkout') {
        checkout scm
    }
    stage ('Build First Part') {
        < do some building >
    }
}
node('node-2') {
    stage ('Checkout') {
        checkout scm
    }     
    stage ('Build Second Part') {
        < do some more building >
    }
}

The task on node-2 requires the task on node-1 to complete first.

I've noticed that if a commit occurs while the task on node-1 is running that the checkout on node-2 contains the new commit.

I'm using Perforce for source control.

How do I ensure that the checkouts on the two nodes are on the same changeset?

Upvotes: 0

Views: 268

Answers (2)

sickgemini
sickgemini

Reputation: 551

Extending on @pitseekers answer you can achieve this by

On the first build node:

  • Save the changeset to a file (p4_changelist.txt)
  • Stash the saved file.

Then on the second build node:

  • Unstash the file
  • Read the changelist value out of the file to a variable.
  • Checkout the repository using the changelist value. This is the pin argument in the perforce populate list.

Pipeline steps:

node('node-1') {
    stage ('Checkout') {
        checkout scm
    }
    stage ('Save changelist number') {
        writeFile file: 'p4_changelist.txt', text: "${env.P4_CHANGELIST}"
        stash includes: 'p4_changelist.txt', name: 'p4_changelist'
    }
    stage ('Build First Part') {
        < do some building >
    }
} 
node('node-2') {
    stage ('Checkout') {
        unstash 'p4_changelist'
        def changelist = readFile 'p4_changelist.txt'
        checkout perforce(
            credential: 'credential',
            populate: autoClean(
                delete: true,
                modtime: false,
                parallel: [
                    enable: false,
                    minbytes: '1024',
                    minfiles: '1',
                    threads: '4'
                ],
                // ****** Use the read changelist value here ******
                pin: changelist,
                quiet: true,
                replace: true,
                tidy: false
            ),
            workspace: manualSpec(
                charset: 'none',
                name: 'jenkins-${NODE_NAME}-${JOB_NAME}-${EXECUTOR_NUMBER}',
                pinHost: false,
                spec: clientSpec(
                    allwrite: false,
                    backup: false,
                    clobber: true,
                    compress: false,
                    line: 'LOCAL',
                    locked: false,
                    modtime: false,
                    rmdir: false,
                    serverID: '',
                    streamName: '',
                    type: 'WRITABLE',
                    view: ''
                )
            )
        )
    }      
    stage ('Build Second Part') {
        < do some more building >
    }
}

Upvotes: 0

pitseeker
pitseeker

Reputation: 2553

You could do the checkout on the master (or anywhere else) and stash it.
Then unstash it on each node. It is actually quicker than you might assume.

For example:

node() {
  stage ('Checkout') {
    checkout scm
    stash name: 'checkout'
  }
}

builders['builder1'] = {
  node('node-1'){
    stage('Build First Part') {
      cleanWs()
      unstash 'checkout'
      < do some building >
    }
  }
}
builders['builder2'] = {
  node('node-2'){
    stage('Build Second Part') {
      cleanWs()
      unstash 'checkout'
      < do some more building >
    }
  }
}
parallel builders

Upvotes: 1

Related Questions