I have been tasked with capturing artifacts in the build process of a Jenkin's build. It is a multi-stage pipeline and I have added, as the last stage, a stage to hopefully accomplish this. I am fairly new to Jenkin's so this may be an obvious error / mistake to more advances users out there.
stage('collect and upload kickstart artifact') {
steps {
def server = Artifactory.server SERVER_ID
def uploadSpec = """{
"files": [
{
"pattern": "ks/*.cfg",
"target": "bin-local-cei/ks/"
},
]
}"""
server.upload(uploadSpec)
def buildInfo = Artifactory.newBuildInfo()
buildInfo.env.capture = true
buildInfo.env.collect()
buildInfo=server.upload(uploadSpec)
server.publishBuildInfo(buildInfo)
}
}
I am getting the following errors ...
WorkflowScript: 117: Expected a step # line 117, column 9.
def server = Artifactory.server SERVER_ID
^
WorkflowScript: 119: Expected a step # line 119, column 9.
def uploadSpec = """{
^
WorkflowScript: 127: Method calls on objects not allowed outside "script" blocks. # line 127, column 9.
server.upload(uploadSpec)
^
WorkflowScript: 129: Expected a step # line 129, column 9.
def buildInfo = Artifactory.newBuildInfo()
^
WorkflowScript: 130: Expected a step # line 130, column 9.
buildInfo.env.capture = true
^
WorkflowScript: 131: Expected a symbol # line 131, column 9.
buildInfo.env.collect()
^
WorkflowScript: 132: Expected a step # line 132, column 9.
buildInfo=server.upload(uploadSpec)
^
WorkflowScript: 133: Method calls on objects not allowed outside "script" blocks. # line 133, column 9.
server.publishBuildInfo(buildInfo)
^
WorkflowScript: 131: Missing required parameter: "message" # line 131, column 9.
buildInfo.env.collect()
^
9 errors
I've dug through blogs, posts, and articles but I am missing something here. Any assistance would be appreciated. Thanks!
you need to add some definitions like, node and script
I'm just not sure if the Artifactory will work, because I dont have this plugin installed.
#!/usr/bin/env groovy
pipeline {
agent none
stages {
stage('collect and upload kickstart artifact') {
steps {
node('master') {
script {
def server = Artifactory.server SERVER_ID
def uploadSpec = """{
"files": [
{
"pattern": "ks/*.cfg",
"target": "bin-local-cei/ks/"
},
]
}"""
server.upload(uploadSpec)
def buildInfo = Artifactory.newBuildInfo()
buildInfo.env.capture = true
buildInfo.env.collect()
buildInfo=server.upload(uploadSpec)
server.publishBuildInfo(buildInfo)
}
}
}
}
}
}
Related
Hi I have the following groovy script that I want to use to build a project in Jenkins
#!/usr/bin/env groovy
def deploymentPaths = '[]'
pipeline{
agent {
label 'jenkins-agent'
}
stages{
stage('Build debug'){
steps{
sh './make_debug.sh'
}
}
}
}
How can I make it wait till make_debug finishes and print its output? I tried
#!/usr/bin/env groovy
def deploymentPaths = '[]'
pipeline{
agent {
label 'jenkins-agent'
}
stages{
stage('Build debug'){
steps{
def sout = new StringBuilder(), serr = new StringBuilder()
def proc = './make_debug.sh'.execute()
proc.consumeProcessOutput(sout, serr)
proc.waitForOrKill(10000)
println "out> $sout\nerr> $serr"
}
}
}
}
But this doesn't work. Got following errors:
WorkflowScript: 13: Expected a step # line 13, column 7.
def sout = new StringBuilder(), serr = new StringBuilder()
^
WorkflowScript: 13: Expected a step # line 13, column 39.
def sout = new StringBuilder(), serr = new StringBuilder()
^
WorkflowScript: 14: Expected a step # line 14, column 7.
def proc = './make_debug.sh'.execute()
^
WorkflowScript: 15: Method calls on objects not allowed outside "script" blocks. # line 15, column 13.
proc.consumeProcessOutput(sout, serr)
^
WorkflowScript: 16: Method calls on objects not allowed outside "script" blocks. # line 16, column 13.
proc.waitForOrKill(1000)
^
WorkflowScript: 12: Missing required parameter: "delegate" # line 12, column 5.
step{
^
WorkflowScript: 15: Arguments to "error" must be explicitly named. # line 15, column 13.
proc.consumeProcessOutput(sout, serr)
^
WorkflowScript: 16: Expecting "class java.lang.String" but got "1000" of type class java.lang.Integer instead # line 16, column 32.
proc.waitForOrKill(1000)
I premise that I am not very familiar with Jenkins and Groovy.
I am trying to set a timeout with a time value that can change based on a specific condition. I was wondering if it is possible to do this and how.
This is a shortened example for simplicity, of the pipeline I'm dealing with:
/**
* prepare tests for parallel
* #param filename Name of the file that contains the testsuites list
*/
def doDynamicParallelSteps(filename){
tests = [:]
echo "doDynamicParallelSteps"
def w = pwd()
def path = "$w/$filename"
// read all the lines into a list, each line is an element in the list
def fh = new File(path)
def lines = fh.readLines()
for (line in lines) {
def values = line.split(":")
def testsuite_name = values[0].trim()
def test_path = values[1].trim()
def test_filename_or_directory = test_path.split("/").getAt(-1);
def is_file = test_filename_or_directory.matches("(.*).php")
def is_custom_mycondition = test_filename_or_directory.matches("MyMatchCondition")
if (is_custom_mycondition){ // large timeout
def time_val = 10
} else { // default timeout
def time_val = 5
}
tests["${test_filename_or_directory}"] = {
stage("UnitTest ${test_filename_or_directory}") {
timeout(time: time_val, unit: 'MINUTES') { // scripted syntax
// other stuff here
} // end timeout
} // end stage
} // end MAP
}
parallel tests
}
If I run this pipeline I got the following output:
hudson.remoting.ProxyException: groovy.lang.MissingPropertyException: No such property: time_val for class: mycustomJob
Then I've tried to set it as global value and it worked but not as expected, because its value doesn't seems to changed, it outputs "5" ignoring my condition.
What am I doing wrong? Can anyone show me the right way or a better approach?
What you are doing looks more pythonic than groovy. You must define the variable 'time_val' on a higher level to make it visible in your scope, like:
def time_val = 5
if (is_custom_mycondition){ // large timeout
time_val = 10
}
Instead of your else part.
You can also define it in a single line, like:
def time_val = is_custom_mycondition ? 10 : 5
Your 'timeout' usage looks correct to me. Just define the variable properly.
I would like to construct a JSON object and write the content to file.
Originally I was inspired by this and tried:
def data = [
a:"test: ${myVar}"
]
writeJSON(file: 'message1.json', json: data)
But this failed with:
Could not instantiate {file=message1.json, json={a=test}} for WriteJSONStep(file: String, json: JSON{}, pretty?: int): java.lang.UnsupportedOperationException: must specify $class with an implementation of interface net.sf.json.JSON
So next I tried:
def data = readJSON text: '{}'
data.a = "test: ${myVar}"
writeJSON(file: 'message1.json', json: data, pretty: 4)
Now the build passes, but the content of the file looks like:
{
"a": {
"bytes": [
114,
101,
108,
101,
97,
115,
101
50
],
"strings": [
"test: ",
""
],
"valueCount": 1,
"values": ["v1.0.2"]
}
}
Whereas my intention was {"a": "test: v1.0.2"}
My end goal is that I want to dynamically construct a JSON object, set some properties with some dynamic data and then write the JSON file.
Is there some syntax that can be used to assign the values as strings, rather than some bytes.
It seems one solution to this is changing the code that adds to the map to specify as String:
def data = readJSON text: '{}'
data.a = "test: ${myVar}" as String
writeJSON(file: 'message1.json', json: data, pretty: 4)
regarding your first attempt, it seems there is a JSONObject.fromObject() function you can use.
def data = JSONObject.fromObject([
a:"test: ${myVar}".toString()
])
writeJSON(file: 'message1.json', json: data)
currently I wish to added a multliline text parmeter to a groovy pipeline. If the text parameter is not left column alighed (no space before paramter), then whitespace is injected into the text parameter list.
Any ideas on how to resolve this?
Here is the code
#!/usr/bin/env groovy
node {
def startTime = new Date()
println "Build start time : " + startTime
// Load system parameters
def projectProperties = [
[$class: 'EnvInjectJobProperty', info: [loadFilesFromMaster: false, secureGroovyScript: [classpath: [], sandbox: false, script: '']], keepBuildVariables: true, keepJenkinsSystemVariables: true, on: true]
]
// Set project parameters
projectProperties.add(parameters([
string(name: 'infraRepo', description: 'Repo Name', defaultValue: 'my-infrastructure' ),
string(name: 'infraBranch', description: 'Repo Branch', defaultValue: 'develop' ),
string(name: 'projectName', description: 'Project name', defaultValue: 'think-more' ),
// Text field not left side aligned now whitespace will be injected
text(name: 'ecrRepoAndVersion', description: 'ECR Docker name and version number',
defaultValue:'''address=3.0.1
address-details=3.0.1
auth=3.2.1'''),
choice(name: 'clusterName', description: 'Ecs cluster name', choices: '---Select---\nblue-ci\ngreen-ci', defaultValue: '---Select---'),
]))
properties(projectProperties)
// Print system variables
sh 'env | sort'
}
And here is an image of how the Jenkins Job UI looks after this pipeline is executed. Note the whitespace in the ecrRepoAndVersion field.
Thank you - that worked perfectly.
text(name: 'ecrRepoAndVersion', description: 'ECR Docker name and
version number',defaultValue:"""address=3.0.7-RC\n
address-details=3.0.3-RC\nauth=3.2.3-RC""")
Setting aside the need for this logic, I would add a bit more readability and ease of maintenance by joining a list of items, instead of verbatim specification:
def ecrRepoAndVersionItemsDefault = [
"address=3.0.7-RC",
"address-details=3.0.3-RC",
"auth=3.2.3-RC",
]
...
// then construct an ArrayList
def jobParams = []
jobParams << ...
...
jobParams << text(
name: 'ecrRepoAndVersion',
description: 'ECR Docker name and version number',
defaultValue: ecrRepoAndVersionItemsDefault.join('\n')
)
// then add the properties
...
projectProperties.add(parameters(jobParams))
...
properties(projectProperties)
...
// etc.
I'm trying to add parameter in Jenkins groovy shell script, then wonder if groovy string interpolation can be used nested way like this.
node{
def A = 'C'
def B = 'D'
def CD = 'Value what I want'
sh "echo ${${A}${B}}"
}
Then what I expected is like this;
'Value what I want'
as if I do;
sh "echo ${CD}"
But it gives some error that $ is not found among steps [...]
Is it not possible?
Like this?
import groovy.text.GStringTemplateEngine
// processes a string in "GString" format against the bindings
def postProcess(str, Map bindings) {
new GStringTemplateEngine().createTemplate(str).make(bindings).toString()
}
node{
def A = 'C'
def B = 'D'
def bindings = [
CD: 'Value what I want'
]
// so this builds the "template" echo ${CD}
def template = "echo \${${"${A}${B}"}}"
// post-process to get: echo Value what I want
def command = postProcess(template, bindings)
sh command
}
In regard to the accepted answer, if you're putting values in a map anyway then you can just interpolate your [key]:
def A = 'C'
def B = 'D'
def bindings = [ CD: 'Value what I want' ]
bindings["${A}${B}"] == 'Value what I want'
${A}${B} is not a correct groovy syntax.
The interpolation just insert the value of expression between ${}.
Even if you change to the correct syntax and create $ method, the result will not be what you want.
def nested = "${${A}+${B}}"
println nested
static $(Closure closure) { //define $ method
closure.call()
}
CD will be printed.