2
votes

I am trying to attach the template file using Jenkins pipeline, emailext. Variable (PROJNAME) is not accessible in the template file and I am receiving exceptions as an email:

Exception raised during template rendering: No such property: env for class: SimpleTemplateScript21 groovy.lang.MissingPropertyException: No such property: env for class: SimpleTemplateScript21 at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:53) at org.codehaus.groovy.runtime.callsite.PogoGetPropertySite.getProperty(PogoGetPropertySite.java:52) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callGroovyObjectGetProperty(AbstractCallSite.java:307) at SimpleTemplateScript21.run(SimpleTemplateScript21.groovy:1) at groovy.text.SimpleTemplateEngine$SimpleTemplate$1.writeTo(SimpleTemplateEngine.java:168) at groovy.text.SimpleTemplateEngine$SimpleTemplate$1.toString(SimpleTemplateEngine.java:180) at hudson.plugins.emailext.plugins.content.ScriptContent.renderTemplate(ScriptContent.java:151) at hudson.plugins.emailext.plugins.content.ScriptContent.evaluate(ScriptContent.java:82) at org.jenkinsci.plugins.tokenmacro.DataBoundTokenMacro.evaluate(DataBoundTokenMacro.java:208) at org.jenkinsci.plugins.tokenmacro.Parser.processToken(Parser.java:308) at org.jenkinsci.plugins.tokenmacro.Action$KiHW1UeqOdqAwZul.run(Unknown Source) at org.parboiled.matchers.ActionMatcher.match(ActionMatcher.java:96) at org.parboiled.parserunners.BasicParseRunner.match(BasicParseRunner.java:77) at org.parboiled.MatcherContext.runMatcher(MatcherContext.java:351)

Pipeline Script:

stage('Email') {
    def mailRecipients = "[email protected]"
    def jobStatus = currentBuild.currentResult
    env.PROJNAME = 'project_name'
    echo "projname is ${PROJNAME}"
emailext body: '''${SCRIPT, template="test.template"}''',
    mimeType: 'text/html',
    subject: "[Jenkins] ${jobStatus}",
    to: "${mailRecipients}"
}

Template (filename - test.template):

<html>
<head>
<title>Page Title</title>
</head>
<body>
<h1>This is a Heading</h1>
<p>Job is '${env.PROJNAME}'</p>
</body>
</html>

Also tried replacing the variable syntax in template file as "${PROJNAME}" and "${ENV, var="PROJNAME"}" but no luck. Any suggestions?

Didn't help when I replaced with ENV(var="PROJNAME") in template file. I received the email as:

This is a Heading

Job is ENV(var="PROJNAME")

3
Did you simple try using : <p>Job is ${env.PROJNAME}</p>? without the single quotes? - Ravindranath Barathy
Yes I did and received the same exception as email. - Sri
I have the same issues. Did you find any solution? - Sergey Bondarev
Solution provided by Pakeer worked for me - Sri

3 Answers

3
votes

Try override the env variable in the html template as below

<%
def envOverrides = it.getAction("org.jenkinsci.plugins.workflow.cps.EnvActionImpl").getOverriddenEnvironment()
    project =  envOverrides["PROJNAME"]
%>

you can then use the local variable project in your html like

<p> Job is ${project} </p>

Note: you can use all the required env variables using the envOverrides

5
votes

The only what worked for me in email template:

<%
    import hudson.model.*

    def YOUR_VARIABLE= build.getEnvVars()["SOME_BUILD_PARAMETER"];
%>

Then you can use

${YOUR_VARIABLE}
1
votes

To complete Pakeer's answer, you can serialize data using json and pass it through env vars if you need to use complex data in the email template. My need was to query some data from jira and then send it in a custom email template, and i ended up with this jenkins pipeline:

payload = [
    jql: "project = WFMA and issuetype in (Incident, Bug) and fixVersion = \"${version}\"",
    startAt: 0,
    maxResults: maxResults,
    fields: [ "id", "issuetype", "summary", "priority", "status", "assignee" ]
]

response = httpRequest(url: jiraRestBaseUrl + "search",
    acceptType: 'APPLICATION_JSON', contentType: 'APPLICATION_JSON', 
    httpMode: 'POST', validResponseCodes: '100:599', requestBody: new JsonBuilder(payload).toString(), 
    authentication: 'jira-wsf-jenkins', timeout: 30)

if (response.status != 200) {
    echo("JIRA REST API returned an error ${response.status} when searching for issues, content is ${response.content}")
    throw new hudson.AbortException(("JIRA REST API returned an error ${response.status}"))
}

jsonResponse = new JsonSlurper().parseText(response.content)
if (jsonResponse.total > jsonResponse.maxResults) {
    throw new hudson.AbortException(("total is bigger than maxResults, please implements pagination"))
}

if (jsonResponse.total == 0) {
    echo('No issue associated with this release, skipping')
} 
else {
    def emailSubject = "Please verify the ticket statuses for the release ${version} deployed on ${plannedUatDate}"
    def releaseIssues = jsonResponse.issues
    env.release_name = version
    env.release_date = plannedUatDate
    env.release_issues = JsonOutput.toJson(releaseIssues)

    emailext(subject: emailSubject, body: '${SCRIPT, template="release-notes.template"}', to: emailRecipients)
}

And this email template:

<STYLE>
BODY, TABLE, TD, TH, P {
    font-family: Calibri, Verdana, Helvetica, sans serif;
    font-size: 14px;
    color: black;
}
.section {
    width: 100%;
    border: thin black dotted;
}
.td-title {
    background-color: #666666;
    color: white;
    font-size: 120%;
    font-weight: bold;
    padding-left: 5px;
}
.td-header {
    background-color: #888888;
    color: white;
    font-weight: bold;
    padding-left: 5px;
}
</STYLE>

<BODY>

<!-- Release TEMPLATE -->

<%
import groovy.json.JsonSlurper

def envOverrides = it.getAction("org.jenkinsci.plugins.workflow.cps.EnvActionImpl").getOverriddenEnvironment()
release_name =  envOverrides["release_name"]
release_date =  envOverrides["release_date"]
release_issues = new JsonSlurper().parseText(envOverrides["release_issues"])
%>

Dear team member,<br/>
<br/>
The release ${release_name} is about to be deployed on the ${release_date} on Master UAT. <br/>
You will find below the list of tickets included in the release. Please have a look and make the necessary updates so the status 
is aligned with our guidelines.<br/>
<br/>

<table class="section">
    <tr class="tr-title">
    <td class="td-title" colspan="6">Issues associated with the release</td>
    </tr>
    <tr>
        <td class="td-header">Issue Key</td>
        <td class="td-header">Issue Type</td>
        <td class="td-header">Priority</td>
        <td class="td-header">Status</td>
        <td class="td-header">Summary</td>
        <td class="td-header">Assignee</td>
    </tr>
    <% release_issues.each {
    issue -> %>
    <tr>
    <td><a href="https://jira.baseurl.com/browse/${issue.key}">${issue.key}</a></td>
    <td>${issue.fields.issuetype?.name.trim()}</td>
    <td>${issue.fields.priority?.name}</td>
    <td>${issue.fields.status?.name}</td>
    <td>${issue.fields.summary}</td>
    <td>${issue.fields.assignee?.name}</td>
    </tr>
    <% } %>
</table>
<br/>

</BODY>