I could not achieve changing the working directory using the suggestion by Vishwas, although I did try creating a Jenkins user inside the container with the same uid as the host. It just didn't work for me. I did however, realize that I didn't actually need to change the directory on the container because the workspace was already in the container.
I'm using the Docker Plugin from CloudBees. After reading their documentation, I realized the workstation folder I thought was on the host machine, was actually in the container. Part of the documentation stated:
The above is a complete Pipeline script. inside will:
- Automatically grab an agent and a workspace (no extra node block is required).
- Pull the requested image to the Docker server (if not already cached).
- Start a container running that image.
- Mount the Jenkins workspace as a "volume" inside the container, using the same file path.
After seeing item number four, I ran docker container inspect <containerID> and I saw the workspace /home/jenkins/workspace was actually a volume mount that was mapped to the /home/jenkins/workspace on the Docker host machine as well. Using this as my workspace, I was able to build the various applications within the container and then moved the results to a second volume used for application collection later in the pipeline. It's not an exact answer to my original question, but it works!
I could not achieve changing the working directory using the suggestion by Vishwas, although I did try creating a Jenkins user inside the container with the same uid as the host. It just didn't work for me. I did however, realize that I didn't actually need to change the directory on the container because the workspace was already in the container.
I'm using the Docker Plugin from CloudBees. After reading their documentation, I realized the workstation folder I thought was on the host machine, was actually in the container. Part of the documentation stated:
The above is a complete Pipeline script. inside will:
- Automatically grab an agent and a workspace (no extra node block is required).
- Pull the requested image to the Docker server (if not already cached).
- Start a container running that image.
- Mount the Jenkins workspace as a "volume" inside the container, using the same file path.
After seeing item number four, I ran docker container inspect <containerID> and I saw the workspace /home/jenkins/workspace was actually a volume mount that was mapped to the /home/jenkins/workspace on the Docker host machine as well. Using this as my workspace, I was able to build the various applications within the container and then moved the results to a second volume used for application collection later in the pipeline. It's not an exact answer to my original question, but it works!
If your master is running as Jenkins user, you should make a user in the docker image which you use as to create your node and do the key exchange. For example jenkinsuser with same UID needs to exist on both master and node docker container.
groovy - Jenkins pipeline how to change to another folder - Stack Overflow
Proper way to use the dir() function inside docker image
Jenkins pipeline create directory - Stack Overflow
java - How to run jenkins pipeline relative to a sub-directory? - Stack Overflow
Use double quotes
dir ("RELEASE/abc/${abc_version}")
in groovy Single quotes are a standard Java String while Double quotes are a templatable String
e.g
a = 10
b = "RELEASE/abc/${a}"
c = 'RELEASE/abc/${a}'
print(b)
print('\n')
print(c)
output will be
RELEASE/abc/10
RELEASE/abc/${a}
You can try it here
We need to use double quotes to resolve variable in groovy script.
use the following sample code
def dirpath = "RELEASE/abc/${abc-version}"
dir(dirpath){
//logic
}
There are lots of ways to do this. Here are two ways I can think of off the top of my head:
steps {
println(WORKSPACE)
}
or
steps {
def foo = sh(script: 'pwd', returnStdout: true)
println(foo)
}
In my MultiBranchPipeline I've achieved the goal using this shared library code:
#!groovy
import jenkins.model.Jenkins
String call() {
String thisMultiBranchProjectName = JOB_NAME.split('/')[0]
def thisMultiBranchProject = Jenkins.getInstance().getItemByFullName(thisMultiBranchProjectName)
def thisBranchProjectFactory = thisMultiBranchProject.getProjectFactory()
String thisStringPath = thisBranchProjectFactory.getScriptPath()
return thisStringPath
}
I do concede that this looks more like a hack…
What you can do is use the dir step, if the directory doesn't exist, then the dir step will create the folders needed once you write a file or similar:
node {
sh 'ls -l'
dir ('foo') {
writeFile file:'dummy', text:''
}
sh 'ls -l'
}
The sh steps is just there to show that the folder is created. The downside is that you will have a dummy file in the folder (the dummy write is not necessary if you're going to write other files). If I run this I get the following output:
Started by user jon
[Pipeline] node
Running on master in /var/lib/jenkins/workspace/pl
[Pipeline] {
[Pipeline] sh
[pl] Running shell script
+ ls -l
total 0
[Pipeline] dir
Running in /var/lib/jenkins/workspace/pl/foo
[Pipeline] {
[Pipeline] writeFile
[Pipeline] }
[Pipeline] // dir
[Pipeline] sh
[pl] Running shell script
+ ls -l
total 4
drwxr-xr-x 2 jenkins jenkins 4096 Mar 7 22:06 foo
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS
Just use a file operations plugin.
fileOperations([folderCreateOperation('directoryname')])
I ended up with a "prepare project" stage that puts the subdirectory content into the root.
It's also probably a good idea to remove all the root contents (stage "clean") to be absolutely sure there are no leftovers from previous builds.
node {
def dockerImage
stage('clean') {
sh "rm -rf *"
}
stage('checkout') {
checkout scm
}
// need to have only 'backend' subdir content on the root level
stage('prepare project') {
// The -a option is an improved recursive option, that preserve all file attributes, and also preserve symlinks.
// The . at end of the source path is a specific cp syntax that allow to copy all files and folders, included hidden ones.
sh "cp -a ./backend/. ."
sh "rm -rf ./backend"
// List the final content
sh "ls -la"
}
stage('build docker image') {
dockerImage = docker.build("docker-image-name")
}
stage('publish docker image') {
docker.withRegistry('https://my-private-nexus.com', 'some-jenkins-credentials-id') {
dockerImage.push 'latest'
}
}
}
You can have jenkinsfiles inside backend and frontend modules and just point to them on each pipeline, eg:

and on the pipeline itself you just cd to the submodule and execute its commands:
pipeline {
agent any
stages {
stage('build') {
steps {
sh 'cd backend'
sh 'mvn clean package'
}
}
//other stages
}
}
if you don't want to cd to a sub module you can use sparse checkouts but in this case you have to change the path to the jenkinsfile accordingly because it will be on the root folder.
Is there any way to create a directory in jenkins declarative pipeline and use it across stages?
i.e
node(){
checkout scm
sh "mkdir ${WORKSPACE/conan}" def String dockerImage = 'development-tools'
stage('Testing') {
parallel (
'Release Build': { docker.image(dockerImage).inside(dockerArgs) {
sh "touch file.txt && mv file.txt ${WORKSPACE/conan"
}
}
stage('Deploy')
// use file.txt here again
}If you want a list of all directories under a specific directory e.g. mydir using Jenkins Utility plugin you can do this:
Assuming mydir is under the current directory:
dir('mydir') {
def files = findFiles()
files.each{ f ->
if(f.directory) {
echo "This is directory: ${f.name} "
}
}
}
Just make sure you do NOT provide glob option. Providing that makes findFiles to return file names only.
More info: https://jenkins.io/doc/pipeline/steps/pipeline-utility-steps/
I didn't find any plugin to list folders, so I used sh/bat script in pipeline, and also this will work irrespective of operating system.
pipeline {
stages {
stage('Find all fodlers from given folder') {
steps {
script {
def foldersList = []
def osName = isUnix() ? "UNIX" : "WINDOWS"
echo "osName: " + osName
echo ".... JENKINS_HOME: ${JENKINS_HOME}"
if(isUnix()) {
def output = sh returnStdout: true, script: "ls -l ${JENKINS_HOME} | grep ^d | awk '{print \$9}'"
foldersList = output.tokenize('\n').collect() { it }
} else {
def output = bat returnStdout: true, script: "dir \"${JENKINS_HOME}\" /b /A:D"
foldersList = output.tokenize('\n').collect() { it }
foldersList = foldersList.drop(2)
}
echo ".... " + foldersList
}
}
}
}
}