Index: html.jelly =================================================================== --- html.jelly (revision 0) +++ html.jelly (revision 0) @@ -0,0 +1,248 @@ + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + BUILD ${build.result}
Build URL${rooturl}${build.url}
Project:${project.name}
Date of build:${it.timestampString}
Build duration:${build.durationString}
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
CHANGES
${spc}Revision ${cs.revision} by + + ${aUser.displayName}: + ${cs.user}: + + (${cs.msgAnnotated}) +
${spc}${p.editType.name}${p.value}
No Changes
+
+
+ + + + + + + + + + + +
BUILD ATRIFACTS
+ +
  • + ${f} +
  • +
    +
    +
    +
    + + + + + + + + + + + + + + + + + + + +
    BUILD ATRIFACTS
    ${m.key.displayName}
    + +
  • + ${f} +
  • +
    +
    +
    +
    + + + + + + + + + + + + + + + + +
    JUnit Tests
    Name: ${packageResult.getName()} Failed: ${packageResult.getFailCount()} test(s), Passed: ${packageResult.getPassCount()} test(s), Skipped: ${packageResult.getSkipCount()} test(s), Total: ${packageResult.getPassCount()+packageResult.getFailCount()+packageResult.getSkipCount()} test(s)
  • Failed: ${failed_test.getFullName()}
  • +
    +
    + + + + + + + + +
    Cobertura Report
    +
    Project Coverage Summary
    + + + + + + + + + + + + + +
    Name${metric.name}
    ${coberturaResult.name}${coberturaResult.getCoverage(metric).percentage}% + (${coberturaResult.getCoverage(metric)}) +
    + + +

    Source

    + + +
    + + + + + + + ${coberturaResult.sourceFileContent} + +
    ${coberturaResult.relativeSourcePath}
    +
    +
    + +

    + Source code is unavailable +

    +
    +
    +
    + + + +
    Coverage Breakdown by ${element.displayName}
    + + + + + + + + + + + + + + + + + + + + + + + + + +
    Name${metric.name}
    + ${child.xmlTransform(child.name)} + ${childResult.percentage}% + (${childResult}) + N/A
    +
    +
    +
    +
    + + + + + + + + + +
    CONSOLE OUTPUT
    ${line}
    +
    +
    + + +
    Index: src/main/java/hudson/plugins/emailext/plugins/content/CustomJellyContent.java =================================================================== --- src/main/java/hudson/plugins/emailext/plugins/content/CustomJellyContent.java (revision 0) +++ src/main/java/hudson/plugins/emailext/plugins/content/CustomJellyContent.java (revision 0) @@ -0,0 +1,167 @@ +package hudson.plugins.emailext.plugins.content; + +import hudson.Functions; +import hudson.maven.reporters.SurefireAggregatedReport; +import hudson.model.AbstractBuild; +import hudson.model.AbstractProject; +import hudson.model.Action; +import hudson.model.Hudson; +import hudson.plugins.emailext.EmailType; +import hudson.plugins.emailext.ExtendedEmailPublisher; +import hudson.plugins.emailext.plugins.EmailContent; +import hudson.tasks.junit.TestResult; +import hudson.tasks.junit.TestResultAction; +import hudson.tasks.test.AggregatedTestResultAction.ChildReport; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.apache.commons.jelly.JellyContext; +import org.apache.commons.jelly.JellyException; +import org.apache.commons.jelly.JellyTagException; +import org.apache.commons.jelly.Script; +import org.apache.commons.jelly.XMLOutput; + +public class CustomJellyContent implements EmailContent { + + private static final String TEMPLATE_NAME_ARG = "template"; + private static final String DEFAULT_HTML_TEMPLATE_NAME = "html"; + private static final String DEFAULT_TXT_TEMPLATE_NAME = "txt"; + private static final String EMAIL_TEMPLATES_FOLDER = "email-templates"; + + public String getToken() { + return "CUSTOM"; + } + + public String getHelpText() { + return "Custom message content. " + + "The content is generated from a jelly template. " + + "If no template name is provided then the default \"" + DEFAULT_HTML_TEMPLATE_NAME + "\" template is used. " + + "Make sure that the message content type is set to HTML then. " + + "The other template that is available is \"" + DEFAULT_TXT_TEMPLATE_NAME + "\" which should be used with Plain Text content type. " + + "You can create your own message template " + + "- the best way to do it is to ask Hudson administrators for the default template, modify it, " + + "and send it back to the administrators who will place it in email templates folder in Hudson home directory.\n" + + "\n"; + } + + public List getArguments() { + return Collections.singletonList(TEMPLATE_NAME_ARG); + } + + public

    , B extends AbstractBuild> String getContent( + AbstractBuild build, ExtendedEmailPublisher publisher, + EmailType type, Map args) throws IOException, + InterruptedException { + File templatesFolder = new File(Hudson.getInstance().getRootDir(), EMAIL_TEMPLATES_FOLDER); + String templateName = Args.get(args, TEMPLATE_NAME_ARG, DEFAULT_HTML_TEMPLATE_NAME); + File templateFile = new File(templatesFolder, templateName + ".jelly"); + return getContentFromJelly(build, templateFile); + } + + public boolean hasNestedContent() { + return false; + } + + private

    , B extends AbstractBuild> String getContentFromJelly( + AbstractBuild build, File file) { + String content = ""; + try { + if (file.exists()) { + content = renderContent(new BuildWrapper(build), build, file); + } else { + content = "* EMAIL TEMPLATE NOT FOUND: " + file.getAbsolutePath() + ", PLEASE CONTACT HUDSON ADMINISTRATORS *"; + } + } catch (Exception e) { + e.printStackTrace(); + } + return content; + } + + private String renderContent(Object it, AbstractBuild build, File file) throws JellyException, IOException { + JellyContext context = createContext(it, build); + Script script = context.compileScript(file.toURI().toURL()); + if (script != null) { + return convert(context, script); + } + return null; + } + + private String convert(JellyContext context, Script script) + throws UnsupportedEncodingException, JellyTagException, IOException { + ByteArrayOutputStream output = new ByteArrayOutputStream(16 * 1024); + XMLOutput xmlOutput = XMLOutput.createXMLOutput(output); + script.run(context,xmlOutput); + xmlOutput.flush(); + xmlOutput.close(); + output.close(); + return output.toString(); + } + + private JellyContext createContext(Object it, AbstractBuild build) { + JellyContext context = new JellyContext(); + context.setVariable("it", it); + context.setVariable("build", build); + context.setVariable("project", build.getParent()); + context.setVariable("rooturl", ExtendedEmailPublisher.DESCRIPTOR.getHudsonUrl()); + return context; + } + + public class BuildWrapper { + + private AbstractBuild build; + + public BuildWrapper(AbstractBuild build) { + this.build = build; + } + + public String getTimestampString() { + return Functions.rfc822Date(build.getTimestamp()); + } + + public Action getAction(String className) { + for (Action a: build.getActions()) { + if (a.getClass().getName().equals(className)) { + return a; + } + } + return null; + } + + public Action getCoberturaAction() { + return getAction("hudson.plugins.cobertura.CoberturaBuildAction"); + } + + public List getJUnitTestResult(){ + List result = new ArrayList(); + List actions = build.getActions(); + for(Action action: actions){ + if(action instanceof hudson.maven.reporters.SurefireAggregatedReport){ + /* Maven Project */ + List reportList =((SurefireAggregatedReport)getAction("hudson.maven.reporters.SurefireAggregatedReport")).getChildReports(); + for(ChildReport report: reportList){ + if(report.result instanceof hudson.tasks.junit.TestResult){ + result.add((TestResult)report.result); + } + } + } + } + if(result.isEmpty()){ + /*FreestyleProject*/ + TestResultAction action = ((TestResultAction)getAction("hudson.tasks.junit.TestResultAction")); + if(action!=null) + result.add(action.getResult()); + } + return result; + } + } +} Index: txt.jelly =================================================================== --- txt.jelly (revision 0) +++ txt.jelly (revision 0) @@ -0,0 +1,83 @@ + +GENERAL INFO + +BUILD ${build.result} +Build URL: ${rooturl}${build.url} +Project: ${project.name} +Date of build: ${it.timestampString} +Build duration: ${build.durationString} + + + +CHANGE SET + + + + Revision ${cs.revision} by ${aUser.displayName}: ${cs.user}: (${cs.msgAnnotated}) + change: ${p.editType.name} ${p.value} + + +No changes + + + + + + +ARTIFACTS +*${f} + + + + +MAVEN ARTIFACTS + ${m.key.displayName} + + + + +*${f} + + + + + + + + + + +JUNIT RESULTS + + +Name: ${packageResult.getName()} Failed: ${packageResult.getFailCount()} test(s), Passed: ${packageResult.getPassCount()} test(s), Skipped: ${packageResult.getSkipCount()} test(s), Total: ${packageResult.getPassCount()+packageResult.getFailCount()+packageResult.getSkipCount()} test(s) + Failed: ${failed_test.getFullName()} + + + + + + + + + + + +COBERTURA RESULTS + +${coberturaResult.getName()} + +${key} ${coberturaResult.getResults().get(key)} (${coberturaResult.getResults().get(key).getPercentage()}%) + + +By packages + + ${coberturaResult.getChild(child).getName()} + + ${childkey} ${coberturaResult.getChild(child).getResults().get(childkey)} (${coberturaResult.getChild(child).getResults().get(childkey).getPercentage()}%) + + + + + +