50

Here's my Jenkins 2.x pipeline:

node ('master'){
    stage 'Checkout'
    checkout scm
    stage "Build Pex"
    sh('build.sh')
}

When I run this pipeline the checkout puts the code into to the workspace as expected, however instead of expecting to find the script in workspace/ (it's really there!), it looks in an unrelated directory: workspace@tmp/durable-d812f509.

Entering stage Build Pex
Proceeding
[Pipeline] sh
[workspace] Running shell script
+ build.sh
/home/conmonsysdev/deployments/jenkins_ci_2016_interns/jenkins_home/jobs/pex/branches/master/workspace@tmp/durable-d812f509/script.sh: line 2: build.sh: command not found

How do I modify this Jenkinsfile so that build.sh is executed in the exact same directory as where I checked out the project source code?

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
Salim Fadhley
  • 6,975
  • 14
  • 46
  • 83

8 Answers8

49

You can enclose your actions in dir block.

checkout scm
stage "Build Pex"
dir ('<your new directory>') { 
    sh('./build.sh')
}
... or ..
checkout scm
stage "Build Pex"
sh(""" <path to your new directory>/build.sh""")

...

<your new directory> is place holder your actual directory. By default it is a relative path to workspace. You can define absolute path, if you are sure this is present on the agent.

Jayan
  • 18,003
  • 15
  • 89
  • 143
  • 2
    What does 'your new directory' stand for? Is it a placeholder? – Bastian Voigt Dec 05 '16 at 07:21
  • 2
    Doen't work for me :-( Where do I have to put the shellscript? Right now it's in the root directory of my git repo. I tried to move it to a subdirectory 'buildscripts' and then use `dir('buildscripts') {}` but no luck – Bastian Voigt Dec 05 '16 at 07:40
  • @ Bastian Voigt : You may need a new question – Jayan Dec 05 '16 at 07:55
  • 1
    The problem I have is exactly the same as the OP had – Bastian Voigt Dec 05 '16 at 08:14
  • 1
    Found that directory doesn't always work, sh "cd path && ${cmd}" should work. – Peter Kahn May 13 '17 at 15:48
  • 6
    This answer doesn't answer to the question, and doesn't work unless you create a new sub-directory. The question was how to run scripts from the workdir of the project (root). For me it works fine when you have a sub directory, but does not work when I'm trying to run the script from the project root. – PHZ.fi-Pharazon Mar 17 '18 at 05:49
31

The reason that your script doesn't work is because build.sh is not in your PATH.

The Jenkinsfile is running a "sh" script, whose entire contents is the string build.sh. The parent script is in the "@tmp" directory and will always be there - the "@tmp" directory is where Jenkins keeps the Jenkinsfile, essentially, during a run.

To fix the problem, change your line to sh "./build.sh" or sh "bash build.sh", so that the sh block in the Jenkinsfile can correctly locate the build.sh script that you want to execute.

Neuron
  • 5,141
  • 5
  • 38
  • 59
Keith Mitchell
  • 319
  • 4
  • 7
4

Jenkins create a folder when it make a clone from your project like this:

/var/lib/jenkins/workspace/job-name@script

For this to work you must set the file as executable if you are in a linux environment and then call the shell script.

Something like this:

// Permission to execute
sh "chmod +x -R ${env.WORKSPACE}/../${env.JOB_NAME}@script"

// Call SH
sh "${env.WORKSPACE}/../${env.JOB_NAME}@script/script.sh"
Rafael Manzoni
  • 627
  • 5
  • 13
  • As I am facing the same issues i.e. having a bash script located at the root of the project directory, my question is is the name `script.sh` you are using just for example? or does jenkins somehow? "renames" whatever bash script name you have provides to `script.sh`? – ApJo Jun 05 '23 at 17:58
  • Not sure what this is supposed to mean, but do not do it. There are simple and straightforward answers. – Jesse Glick Aug 17 '23 at 22:42
2

I am having the same issue and dir is not helping, possibly because I am working inside a subdirectory of the tmp dir itself (for reason not germane here). My code looks like this

dir(srcDir){
  sh 'pwd; la -l; jenkins.sh "build.sh"'
}

(the pwd and la -l statements were added just for debugging. Issue exists w/o them.) With them I get output like:

+ pwd
/jenkins/workspace/aws-perf-test@tmp/repos/2
+ ls -l
total 72
-rw-r--r-- 1 jenkins jenkins   394 May 19 12:20 README.md
drwxr-xr-x 3 jenkins jenkins  4096 May 19 12:20 api-automation
-rwxr-xr-x 1 jenkins jenkins   174 May 19 12:20 build-it.sh
-rwxr-xr-x 1 jenkins jenkins   433 May 19 12:20 build-release.sh
-rwxr-xr-x 1 jenkins jenkins   322 May 19 12:20 build.sh
drwxr-xr-x 3 jenkins jenkins  4096 May 19 12:20 ix-core
drwxr-xr-x 3 jenkins jenkins  4096 May 19 12:20 ix-java-client
drwxr-xr-x 3 jenkins jenkins  4096 May 19 12:20 ix-rest-models
drwxr-xr-x 4 jenkins jenkins  4096 May 19 12:20 ix-service
drwxr-xr-x 7 jenkins jenkins  4096 May 19 12:20 ixternal
drwxr-xr-x 5 jenkins jenkins  4096 May 19 12:20 ixtraneous-stuff
-rwxr-xr-x 1 jenkins jenkins   472 May 19 12:20 jenkins.sh
-rw-r--r-- 1 jenkins jenkins 16847 May 19 12:20 pom.xml
+ jenkins.sh build.sh
/home/jenkins/workspace/aws-perf-test@tmp/repos/2@tmp/durable-a3ec0501/script.sh: line 2: jenkins.sh: command not found

I ultimately did this:

dir(srcDir){
  sh 'cdr=$(pwd); $cdr/jenkins.sh "build.sh"'
}
Kenneth Baltrinic
  • 2,941
  • 2
  • 28
  • 45
0

I compiled all the answers above and for me it worked like this:

stage('Run Script'){
    steps {
        script {
            sh('cd relativePathToFolder && chmod +x superscript.sh && ./superscript.sh parameter1 paraeter2')
        }
    }
}

Thanks to @Rafael Manzoni @Keith Mitchell and @Jayan

Neuron
  • 5,141
  • 5
  • 38
  • 59
TudorIftimie
  • 1,050
  • 11
  • 21
0

I was able to get my script execution working with a simplified derivative of Rafael Manzoni's response. I wondered about the whole "JOB_NAME@script" thing and found that unnecessary, at least for declarative using our version of Jenkins. Simply set the access permissions on the workspace. No need to go any deeper than that.

stage('My Stage') {
    steps {
        sh "chmod +x -R ${env.WORKSPACE}"
        sh "./my-script.sh"
    }
}
tbradt
  • 626
  • 6
  • 8
0

If you can set the executable bit on build.sh in your SCM repository, along with an executable header such as

#!/bin/bash

then it should also be executable in the checkout, and so simply

sh './build.sh'

will work. If you prefer not to have mode bits set on files in your SCM repository (for example because it causes problems for Windows users), simple alternatives include

sh 'sh build.sh'

or

sh 'bash build.sh'

(depending on whether it is in fact a pure Bourne shell script, or really Bash), or

sh '. build.sh'

(This last idiom is potentially error-prone since it will run the script inside the default shell on the agent, which on many Linux distributions will be Bash, but on Debian/Ubuntu will be “Dash” which deliberately blocks Bash-specific features.)

If you do not wish to make the Pipeline script hard-code a particular shell (or other interpreter, such as Python) then include the #! header as above but run

sh 'chmod a+x build.xml && ./build.xml'
Jesse Glick
  • 24,539
  • 10
  • 90
  • 112
-1

Use the GIT_CHECKOUT_DIR environment variable

Jenkinsfile:

pipeline {
  agent any
  stages {
    stage('Install dependencies') {
      steps {
        dir(GIT_CHECKOUT_DIR) {
          // now everything is executed in your checkout directory
          sh 'yarn'
        }
      }
    }
  }
  post {
    // ...
  }
}

Set your GIT_CHECKOUT_DIR while setting up your pipeline. See this question: pipeline-checkout-dir

List of more environment variables:

  • ${YOUR_JENKINS_HOST}/env-vars.html
  • example: http://localhost:8000/env-vars.html

The most upvoted answer is dangerous and brittle. No need to use static operating system dependant ABSOLUTE PATHs in multiple places that break your builds once you change the machine.

EliteRaceElephant
  • 7,744
  • 4
  • 47
  • 62