Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jenkins is re-using a pipeline workspace and I wish for each build to have a unique workspace

So, most of the questions and answers I've found on this subject is for people who want to use the SAME workspace for different runs. (Which baffles me, but then I require a clean slate each time I start a job. Leftover stuff will only break things)

My issue is the EXACT opposite - I MUST have a separate workspace for each run (or I need to know how to create files with the same name in different runs that stay with that run only, and which are easily reachable from bash scripts started by the pipeline!)

So, my question is - how do I either force Jenkins to NOT use the same workspace for two concurrently-running jobs on different hosts, OR what variable can I use in the 'custom workspace' field to accomplish this?

After I responded to the question by @Joerg S I realized that I'm saying the thing that Joerg S says CAN'T happen is EXACTLY what I'm observing! Jenkins is using the SAME workspace for 2 different, concurrent, jobs on 2 different hosts. Is this a Jenkins pipeline bug?

See below for a bewildering amount of information.

Given the way I have to go onto and off of nodes during the run, I've found that I can start 2 different builds on different hosts of the same job, and they SHARE the workspace dir! Since each job has shell scripts which are busy writing files into that directory, this is extremely bad.

In Custom workspace in jenkins we are told to use custom workspace, and I'm set up just like that

In Jenkins: how to run builds in unique directories we are told to use ${BUILD_NUMBER} in the above custom workspace field, so what I tried was:

 ${JENKINS_HOME}/workspace/${ITEM_FULLNAME}/${BUILD_NUMBER}

All that happens to me when I use that is that the workspace name is, you guessed it, "${BUILD_NUMBER}" (and I even got a "${BUILD_NUMBER}@2" just for good measure!)

I tried {$BUILD_ID}, same thing (uses that literally, does not substitute the number).

I have the 'allow concurrent builds' turned on.

I'm using pipelines exclusively.

All jobs here, as part of normal execution, cause the slave, non-master host to reboot into an OS that does not have the capability to run slave.jar (indeed, it has no network access at all), so I cannot run the entire pipeline on that host.

All jobs use the following construct somewhere inside them:

    tests=Arrays.asList(tests.split("\\r?\n"))
    shellerror=231
    for( line in tests){

So let's call an example job 'foo' that loops through a list, as above, that I want to run on 2 different hosts. The pipeline for that job starts running on master (since the above for (line in tests) is REQUIRED to run on a node!)). Then goes back and forth between master and slave, often multiple times.

If I start this job on host A and host B at about the same time, they will BOTH use the workspace ${JENKINS_HOME}/workspace/${JOB_NAME}, or in my case /var/lib/jenkins/jenkins/workspace/job

Since they write different data to files with the same name in that directory, I'm clearly totally broken immediately.

So, how do I force Jenkins to use a unique workspace EVERY SINGLE JOB?

Or, what???

Other things: pipeline build step version 2.5.1, Jenkins 2.46.2

I've been trying to get the workspace statement ('ws') to work, but that doesn't quite work as I expected either - some files are in the workspace I explicitly name, and some are still in the 'built-in' workspace (workspace/).

I was asked to provide code. The 'standard' pipeline I use is about 26K bytes, composing about 590 lines. So, I'm going to GREATLY reduce. That being said:

node("master") { // 1
   ..... lots of stuff....
}  // this matches the "node('master')" above
node(HOST) {
  echo "on $HOST, check what os"
  if (isUnix()) 
      ...some more stuff...
} // end of 'node(HOST)' above
if (isok == 0 ) {
   node("master") { 
      echo "----------------- Running on MASTER 19 $shellerror waiting on boot out of windows ------------"
      sleep 120
      echo "----------------- Leaving MASTER ------------"
   }
}
 ... lots 'o code ...

node(HOST) {
  ... etc 
} // matches the latest 'node HOST' above
node("master") { // 120
    .... code ...
    for( line in tests) {
        ...code...
    }
}
... and on and on and on, switching back and forth from one to the other

FWIW, when I tried to make the above use 'ws' so that I could make certain the ws name was unique, I simply added a 'ws wsname' block directly under (almost) every 'node' opening so it was

node(name) { ws (wsname) { ..stuff that was in node block before... } }

But then I've got two directories to worry about checking - both the 'default' workspace/jobname dir AND the new wsname one.

like image 375
RustyCar Avatar asked Oct 31 '18 00:10

RustyCar


People also ask

Does Jenkins reuse workspace?

Right, the workspace will be reused for the same job in the while running in the same node.

How do I change the workspace in Jenkins pipeline?

So if you wish to change the Jenkins workspace, all you've do is change the path of your JENKINS_HOME. For slave nodes, specify the default workspace on the slave machine in the slave configuration under Manage Jenkins > Manage Nodes > > Configure > Remote FS root.

How do I keep my Jenkins workspace?

Jenkins stores current workspace as an environment ${WORKSPACE} variable. You can rename it at any moment of the job as long as you also set the renamed absolute directory path to ${WORKSPACE} variable within the build.


1 Answers

Try using customWorkspace node common option:

pipeline {
  agent {
    node {
      label 'node(s)-defined-label'
      customWorkspace "${JENKINS_HOME}/workspace/${JOB_NAME}/${BUILD_NUMBER}"
    }
  }
  stages {
    // Your pipeline logic here
  }
}

customWorkspace

A string. Run the Pipeline or individual stage this agent is applied to within this custom workspace, rather than the default. It can be either a relative path, in which case the custom workspace will be under the workspace root on the node, or an absolute path.

Edit

Since this doesn't work for your complex pipeline. Maybe try this silly solution:

def WORKSPACE = "${JENKINS_HOME}/workspace/${JOB_NAME}/${BUILD_NUMBER}"

node(HOST) {
   sh(script: "mkdir -p ${WORKSPACE}")
   sh(script: "cd ${WORKSPACE}")
   //Do stuff here
}

or if dir() is accessible:

def WORKSPACE = "${JENKINS_HOME}/workspace/${JOB_NAME}/${BUILD_NUMBER}"

node(HOST) {
   sh(script: "mkdir -p ${WORKSPACE}")
   dir(WORKSPACE) {
   //Do stuff here
   }
}
like image 84
Raoslaw Szamszur Avatar answered Oct 18 '22 18:10

Raoslaw Szamszur