How can I force Jenkins Blue Ocean to display print output instead of "Print Message"? - jenkins

In the below screenshot some debug entries display the output text (with - Print Message at the end) while others simply display Print Message. To view these you have to expand the step to see the output.
All lines are using the format print "TEXT HERE". I've tried using print, println, and echo. All have the same output.
Why do these sometimes display the message, while others force it into a collapsed section? Is it possible to configure this to always show? The normal non-Blue Ocean Jenkins interface displays fine but there is a lot of verbosity.

This seems to be a known issue:
https://issues.jenkins-ci.org/browse/JENKINS-53649
It looks like that BlueOcean does not handle the Groovy GStrings correctly. This is what I've observed:
A simple:
echo "hello world"
will work as expected and will display correctly.
Whereas a templated string with variables, like:
echo "hello ${some_variable}"
will hide the message under a "Print Message" dropdown.
See also this answer.

It appears that if echo uses a variable with value from params or environment (i.e. "params.*"), then step label gets "Print message" name instead of actual value being echoed. It does not matter if the variable itself is a String or not. Even explicitly converting the params value to String does not help.
String param_str
String text_var_2
parameters {
string(name: 'str_param', defaultValue: 'no value')
}
param_str = params.str_param.toString()
echo "string text in double quotes is ${param_str}"
echo "simple quoted string is here"
echo 'simple quoted string is here'
echo 'Single quoted with str ' + param_str + ' is here'
echo param_str
text_var_2 = 'Single quoted str ' + param_str + ' combined'
echo "GString global text2 is ${text_var_2}"
echo 'String global text2 is' + text_var_2
BlueOcean shows simple quoted strings in step label, but everything else as "Print message".
BlueOcean output
Note that 'normal' variables (strings, integers) are not included into this example, but they are also shown in the label normally. So if you have a code like this
def text_str = 'Some string'
def int_var = 1+2
echo text_str + ' is here'
echo int_var
These will be shown on the label.
And indeed it appears to be a known Jenkins issue as stated in a previous answer.

This is a known BlueOcean bug. The console output in the "classic" view interpolates variables correctly.
One workaround is to use the label parameter of the sh step:
def message = 'Hello World'
sh(script: "echo $message", label: message)

I tried lots of things and seems the moment an environment variable is going to be displayed, it uses Print Message instead the text.

Another workaround would be to split the multiline string into an array and iterate over it :-
String[] splitData = MULTI_LINE_STRING.split("\n");
for (String eachSplit : splitData) {
print(eachSplit);
}

Related

Use groovy-variable in Jenkins-Batchscript

I have this pipeline-script:
script {
def resultFile = "logs/Resharper-Warnings.out.xml"
bat (script:
'''
set PlotFrameworkVersion=v4.5.1
set ReferencePath='C:/lib'
call ".../InspectCode.exe" "Path/To/My.sln" -a -o="${resultFile}"
'''
)
recordIssues(
qualityGates: [[threshold: 1, type: 'TOTAL', unstable: true]],
tools: [resharperInspectCode(pattern: "${resultFile}")]
)
}
As you can see I want to use the variable resultFile within both the recordIssues-step as well as the bat-step. When I execute it, I get the following log:
Inspection report was written to D:\Workspace\${resultFile}
so the variable isn´t expanded correctly. The recorsIssues-step however does parse the variable, as seen in the log:
Searching for all files in 'D:\Workspace' that match the pattern 'logs/Resharper-Warnings.out.xml'
So how do I use the variable correctly within my bat-step?
It´s just about concatenating strings in groovy, which we can achieve using +. I ended up with this which isn´t the neatest way but it gets its job done:
''' set PlotFrameworkVersion=v4.5.1
set ReferencePath='C:/lib'
call ".../InspectCode.exe" "Path/To/My.sln" ''' + "-a -o=${resultFile}"

Environment variables manipulation

When using:
echo "${env.PRODUCT_NAME}"
it will echo:
MyProdName
When using:
echo "${env.MyProdName_Key}"
it will echo:
123456789
I would like to use something as follows:
echo "${env.${env.PRODUCT_NAME}_Key}"
Is this possible? How?
In Bash this is termed as variable in direction
Try using variables to make it further simplified
PRODUCT_NAME=$(echo "${env.PRODUCT_NAME}")
This would assign PRODUCT_NAME=MyProdName
Similarly
MyProdName=$(echo "${env.MyProdName_Key}")
This would assign MyProdName=123456789
Now when you print PRODUCT_NAME value you will get
echo ${PRODUCT_NAME}
MyProdName
And adding '!' variable indirection will give you the value of another variable values
echo ${!PRODUCT_NAME}
123456789
Maybe this will help you somehow:
def env = [
PRODUCT_NAME:'MyProdName',
MyProdName_Key: 123456789,
]
println "${env[env.PRODUCT_NAME+'_Key']}"
env is Map in the example provided but it works in the exactly same way.
Important note, regardless of how you're deriving variables:
There's no need to use string interpolation if the only value in a
string is a variable itself. This just clutters your code.
Instead of:
echo "${env.PRODUCT_NAME}"
you can do:
echo.PRODUCT_NAME.
Additionally you can grab nested object values dynamically using bracket notation
def obj = [a: '1']
echo obj[a] // outputs '1'
Using these put together, you can do:
def prodName = env.PRODUCT_NAME //will set var prodName to "MyProdName"
echo env[prodName + '_Key'] //gets nested field with key "MyProdName_Key"
(Note: this is similar to Opal's answer, hopefully my breakdown helps)

How can I convert GPathResult to text without pretty format

I'm trying to use groovy to update Jenkins job config.xml by the following code
def updateParameter(String key, String value){
println "changing defult value as $value for key $key"
def xml = new XmlSlurper().parseText(jobConfig)
xml.properties.'hudson.model.ParametersDefinitionProperty'.'parameterDefinitions'.'hudson.model.StringParameterDefinition'.each {
println 'found parameter: ' + it.name
if(it.name.text() == key){
println('default value changed')
it.defaultValue=value
}
}
jobConfig = XmlUtil.serialize(xml)
}
When running jobConfig = XmlUtil.serialize(xml), it changes the format, which is pretty, but I lost link break in pipeline plugin, so pipeline script doesn't work anymore. Is there a way to convert GPathResult to String without format changing?
Best Regards,
Eric
It is all my fault, the line breaks were removed when I read the xml. It seems XmlUtil.serialize(xml) doen't format the text of a xml tag, which is good :)
Best Regards,
Eric

Jenkins Customize Editable Email Content

In my Jenkins step I have windows batch command which runs a java jar file (java -Dfile.encoding=UTF-8 -jar C:\Test1\Test.jar C:\Test\test.log) and output of which is a String value (verified Jenkins console the string is getting printed) . How will I use this string content and insert in the editable email content body so I can send this content as an email . I wouldn't want the whole Jenkins console in the email only this String. I would assume the string has to be set as an environment variable after the script runs . Not sure how exactly I can use EnvInjPlugin for my scenario if at all it can be.
Try to use pre-send script.
For example You have in log the string like: "this random integer should be in email content: 3432805"
and want to add randomly generated integer to email content.
Set the Default Content with whatever you want but add some
value which will be replaced. For example:
This is the random int from build.log: TO_REPLACE
Then click "Advanced Settings" and add Pre-send Script:
String addThisStringToContent = "";
build.getLog(1000).each() { line ->
java.util.regex.Pattern p = java.util.regex.Pattern.compile("random\\sinteger.+\\:\\s(\\d+)");
java.util.regex.Matcher m = p.matcher(line);
if (m.find()) {
addThisStringToContent = m.group(1);
}
}
if (addThisStringToContent == "") {
logger.println("Proper string not found. Email content has not been updated.");
} else {
String contentToSet = ((javax.mail.Multipart)msg.getContent()).getBodyPart(0).getContent().toString().replace("TO_REPLACE", addThisStringToContent);
msg.setContent(contentToSet, "text/plain");
}
where:
build.getLog(1000) - retrieves the last 1000 lines of build output.
Pattern.compile("random\\sinteger.+\\:\\s(\\d+)") - regex to find the proper string
"text/plain" - Content Type
String contentToSet = ((javax.mail.Multipart)msg.getContent()).getBodyPart(0).getContent().toString().replace("TO_REPLACE", addThisStringToContent); - replaces the string TO_REPLACE with your value
Hope it will help you.
Unfortunately I have not enough reputation to comment Alex' great answer, so I write a new answer. The call
msg.setContent(contentToSet, "text/plain")
has two disadvantages:
Special characters are garbled
An attachment gets lost
So I use the following call to set the modified text
((javax.mail.Multipart)msg.getContent()).getBodyPart(0).setContent(contentToSet, "text/plain;charset=UTF-8")

changing a variable using gets.chomp()

im trying to write to a file using this code:
puts "-------------------- TEXT-EDITOR --------------------"
def tor(old_text)
old_text = gets.chomp #
end
$epic=""
def torr(input)
tore= $epic += input + ", "
File.open("tor.txt", "w") do |write|
write.puts tore
end
end
loop do
output = tor(output)
torr(output)
end
i have read the ultimate guide to ruby programming
and it says if i want to make a new line using in the file im writing to using File.open
i must use "line one", "line two
how can i make this happend using gets.chomp()? try my code and you will see what i mean
thank you.
The gets method will bring in any amount of text but it will terminate when you hit 'Enter' (or once the STDIN receives \n). This input record separator is stored in the global variable $/. If you change the input separator in your script, the gets method will actually trade the 'Enter' key for whatever you changed the global variable to.
$/ = 'EOF' # Or any other string
lines = gets.chomp
> This is
> multilined
> textEOF
lines #=> 'This is\nmultilined\ntext'
Enter whatever you want and then type 'EOF' at the end. Once it 'sees' EOF, it'll terminate the gets method. The chomp method will actually strip off the string 'EOF' from the end.
Then write this to your text file and the \n will translate into new lines.
File.open('newlines.txt', 'w') {|f| f.puts lines}
newlines.txt:
This is
multilined
text
If you dont use .chomp() the \n character will be added whenever you write a new line, if you save this to the file it also will have a new line. .chomp() removes those escape characters from the end of the input.
If this doesnt answer your question, i am sorry i dont understand it.

Resources