Thursday, July 21, 2011

Customizing Post-Build Email Notifications in Jenkins

Jenkins, the successor to Hudson, is a general purpose jobs-management console in Java. Lately I've been using this tool a lot to create and monitor nightly automation tests. After a job is run, I like to get an email notification, and in this notification, I want only a summary of the results, a custom-parsing of my console output. It happens that in my console output I've printed each test's results with a line that looks like this: RESULT ==> PASSED: nameOfTest or RESULT ==> FAILED: nameOfTest. All I want in the email is the list of these lines.

The default post-build email job in Jenkins is not very configurable. Fortunately there is an extensible email plugin which provides more functionality. To use it, though, you need to become at least a little familiar with something called 'jelly' - Java/XML hybrid language that apparently belongs to the Maven project.

The plugin comes with a couple of 'jelly' scripts which demonstrate a lot of stuff, including how to paste the console output into your post-build email notification. I only wanted to paste part of the output, though, and had to modify the original script. This was tricky only until I understood that within this jelly language, you call normal Java functions.

Eventually, I did have  success parsing the console output using the jelly script. I made a copy of the html.jelly included in the email-ext, found in /var/lib/jenkins/plugins/email-ext/WEB-INF/classes/hudson/plugins/emailext/templates

at the bottom of html.jelly is this section: <br />
<j:getstatic classname="hudson.model.Result" field="FAILURE" var="resultFailure">
<j:if test="${build.result==resultFailure}">


<j:foreach items="${build.getLog(100)}" var="line"></j:foreach>
<table cellpadding="0" cellspacing="0"><tbody>
<tr><td class="bg1">CONSOLE OUTPUT</td></tr>
<tr><td class="console">${line}</td></tr>
</tbody></table>
</j:if></j:getstatic>


I wanted to parse out any line containing the word 'RESULT' regardless of whether the build passed or failed, so I removed the build.result lines and added an if statement inside the forEach loop. Reading the last 100 lines of the console output (retrieved by build.getLog), I tested each line for 'RESULT' using the Java String indexOf function, and when that resulted in 'true', I printed out the line
<br />
<j:foreach items="${build.getLog(100)}" var="line">
<j:if test="${line.indexOf('RESULT')&gt;=0}">
</j:if></j:foreach>


<table cellpadding="0" cellspacing="0"><tbody>
<tr><td class="console">${line}</td></tr>
</tbody></table>
</pre>
<br />
<br />
in the Jenkins job configuration (Editable Email Notification, in the post-build options), I selected HTML output and referenced this new, modified file (I called it custom_html2.jelly)
in DEFAULT CONTENT, like this: <br />
${JELLY_SCRIPT,template="custom_html2"} <br />
<br />
On post-build, the plugin uses the custom_html2.jelly to prepare and include the parsed output into the email notification