I am trying to render information obtained from the shell in an active Active Choices parameter with a groovy script. I can easily access the shell from a groovy script in a jenkins pipeline with the sh method like this:
node()
{
sh 'git log ...'
}
But when I try this in the groovy script of Active choices, it crashes and the fallback script is executed.
Is it possible to switch to a node in this context and execute a shell command ?
Thanks for the help!
Here is sample snippet using the active choice plugin.
def command = $/aws ec2 describe-instances \
--filters Name=tag:Name,Values=Test \
--query Reservations[*].Instances[*].PrivateIpAddress \
--output text /$
def proc = command.execute()
proc.waitFor()
def output = proc.in.text
def exitcode= proc.exitValue()
def error = proc.err.text
if (error) {
println "Std Err: ${error}"
println "Process exit code: ${exitcode}"
return exitcode
}
//println output.split()
return output.tokenize()
Related
I want to get a line from a file in my workspace. I am using this script :
stage('Test') {
steps {
script {
outputJenkins = 'output-jenkins.log'
sh "cd invoker && mvn clean install && mvn exec:java -Dexec.mainClass=\"com.JenkinsRunner\" -Dexec.args=\"qal ${GIT_COMMIT_HASH}\" > ../${outputJenkins}"
logFile = readFile(outputJenkins)
echo logFile
adminRepoLogLine = sh "echo logFile | grep \"Admin repo url is :::\""
echo adminRepoLogLine
}
}
}
But I am getting this error:
+ echo logFile
+ grep Admin repo url is :::
script returned exit code 1
The script works fine in my shell when I try it locally. Are there any contains around doing it in a JenkinsFile?
If we apply various fixes and improvements to the code in the question to achieve the desired functionality, then it will succeed:
stage('Test') {
steps {
script {
dir('invoker') {
sh(label: 'Maven Clean Install', script: 'mvn clean install')
// assign maven output to variable
String output = sh(label: 'Maven Git Log', script: "mvn exec:java -Dexec.mainClass=\"com.JenkinsRunner\" -Dexec.args=\"qal ${GIT_COMMIT_HASH}\"", returnStdout: true)
}
// assign regex return to variable
def adminRepoLogLine = output =~ /(.*Admin repo url is :::.*)/
// print extracted string from return
print adminRepoLogLine[0][1]
}
}
}
Note that GIT_COMMIT_HASH is neither an intrinsic Jenkins environment variable, nor defined in the pipeline code in the question, so it will need to be defined at Pipeline scope elsewhere in your code.
This is because the string literal logFile does not contain the string Admin repo url is :::. If there's no such match, then grep will exit with status 1.
You probably want to use
cat logFile | grep \"Admin repo url is :::\"
instead, or, even simpler:
grep \"Admin repo url is :::\" logFile
Append || true (or ||:) to the command if you want to avoid the errors when the log line does not appear.
In my scripted Jenkinsfile I have a line that runs parallel deployments . I omitted the other stages and code for security.
When I run this, it can't find the reportUrl and I get the error: groovy.lang.MissingPropertyException: No such property: teamsUrl for class: groovy.lang.Binding.
However, if I run without the parallel deployments it works and I'm able to reach the value of reportUrl. I tested with echo statements. Any thoughts?
Am I not exiting the parallel statement properly?
stage("Deploy") {
def deployments = [:]
// Code here not pasted
parallel deployments
echo "Deployed to clusters"
}
stage('Reporting') {
def reportUrl = 'https://testurl'
echo "${reportUrl}"
sh """
./my-tool report deploy \
--report-url "${reportUrl}" \
--force
"""
}
EDIT 6/22
reportUrl comes from a groovy file: example.groovy
example = load("deploy/example.groovy")
def reportUrl = example.REPORT_URL['report']
//I can see the url being pulled correctly here
echo "${reportUrl}"
I am working on Jenkins [Multibranch Pipeline]. I configure the GitHub and its working fine.But I am facing an issue when I am trying to deploy the GitHub project to SALESFORCE production. I also placed Jenkins file in GitHub project.
Here is the code of my Jenkins file
#!groovy
import groovy.json.JsonSlurperClassic
node {
def BUILD_NUMBER=env.BUILD_NUMBER
def RUN_ARTIFACT_DIR="tests/${BUILD_NUMBER}"
def SFDC_USERNAME
def HUB_ORG=env.HUB_ORG_DH
def SFDC_HOST = env.SFDC_HOST_DH
def JWT_KEY_CRED_ID = env.JWT_CRED_ID_DH
def CONNECTED_APP_CONSUMER_KEY=env.CONNECTED_APP_CONSUMER_KEY_DH
println 'KEY IS'
println JWT_KEY_CRED_ID
println HUB_ORG
println SFDC_HOST
println CONNECTED_APP_CONSUMER_KEY
def toolbelt = tool 'toolbelt'
stage('checkout source') {
// when running in multi-branch job, one must issue this command
checkout scm
}
withCredentials([file(credentialsId: JWT_KEY_CRED_ID, variable: 'jwt_key_file')]) {
stage('Create Scratch Org') {
rc = bat returnStatus: true,
script: "${toolbelt}/sfdx force:auth:jwt:grant --clientid ${CONNECTED_APP_CONSUMER_KEY} --username ${HUB_ORG} --jwtkeyfile ${jwt_key_file} --setdefaultdevhubusername --instanceurl ${SFDC_HOST}"
if (rc != 0) { error 'hub org authorization failed' }
// need to pull out assigned username
rmsg = bat returnStdout: true, script: "${toolbelt}/sfdx force:org:create --definitionfile config/project-scratch-def.json --json --setdefaultusername"
printf rmsg
def jsonSlurper = new JsonSlurperClassic()
def robj = jsonSlurper.parseText(rmsg)
if (robj.status != 0) { error 'org creation failed: ' + robj.message }
SFDC_USERNAME=robj.result.username
robj = null
}
}
}
I am trying to authorize salesforce by useing this line of code.
rc = bat returnStatus: true,
script: "${toolbelt}/sfdx force:auth:jwt:grant --clientid ${CONNECTED_APP_CONSUMER_KEY} --username ${HUB_ORG} --jwtkeyfile ${jwt_key_file} --setdefaultdevhubusername --instanceurl ${SFDC_HOST}"
But when i run jenkins I am getting this error.
'cmd' is not recognized as an internal or external command, operable program or batch file.
I WILL APPRECIATE IF ANYONE WILL HELP ME
I am executing a cURL command using sh command with no issue.
pulic uploadArtifct (String user, String password, String file, String
location) {
def cred = "${user}:${password}"
def cmd = "curl -v -u cred --upload-file ${file} ${location}"
sh cmd
}
However, when I try to execute the same cmd, using the Process object. I get an error:
public uploadArtifct (String user, String password, String file, String
location) {
def cred = "${user}:${password}"
def cmd = "curl -v -u cred --upload-file ${file} ${location}"
try {
def sout = new StringBuffer(), serr = new StringBuffer()
def proc = cmd.execute()
proc.consumeProcessOutput(sout, serr)
proc.waitForOrKill(1000)
println sout
} catch (Exception e) {
throw new RuntimeExceptipon("Cannot execute curl, exception: [${e.getClass().getName()} - '${e.getMessage()}']")
}
}
The error that I see is:
java.lang.RuntimeException: Cannot execute curl, exception: [java.lang.RuntimeException - 'Error running; stdout='', stderr='curl: Can't open 'Folder/artifact/file.zip'!
curl: try 'curl --help' or 'curl --manual' for more information
'']
What is it about Process.execute() that does not work. Am I missing something?
I ran into a similar issue half a year ago. As i found out , the curl request that you run using the sh command is executed on the agent where the build is run
sh cmd //this runs on the agent and hence finds the ${file}
However the second piece of code
def proc = cmd.execute() . //This is run on the master and hence it cannot find the ${file}
When you use groovy classes, it is by design to be executed on the master node. This is because the groovy engine that Jenkins uses is on the master
For example:
var output=sh "echo foo";
echo "output=$output";
I will get:
output=0
So, apparently I get the exit code rather than the stdout. Is it possible to capture the stdout into a pipeline variable, such that I could get:
output=foo
as my result?
Now, the sh step supports returning stdout by supplying the parameter returnStdout.
// These should all be performed at the point where you've
// checked out your sources on the slave. A 'git' executable
// must be available.
// Most typical, if you're not cloning into a sub directory
gitCommit = sh(returnStdout: true, script: 'git rev-parse HEAD').trim()
// short SHA, possibly better for chat notifications, etc.
shortCommit = gitCommit.take(6)
See this example.
Note: The linked Jenkins issue has since been solved.
As mention in JENKINS-26133 it was not possible to get shell output as a variable. As a workaround suggested using of writ-read from temporary file. So, your example would have looked like:
sh "echo foo > result";
def output=readFile('result').trim()
echo "output=$output";
Try this:
def get_git_sha(git_dir='') {
dir(git_dir) {
return sh(returnStdout: true, script: 'git rev-parse HEAD').trim()
}
}
node(BUILD_NODE) {
...
repo_SHA = get_git_sha('src/FooBar.git')
echo repo_SHA
...
}
Tested on:
Jenkins ver. 2.19.1
Pipeline 2.4
You can try to use as well this functions to capture StdErr StdOut and return code.
def runShell(String command){
def responseCode = sh returnStatus: true, script: "${command} &> tmp.txt"
def output = readFile(file: "tmp.txt")
if (responseCode != 0){
println "[ERROR] ${output}"
throw new Exception("${output}")
}else{
return "${output}"
}
}
Notice:
&>name means 1>name 2>name -- redirect stdout and stderr to the file name
I had the same issue and tried almost everything then found after I came to know I was trying it in the wrong block. I was trying it in steps block whereas it needs to be in the environment block.
stage('Release') {
environment {
my_var = sh(script: "/bin/bash ${assign_version} || ls ", , returnStdout: true).trim()
}
steps {
println my_var
}
}
A short version would be:
echo sh(script: 'ls -al', returnStdout: true).result
def listing = sh script: 'ls -la /', returnStdout:true
Reference : http://shop.oreilly.com/product/0636920064602.do Page 433