Files
jenkins-share-library/resources/templates/build_email.html
T
2025-09-21 19:52:30 +08:00

475 lines
16 KiB
HTML

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Jenkins构建通知 - ${projectName}</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
line-height: 1.6;
color: #24292e;
background-color: #f6f8fa;
margin: 0;
padding: 0;
}
.container {
max-width: 800px;
margin: 20px auto;
background-color: #ffffff;
border-radius: 12px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
overflow: hidden;
}
.header {
padding: 28px 32px;
text-align: center;
border-bottom: 1px solid #eaecef;
background: linear-gradient(135deg, #f5f7fa 0%, #f6f8fa 100%);
}
.status-badge {
display: inline-flex;
align-items: center;
padding: 8px 16px;
border-radius: 24px;
font-weight: 600;
font-size: 14px;
margin-bottom: 16px;
}
.status-success {
background-color: rgba(46, 188, 79, 0.15);
color: #26a641;
}
.status-failure {
background-color: rgba(218, 54, 51, 0.15);
color: #da3633;
}
.status-unstable {
background-color: rgba(242, 211, 38, 0.15);
color: #b08800;
}
.status-unknown {
background-color: rgba(158, 158, 158, 0.15);
color: #6e7781;
}
.header h1 {
font-size: 28px;
font-weight: 600;
margin: 8px 0;
color: #1f2328;
}
.header p {
color: #656d76;
font-size: 16px;
margin-top: 4px;
}
.content {
padding: 32px;
}
.section {
margin-bottom: 28px;
}
.section-title {
font-size: 18px;
font-weight: 600;
margin-bottom: 16px;
padding-bottom: 8px;
border-bottom: 1px solid #eaecef;
color: #1f2328;
display: flex;
align-items: center;
}
.section-title svg {
margin-right: 10px;
}
.info-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 16px;
}
.info-item {
display: flex;
flex-direction: column;
}
.info-label {
font-size: 13px;
color: #656d76;
margin-bottom: 4px;
font-weight: 500;
}
.info-value {
font-size: 15px;
font-weight: 500;
color: #1f2328;
word-break: break-word;
}
.badge {
display: inline-block;
padding: 4px 10px;
border-radius: 16px;
font-size: 12px;
font-weight: 500;
margin-right: 6px;
}
.badge-env {
background-color: rgba(84, 174, 255, 0.15);
color: #218bff;
}
.badge-success {
background-color: rgba(46, 188, 79, 0.15);
color: #26a641;
}
.badge-failure {
background-color: rgba(218, 54, 51, 0.15);
color: #da3633;
}
.badge-warning {
background-color: rgba(242, 211, 38, 0.15);
color: #b08800;
}
.badge-secondary {
background-color: rgba(158, 158, 158, 0.15);
color: #6e7781;
}
.build-details {
background-color: #f6f8fa;
border-radius: 8px;
padding: 20px;
margin: 20px 0;
border-left: 4px solid #0969da;
}
.cta-button {
display: inline-block;
padding: 12px 24px;
background-color: #0969da;
color: white;
text-decoration: none;
border-radius: 6px;
font-weight: 500;
font-size: 15px;
transition: background-color 0.2s;
margin: 16px 0;
}
.cta-button:hover {
background-color: #0858c7;
}
.footer {
padding: 24px 32px;
text-align: center;
font-size: 13px;
color: #656d76;
background-color: #f6f8fa;
border-top: 1px solid #eaecef;
}
.footer-links {
margin-top: 8px;
}
.footer-links a {
color: #0969da;
text-decoration: none;
margin: 0 8px;
}
.footer-links a:hover {
text-decoration: underline;
}
.timeline {
margin: 20px 0;
position: relative;
padding-left: 20px;
}
.timeline:before {
content: '';
position: absolute;
left: 0;
top: 8px;
bottom: 8px;
width: 2px;
background-color: #d0d7de;
}
.timeline-item {
position: relative;
margin-bottom: 16px;
padding-left: 20px;
}
.timeline-item:before {
content: '';
position: absolute;
left: -20px;
top: 8px;
width: 10px;
height: 10px;
border-radius: 50%;
background-color: #0969da;
}
.timeline-item.success:before {
background-color: #26a641;
}
.timeline-item.failure:before {
background-color: #da3633;
}
.timeline-item.warning:before {
background-color: #b08800;
}
.timeline-title {
font-weight: 600;
margin-bottom: 4px;
}
.timeline-desc {
font-size: 14px;
color: #656d76;
}
.stage-table {
width: 100%;
border-collapse: collapse;
margin: 16px 0;
font-size: 14px;
}
.stage-table th,
.stage-table td {
padding: 12px;
text-align: left;
border-bottom: 1px solid #eaecef;
}
.stage-table th {
background-color: #f6f8fa;
font-weight: 600;
}
.stage-table tr:hover {
background-color: #f6f8fa;
}
.stage-success {
color: #26a641;
}
.stage-failure {
color: #da3633;
}
.stage-warning {
color: #b08800;
}
.summary-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 16px;
margin: 20px 0;
}
.summary-card {
background-color: #f6f8fa;
border-radius: 8px;
padding: 16px;
text-align: center;
}
.summary-value {
font-size: 24px;
font-weight: 600;
margin: 8px 0;
}
.summary-label {
font-size: 14px;
color: #656d76;
}
@media (max-width: 768px) {
.container {
margin: 0;
border-radius: 0;
}
.info-grid, .summary-grid {
grid-template-columns: 1fr;
}
.content {
padding: 24px;
}
.header {
padding: 24px;
}
.stage-table {
font-size: 12px;
}
.stage-table th,
.stage-table td {
padding: 8px;
}
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<div class="status-badge ${statusClass}">
${statusEmoji} ${statusText}
</div>
<h1>${projectName}</h1>
<p>构建 #${buildNumber} • ${buildTime} • 耗时 ${buildDuration}</p>
</div>
<div class="content">
<!-- 构建摘要 -->
<div class="section">
<h2 class="section-title">
<svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor">
<path d="M8 16A8 8 0 1 1 8 0a8 8 0 0 1 0 16zm1-11a1 1 0 1 0-2 0v3a1 1 0 0 0 .293.707l2.828 2.829a1 1 0 1 0 1.415-1.415L9 6.586V5z"/>
</svg>
构建摘要
</h2>
<div class="summary-grid">
<div class="summary-card">
<div class="summary-value">${totalStages}</div>
<div class="summary-label">总Stage数</div>
</div>
<div class="summary-card">
<div class="summary-value">${successStages}</div>
<div class="summary-label">成功Stage数</div>
</div>
<div class="summary-card">
<div class="summary-value">${failedStages}</div>
<div class="summary-label">失败Stage数</div>
</div>
<div class="summary-card">
<div class="summary-value">${successRate}%</div>
<div class="summary-label">成功率</div>
</div>
</div>
<div class="info-grid">
<div class="info-item">
<span class="info-label">项目名称</span>
<span class="info-value">${projectName}</span>
</div>
<div class="info-item">
<span class="info-label">构建状态</span>
<span class="info-value">
<span class="badge ${badgeClass}">${badgeText}</span>
</span>
</div>
<div class="info-item">
<span class="info-label">构建编号</span>
<span class="info-value">#${buildNumber}</span>
</div>
<div class="info-item">
<span class="info-label">构建ID</span>
<span class="info-value">${buildId}</span>
</div>
<div class="info-item">
<span class="info-label">构建时间</span>
<span class="info-value">${buildTime}</span>
</div>
<div class="info-item">
<span class="info-label">构建时长</span>
<span class="info-value">${buildDuration}</span>
</div>
<div class="info-item">
<span class="info-label">环境</span>
<span class="info-value">
<span class="badge badge-env">${profiles}</span>
</span>
</div>
<div class="info-item">
<span class="info-label">构建节点</span>
<span class="info-value">${nodeName}</span>
</div>
</div>
</div>
<!-- Git信息 -->
<div class="section">
<h2 class="section-title">
<svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor">
<path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"/>
</svg>
Git信息
</h2>
<div class="info-grid">
<div class="info-item">
<span class="info-label">代码分支</span>
<span class="info-value">${gitBranch}</span>
</div>
<div class="info-item">
<span class="info-label">提交版本</span>
<span class="info-value">${gitCommitShort}</span>
</div>
<div class="info-item">
<span class="info-label">完整提交ID</span>
<span class="info-value">${gitCommit}</span>
</div>
<div class="info-item">
<span class="info-label">代码库</span>
<span class="info-value">${gitUrl}</span>
</div>
</div>
</div>
<!-- 构建产物和部署信息 -->
<div class="build-details">
<h3 style="margin-bottom: 16px;">构建产物</h3>
<div class="info-grid">
<div class="info-item">
<span class="info-label">镜像名称</span>
<span class="info-value">${imageFullName}</span>
</div>
<div class="info-item">
<span class="info-label">镜像标签</span>
<span class="info-value">${imageTags}</span>
</div>
</div>
<h3 style="margin: 20px 0 16px 0;">部署信息</h3>
<div class="info-grid">
<div class="info-item">
<span class="info-label">部署策略</span>
<span class="info-value">${deploymentStrategy}</span>
</div>
<div class="info-item">
<span class="info-label">健康检查</span>
<span class="info-value">
<span class="badge badge-success">${healthCheckStatus}</span>
</span>
</div>
</div>
</div>
<!-- 构建时间线 -->
<div class="section">
<h2 class="section-title">
<svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor">
<path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Zm7-3.25v2.992l2.028.812a.75.75 0 0 1-.557 1.392l-2.5-1A.751.751 0 0 1 7 8.25v-3.5a.75.75 0 0 1 1.5 0Z"/>
</svg>
构建时间线
</h2>
<div class="timeline">
<div class="timeline-item success">
<div class="timeline-title">代码检出</div>
<div class="timeline-desc">从 ${gitBranch} 分支成功检出代码</div>
</div>
${stagesContent}
</div>
</div>
<!-- 操作按钮 -->
<div style="text-align: center; margin: 28px 0;">
<a href="${buildUrl}" class="cta-button">查看构建详情</a>
<p style="font-size: 14px; color: #656d76; margin-top: 8px;">点击查看完整的构建日志和详细信息</p>
</div>
</div>
<div class="footer">
<p>此邮件由Jenkins自动发送,请勿直接回复。</p>
<!-- <p>Jenkins服务器: ${jenkinsUrl}</p> -->
<div class="footer-links">
<a href="${jenkinsUrl}">访问Jenkins</a> •
<a href="${buildUrl}">构建详情</a> •
<a href="${gitUrl}">代码库</a>
</div>
<p style="margin-top: 12px;">© 2025 小蚂蚁云 DevOps Team. All rights reserved.</p>
</div>
</div>
</body>
</html>