How to access variables out of a sh script inside a Jenkinsfile - jenkins

The following code is a very simplified version of my code just for a better explanation:
def String FOLDER_NAME = "TestFolder"
def createFolder() {
sh('''
ls
mkdir ${FOLDER_NAME}
ls
''')
}
I want to use the name, stored inside the FOLDER_NAME variable, to create a new folder. The problem is that the current code does not use it. My first approach was to use ' ' around the variable access like this:
def createFolder() {
sh('''
ls
mkdir '${FOLDER_NAME}'
ls
''')
}
But this creates a new folder called ${FOLDER_NAME} and does not use the variable value.
My question is, how do I have to change my code so that it uses the variable value, not the variable call?

Your solution will be resolved by differentiating between groovy's single and double quotes.
String replacements are done inside double quotes "" only. Therefore, to resolve the issue just change sh command to:
def createFolder() {
sh("""
ls
mkdir '${FOLDER_NAME}'
ls
""")
}

Related

Jenkins pipeline returns "Bad Subtitution" for shell command

I'm attempting to run the following command in a shell block in my Jenkins pipeline:
jq '.Resources[].TargetService.Properties.TaskDefinition = "'"arn:aws:ecs:us-east-1:${ACCOUNT_NUMBER}:task-definition/${TASK_NAME}:${NEW_REVISION}"'"'
This command works perfectly fine when I run it directly on the Jenkins node in shell.
When I insert it into the Pipeline like this:
stage('process json') {
steps {
dir('mydir') {
sh """
NEW_REVISION=\$(cat revision.txt)
jq '.Resources[].TargetService.Properties.TaskDefinition = "'"arn:aws:ecs:us-east-1:\${env.AWS_ACCOUNT_NUMBER}:task-definition/\${env.TASK_NAME}:\${NEW_REVISION}"'"'
"""
}
}
}
I get a Bad substitution error without any more information. As far as I know, I'm escaping variables and quotation correctly. I can bypass the error if I remove the double quotes like this:
jq '.Resources[].TargetService.Properties.TaskDefinition = "arn:aws:ecs:us-east-1:${ACCOUNT_NUMBER}:task-definition/${TASK_NAME}:${NEW_REVISION}"'
But that ends up processing the variables literally.
Notes: I'm aware of the security issue by not passing jq --arg and prepared to modify my command after I can get the simpler format working. revision.txt contains a numeric value. The env.* variables are declared earlier as part of the pipeline environment.
env is a Jenkins Object and you seem to be escaping env.* variables as well. If you have already exported these variables as Environment variables they should be available to you in the shell environment. So simply drop the env part from the variables or remove the escape characters from such variables and let Jenkins interpolate them.
stage('process json') {
steps {
dir('mydir') {
sh """
NEW_REVISION=\$(cat revision.txt)
jq '.Resources[].TargetService.Properties.TaskDefinition = "'"arn:aws:ecs:us-east-1:\${AWS_ACCOUNT_NUMBER}:task-definition/\${TASK_NAME}:\${NEW_REVISION}"'"'
"""
}
}
}

How to pass dynamic params to jenkins resource method in python?

I am trying to extend Jenkins shared library with some python functions which I have in my resources directory. I can call the function in my jenkins pipeline but I am struggling to pass params.
In my jenkinsfile I tried the following
script{
getLabelsPerPullRequest.runMyPython(git_url="${env.GIT_URL}", github_token="${env.GITHUB_CREDENTIALS_ID}", prNbr_name="${BRANCH_NAME}")
}
where getLabelsPerPullRequest.runMyPython in vars folder looks like this:
def runMyPython(String git_url, String github_token, String prNbr_name) {
final pythonContent = libraryResource('com/sophia/sharedlib/getLabelsPerPullRequest.py')
sh('echo ${git_url} ${github_token} ${prNbr_name}')
writeFile(file: 'getLabelsPerPullRequest.py', text: pythonContent)
sh('chmod +x getLabelsPerPullRequest.py && ./getLabelsPerPullRequest.py -u ${git_url} -t ${github_token} -p ${prNbr_name}')
}
echo not returning anything. How can I pass the params from pipeline to the function?
The goal is to be able to use the passed params to substitute the flags in the last sh command. I can run a python script with no params using the same method, but these can only do so much.
You shared library function runMyPython is fine, just use double quotes "" instead of single quotes '' to enable the string interpolation and the substitution of variables:
("echo ${git_url} ${github_token} ${prNbr_name}")
Another thing is that as far is i know groovy does not support named arguments like you used it, it supports named arguments as map, so you will need to update you call to the shared library method to:
getLabelsPerPullRequest.runMyPython(env.GIT_URL, env.GITHUB_CREDENTIALS_ID, BRANCH_NAME)
or alternatively change your runMyPython function to receive a map, and then use the param:value notation to call it.

Jenkins - withCredentials file truncates path

I'm trying to reference a secret file to run with newman under a sub directory of the workspace like so:
String integrationFile = "src/test/postman/integration.json"
String environmentFile = "src/test/postman/environment-dev.json"
String reportFile = "integrationReport.xml"
String reportArgs = "--reporters cli,junit --reporter-junit-export ${reportFile}"
node {
withCredentials([file(credentialsId: "${env.FILE_KEY}", variable: "FILE_PATH")]) {
String dataFile = "${env.FILE_PATH}"
dir('sub-dir') {
git branch: 'master',
credentialsId: "${config.GitHubKeyId}",
url: 'https://github.com/xxx/repo.git'
withEnv(["PATH=${tool 'nodejs-12.8.0'}/bin:${env.PATH}"]) {
try {
sh ("newman run \"${integrationFile}\" -e \"${environmentFile}\" --global-var \"baseUrl=${route}\" -d ${dataFile} ${reportArgs}")
} catch (error) {
throw error
} finally {
junit "${reportFile}"
}
}
}
}
}
}
But when I run the code above, Jenkins throws an error:
error: iteration data could not be loaded
ENOENT: no such file or directory, open '/var/jenkins_home/workspace/Platform'
The path looks to be truncated because when I run a pwd command before the node closure runs, the workspace should be:
/var/jenkins_home/workspace/Platform Management/JJob#2
My question is, why is Jenkins doing this? Do I need to format the variable of the secret another way? Or should I reference it differently?
I know the file exists because in another Jenkins pipeline that does not have a sub directory (dir("")), it works fine.
I see from the Jenkins docs about withCredentials shows that how the file is reference gets tricky when you move between directories, see here: https://www.jenkins.io/doc/pipeline/steps/credentials-binding/
Here are the things that I've tried:
${env.FILE_PATH}
${FILE_PATH}
$FILE_PATH
(all of the above with double and single quotes around the sh command)
Any help is appreciated,
Thanks!
Ok - after playing around alot more with it, I eventually added a double quote around the variable to keep the spaces. This SO helped me out: Jenkins coping with spaces in batch file arguments
In the newman command line script, I just had add double quotes within the param args, like so:
sh ("newman run \"${integrationFile}\" -e \"${environmentFile}\" --global-var \"baseUrl=${route}\" -d \"${dataFile}\" ${reportArgs}")

Jenkins doesn't fully resolve variables values

I have a Jenkinsfile where I want to declare some variables to later use in other sections. I know about Jenkins use the Groovy syntax rules for variable expansion but I expected some variable values where fully resolved. Instead I found that they just resolved in one level. Code inlcuded below shows what I want: Trying to use $PATHTOFILES variable to link data downloaded/generated in previous stages for a Docker container. Instead the variable is just resolved as pwd.
I tried several options seeking to expand the values that I need, so far unsuccessfully.
agent none
environment {
...
PATHTOFILES = "`pwd`"
...
}
...
stage('Unit'){
agent {
docker {
image "${DOCKERIMAGEURI}"
args '-v $PATHTOFILES:$CONTAINER_DATA_PATH'
}
}
}
Logs show that a value '-v `pwd`:/some/valid/path' is used as argument, leading to an error. Any ideas?
You did wrong to get current workspace of job. One of below 3 methods should work:
1) use shell cmd: pwd and pipeline step: sh() together
PATHTOFILES = sh(script: 'pwd', returnStdout:true).trim()
2) use pipeline step: pwd()
PATHTOFILES = pwd()
3) use environment variable: WORKSPACE
PATHTOFILES = env.WORKSPACE

How to use environment variable inside Jenkinsfile

I am having similar issue as mentioned here
I am trying to deploy an application via Jenkinsfile. For which I have to run this command on the deploy stage in Jenkins (if I hardcode the value then it works fine):
xldDeploy serverCredentials: 'usernam', environmentId: 'Environments/SysTest1/SysTest1_1', packageId: 'Applications/Testapp/testapp_1.0.4.5.Build39_TAG-test'
"testapp_1.0.4.5.Build39_TAG-test" is getting generated at running time. Which can be created by concating "${TagVersion}.Build${env.BUILD_NUMBER}_${ComponentTagName}"
I tried below code in my Jenkins pipeline:
stage('Deploy') {
node('noibuild01') {
if ("${env.Build_WildflyCPECommon}" == 'true') {
echo "${TagVersion}"
echo "${ComponentTagName}"
echo "${env.BUILD_NUMBER}"
script {
env.buildNumber = "${TagVersion}.Build${env.BUILD_NUMBER}_${ComponentTagName}"
env.packageid = "'Applications/Testapp/${env.buildNumber}'"
}
echo "${env.buildNumber}"
echo "${env.packageid}"
xldDeploy serverCredentials: 'nex8voo', environmentId: 'Environments/SysTest1/SysTest1_1', packageId: "${env.packageid}"
}
}
}
I checked the output, it is showing correctly:
echo "${env.buildNumber}" giving
testapp_1.0.4.5.Build39_TAG-test
echo "${env.packageid}" giving
'Applications/Testapp/testapp_1.0.4.5.Build39_TAG-test'
But xldDeploy serverCredentials: 'username', environmentId: 'Environments/SysTest1/SysTest1_1', packageId: "${env.packageid}"
is taking as:
[/repository/ci/'Applications/Testapp/testapp_1.0.4.5.Build39_TAG-test']
Repository entity: ['Applications/Testapp/testapp_1.0.4.5.Build39_TAG-test'] not found
I think I can't use packageId: "${env.packageid}".
Is there anything I could try? Maybe Groovy or Python code?
Your packageid environment variable is not being assigned a concatenated string correctly. You have literal quotes inside the string interpolation quotes. You should change it to:
env.packageid = "Applications/Testapp/${env.buildNumber}"
to only interpolate the string, which is the functionality you want here.
Additionally, you do not need to interpolate the environment variable inside an empty string for your method parameter, so your method invocation can be cleaned up as:
xldDeploy serverCredentials: 'nex8voo', environmentId: 'Environments/SysTest1/SysTest1_1', packageId: env.packageid

Resources