Jenkins 詹金斯:我如何将最新的性能更改列表添加到通知电子邮件中?
我有一个Jenkins CI设置,我们使用Perforce作为SCM 我已经配置了Email-ext插件,以便在构建中断时以及修复时通知开发人员 目前,通知电子邮件正文仅使用$DEFAULT\u内容,但我真的希望在电子邮件内容中指出最新的性能更改列表,因为这将对开发人员更有帮助 我在想变更列表编号,变更列表标题和提交人Jenkins 詹金斯:我如何将最新的性能更改列表添加到通知电子邮件中?,jenkins,perforce,changelist,email-ext,Jenkins,Perforce,Changelist,Email Ext,我有一个Jenkins CI设置,我们使用Perforce作为SCM 我已经配置了Email-ext插件,以便在构建中断时以及修复时通知开发人员 目前,通知电子邮件正文仅使用$DEFAULT\u内容,但我真的希望在电子邮件内容中指出最新的性能更改列表,因为这将对开发人员更有帮助 我在想变更列表编号,变更列表标题和提交人 关于如何做到这一点有什么想法吗?在詹金斯邮件列表的某个地方,我找到了这个模板,我认为它符合您的要求。 在jenkins根目录中创建一个文件夹“email templates”,将
关于如何做到这一点有什么想法吗?在詹金斯邮件列表的某个地方,我找到了这个模板,我认为它符合您的要求。 在jenkins根目录中创建一个文件夹“email templates”,将文件放入其中并命名为“p4htmlmail.jelly”。 然后在jenkins配置中,将
${JELLY_脚本,template=“p4htmlmail”}
放在email ext插件配置的默认内容字段中
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define">
<link type="text/css" rel="stylesheet" href="${rooturl}static/e59dfe28/css/style.css"/>
<link type="text/css" rel="stylesheet" href="${rooturl}static/e59dfe28/css/color.css"/>
<STYLE>
a:link,a:visited {
text-decoration: underline;
<!--color: #3B5998;-->
color: #8B9DC3
}
a.success:link,a.success:visited {
text-decoration: underline;
color: #338033;
}
a.failure:link,a.failure:visited {
text-decoration: underline;
color: #900;
}
a.unstable:link,a.unstable:visited {
text-decoration: underline;
color: #F0C000;
}
<!--
body {
background-color: #DFE3EE;
}-->
.pane {
margin-top: 4px;
white-space: nowrap;
}
.pane TD {
padding: 4px 4px 3px 4px;
}
TABLE.pane {
width: 100%;
border: none;
}
TD.style1 {
color: #3B5998;
width: 10%;
}
TD.pane {
padding: 3px 4px 3px 4px;
vertical-align: middle;
}
TD.pane-header {
border-top: 1px #8B9DC3 solid;
border-bottom: 1px #8B9DC3 solid;
background-color: #DFE3EE;
font-weight: bold;
font-family: Verdana, Helvetica, sans serif;
font-size: 11px;
color: #8B9DC3;
padding-top: 10px;
padding-bottom: 10px;
}
TD.pane-header-success {
border-top: 1px #338033 solid;
border-bottom: 1px #338033 solid;
background-color: #E0FFE0;
font-weight: bold;
font-family: Verdana, Helvetica, sans serif;
font-size: 11px;
color: #338033;
padding-top: 10px;
padding-bottom: 10px;
}
TD.pane-header-failure {
border-top: 1px #900 solid;
border-bottom: 1px #900 solid;
background-color: #FCC;
font-weight: bold;
font-family: Verdana, Helvetica, sans serif;
font-size: 11px;
color: #900;
padding-top: 10px;
padding-bottom: 10px;
}
TD.pane-header-unstable {
border-top: 1px #F0C000 solid;
border-bottom: 1px #F0C000 solid;
background-color: #FFFFCE;
font-weight: bold;
font-family: Verdana, Helvetica, sans serif;
font-size: 11px;
color: #F0C000;
padding-top: 10px;
padding-bottom: 10px;
}
TH.pane {
font-weight: bold;
}
SPAN.style1 {
font-weight: bold;
color: #8B9DC3;
}
SPAN.success {
color: #338033;
}
SPAN.failure {
color: #900;
}
LI.style1 {
list-style: cirle outside;
}
LI.failure {
list-style: cirle outside;
color: #900;
}
</STYLE>
<BODY>
<j:set var="spc" value="&nbsp;&nbsp;" />
<!-- GENERAL INFO -->
<TABLE class="pane">
<TBODY>
<TR>
<j:choose>
<j:when test="${build.result=='SUCCESS'}">
<TD colspan="2" class="pane-header-success">
<SPAN>Build Result Summary - <A class="success" href="${rooturl}${build.url}">See full build details</A></SPAN>
</TD>
</j:when>
<j:when test="${build.result=='FAILURE'}">
<TD colspan="2" class="pane-header-failure">
<SPAN>Build Result Summary - <A class="failure" href="${rooturl}${build.url}">See full build details</A></SPAN>
</TD>
</j:when>
<j:otherwise>
<TD colspan="2" class="pane-header-unstable">
<SPAN>Build Result Summary - <A class="unstable" href="${rooturl}${build.url}">See full build details</A></SPAN>
</TD>
</j:otherwise>
</j:choose>
</TR>
<TR>
<TD class="style1">Project:</TD>
<TD><A href="${rooturl}${project.url}">${project.name}</A></TD>
</TR>
<TR>
<TD class="style1">Completion:</TD>
<TD>${it.timestampString}</TD>
</TR>
<TR>
<TD class="style1">Duration:</TD>
<TD>${build.durationString}</TD>
</TR>
<TR>
<TD class="style1">Status:</TD>
<TD>
<j:choose>
<j:when test="${build.result=='SUCCESS'}">
<IMG SRC="${rooturl}static/e59dfe28/images/16x16/blue.png"/>
</j:when>
<j:when test="${build.result=='FAILURE'}">
<IMG SRC="${rooturl}static/e59dfe28/images/16x16/red.png"/>
</j:when>
<j:otherwise>
<IMG SRC="${rooturl}static/e59dfe28/images/16x16/yellow.png"/>
</j:otherwise>
</j:choose>
${build.result}
</TD>
</TR>
<TR>
<TD class="style1">Help:</TD>
<TD>
Help text goes here.
</TD>
</TR>
</TBODY>
</TABLE>
<BR/>
<!-- CHANGE SET -->
<j:set var="changeSet" value="${build.changeSet}" />
<j:if test="${changeSet!=null}">
<j:set var="hadChanges" value="false" />
<TABLE class="pane">
<TBODY>
<TR>
<TD colspan="2" class="pane-header">
<SPAN>Code Changes - <A href="${rooturl}${build.url}/changes">See full change details</A></SPAN>
</TD>
</TR>
<j:forEach var="cs" items="${changeSet}" varStatus="loop">
<j:set var="hadChanges" value="true" />
<j:set var="aUser" value="${cs.hudsonUser}"/>
<TR>
<TD colspan="2">
<SPAN class="style1">
Change <B>${cs.changeNumber}</B> by
<B>${aUser!=null?aUser.displayName:cs.author.displayName}: </B>
'${cs.msgAnnotated}'
</SPAN>
</TD>
</TR>
<j:forEach var="p" items="${cs.affectedFiles}">
<TR>
<TD width="2%">
<j:switch on="${p.editType.name}">
<j:case value="add">
<IMG SRC="${rooturl}plugin/perforce/icons/action-ADD.gif"/>
</j:case>
<j:case value="branch">
<IMG SRC="${rooturl}plugin/perforce/icons/action-BRANCH.gif"/>
</j:case>
<j:case value="delete">
<IMG SRC="${rooturl}plugin/perforce/icons/action-DELETE.gif"/>
</j:case>
<j:case value="edit">
<IMG SRC="${rooturl}plugin/perforce/icons/action-EDIT.gif"/>
</j:case>
<j:case value="import">
<IMG SRC="${rooturl}plugin/perforce/icons/action-IMPORT.gif"/>
</j:case>
<j:case value="integrate">
<IMG SRC="${rooturl}plugin/perforce/icons/action-INTEGRATE.gif"/>
</j:case>
<j:case value="move_add">
<IMG SRC="${rooturl}plugin/perforce/icons/action-MOVE_ADD.gif"/>
</j:case>
<j:case value="move_delete">
<IMG SRC="${rooturl}plugin/perforce/icons/action-MOVE_DELETE.gif"/>
</j:case>
<j:default>
${p.editType.name}
</j:default>
</j:switch>
</TD>
<TD><SPAN>${p.path}</SPAN></TD>
</TR>
</j:forEach>
</j:forEach>
<j:if test="${!hadChanges}">
<TR><TD colspan="2">No Changes</TD></TR>
</j:if>
</TBODY>
</TABLE>
<BR/>
</j:if>
<!-- JUNIT TEST OUTPUT -->
<j:set var="junitResultList" value="${it.JUnitTestResult}" />
<j:if test="${junitResultList.isEmpty()!=true}">
<TABLE class="pane">
<TBODY>
<TR>
<TD colspan="2" class="pane-header">
<SPAN>Unit Tests - <A href="${rooturl}${build.url}/testReport">See full test details</A></SPAN>
</TD>
</TR>
<j:forEach var="junitResult" items="${it.JUnitTestResult}">
<j:forEach var="packageResult" items="${junitResult.getChildren()}">
<TR>
<TD>
Name: ${packageResult.getName()}, Failed: <SPAN class="failure">${packageResult.getFailCount()}</SPAN> test(s), Passed: <SPAN class="success">${packageResult.getPassCount()}</SPAN> test(s), Skipped: ${packageResult.getSkipCount()} test(s), Total: ${packageResult.getPassCount()+packageResult.getFailCount()+packageResult.getSkipCount()} test(s)
</TD>
</TR>
<j:forEach var="failed_test" items="${packageResult.getFailedTests()}">
<TR>
<TD>
<UL>
<B>
<LI class="failure">Failed: ${failed_test.getFullName()}</LI>
</B>
</UL>
</TD>
</TR>
</j:forEach>
</j:forEach>
</j:forEach>
</TBODY>
</TABLE>
<BR/>
</j:if>
<!-- CONSOLE OUTPUT -->
<j:getStatic var="resultFailure" field="FAILURE" className="hudson.model.Result"/>
<j:if test="${build.result==resultFailure}">
<TABLE class="pane">
<TBODY>
<TR>
<TD colspan="2" class="pane-header">
<SPAN>Console Output - <A href="${rooturl}${build.url}/console">See full console details</A></SPAN>
</TD>
</TR>
<j:forEach var="line" items="${build.getLog(100)}">
<TR>
<TD>${line}</TD>
</TR>
</j:forEach>
</TBODY>
</TABLE>
<BR/>
</j:if>
</BODY>
</j:jelly>
a:链接,a:已访问{
文字装饰:下划线;
颜色:#8B9DC3
}
a、 成功:链接,a。成功:访问{
文字装饰:下划线;
颜色:#338033;
}
a、 失败:链接,a。失败:已访问{
文字装饰:下划线;
颜色:#900;
}
a、 不稳定:链接,a.不稳定:已访问{
文字装饰:下划线;
颜色:#F0C000;
}
.窗格{
利润上限:4倍;
空白:nowrap;
}
.TD{
填充:4px4p3px4px;
}
TABLE.pane{
宽度:100%;
边界:无;
}
TD.1{
颜色:#3B5998;
宽度:10%;
}
TD.pane{
填充:3px4px3px4px;
垂直对齐:中间对齐;
}
TD.pane-header{
边框顶部:1px#8B9DC3实心;
边框底部:1px#8B9DC3实心;
背景色:#DFE3EE;
字体大小:粗体;
字体系列:Verdana、Helvetica、无衬线;
字体大小:11px;
颜色:#8B9DC3;
填充顶部:10px;
垫底:10px;
}
TD.pane-header-success{
边框顶部:1px#338033实心;
边框底部:1px#338033实心;
背景色:#e00ffe0;
字体大小:粗体;
字体系列:Verdana、Helvetica、无衬线;
字体大小:11px;
颜色:#338033;
填充顶部:10px;
垫底:10px;
}
TD.pane-header-failure{
边框顶部:1px#900实心;
边框底部:1px#900实心;
背景色:#FCC;
字体大小:粗体;
字体系列:Verdana、Helvetica、无衬线;
字体大小:11px;
颜色:#900;
填充顶部:10px;
垫底:10px;
}
TD.pane-header-unstable{
边框顶部:1px#F0C000实心;
边框底部:1px#F0C000实心;
背景色:#FFFFCE;
字体大小:粗体;
字体系列:Verdana、Helvetica、无衬线;
字体大小:11px;
颜色:#F0C000;
填充顶部:10px;
垫底:10px;
}
第四窗格{
字体大小:粗体;
}
SPAN.style1{
字体大小:粗体;
颜色:#8B9DC3;
}
成功{
颜色:#338033;
}
SPAN.故障{
颜色:#900;
}
LI.1{
列表样式:外部卷曲;
}
李:失败{
列表样式:外部卷曲;
颜色:#900;
}
生成结果摘要-
生成结果摘要-
生成结果摘要-
项目:
完成:
${it.timestampString}
持续时间:
${build.durationString}
地位:
${build.result}
帮助:
这里是帮助文本。
代码更改-
更改${cs.changeNumber}by
${aUser!=null?aUser.displayName:cs.author.displayName}:
“${cs.msgAnnotated}”
${p.editType.name}
${p.path}
不变
单元测试-
名称:${packageResult.getName()},失败:${packageResult.getFailCount()}测试,通过:${packageResult.getPassCount()}测试,跳过:${packageResult.getSkipCount()}测试,总计:${packageResult.getPassCount()+packageResult.getFailCount()+packageResult.getSkipCount()}测试
- 失败:${Failed_test.getFullName()}
控制台输出-
${line}
只需使用Groovy模板,请参阅感谢您的精彩回复!这几乎正是我所需要的。我发现这个jelly脚本报告构建成功/失败,但没有获取我的构建变更集(即“无变更”)。但是,当我在Perforce作业上运行相同的模板时,将忠实地呈现变更列表信息。我想知道-我可以从这个脚本中引用第二个作业的变更集吗?i、 e.参考Performce作业的变更集,但报告的作业的构建/失败信息?我是否理解您的意思,您有两个作业?一个用于从perforce同步,另一个用于构建?实际上,我们通常只有一项同步和构建的工作。如果构建失败,提交者将收到一封邮件,其中包括触发构建的更改。抱歉,让第二份工作获取另一份工作的变更单信息是不可能的(或不容易的)。这是正确的-正如您所描述的,我们有两份工作。如果我找不到一种简单的方法来引用jelly temple中的Performce作业,那么我可能会尝试@JoshUnger推荐的groovy模板