Checkout and run SCM pipeline only on master node

Viewed 3530

I coded a generic pipeline which accepts several parameters in order to deploy releases from a pre-defined GitHub repository to specific nodes. I wanted to host this pipeline on a Jenkinsfile on GitHub, so I configured the job to work with a "Pipeline script from SCM". The fact is - when I try and build the job - the Jenkinsfile gets checked out on every node. Is it possible to checkout and execute the Jenkinsfile only on, say, the master node and run the pipeline as intended?

EDIT: As I stated before, the pipeline works just fine and as intended setting the job to work with a pipeline script. The thing is when I try and change it to be a "Pipeline script from SCM", the Jenkinsfile gets checked out on every agent, which is a problem since I don't have git installed on any agent other than master. I want the Jenkinsfile to be checked out only on master agent and be executed as intended. FYI the pipeline below:

def agents = "$AGENTS".toString()
def agentLabel = "${ println 'Agents: ' + agents; return agents; }"

pipeline {
    agent none

    stages {
        stage('Prep') {
            steps {
                script {
                    if (agents == null || agents == "") {
                        println "Skipping build"
                        skipBuild = true
                    }
                                    
                    if (!skipBuild) {
                        println "Agents set for this build: " + agents
                    }
                }
            }
        }
    
        stage('Powershell deploy script checkout') {
            agent { label 'master' }
        
            when {
                expression {
                    !skipBuild
                }
            }
        
            steps {
                git url: 'https://github.com/owner/repo.git', credentialsId: 'git-credentials', branch: 'main'
                stash includes: 'deploy-script.ps1', name: 'deploy-script'
            }
        }
    
        stage('Deploy') {
            agent { label agentLabel }
        
            when {
                expression {
                    !skipBuild
                }
            }
        
            steps {
                unstash 'deploy-script'
            
                script {
                    println "Execute powershell deploy script on agents set for deploy"
                }
            }
        }
    }
}
4 Answers

I think that skipDefaultCheckout is what are you looking for:

pipeline {
    options {
        skipDefaultCheckout true
    }

    stages {
        stage('Prep') {
                steps {
                    script {
                            ........................
                    }
                }       
        }
    }
}

Take a look to the documentation:

skipDefaultCheckout Skip checking out code from source control by default in the agent directive.

https://www.jenkins.io/doc/book/pipeline/syntax/

I think you are requesting the impossible.

Now:

your Jenkinsfile is inside your jenkins configuration and is sent as such to each of your agents. No need for git on your agents.

Pipeline script for SCM:

Since you use git, SCM = git. So you are saying: my Pipeline needs to be fetched from a git repository. You are declaring the Deploy step to run on agent { label agentLabel }, so that step is supposed to run on another agent than master. How would you imagine that agent could get the content of the Jenkinsfile to know what to do, but not use git ?

What happens in Jenkins?

  • Your master agent gets triggered that it needs to build
  • the master agent checkouts the Jenkinsfile using git (since it is a Pipeline script from SCM)
  • jenkins reads the Jenkinsfile and sees what has to be done.
  • for the Prep stage, I'm not quite sure what happens without agent, I guess that runs on master agent.
  • the Powershell deploy script checkout is marked to run on master agent, so it runs on master agent (note that the Jenkinsfile will get checked out with git two more times:
    • before starting the stage, because jenkins needs to know what to execute
    • one more checkout because you specify git url: 'https://github.com/owner/repo.git'...
  • the Deploy stage is marked to run on agentLabel, so jenkins tries to checkout your Jenkinsfile on that agent (using git)...

You can use Scripted Pipeline to do this, it should basically look like this

node('master') {
    checkout scm
    stash includes: 'deploy-script.ps1', name: 'deploy-script'
}

def stepsForParallel = [:]
env.AGENTS.split(' ').each { agent ->
    stepsForParallel["deploy ${agent}"] = { ->

    node(agent) {
        unstash 'deploy-script'
    }
}
parallel stepsForParallel

you can find all info about jenkins agent section here. Shortly: you can call any agent by name or label.

pipeline {
  agent {
    label 'master'
  }
}

If it will not work for you, then you will need to set any label on master node and call it by label

pipeline {
  agent {
    label 'master_label_here'
  }
}
Related