Techkriti

August 30, 2008

Using Groovy with Hudson to send rich text email

Filed under: Java — Chetan @ 7:27 pm

Recently I migrated from CruiseControl to Hudson as our CI build server. One thing I found lacking in Hudson was to send rich text email containing information regarding changelist details, test result etc. The email extender plugin do provide few variables to be inserted into the mail but that is very limiting.So I modified the plugin to send HTML email which were generated using Groovy‘s SimpleTemplate.

In the template the AbstractBuild object was exposed as a binding. Using that one can compose email containing some changelist info, test stats etc. Further the Groovy template can be used to write email content in any form, look and feel as one wants. This post would explain how to write a simple groovy script to display build related information

A patch has been submitted to Hudson as REF2175. In this post I would try to explain how this feature can be put to use.

Plugin Configuration

Email-Ext configuration

Email-Ext configuration

The updated plugin now provides new fields for adding the mail template. In the plugin template you can add any groovy based script which would then be passed to the groovy template engine. Also you can enable weather the email is of type text/html or text/plain.

All the variables provided by the email-ext plugin earlier are still available for use as bindings

Mail Content

For the mail content we would use the Groovy’s SimpleTemplate. The complete template can be accessed from here. The email generated has following main sections.

  • General Information
  • Committed changelist
  • Test Result summary
  • Build logs

Lets see few of these in details.

Collecting Changelist

In the template we first collect the changelist information from the build object. For more details refer to the properties exposed by the AbstractBuild. So here we collect all the changelists from lastSuccesfulBuild. Later we would use this to display the changelist contents in details

<%
def lastSuccesfulBuild = build.previousNotFailedBuild
def failed = build.result != hudson.model.Result.SUCCESS

def currResult = build.result
def prevResult = build.previousBuild?.result ?: null

def consecutiveSuccess = currResult == hudson.model.Result.SUCCESS && prevResult == hudson.model.Result.SUCCESS

def builds = []
def changes = []
def count = 0

if(consecutiveSuccess){
   builds << build
   def changeItems = build.changeSet.items
   count += changeItems.length
   changes += changeItems as List
}else{
    while(lastSuccesfulBuild){
	builds << lastSuccesfulBuild
	def changeItems = lastSuccesfulBuild.changeSet.items
	count += changeItems.length
	changes += changeItems as List
    	lastSuccesfulBuild = lastSuccesfulBuild.nextBuild
    }
}
%>

Displaying the Changelist details

Now we would iterate over the changes to display the details. The groovy code is highlighted below. In my case the SCM repository is Perforce. So the changelist object is PerforceChangeLogSet and hence the properties accessed are exposed by it

 <tr>
    <td><b>Modifications since last  successful build:&nbsp; (${count}) </b><hr size="2" width="100%" align="center"/></td>
   </tr>
   <tr>
   	<td>
    	<table width="100%" border="0">
        <% changes.each { item ->
	    def cl = item.change
	%>
          <tr>
            <td style="font-size:10pt; font-family:Arial, Helvetica, sans-serif">
              <a href="http://perforceserver/cgi-bin/p4describe.pl?@${cl.changeNumber}">${cl.changeNumber}</a>
                by ${cl.user}@${cl.workspace} on ${cl.date}</td>
          </tr>
          <tr>
            <td><pre style="font-size:8pt; font-family:Arial, Helvetica, sans-serif">${cl.description}</pre></td>
          </tr>
          <tr>
            <td style="font-size:10pt; font-family:Arial, Helvetica, sans-serif">
             <span style="font-size:10pt; font-family:Arial, Helvetica, sans-serif; "> Affected files:</span>
            	<ul style="font-size:8pt; font-family:Arial, Helvetica, sans-serif">
                <% cl.files.each{ fileEntry -> %>
                  <li>[<a href="http://perforceserver/cgi-bin/p4browse.pl?@diff+${fileEntry.filename}+${fileEntry.revision}+{@action}">Diff</a>]
                  [<a href="http://perforceserver/cgi-bin/p4browse.pl?@filelog+${fileEntry.filename}">History</a>]
                  ${fileEntry.action} ${fileEntry.filename} (${fileEntry.revision})
                  </li>
             	<% } %>
      		   </ul>
               <hr size="1" width="80%" align="left" />
            </td>
          </tr>
         <% } %>
	    </table>
    </td>
   </tr>

This results in following output

Test Result display

I had a requirement to depict the test results in the mail. The result should display the testcases which have started failing seperately from the previous failing test.(I know all test should pass but in reality few test continue failing due to some reasons or other). So here we iterate over current test results and previous test results to determine the delta. Also we collect some data to create a link for the failing test

Segregating the test results in such a way brings the required attention to the test cases which had started failing

  <%
	if(build.testResultAction) {
	    def rootUrl = hudson.model.Hudson.instance.rootUrl
		def testResult = build.testResultAction
		def jobName = build.parent.name

		def lastBuildSuccessRate = String.format("%.2f",(testResult.totalCount-testResult.result.failCount)*100f/(testResult.totalCount))
		def lastBuildDuration = String.format("%.2f",(testResult.result.duration ))

		def startedPassing = []
		def startedFailing = []
		def failing = []

		def previousFailedTestCases = new HashSet()
		def currentFailedTestCase = new HashSet()

		if(build.previousBuild?.testResultAction){
			build.previousBuild.testResultAction.failedTests.each {
				previousFailedTestCases << it.simpleName +"." + it.safeName
			}
		}

		testResult.failedTests.each{tr ->
			  def packageName = tr.packageName
			  def className = tr.simpleName
			  def testName = tr.safeName
			  def displayName = className+"."+testName

			  currentFailedTestCase << displayName
			  def url = "${rootUrl}job/$jobName/lastBuild/testReport/$packageName/$className/$testName"
			  if(tr.age == 1){
				startedFailing << [displayName:displayName,url:url,age:1]
			  } else{
				failing << [displayName:displayName,url:url,age:tr.age]
			  }
		}

		startedPassing = previousFailedTestCases - currentFailedTestCase

		startedFailing = startedFailing.sort {it.displayName}
		failing = failing.sort {it.displayName}
		startedPassing = startedPassing.sort()
   %>

This data is then later displayed in list form as shown below

Conclusion

Using Groovy for generating the email content provides considerable flexibility. It exposes the Hudon data model (which is quite neatly designed) and makes it easy to extract information from it. Further it reduces the requirements to modify the plugin code considerably.

I find it more convenient over the xsl based approach used by CruiseControl. Below is a snapshot of the complete mail send to the users.

Update

I have uploaded the compile hpi file here. Just download it and then add it to your Hudson setup at Hudson -> Manage Hudson -> Manage Plugins -> Advanced

About these ads

104 Comments

  1. Any chance you could compile the plugin and post a link to it? I’d love to try this out!

    Comment by Ruel — September 9, 2008 @ 2:36 pm

  2. Sure added the link at the bottom of the post. Try it out and let me know if you face any issue. Also vote for the patch at Hudson site so that it get included

    Comment by Chetan — September 9, 2008 @ 4:18 pm

  3. EWW! Rich Text email? Email should remain simple text. Using tinyurls so that the rich text can be seen in the browswer where it should be.

    Comment by Jesus M. Rodriguez — September 10, 2008 @ 12:50 am

  4. @Jesus – Its configurable. In my case I wanted to summarize and extract some information and have to show in list for. Now doing it on browser means to have that page in Hudson which would require more effort. Here I can just generate that content in email itself

    You can also go for plain text email

    Comment by Chetan — September 10, 2008 @ 2:34 am

  5. Hello Chetan,

    I have downloaded your hpi-file and inserted your groovy template. When Hudson wants to send the mail, an error occurs. Maybe you can help me??

    Windows 2003
    Hudson 1.252

    Thanks,
    Jens

    Stacktrace:
    Email was triggered for: Failure

    There are 1 triggered emails.

    Sending email for trigger: Failure

    FATAL: Error using the template

    java.lang.RuntimeException: Error using the template

    at hudson.plugins.emailext.ExtendedEmailPublisher.transformUsingScript(ExtendedEmailPublisher.java:385)

    at hudson.plugins.emailext.ExtendedEmailPublisher.transformText(ExtendedEmailPublisher.java:355)

    at hudson.plugins.emailext.ExtendedEmailPublisher.createMail(ExtendedEmailPublisher.java:302)

    at hudson.plugins.emailext.ExtendedEmailPublisher.sendMail(ExtendedEmailPublisher.java:274)

    at hudson.plugins.emailext.ExtendedEmailPublisher._perform(ExtendedEmailPublisher.java:266)

    at hudson.plugins.emailext.ExtendedEmailPublisher.perform(ExtendedEmailPublisher.java:224)

    at hudson.model.AbstractBuild$AbstractRunner.performAllBuildStep(AbstractBuild.java:318)

    at hudson.model.AbstractBuild$AbstractRunner.performAllBuildStep(AbstractBuild.java:306)

    at hudson.model.Build$RunnerImpl.cleanUp(Build.java:131)

    at hudson.model.Run.run(Run.java:832)

    at hudson.model.Build.run(Build.java:88)

    at hudson.model.ResourceController.execute(ResourceController.java:70)

    at hudson.model.Executor.run(Executor.java:88)

    Caused by: groovy.lang.MissingPropertyException: No such property: change for class: hudson.scm.SubversionChangeLogSet$LogEntry

    at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:51)

    at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.getProperty(ScriptBytecodeAdapter.java:502)

    at Script1$_run_closure1.doCall(Script1.groovy:58)

    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)

    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)

    at java.lang.reflect.Method.invoke(Unknown Source)

    at org.codehaus.groovy.runtime.metaclass.ReflectionMetaMethod.invoke(ReflectionMetaMethod.java:56)

    at org.codehaus.groovy.runtime.MetaClassHelper.doMethodInvoke(MetaClassHelper.java:538)

    at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:243)

    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:643)

    at groovy.lang.Closure.call(Closure.java:291)

    at groovy.lang.Closure.call(Closure.java:304)

    at org.codehaus.groovy.runtime.DefaultGroovyMethods.each(DefaultGroovyMethods.java:848)

    at org.codehaus.groovy.runtime.DefaultGroovyMethods.each(DefaultGroovyMethods.java:827)

    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)

    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)

    at java.lang.reflect.Method.invoke(Unknown Source)

    at org.codehaus.groovy.runtime.metaclass.ReflectionMetaMethod.invoke(ReflectionMetaMethod.java:56)

    at org.codehaus.groovy.runtime.metaclass.NewInstanceMetaMethod.invoke(NewInstanceMetaMethod.java:54)

    at org.codehaus.groovy.runtime.MetaClassHelper.doMethodInvoke(MetaClassHelper.java:538)

    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:803)

    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:643)

    at org.codehaus.groovy.runtime.Invoker.invokePojoMethod(Invoker.java:87)

    at org.codehaus.groovy.runtime.Invoker.invokeMethod(Invoker.java:75)

    at org.codehaus.groovy.runtime.InvokerHelper.invokeMethod(InvokerHelper.java:69)

    at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.invokeMethodN(ScriptBytecodeAdapter.java:170)

    at Script1.run(Script1.groovy:57)

    at groovy.text.SimpleTemplateEngine$SimpleTemplate$1.writeTo(SimpleTemplateEngine.java:110)

    at groovy.text.SimpleTemplateEngine$SimpleTemplate$1.toString(SimpleTemplateEngine.java:122)

    at hudson.plugins.emailext.ExtendedEmailPublisher.transformUsingScript(ExtendedEmailPublisher.java:380)

    … 12 more

    Comment by Jens Goldhammer — September 19, 2008 @ 5:21 pm

  6. Hi Jens,

    The exception is because I am using Perforce and the change property is part of PerforceChangeLogEntry. In case of Subversion it is SubversionChangeLogSet.LogEntry. So you would have to use its properties. So possibly following mapping would be used (refer to javadocs for LogEntry to to see more info)
    cl.changeNumber -> item.revision
    cl.user -> item.author
    cl.date -> item.date
    cl.description -> item.msg
    cl.workspace -> Subversion has no concept of workspace so remove it
    cl.files -> item.paths
    fileEntry.action -> fileEntry.editType
    fileEntry.filename -> fileEntry.value
    fileEntry.revision -> item.revision //This is because Subversion’s concept of Revision no is for whole trunk instead of per file as maintained by Perforce

    So I am pasting the modified template for Modification set. Replace it accordingly in the main template and give it a try

    <tr>
    <td><b>Modifications since last successful build:&nbsp; (${count}) </b><hr size="2" width="100%" align="center"/></td>
    </tr>
    <tr>
    <td>
    <table width="100%" border="0">
    <% changes.each { item -> %>
    <tr>
    <td style="font-size:10pt; font-family:Arial, Helvetica, sans-serif">
    ${item.revision} by ${item.author} on ${item.date}</td>
    </tr>
    <tr>
    <td><pre style="font-size:8pt; font-family:Arial, Helvetica, sans-serif">${item.msg}</pre></td>
    </tr>
    <tr>
    <td style="font-size:10pt; font-family:Arial, Helvetica, sans-serif">
    <span style="font-size:10pt; font-family:Arial, Helvetica, sans-serif; "> Affected files:</span>
    <ul style="font-size:8pt; font-family:Arial, Helvetica, sans-serif">
    <% item.paths.each{ fileEntry -> %>
    <li> ${fileEntry.editType} ${fileEntry.value} </li>
    <% } %>
    </ul>
    <hr size="1" width="80%" align="left" />
    </td>
    </tr>
    <% } %>
    </table>
    </td>
    </tr>

    Comment by Chetan — September 19, 2008 @ 7:22 pm

  7. Thanks for this hint! I was not considering that you use perforce (I have copied it without reading!).

    The new version causes following error.

    Sending email for trigger: Failure
    FATAL: Error using the template
    java.lang.RuntimeException: Error using the template
    at hudson.plugins.emailext.ExtendedEmailPublisher.transformUsingScript(ExtendedEmailPublisher.java:385)
    at hudson.plugins.emailext.ExtendedEmailPublisher.transformText(ExtendedEmailPublisher.java:355)
    at hudson.plugins.emailext.ExtendedEmailPublisher.createMail(ExtendedEmailPublisher.java:302)
    at hudson.plugins.emailext.ExtendedEmailPublisher.sendMail(ExtendedEmailPublisher.java:274)
    at hudson.plugins.emailext.ExtendedEmailPublisher._perform(ExtendedEmailPublisher.java:266)
    at hudson.plugins.emailext.ExtendedEmailPublisher.perform(ExtendedEmailPublisher.java:224)
    at hudson.model.AbstractBuild$AbstractRunner.performAllBuildStep(AbstractBuild.java:318)
    at hudson.model.AbstractBuild$AbstractRunner.performAllBuildStep(AbstractBuild.java:306)
    at hudson.model.Build$RunnerImpl.cleanUp(Build.java:131)
    at hudson.model.Run.run(Run.java:832)
    at hudson.model.Build.run(Build.java:88)
    at hudson.model.ResourceController.execute(ResourceController.java:70)
    at hudson.model.Executor.run(Executor.java:88)
    Caused by: groovy.lang.MissingPropertyException: No such property: duration for class: hudson.tasks.test.AggregatedTestResultPublisher$TestResultAction
    at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:51)
    at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.getProperty(ScriptBytecodeAdapter.java:502)
    at Script1.run(Script1.groovy:91)
    at groovy.text.SimpleTemplateEngine$SimpleTemplate$1.writeTo(SimpleTemplateEngine.java:110)
    at groovy.text.SimpleTemplateEngine$SimpleTemplate$1.toString(SimpleTemplateEngine.java:122)
    at hudson.plugins.emailext.ExtendedEmailPublisher.transformUsingScript(ExtendedEmailPublisher.java:380)
    … 12 more

    For this reason I deleted the test section because we have no unit tests in this build.
    Now it works well!

    Thanks a lot,
    Jens

    Comment by Jens Goldhammer — September 22, 2008 @ 8:11 am

  8. Great Stuff! Very useful!

    Comment by Michael Kebe — September 29, 2008 @ 9:00 pm

  9. hi,

    Can this plugin be used to grab content from the filesystem? E.g., I’d like to pull in some lines from a file.

    I’m not familiar at all with Groovy, so forgive me if this should be obvious.

    brian.

    Comment by Brian Gerkey — October 17, 2008 @ 11:25 pm

  10. Hi Brian,

    Yes its very much possible to access the file system and read the files. Groovy is very much like so you can try it easily. You have the full power of IO library in JDK at your disposal. You can also invoke a process and capture it output

    Comment by Chetan — October 20, 2008 @ 5:21 pm

  11. Hi Chetan,

    This is a really good tutorial. :)
    We are currently using Hudson for our project’s CI and your email template is just what we needed!
    Could we use your template and modify it for our own needs?
    Please let me know if you think otherwise.

    Qing

    Comment by Qing — October 22, 2008 @ 2:58 am

  12. Yes you can definitely use the template. Probably I should have been explicit in stating that in the post. If possible let me know how it worked for you

    Comment by Chetan — October 22, 2008 @ 4:29 am

  13. Oh it works very well. Just need to make some minor changes, like moving the test results before the changes, since we usually got a long list of changes which hides the results.
    Also put in some color coding for failures to catch people’s eyes :). You also got a test duration variable but it’s not displayed. It’s small things like that I’ve changed. In general, it works great lol

    Comment by Qing Wei — October 22, 2008 @ 2:11 pm

  14. Cool … good to know it worked for u. Are you using SVN or Perforce

    Comment by Chetan — October 22, 2008 @ 2:38 pm

  15. Perforce

    Comment by Qing — October 23, 2008 @ 3:57 am

  16. Maybe you can provide your templates on the hudson wiki?
    Thanks for your work again.

    Bye,
    Jens

    Comment by Jens Goldhammer — November 19, 2008 @ 5:45 pm

  17. The link to the .hpi doesn’t work anymore….

    Comment by Claus Nielsen — November 26, 2008 @ 6:28 am

  18. I checked the link and it was working. Can you try again

    Comment by Chetan — November 26, 2008 @ 10:14 am

  19. https://share.acrobat.com/adc/adc.do?docid=c122d416-09de-4841-af4b-1a48555cecdd just opens a window where the text is Acrobat.

    Comment by Claus Nielsen — November 27, 2008 @ 6:57 am

  20. Both in IE and FF

    Comment by Claus Nielsen — November 27, 2008 @ 6:58 am

  21. Hmm it probably downloads a Flash client while it shows the Acrobat logo. I have also shared the file at http://chetan.mehrotra.googlepages.com/email-ext.hpi . You can try it from there

    Comment by Chetan — November 27, 2008 @ 5:30 pm

  22. Great job, thanks :) I want to change the ChangeLog diff to Trac, where should I look for?

    Comment by Hieu Le Trung — December 1, 2008 @ 9:21 am

  23. I am not aware of how Trac works. If it can provide any url which can provide this info on passing the changelist no then refer to that url in the section explained at “Displaying the Changelist details”

    Comment by Chetan — December 2, 2008 @ 5:11 pm

  24. Thanks for your work.
    I deleted the test part because i had an error : $testResult.failCount was not recognized.

    Do you think it’s connected to my version of hudson ? (Hudson ver. 1.260)

    Comment by maor — December 2, 2008 @ 6:19 pm

  25. Not sure, my Hudson version is 1.238. Whats the error you got which made you remove that. The template checks that build.testResultAction is not null. In that case it invokes the getFailCount part of AbstractTestResultAction. So I do think that its not recognized.

    Comment by Chetan — December 3, 2008 @ 5:48 pm

  26. This is a great extension! I think you should work very hard to add this functionality to the ‘official’ plugin. Just annoy these people, until they include it! :-)

    (I am not feeling well using your patched version of the plugin, as there seems to be a more recent version of the official plugin an Hudson keeps telling me I should upgrade.)

    Comment by Mike — January 10, 2009 @ 2:31 pm

  27. First, thanks much for the patched plugin; it’s been working great!

    I just switched to a master / slave setup and my email-ext Groovy script that extracts data from build-generated files are no longer working. It would appear that the Groovy script is executed in the context of the master, not the slave. Is this the case?

    If so, that makes it difficult to construct sophisticated notification emails when using build slaves. Any advice?

    brian.

    Comment by Brian Gerkey — January 12, 2009 @ 3:22 am

  28. @Mike – I have mailed it multiple times on the mailing list. Probably it may get included now as email-ext plugin has seen some activity.

    @Brian – I have used it only with single machine setup and not in a master-slave pattern. I have not much idea related to how Hudson handles that. May be the email publisher gets executed on Master as it is its responsibility to collect the details and decide to send the mail. Slaves are only responsible for executing the builds.
    Take a look at hudon.model.Hudson.instance. It has methods to get access to Slaves and from there you may find some way to navigate the data model. Would require some code digging :)

    Comment by Chetan — January 12, 2009 @ 10:03 am

  29. Ok, so I’ve pretty much got it working with a slave.

    I used to do this to get the contents of a file into the notification email:
    def ws = build.getParent().getWorkspace()
    def build_failures = “cat ${ws}/ros/rosmakeall-buildfailures.txt”.execute()
    println “${build_failures.text}”

    Now I do this:
    def ws = build.getParent().getWorkspace()
    // Would be nice to get slave name from somewhere…
    computer = hudson.model.Hudson.instance.getComputer(“vm2″)
    def build_failures = hudson.util.RemotingDiagnostics.executeGroovy(“new File(\”${ws}/ros/rosmakeall-buildfailures.txt\”).text”,computer.getChannel())
    println “${build_failures}”

    Pretty much it’s a switch to calling RemotingDiagnostics.executeGroovy, along with a switch from shelling out to cat (I couldn’t get that to work remotely) to using Groovy’s builtin file-reading support.

    The one nasty thing that remains is that I hardcode the slave’s name. Can I retrieve that from somewhere? In my case it’s not too bad, because my jobs are tied to particular slaves, but it’s still not elegant.

    brian.

    Comment by Brian Gerkey — January 12, 2009 @ 5:19 pm

  30. The groovy script template link is a picture of the output. Can you provide a working groovy script? Also do you have details on how to create/debug these scripts? Waiting for hudson jobs to build can be very time consuming to see your emails lost in configuration errors.

    Comment by Brian — March 2, 2009 @ 11:11 pm

  31. Brian,

    The working groovy script is also linked. You can download it from http://chetan.mehrotra.googlepages.com/mail-template.txt. To create the script you can make use of the Groovy console present in Hudson itself

    As of now there is no way to debug them though.

    Comment by Chetan — March 4, 2009 @ 5:25 am

  32. How can I include a html file contents in the ‘default contents’ using this plugin. I have a html file whose content I would like to send via in the email body.
    I notice that I cannot use any hudson’s environment variables like %JOB_NAME%. I also notice that I cannot use ‘/’ . i need to specify the location of my html file (C:\testing\%JOB_NAME%\email.html)

    Can i get some help please.

    Ali

    Comment by Ali Raza — March 10, 2009 @ 4:40 am

  33. This is what I have in my contents

    The error I get is
    FATAL: Error using the template
    java.lang.RuntimeException: Error using the template
    at hudson.plugins.emailext.ExtendedEmailPublisher.transformUsingScript(ExtendedEmailPublisher.java:385)
    at hudson.plugins.emailext.ExtendedEmailPublisher.transformText(ExtendedEmailPublisher.java:355)
    at hudson.plugins.emailext.ExtendedEmailPublisher.createMail(ExtendedEmailPublisher.java:302)
    at hudson.plugins.emailext.ExtendedEmailPublisher.sendMail(ExtendedEmailPublisher.java:274)
    at hudson.plugins.emailext.ExtendedEmailPublisher._perform(ExtendedEmailPublisher.java:266)
    at hudson.plugins.emailext.ExtendedEmailPublisher.perform(ExtendedEmailPublisher.java:224)
    at hudson.model.AbstractBuild$AbstractRunner.performAllBuildStep(AbstractBuild.java:365)
    at hudson.model.AbstractBuild$AbstractRunner.performAllBuildStep(AbstractBuild.java:353)
    at hudson.model.Build$RunnerImpl.cleanUp(Build.java:174)
    at hudson.model.Run.run(Run.java:933)
    at hudson.model.Build.run(Build.java:112)
    at hudson.model.ResourceController.execute(ResourceController.java:93)
    at hudson.model.Executor.run(Executor.java:119)
    Caused by: groovy.lang.GroovyRuntimeException: Failed to parse template script (your template may contain an error or be trying to use expressions not currently supported): startup failed, SimpleTemplateScript32.groovy: 3: unexpected char: ‘\’ @ line 3, column 27.
    1 error

    at groovy.text.SimpleTemplateEngine.createTemplate(SimpleTemplateEngine.java:75)
    at groovy.text.TemplateEngine.createTemplate(TemplateEngine.java:38)
    at hudson.plugins.emailext.ExtendedEmailPublisher.transformUsingScript(ExtendedEmailPublisher.java:365)
    … 12 more

    Comment by Ali Raza — March 10, 2009 @ 11:45 pm

  34. this form on wordpress strips out script tags so lets try again.

    Comment by Ali Raza — March 10, 2009 @ 11:48 pm

  35. one more try

    (this is inside the script tags in hudson email plugin)

    def content = new File(“F:\%JOB_NAME%\%BUILD_NUMBER%\email.html”).text

    Comment by Ali Raza — March 10, 2009 @ 11:49 pm

  36. Hi Ali

    Couple of points
    – Try using the forward slash ‘/’ in path names
    – I am not sure that JOB_NAME would be replaced. Is this from the same list as provided by email-ext plugin. The plugin only support replacement of those variables which are supported by email-ext
    – The file approach should work. As Brian got it working (Comment #29)

    Let me know how it turns out

    Comment by Chetan — March 11, 2009 @ 9:03 am

  37. Hi Chetan,
    The forward slash definitely worked. Can’t believe I was pulling out my hair for such a simple thing.
    I have this in my content now and it reads and send the email.

    content = new File(“F:/HudsonResults/$PROJECT_NAME/$BUILD_NUMBER/email.html”).text
    println(content)

    Comment by Ali Raza — March 12, 2009 @ 12:51 am

  38. Won’t it be better to rename this plugin? Something like email-ext-groovy will avoid Hudson warning me there is a new version, which would overwrite this plugin..

    Comment by AJ — March 15, 2009 @ 8:50 pm

  39. I agree, that would be wounderful! Thank you in advance! :)

    Comment by Mike — March 25, 2009 @ 11:57 am

  40. Hi Chethan,

    This patch seems to be an useful one. I tried to install the hpi and when I get to the configuration page, I’m able to see the extra options, Default content Script & Default content Html. But I added the test summary related snippets in the Default content and waited for the results (like the one you have illustrated), In my case I’m getting a blank email. I’ve deployed hudson on a ubuntu server and I’m using ant. Is there something I need to install furthermore.

    Thanks

    Comment by Ponns — March 25, 2009 @ 11:07 pm

  41. Wow,I figured out my mistake. I got that work. Excellent patch chethan. I think this should be added to the email-ext.hpi asap

    Comment by Ponns — March 26, 2009 @ 2:02 am

  42. Hi Chetan,

    I have been using this plugin patch for a while now, and it has been most useful. In my case, I have SoapUI tests setup on Hudson that are being used to run parallel reconciliation tests to validate that the results of our services match with the legacy Mainframe functionality, and there are times when we have reconciliation errors. I use another step in my Ant script to identify the cause of the reconciliation error, dump that in a file, and email the contents of the file. This way, the testers not only see the failed tests, but also see the reason for the failure.

    Regarding the plugin patch itself, I wonder if it would be possible to have an option where the Groovy email script itself is in an external file, rather than inline in the Hudson configuration. I have several Hudson jobs that use the same email Groovy script, and if I have to change the email script, I have to apply it in multiple jobs manually. Ideally, I would like to check in the Groovy email script into version control, and have the Hudson email-ext plugin use the version controlled file.

    Thanks

    Comment by Mahesh — April 10, 2009 @ 4:53 pm

  43. Hi Mahesh,

    Not sure but can trying pulling in the content from a file and eval that as a script in the script itself. Sort of hacky but should work given the dynamic nature of Groovy.

    I have started work on integrating it with main code base ,just that things have changed quite bit since the time I worked on it. Hope to integrate it soon. Would see if a explicit file support can also be provided

    Comment by Chetan — April 11, 2009 @ 2:07 pm

  44. I am using TFS for SCM. the above code for displaying the Modification is for Perforce and someone posted the code for Subversion.
    Can someone help for displaying the changes if the SCM is MS TFS.

    Thanks

    Ali

    Comment by Ali — April 21, 2009 @ 1:10 am

    • Hi Ali,

      Did you ever resolve this? I am attempting to use with TFS as well…

      Thanks!

      Comment by Bernie — August 11, 2010 @ 7:58 pm

  45. I am using the code at http://chetan.mehrotra.googlepages.com/mail-template.txt
    to generate a test case failure history. The part I am having some issues with is this. I don’t know why the code is not picking up the correct packageName from the JunitReport.

    testResult.failedTests.each{tr ->
    def packageName = tr.packageName
    def className = tr.simpleName
    def testName = tr.safeName
    def displayName = packageName + ” –> ” + className +” –> “+testName

    I notice that in my email has
    (root)–> testSuiteH1 –>H1_TC2

    My Junit looks like this

    Why is packageName not resolved as per the junit report i.e. ‘AAAAAAAAA”

    thanks

    Comment by Ali — April 21, 2009 @ 10:56 pm

  46. posting junit report again (removing tags)

    ?xml version=”1.0″ encoding=”UTF-8″?
    testsuites
    testsuite name=”TestSuiteH1″ tests=”4″ failures=”1″ errors=”0″ time=”1197″ package=”AAAAAAAAAA” id=”1″
    properties
    ……

    Comment by Ali — April 21, 2009 @ 11:27 pm

  47. I copied the template from http://chetan.mehrotra.googlepages.com/mail-template.txt and pasted it in Default Content. But i get email with same content it is not parsing it. Any idea what i am missing.
    Do we need to run that Groovy script

    Comment by skumar — April 28, 2009 @ 4:18 pm

  48. We are using this plugin with good success, the only thing that we noticed is that the checkbox for “Include Culprits” is not there. I am able to get that checkbox and label displayed again via modifying the configuration files behind the scenes, but when checked, it doesn’t do anything. Even if I modify the config.xml under the Hudson job directory to include the entry for true with the block, it does nothing. Why was this functionality taken out? Can we get it back?

    Comment by Chris — April 29, 2009 @ 5:19 pm

  49. Great plugin.

    Is it possible to set the content/script at the global level? Having to reproduce a standard template for every project is less than ideal.

    Comment by KC — May 6, 2009 @ 7:55 pm

  50. Hi,

    Do someone have a html template which is working for SVN

    -Som Singh

    Comment by Som Singh — June 29, 2009 @ 11:38 am

  51. is there a way to grab a project’s parameters with groovy? I’ve been trying to find the way to catch the parameters you can set for a project using the “This build is parameterized” option, but no luck yet. Has anybody done this already?

    Thank you

    Regards

    Comment by juan carlos — July 13, 2009 @ 7:55 pm

  52. I’ve been able to get the Parameters for a parameterized build like this:

    ${build.envVars.TARGET_BUILD_NUMBER}

    TARGET_BUILD_NUMBER is one of the parameters for my build.

    Comment by KC Baltz — July 14, 2009 @ 8:15 pm

  53. Thanks for the plugin. Really loving the customized e-mail. One question. Is it possible to get the results from other plugins in the e-mail? For example, we are running Checkstyle and Findbugs. I assume you need to call build.getAction(?) but I can’t seem to get it to work. Anyone else doing something like this?

    Comment by Chuck — July 23, 2009 @ 10:08 pm

    • Hi Chuck,

      Did you implemented checkstyle into email using ext-mail plugin? If yes please guide me.

      Thanks,

      Comment by vikas — September 4, 2009 @ 9:14 am

      • Here is the code snippet to get them:

        def checkstyleResults = []
        build.actions.each { plugin ->
        if (plugin.displayName.toLowerCase().contains(‘checkstyle’)) {
        plugin.result.annotations?.each { warn ->
        checkstyleResults << warn
        }
        }
        }

        Comment by Chuck — September 4, 2009 @ 12:54 pm

  54. Hi,

    I’m evaluating now Hudson for our company and your email plugin makes all the difference. Thanks for that. Without extended info in the email for sure we would keep cruise control.

    Just one small question: Is there a way to control also the subject of the email? I would like to add there the success rate or at least the number of tests that failed.

    Thank you,
    Pavel

    Comment by Pavel — August 3, 2009 @ 1:42 am

  55. The Subject can be controlled in the same way as Body. I use following in my emails $DEFAULT_SUBJECT (${build.testResultAction?.failCount} ${build.testResultAction?.failureDiffString})

    Comment by Chetan — August 3, 2009 @ 11:50 am

  56. Thank you for the reply. The subject works perfectly!
    Cheers,
    Pavel

    Comment by Pavel — August 4, 2009 @ 6:28 am

  57. This plugin is required for any type of advanced build publishing.

    I found the groovy JDK API (http://groovy.codehaus.org/groovy-jdk/)
    and the Hudson classes (https://hudson.dev.java.net/javadoc/hudson/model/AbstractModelObject.html)
    to be very helpful in applying this template for AccuRev SCM.

    If you are having trouble applying it to an SCM, use google code search or checkout the HudsonSCM code. (I examined the AccurevSCM hudson plugin code). In these files you’ll find what fields are available inside groovy. For instance, the Accurev plugin has this function, which tells me all the feilds I have access to…


    public final class AccurevTransaction extends ChangeLogSet.Entry {
    private String revision;
    private User author;
    private Date date;
    private String msg;
    private String action;
    private List affectedPaths = new ArrayList();

    Using the provided template, all I had to do was use code like the following snippet:

    changes.each { cs ->

    println “”
    println “”
    println “”
    println “Transaction ${cs.revision} by”

    If you are still having trouble, peek at the index.jelly and digest.jelly files which are in the AccuRev (or whatever your SCM is) plugin folder in the hudson source.. This will hint at how to expose the changes in HTML (minus the .jelly syntax, of course).

    C:\HudsonSourceCodeFolder\hudson\plugins\accurev\src\main\resources\hudson\plugins\accurev\AccurevChangeLogSet\

    Also, the name of the node is different from the machine its running on.


    import hudson.model.Computer
    def computer = Computer.currentComputer()

    //get the machine that the build is running on:
    println ${computer.toString().tokenize(“@”)[1]}

    //get the name of the NODE, (also computer.getNode() ? )
    println ${computer.nodeName}

    Comment by max — August 15, 2009 @ 12:03 am

  58. I’m reproducibly getting a NullPointerException when I use this plugin for a project that has never been built before.

    Stack trace:

    Caused by: java.lang.NullPointerException
    at hudson.plugins.emailext.plugins.content.ChangesSinceLastBuildContent.getContent(ChangesSinceLastBuildContent.java:26)
    at hudson.plugins.emailext.ExtendedEmailPublisher.transformUsingScript(ExtendedEmailPublisher.java:373)
    … 14 more

    Comment by max — August 28, 2009 @ 3:05 am

    • I am also seeing the NullPointerException.
      Stack trace:

      Caused by: java.lang.NullPointerException
      at hudson.plugins.emailext.plugins.content.ChangesSinceLastBuildContent.getContent(ChangesSinceLastBuildContent.java:26)
      at hudson.plugins.emailext.ExtendedEmailPublisher.transformUsingScript(ExtendedEmailPublisher.java:373)
      … 14 more

      Do you think that this could be caused by a change not having a comment? I have noticed a pattern in the builds that I have seen this in and they all have changes that do not have comments.

      Comment by david — November 16, 2009 @ 10:19 pm

  59. It’s regarding comment 5.
    In this comment you mentioned about setting some properties for Subversion.
    May I know where should I configure these properties. And what should be values assigned to them.

    Thanks in advance,

    Vikas

    Comment by Vikas — September 1, 2009 @ 8:43 am

  60. Hi Chetan,

    Issue of setting properties for Subversion is resolved. Actual issue was with my configuration.

    Now I wanted to add checkstyle’s result to email.

    Please guide me.

    Comment by vikas — September 4, 2009 @ 6:18 am

  61. I’ve tried applying the patch to the latest version of the ext mail plugin, but it’s failing miserably. I see that you had planned on updating things for the new code changes….any progress? Or have you created a version with a different name, like groovy-mail-ext or something?

    Comment by Ed M — September 4, 2009 @ 2:25 pm

  62. It would be nice if the Mail-to list was a groovy script (just like the subject is), as it would allow us to set environment variables for mail-to groups, as well as allow access to the builds parameters (if they were to pass in an email address, or a file of email addresses) for more customizable mail-to logic.

    Comment by max — September 14, 2009 @ 4:12 pm

  63. Hi,
    I get these errors on using the plugin you have mentioned and sending of mails fails. Can you please tell me how to overcome this ?

    FATAL: Error using the template

    java.lang.RuntimeException: Error using the template

    at hudson.plugins.emailext.ExtendedEmailPublisher.transformUsingScript(ExtendedEmailPublisher.java:385)

    at hudson.plugins.emailext.ExtendedEmailPublisher.transformText(ExtendedEmailPublisher.java:355)

    at hudson.plugins.emailext.ExtendedEmailPublisher.createMail(ExtendedEmailPublisher.java:302)

    at hudson.plugins.emailext.ExtendedEmailPublisher.sendMail(ExtendedEmailPublisher.java:274)

    at hudson.plugins.emailext.ExtendedEmailPublisher._perform(ExtendedEmailPublisher.java:266)

    at hudson.plugins.emailext.ExtendedEmailPublisher.perform(ExtendedEmailPublisher.java:224)

    at hudson.tasks.BuildStepMonitor$3.perform(BuildStepMonitor.java:36)

    at hudson.model.AbstractBuild$AbstractRunner.perform(AbstractBuild.java:480)

    at hudson.model.AbstractBuild$AbstractRunner.performAllBuildStep(AbstractBuild.java:466)

    at hudson.maven.MavenModuleSetBuild$RunnerImpl.cleanUp(MavenModuleSetBuild.java:620)

    at hudson.model.Run.run(Run.java:1159)

    at hudson.maven.MavenModuleSetBuild.run(MavenModuleSetBuild.java:301)

    at hudson.model.ResourceController.execute(ResourceController.java:93)

    at hudson.model.Executor.run(Executor.java:122)

    Caused by: groovy.lang.MissingPropertyException: No such property: revision for class: hudson.scm.CVSChangeLogSet$CVSChangeLog

    at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:49)

    at org.codehaus.groovy.runtime.callsite.GetEffectivePojoPropertySite.getProperty(GetEffectivePojoPropertySite.java:59)

    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callGetProperty(AbstractCallSite.java:236)

    at SimpleTemplateScript8$_run_closure1.doCall(SimpleTemplateScript8.groovy:61)

    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

    at java.lang.reflect.Method.invoke(Method.java:597)

    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:86)

    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:234)

    at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:272)

    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:892)

    at groovy.lang.Closure.call(Closure.java:279)

    at groovy.lang.Closure.call(Closure.java:292)

    at org.codehaus.groovy.runtime.DefaultGroovyMethods.each(DefaultGroovyMethods.java:1165)

    at org.codehaus.groovy.runtime.DefaultGroovyMethods.each(DefaultGroovyMethods.java:1141)

    at org.codehaus.groovy.runtime.dgm$87.invoke(Unknown Source)

    at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoMetaMethodSiteNoUnwrapNoCoerce.invoke(PojoMetaMethodSite.java:270)

    at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:52)

    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:43)

    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)

    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:124)

    at SimpleTemplateScript8.run(SimpleTemplateScript8.groovy:57)

    at groovy.text.SimpleTemplateEngine$SimpleTemplate$1.writeTo(SimpleTemplateEngine.java:112)

    at groovy.text.SimpleTemplateEngine$SimpleTemplate$1.toString(SimpleTemplateEngine.java:124)

    at hudson.plugins.emailext.ExtendedEmailPublisher.transformUsingScript(ExtendedEmailPublisher.java:380)

    … 13 more

    Comment by Nanditha — September 16, 2009 @ 1:19 pm

  64. how can i get “Diff” and “History ” for changed files in changelist details section of the script when using subversion.In the above example links to diff and history are posted in front of every changed file when perforce is used.I want to do the same thing with svn , so can anybody pls suggest me how that can be done.I am new to svn…

    Comment by singh — September 16, 2009 @ 11:03 pm

  65. Nanditha, refer to post #6, it is a very similar issue.

    hudson.scm.CVSChangeLogSet$CVSChangeLog does not have property ‘revision’, probably because you are not using perforce as your source control management tool. You need to look into your own SCMs plugin to see which properties its transactions have. If you don’t care about detecting transactions, just remove the code which tries to access the changeset and your email should work fine

    singh
    This is basically the same issue. Look at the template that is provided, and you can see where Chetan is hyperlinking to the diff on his perforce server. To do this for SVN, you will need modify the groovy template to link to the changes which are stored on a server or you can manually query SVN for the difference between each file and then insert it somehow into the email (perhaps store it in userContent directory and link to it there). If this doesn’t work, you can rebuilt the SVN plugin from source so that it queries and stores the desired Diff information in the transaction object, which can then be accessed via the groovy template in your emails.

    Comment by Mewl — September 22, 2009 @ 3:01 am

  66. Could you please post the template for printing the all the ” modifications since last successful build ” for SCM ? Any quick update on this will be very useful …

    Comment by Nanditha — September 22, 2009 @ 5:21 am

    • Hi Nanditha

      We are having the same issue with CVS plugin in Hudosn as you experienced at #66 Could you please post the solution here?

      Comment by Maruf — December 29, 2009 @ 9:30 am

  67. The properties revision and item.paths are giving errors and hence the mails will not be triggered …

    Comment by Nanditha — September 22, 2009 @ 7:06 am

  68. Are you using a source control management system? (SCM) such as SVN, AccuRev, or Perforce? If not, you can remove this part of the template, or create your own:

    <%
    println This build: ${build.number}”
    %>

    Comment by max — September 24, 2009 @ 7:58 pm

  69. Yeah , I’m using CVS and I want to print the details of the affected files too … Could you please suggest me a way for doing this ?

    Comment by Nanditha — September 25, 2009 @ 5:19 am

  70. Hi,

    I have tried using the template posted in this article with my hudson email-extn plugin.
    I ended up getting only partial output. I see that only hudson variables are expanded into runtime values.

    But the AbstractBuild object binding is not working, hence i get an output: Build on – {build.timestampString2}
    were the actual timeStamp value is not shown in the email.

    Can you please help me in figuring out what could be wrong..??

    Output snippet:
    ===============
    Build Information
    ——————————————————————————–

    Project Url – http://localhost:8080/hudson//job/hudson-email/
    Project name – hudson-email
    Build on – {build.timestampString2}
    Time taken to build – {build.durationString}

    Comment by Kiran — October 3, 2009 @ 9:11 am

  71. Kiran,

    This feature is currently not part of the std email-ext plugin so it would not be able to work on that. So to use the script feature use the attached email-ext.hpi

    @Mewl – Thnaks for your help on this

    Comment by Chetan — October 4, 2009 @ 9:44 am

  72. For some reason, when I upload the email-ext.hpi file, nothing seems to happen. Is the email-ext.hpi no longer working with the latest versions of hudson? I tried first 1.322 and then 1.330. I’ve installed the plugin and restarted Tomcat many times. I’ve see the version number on the plugin change to “2.2-SNAPSHOT (private-08/01/2008 07:18-chetanm)”. But the new fields in the configuration page consistently do not appear.

    Am I missing something?

    Comment by Harold Shinsato — October 27, 2009 @ 10:48 pm

  73. Ok, I found what I was missing – the fields are added to the project configuration page, not the top level hudson configuration page. The template seems to be giving me a problem though. The “failCount” doesn’t seem to work. I’m trying to remove it- but I wonder why some of this functionality can’t be bundled like it is with CruiseControl. It makes it really hard to have project transparency if detailed scripts have to be maintained on the hudson server.

    FATAL: Error using the template
    java.lang.RuntimeException: Error using the template
    at hudson.plugins.emailext.ExtendedEmailPublisher.transformUsingScript(ExtendedEmailPublisher.java:385)
    at hudson.plugins.emailext.ExtendedEmailPublisher.transformText(ExtendedEmailPublisher.java:355)
    at hudson.plugins.emailext.ExtendedEmailPublisher.createMail(ExtendedEmailPublisher.java:302)
    at hudson.plugins.emailext.ExtendedEmailPublisher.sendMail(ExtendedEmailPublisher.java:274)
    at hudson.plugins.emailext.ExtendedEmailPublisher._perform(ExtendedEmailPublisher.java:266)
    at hudson.plugins.emailext.ExtendedEmailPublisher.perform(ExtendedEmailPublisher.java:224)
    at hudson.tasks.BuildStepMonitor$3.perform(BuildStepMonitor.java:36)
    at hudson.model.AbstractBuild$AbstractRunner.perform(AbstractBuild.java:508)
    at hudson.model.AbstractBuild$AbstractRunner.performAllBuildStep(AbstractBuild.java:494)
    at hudson.maven.MavenModuleSetBuild$RunnerImpl.cleanUp(MavenModuleSetBuild.java:623)
    at hudson.model.Run.run(Run.java:1216)
    at hudson.maven.MavenModuleSetBuild.run(MavenModuleSetBuild.java:303)
    at hudson.model.ResourceController.execute(ResourceController.java:88)
    at hudson.model.Executor.run(Executor.java:123)
    Caused by: groovy.lang.MissingPropertyException: Exception evaluating property ‘failCount’ for hudson.tasks.test.AggregatedTestResultAction$1, Reason: groovy.lang.MissingPropertyException: No such property: failCount for class: hudson.tasks.test.AggregatedTestResultAction$ChildReport
    at org.codehaus.groovy.runtime.DefaultGroovyMethods.getAt(DefaultGroovyMethods.java:3544)
    at groovy.lang.MetaClassImpl$7.getProperty(MetaClassImpl.java:1707)
    at org.codehaus.groovy.runtime.callsite.GetEffectivePojoPropertySite.getProperty(GetEffectivePojoPropertySite.java:57)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callGetProperty(AbstractCallSite.java:236)
    at SimpleTemplateScript2.run(SimpleTemplateScript2.groovy:93)
    at groovy.text.SimpleTemplateEngine$SimpleTemplate$1.writeTo(SimpleTemplateEngine.java:112)
    at groovy.text.SimpleTemplateEngine$SimpleTemplate$1.toString(SimpleTemplateEngine.java:124)
    at hudson.plugins.emailext.ExtendedEmailPublisher.transformUsingScript(ExtendedEmailPublisher.java:380)
    … 13 more

    Comment by Harold Shinsato — October 28, 2009 @ 3:38 pm

  74. I have run into the same problem like Harold. We are using Perforce 2009.1 and the latest Hudson 1.330.
    I tried to eliminate the “failCount” in the template, but it seems not to be the problem.
    The error appear even when trying to send static-html via the plugin:

    Sending email for trigger: Still Unstable

    FATAL: Error using the template

    java.lang.RuntimeException: Error using the template

    at hudson.plugins.emailext.ExtendedEmailPublisher.transformUsingScript(ExtendedEmailPublisher.java:385)

    at hudson.plugins.emailext.ExtendedEmailPublisher.transformText(ExtendedEmailPublisher.java:355)

    at hudson.plugins.emailext.ExtendedEmailPublisher.createMail(ExtendedEmailPublisher.java:302)

    at hudson.plugins.emailext.ExtendedEmailPublisher.sendMail(ExtendedEmailPublisher.java:274)

    at hudson.plugins.emailext.ExtendedEmailPublisher._perform(ExtendedEmailPublisher.java:266)

    at hudson.plugins.emailext.ExtendedEmailPublisher.perform(ExtendedEmailPublisher.java:224)

    at hudson.tasks.BuildStepMonitor$3.perform(BuildStepMonitor.java:36)

    at hudson.model.AbstractBuild$AbstractRunner.perform(AbstractBuild.java:508)

    at hudson.model.AbstractBuild$AbstractRunner.performAllBuildStep(AbstractBuild.java:494)

    at hudson.maven.MavenModuleSetBuild$RunnerImpl.cleanUp(MavenModuleSetBuild.java:623)

    at hudson.model.Run.run(Run.java:1216)

    at hudson.maven.MavenModuleSetBuild.run(MavenModuleSetBuild.java:303)

    at hudson.model.ResourceController.execute(ResourceController.java:88)

    at hudson.model.Executor.run(Executor.java:123)

    Caused by: groovy.lang.MissingPropertyException: Exception evaluating property ‘failCount’ for hudson.tasks.test.AggregatedTestResultAction$1, Reason: groovy.lang.MissingPropertyException: No such property: failCount for class: hudson.tasks.test.AggregatedTestResultAction$ChildReport

    at org.codehaus.groovy.runtime.DefaultGroovyMethods.getAt(DefaultGroovyMethods.java:3544)

    at groovy.lang.MetaClassImpl$7.getProperty(MetaClassImpl.java:1707)

    at org.codehaus.groovy.runtime.callsite.GetEffectivePojoPropertySite.getProperty(GetEffectivePojoPropertySite.java:57)

    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callGetProperty(AbstractCallSite.java:236)

    at SimpleTemplateScript20.run(SimpleTemplateScript20.groovy:93)

    at groovy.text.SimpleTemplateEngine$SimpleTemplate$1.writeTo(SimpleTemplateEngine.java:112)

    at groovy.text.SimpleTemplateEngine$SimpleTemplate$1.toString(SimpleTemplateEngine.java:124)

    at hudson.plugins.emailext.ExtendedEmailPublisher.transformUsingScript(ExtendedEmailPublisher.java:380)

    … 13 more

    Comment by tholeu — October 29, 2009 @ 9:17 am

  75. Hi Chetan,

    I am seeing the same issue as posted in #58.
    Caused by: java.lang.NullPointerException
    at hudson.plugins.emailext.plugins.content.ChangesSinceLastBuildContent.getContent(ChangesSinceLastBuildContent.java:26)

    I believe that this might be caused by not having a comment for a change. At least in my environment every time I see this I have a change without a comment.

    Any chance of getting a patch that handles null change comments?

    Comment by david — November 18, 2009 @ 6:11 pm

  76. Is this plugin still available somewhere? The link you provide in this
    page given me a file not found error. Thanks,

    Comment by Miller — November 29, 2009 @ 12:21 am

  77. If the message contains chinese, in the mail, it will presented as ?????,
    How to solved the encoding problem?

    Thanks,
    yunshan

    Comment by yunshan — January 7, 2010 @ 3:18 am

  78. Hi Chetan,

    Could you give me some suggestion on handle unicode email content?

    Thanks
    yunshan

    Comment by yunshan — January 8, 2010 @ 11:29 am

  79. HiChetan,
    Can I get the source code of your changes, as I wanted to implement few changes with latest ext-mail plugin, I tried finding but did not got the src code of your changes.
    I want to make changes for “$CHANGES – Displays the changes since the last build.” as in your ext-mail plugin it shows the histroty from “CHANGES_SINCE_LAST_SUCCESS build” which in my case gives a very long list of changed files.
    I will not change the licence agreement and due credit will be given to you for your efforts.
    I will be thankful to you.

    Comment by Saharey — January 13, 2010 @ 5:34 am

  80. Hi

    Is this fix going to be added email-ext plugin? This is a great feature and must be added to email-ext plugin I think.

    Comment by cepnyci — January 21, 2010 @ 8:06 pm

  81. Hi Chetan,
    I am facing an issue here, whenever there is failure in build the rich text email send an entire list of Changelist from last failed build till the latest failed build this makes the email size sometimes around 25MB.
    It will be a great help if there is any workaround for this issue?
    Thanks
    Saharey

    Comment by Saharey — January 28, 2010 @ 7:35 am

  82. Hi

    In the script below it seems
    ${build.timestampString2} and ${item.time} is not getting local time on the machine. They are getting GMT time instead of local time set on the server.

    How can I fetch local time or make these times GMT+2?

    Regards
    Maruf

    .tablerow0 {
    background: #EEEEEE;
    }

    .tablerow1 {
    background: white;
    }

    .detailrow0 {
    background: #EEEEEE;
    }

    .detailrow1 {
    background: white;
    }

    .tableheader {
    background: #b9b9fe;
    font-size: larger;
    }

    <%
    def lastSuccesfulBuild = build.previousNotFailedBuild
    def failed = build.result != hudson.model.Result.SUCCESS

    def currResult = build.result
    def prevResult = build.previousBuild?.result ?: null

    def consecutiveSuccess = currResult == hudson.model.Result.SUCCESS && prevResult == hudson.model.Result.SUCCESS

    findbugsFileName = "findbugs.html.content"
    findbugsFile = new File(build.environment.workspace + "/"+ "target" + "/" + findbugsFileName)
    printFileLine = { println it }

    def builds = []
    def changes = []
    def count = 0

    if(consecutiveSuccess){
    builds << build
    def changeItems = build.changeSet.items
    count += changeItems.length
    changes += changeItems as List
    }else{
    while(lastSuccesfulBuild){
    builds <

    Build Result – $BUILD_STATUS

    Build Information

    Project Url – $PROJECT_URL
    Project name – $PROJECT_NAME
    Build on – ${build.timestampString2}
    Time taken to build – ${build.durationString}

    Modifications since last successful build:  (${count})

    %>

    by ${item.author} on ${item.date} ${item.time}

    ${item.msg}

    Affected files:

    %>
    ${fileEntry.path}

    Server Logs

    ${build.getLog(250).join(”)}

    Comment by Maruf Aytekin — January 28, 2010 @ 9:53 am

  83. A bit off topic, but it seems as if you are familiar with hudson good enough.
    I am also using Perforce for the first time (after years with CVS & SNV) and I would like the Build number to be set as the Change list number – and for “releases” I would like the build number to have an R added – I tried updating the NextBuildNumber text file in the jobs dir although I cannot add any text to it (its an int).
    Would you by any chance have any insight here?

    Comment by HagZag — January 30, 2010 @ 10:31 pm

  84. Whew – I thought I couldn’t get this working again on a new installation. It is very important that you install and configure the standard email-ext plugin on a project before you install the altered email-ext.hpi – or you won’t be able to change the triggers and the default content. Took me hours to figure it out – hopefully you can avoid that problem. This is a very useful extension – I hope more people vote for it at https://hudson.dev.java.net/issues/show_bug.cgi?id=2175

    Comment by Harold Shinsato — March 5, 2010 @ 2:49 pm

  85. I am having difficulties getting this plugin to work with Hudson running on a Solaris host. I installed the plugin in a clean install of Hudson and I am unable to add email triggers. It works when the Hudson server is running on Windows 2003. If I install the email-ext plugin from Hudson’s site, I can add email triggers and remove them from any job. If I swap out the plugin for this one, the jobs will send emails according to the triggers already defined and the groovy script works correctly, but I am unable to modify the triggers in any job. Can someone help?

    Comment by Matthew — March 11, 2010 @ 3:22 am

  86. @Matthew- I have the same problem. The only solution is to keep the modified email-ext plugin hpi file – and whenever you want to add triggers – upgrade to the latest – restart the server – add your triggers – then install the patched email-ext plugin – restart the server. The additional fields added by the patch are not modified when you swap back and forth. So it’s just really painful.

    I wish this feature would get into the actual email-ext plugin! Please do vote for it.

    Comment by Harold Shinsato — March 11, 2010 @ 11:06 pm

  87. Hi All

    I found about ${build.timestampString2} and ${item.time} not getting local time on the machine. Here i smy soulution in case others are having the same issue.

    - instead of “build.timestampString2″ I used “build.time”. It gives the local time that Hudson JVM started in.
    Defined formatted Build Time as follows:
    def formattedBuildTime=build.time.format(“yyyy-MM-dd HH:mm”)
    Used it in the email as follows:
    …………

    Project Url – $PROJECT_URL
    Project name – $PROJECT_NAME
    Build on – ${formattedBuildTime}
    Time taken to build – ${build.durationString}

    ………….

    - Parsed “item.time” string and created a date object and formatted it as follows:
    ………….

    %>

    by ${item.author} on

    ${formattedDateTime}

    ……………..

    Comment by Maruf Aytekin — April 1, 2010 @ 11:48 am

  88. Hi All

    I found about ${build.timestampString2} and ${item.time} not getting local time on the machine. Here i smy soulution in case others are having the same issue.

    - instead of “build.timestampString2″ I used “build.time”. It gives the local time that Hudson JVM started in.
    I defined formatted build time as follows:

    def formattedBuildTime=build.time.format(“yyyy-MM-dd HH:mm”)

    I used it in the email as follows:


    ..............
    Project Url – $PROJECT_URL
    Project name – $PROJECT_NAME
    Build on – ${formattedBuildTime}
    Time taken to build – ${build.durationString}
    ...............

    - Parsed “item.time” string and created a date object and formatted it as follows:

    ............
    by ${item.author} on

    ${formattedDateTime}

    ............

    Comment by Maruf Aytekin — April 1, 2010 @ 11:52 am

  89. 
    ............
               by ${item.author} on 
    
    ${formattedDateTime}
    
    .............
    

    Comment by Maruf Aytekin — April 1, 2010 @ 11:54 am

  90. 
    ...............
    
      def dateTime=new Date().parse("yyyy-MM-dd HH:mm z", item.date + " " + item.time + " " +  "GMT")
      def formattedDateTime=dateTime.format("yyyy-MM-dd HH:mm")
    
    ................
    

    Comment by Maruf Aytekin — April 1, 2010 @ 11:57 am

  91. is there latest plugin of rich text email created from latest code of email-ext plugin version 2.5

    Comment by Saharey — April 8, 2010 @ 8:41 am

  92. bump on getting a more recent build of the email-ext plugin (version 2.5) with the rich text patch applied.

    Comment by wcb00 — April 27, 2010 @ 7:37 pm

  93. [...] should support natively – you can see a change log via the UI.) After some research, I came across Using Groovy with Hudson to send rich text email posted by [...]

    Pingback by MEE SQA Blog » Blog Archive » Send a Subversion Change Log from a Hudson build — July 31, 2010 @ 3:41 pm

  94. HI,

    I have loaded the new plugin, thanks it is exactly what i was looking for. I have noticed a problem though, when configuring the plugin in Hudson, I can not change the trigger, or delete the existing one. I select something in the pull-down, but nothing happens. So i can only trigger an e-mail at a failure. The other e-mail-ext plugin allowed the user to ad as many triggers as were needed. Any ideas?
    Thanks! Great job and post!

    Comment by Bernie — August 11, 2010 @ 1:56 pm

    • Sorry, just saw the same problem reported above in post 86. please disregard, unless there is another solution or news of new plugin…

      Thanks again.

      Comment by Bernie — August 11, 2010 @ 3:33 pm

  95. Hello Chetan,
    Will this work with Clear Case?

    Comment by Priya — October 11, 2010 @ 6:13 pm

  96. Hi Chetan,

    I tried to use the plugin with latest hudson version 1.382 and i am getting folowing error:
    SEVERE: Failed Loading plugin email-ext hudson.util.IOException2: Failed to initialize

    what is the solution?

    thanks.

    Comment by Star — November 2, 2010 @ 9:02 pm

  97. PjFUtK http://gdjI3b7VaWpU1m0dGpvjRrcu9Fk.com

    Comment by frenky — May 7, 2011 @ 8:26 pm

  98. Hi Chetan
    This is an excellent plugin, was using it with Hudson but we have now upgraded to Jenkins ver. 1.413 and it doesn’t seem to be working any more. Have you update the plugin to work for the latest Jenkins version? If yes can you share it.
    Thanks,
    Rahul

    Comment by Rahul — June 1, 2011 @ 5:19 pm


RSS feed for comments on this post.

Sorry, the comment form is closed at this time.

The WordPress Classic Theme. Create a free website or blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: