jenkins workspace folder cut in multibranch pipeline - jenkins

I note that in multibranch pipeline the workspace folder is cut.
For example a project named:
Sample09-Netbeans-MultiBranch-Pipeline-Maven-Svn
that comes from a subversion repository like
https://my-favourite-repo/svn/ProjectsJava/DevOps/Jenkins/Test/test-jenkins-java-maven-multibranch/
with a project folder like
D:\ProjectsJava\DevOps\Jenkins\Test\test-jenkins-java-maven-multibranch\trunk\myproject
produce a workspace folder like this
D:\Jenkins.jenkins\workspace\peline-Maven-Svn_trunk_myproject
other types of project whit similar names doesn't have this problem
I found a workaround adding
-a node definition
-a customWorkspace
but when i use it maven doesn't see
the settings.xml file and i must directly specify it in the maven command passing
a jenkins-global property.
No other action can provide it to the command (define a jenkins-config-file,
define it in jenkins-maven configuration or in project-maven configuration)
pipeline {
agent{
node{
label 'my-node'
customWorkspace "${JENKINS_HOME}/Workspace/${JOB_NAME}/${BUILD_NUMBER}"
}
}
stages {
stage('Build-And-Test') {
steps {
withMaven {
bat "mvn clean package test -B -s ${MAVEN_SETTINGS}"
}
}
}
}
}
Why Jenkins cut the folder name only in multibranch pipelines?
There is another way to define the workspace-job-folder-name outside of the jenkinsfile ?
OR
There is a way to let maven see the settings.xml configured in one of the Jenkins configuration?

Most operating systems have an upper bound on the length of a file name and the length of a directory path. Jenkins pipeline jobs that use full length strings were encountering operating system path limitations (especially the 256 character default limit on Windows).
Pipeline job names were intentionally changed to shorter forms so that they would reduce the likelihood of encountering an operating system or file system limit on path length.

Related

how to change the # and #tmp directory creation in jenkins workspace

Every time my build is running, i got 2 or 3 folders with # and #tmp
Example: If my build name is test, I run the build it fetches some code from git and store it in the jenkins workspaces with names test, test#2 test#2tmp test#tmp. But original folder is test. I only want the test folder and i need to remove the next 2 folders. How can i do this.
My present working directory is automatically choosing as test#2
I want the default pwd to be /var/lib/jenkins/workspace/
I want to delete the #2 and #tmp files and change my working directory to after the build runs
Sample output is:
pwd
/var/lib/jenkins/workspace/test#2
You can use customWorkspace in your jenkins pipelines:
Example:
agent {
node {
label 'my-label'
customWorkspace '/my/path/to/workspace'
}
}
Note that Jenkins use different directories to support concurrent builds:
If concurrent builds ask for the same workspace, a directory with a suffix such as #2 may be locked instead.
Since you don't want this behaviour I advise you to use disableConcurrentBuilds option:
Disallow concurrent executions of the Pipeline. Can be useful for preventing simultaneous accesses to shared resources, etc. For example: options { disableConcurrentBuilds() }
References on customWorkspace and disableConcurrentBuilds: https://jenkins.io/doc/book/pipeline/syntax/
look for agent{ } block in your pipeline groovy script. it should be only at the pipeline block level and not into any stage block.

How to set specific workspace folder for jenkins multibranch pipeline projects

I have an external tool that should be called as build-step in one of my jenkins jobs. Unfortunately, this tool has some issues with quoting commands to avoid problems with whitespaces in the path that is called from.
Jenkins is installed in C:\Program Files (x86)\Jenkins. Hence I'm having trouble with jenkins calling the external tool.
What I tried is to set "Workspace Root Directory" in Jenkins->configuration to C:\jenkins_workspace in order to avoid any whitespaces. This works for Freestyle Projects but my Multibranch Pipeline Project is still checked out and built under C:\Program Files (x86)\Jenkins\workspace.
One solution would be to move the whole jenkins installation to e.g. C:\jenkins. This I would like to avoid. Is there a proper way to just tell Jenkins Pipeline jobs to use the "Workspace Root Directory" as well?
Thanks for any help
the ws instruction sets the workspace for the commands inside it. for declarative pipelines, it's like this:
ws("C:\jenkins") {
echo "awesome commands here instead of echo"
}
You can also call a script to build the customWorkspace to use:
# if the current branch is master, this helpfully sets your workspace to /tmp/ma
partOfBranch = sh(returnStdout: true, script: 'echo $BRANCH_NAME | sed -e "s/ster//g"')
path = "/tmp/${partOfBranch}"
sh "mkdir ${path}"
ws(path) {
sh "pwd"
}
you can also set it globally by using the agent block (generally at the top of the pipeline block), by applying it to a node at that level:
pipeline {
agent {
node {
label 'my-defined-label'
customWorkspace '/some/other/path'
}
}
stages {
stage('Example Build') {
steps {
sh 'mvn -B clean verify'
}
}
}
}
Another node instruction later on might override it. Search for customWorkspace at https://jenkins.io/doc/book/pipeline/syntax/. You can also it use it with the docker and dockerfile instructions.
Try this syntax instead:
pipeline {
agent {
label {
label 'EB_TEST_SEL'
customWorkspace "/home/jenkins/workspace/ReleaseBuild/${BUILD_NUMBER}/"
}
}
}

Multi-branch configuration with externally-defined Jenkinsfile

I have an open-source project, that resides in GitHub and is built using a build farm, controlled by Jenkins.
I want to build it branch-wise using a pipeline, but I don't want to store Jenkinsfile inside the code. Is there a way to accomplish this?
I have encountered the same issue as you. While the idea of having the build process as part of the code is good, there is information that the Jenkinsfile would include that are not intrinsic to the project build itself, but rather are specific to the build environment instance, which may change.
The way I accomplished this is:
Encapsulate the core build process in a single script (build.py or build.sh). This may call specific build tools like Make, CMake, Ant, etc.
Tell Jenkins via the Jenkinsfile to call a function defined in a single global library
Define the global Jenkins build function to call the build script (e.g. build.py) with appropriate environment settings. For example, using custom tools and setting up the PATH.
So for step 2, create a Jenkinsfile in your project containing just the line
build_PROJECTNAME()
where PROJECTNAME is based on the name of your project.
Then use the Pipeline Shared Groovy Libraries Plugin and create a Groovy script in the shared library repository called vars/build_PROJECTNAME.groovy containing the code that sets up the environment and calls the project build script (e.g. build.py):
def call() {
node('linux') {
stage("checkout") {
checkout scm
}
stage("build") {
withEnv([
"PATH+CMAKE=${tool 'CMake'}/bin",
"PATH+PYTHON=${tool 'Python-3'}",
"PATH+NINJA=${tool 'Ninja'}",
]) {
execute 'python build.py'
}
}
}
}
First of all, why do you not want a Jenkinsfile in your code? The pipeline is just as much part of the code as would be your build file.
Other then that, you can load groovy files to be evaluated as a pipeline script. You can do this either from a different location with the from SCM option and then checkout the actual code. But this will force you to manually take care of the branch builds.
Another option would be to have a very basic Jenkinsfile that merely checkouts an external pipeline.
You would get something like this:
node{
deleteDir()
git env.flowScm
def flow = load 'pipeline.groovy'
stash includes: '**', name: 'flowFiles'
stage 'Checkout'
checkout scm // short hand for checking out the "from scm repository"
flow.runFlow()
}
Where the pipeline.groovy file would contain the actual pipeline would look like this:
def runFlow() {
// your pipeline code
}
// Has to exit with 'return this;' in order to be used as library
return this;

Get absolute path to workspace directory in Jenkins Pipeline plugin

I'm currently doing some evaluation on the Jenkins Pipeline plugin (formerly know as Workflow plugin).
Reading the documentation I found out that I currently cannot retriev the workspace path using
env.WORKSPACE:
The following variables are currently unavailable inside a workflow script:
NODE_LABELS
WORKSPACE
SCM-specific variables such as SVN_REVISION
Is there any other way how to get the absolute path to the current workspace? I need this running some test which in turn gets some parameter (absolute path to some executable file).
I already tried using new File("").absolutePath() inside a #NonCPS section but looks like the non-CPS stuff gets always executed on the master.
Does anybody have a clue how to get this path without running some batch script which stores the path into some file which later on can be read in again?
Since version 2.5 of the Pipeline Nodes and Processes Plugin (a component of the Pipeline plugin, installed by default), the WORKSPACE environment variable is available again. This version was released on 2016-09-23, so it should be available on all up-to-date Jenkins instances.
Example
node('label'){
// now you are on slave labeled with 'label'
def workspace = WORKSPACE
// ${workspace} will now contain an absolute path to job workspace on slave
workspace = env.WORKSPACE
// ${workspace} will still contain an absolute path to job workspace on slave
// When using a GString at least later Jenkins versions could only handle the env.WORKSPACE variant:
echo "Current workspace is ${env.WORKSPACE}"
// the current Jenkins instances will support the short syntax, too:
echo "Current workspace is $WORKSPACE"
}
Note: this solution works only if the slaves have the same directory structure as the master. pwd() will return the workspace directory on the master due to JENKINS-33511.
I used to do it using pwd() functionality of pipeline plugin. So, if you need to get a workspace on slave, you may do smth like this:
node('label'){
//now you are on slave labeled with 'label'
def workspace = pwd()
//${workspace} will now contain an absolute path to job workspace on slave
}
"WORKSPACE" environment variable works for the latest version of Jenkins Pipeline. You can use this in your Jenkins file: "${env.WORKSPACE}"
Sample use below:
def files = findFiles glob: '**/reports/*.json'
for (def i=0; i<files.length; i++) {
jsonFilePath = "${files[i].path}"
jsonPath = "${env.WORKSPACE}" + "/" + jsonFilePath
echo jsonPath
hope that helps!!
For me WORKSPACE was a valid property of the pipeline itself. So when I handed over this to a Groovy method as parameter context from the pipeline script itself, I was able to access the correct value using "... ${context.WORKSPACE} ..."
(on Jenkins 2.222.3, Build Pipeline Plugin 1.5.8, Pipeline: Nodes and Processes 2.35)

Best way to configure jenkins job running on different slaves

I want to run a Jenkins job on 4 different slaves (windows, linux, solaris, Mac). Instead of making 4 different jobs I want to have a single job. I can use a Node parameter to execute on different slaves. My job runs a script which uses Jenkins workspace of slave and a few other scripts. My script is in a different folder on each slave, and other required scripts are in a different folder. So now I have created 4 different jobs for each slave and hard-coded Jenkins workspace and other required scripts path.
Is there any way so that I can put all paths in some JSON-like structure and depending on slave will pick those paths? So that I will have 1 job only.
Please suggest, Thanks in advance!
my idea is to use e.g "Execute system Groovy script" to get slave value and then use if statement to assigne proper path and create parameter visible in Environment Variables:
import hudson.model.Computer
import hudson.model.StringParameterValue
import hudson.model.ParametersAction
//get slave name
def slaveName = Computer.currentComputer().getNode().name
def path
//choose path
if(slaveName.equals("slave01")){
path = "C:"
}
if(slaveName.equals("slave02")){
path = "/root"
}
if(slaveName.equals("slave03")){
path = "D:"
}
//pass path as env. variable
build.addAction(new ParametersAction(new StringParameterValue('path', path)))
then you can use variable path in command:
echo %path%
or use Conditional BuildStep Plugin to set separable steps for each operation system and control when each step should be executed
Jenkins is designed to check out files from a version control system (Subversion, Git, whatever) and run tasks. Instead of trying to manage separate files on separate slaves, you should put your scripts in some form of version control and let Jenkins check out the files in the workspace as part of its build process.

Resources