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

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.

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}"'"'
"""
}
}
}

Jenkins Pipeline - inserting variable in shell creates a new line

I am using Choice param in my jenkins file to select environment as follows:
pipeline {
agent any
parameters {
choice(
name: 'ENVIRONMENT_URL',
choices: "https://beta1.xyz.com\nhttps://beta2.xyz.com\nhttps://beta3.xyz.com",
description: 'interesting stuff' )
}
in the Stage section, i have the following piece
stage('execute tests') {
steps {
script {
sh """URL=${ENVIRONMENT_URL} npm run e2e:tests"""
sh 'echo -e "\nTest Run Completed.\n"'
}
}
}
However, when i run the pipeline job by selecting the choice parameter i added, the following gets executed (the inserted choice param creates a line break):
+ URL=https://beta1.xyz.com
+ npm run e2e:tests
Using the variable is causing a line break and that's what is causing issue.
I have tried different ways to avoid line break. Tried using a variable but that didn't help. tried with different quotations, that didn't either.
What can i do to avoid line break ?
You can use the trim method on a String class type to remove trailing whitespace and newline:
sh "URL=${params.ENVIRONMENT_URL.trim()} npm run e2e:tests"
Note I also specified your parameter is in the params map and removed the triple quotes as those are for multiline string formatting.
Alternatively, you can specify the choices as an array instead of as a multiline string. The choices argument would then appear like:
choice(
name: 'ENVIRONMENT_URL',
choices: ['https://beta1.xyz.com', 'https://beta2.xyz.com', 'https://beta3.xyz.com'],
description: 'interesting stuff'
)
Either solution would fix your issue.

What is use of sh ''' <command > ''' - three ticks - in a Jenkinsfile?

I have a Jenkinsfile which uses three tick marks surrounding a command to execute as in:
sh ''' command '''
We have no idea why three tick marks are required or what role they perform.
This syntax is seen in the Jenkinsfile doc set.
This has nothing at all to do with bash (in which triple-quotes have no special meaning at all), and everything to do with Groovy (the separate, non-bash interpreter that parses Jenkinsfiles).
In Groovy, but not in bash, strings must use triple-quotes to span multiple lines.
In the context of a sh directive in a Jenkinsfile, the content of your triple-quoted string is passed to a shell as a script to execute; however, the syntax is parsed by Groovy, so it's only Groovy that cares about the quotes themselves (as opposed to the quoted content).
Can you give more idea about what kind of command is it, is it a unix command or some script ?
The single quote and its variation like '''(3 ticks) as mentioned in question skip the variable expansion, and it could used to show what is being executed.
echo '''Updating JAVA_HOME variable :
export $JAVA_HOME="$NEW_JAVA_HOME" '''
However in your question, a command (some string) is enclosed between 3 ticks marks and sh tries to execute this command or script. One such example below
$ echo "echo hello" > /tmp/tesh.sh
$ sh '''/tmp/test.sh'''
hello

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

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

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
""")
}

Resources