Jenkins+Git持续集成Python项目并邮件发送构建结果

一、Jenkins的安装

1、安装Java11 64位,https://www.oracle.com/java/technologies/javase/jdk11-archive-downloads.html;

image-20220706223214113

2、安装Git,https://git-scm.com/downloads/;

image-20220706223034090

3、安装Python,https://www.python.org/downloads/;

image-20220706223812111

4、安装Jenkins,https://www.jenkins.io/download/,以下为Jenkins 2.357安装为例;

image-20220706223300028
image-20220706224454526
image-20220708101923287
image-20220706225438601
image-20220706225723876
image-20220706230152379
image-20220706230321506
image-20220706230406699
image-20220706230511465

5、修改JENKINS_HOME位置(建议,非必要步骤);

1)打开任务管理器-服务,找到Jenkins服务,右击停止;
image-20220706231358801
2)编辑C:\Program Files\Jenkins\jenkins.xml配置文件,将JENKINS_HOME属性修改为D:\JenkinsHome并保存;
<env name="JENKINS_HOME" value="D:\JenkinsHome"/>
image-20220708103215183
3)重新启动Jenkins服务;
image-20220706232251358

二、Jenkins初始化

1、使用浏览器以IP+端口形式打开Jenkins,首次打开请等待加载完成自动跳转;

image-20220706232725034

2、查看本机该文件内容,将解锁密码粘贴至输入框;

image-20220706232954731

3、安装推荐的插件,此过程可能耗时较长,需要考虑网络因素(约10分钟左右);

image-20220706233511251
image-20220706233804268

4、创建管理员账号;

image-20220706234727437

5、配置Jenkins URL;

image-20220706234838383

6、重启;

image-20220706234957227

三、Jenkins插件安装和系统配置

1、登录Jenkins;

image-20220707142705678

2、安装一些必要插件;

image-20220708110126494
1)可选插件搜索安装Build Timestamp插件(这个插件在后面发送构建邮件中需要使用到时间戳变量);
image-20220708111114995
2)Git、Email Extension Plugin插件在安装推荐插件的时候已经帮我们安装过了,如果未安装手动搜索进行安装;

3、系统配置

image-20220708112122132
1)配置系统管理员邮件地址(Jenkins全局邮件地址);
image-20220708112444139
2)配置邮件服务器和登录信息;
image-20220708113040764
image-20220708113157149
image-20220708113540957
image-20220708113657422 image-20220708113934423
image-20220708114311680

四、新建构建任务

image-20220708114538778
1)新建任务(自由风格);
image-20220708114923234
2)源码管理,这里我们选择Git;
image-20220708115354591
3)构建触发器,有多种触发器可选,一般我们用到定时触发和代码变更触发;
image-20210208121816716
image-20210208121842511
4)构建步骤;
image-20220708122106282
image-20220708122928539
5)添加构建后操作,发送构建结果邮件;
image-20220708123222792
image-20220708124113747
image-20220708124625087

邮件主题模板(复制即可):

项目<${PROJECT_NAME}>#${BUILD_NUMBER}构建情况 - ${BUILD_STATUS}

邮件正文模板(复制即可):

<!DOCTYPE html>
<html style="box-sizing: border-box; --bg-color: #ffffff; --text-color: #333333; --select-text-bg-color: #B5D6FC; --select-text-font-color: auto; --monospace: 'Lucida Console',Consolas,'Courier',monospace; --title-bar-height: 20px; font-size: 14px; background-color: var(--bg-color); color: var(--text-color); font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; --side-bar-bg-color: #fafafa; --control-text-color: #777; overflow-x: initial;">
<head>
<meta charset="UTF-8"><meta name="viewport" content="width=device-width initial-scale=1">
<link href="http://fonts.googleapis.com/css?family=Open+Sans:400italic,700italic,700,400&subset=latin,latin-ext" rel="stylesheet" type="text/css"><style type="text/css">
a:active,
a:hover {
  outline: 0px;
}
@media screen and (max-width: 500px) {
  body.typora-export {
    padding-left: 0px;
    padding-right: 0px;
  }
  #write {
    padding-left: 20px;
    padding-right: 20px;
  }
  .CodeMirror-sizer {
    margin-left: 0px !important;
  }
  .CodeMirror-gutters {
    display: none !important;
  }
}
div.hr:focus {
  cursor: none;
}
@media print {
  body,
html {
    border: 1px solid transparent;
    height: 99%;
    break-after: avoid;
    break-before: avoid;
    font-variant-ligatures: no-common-ligatures;
  }
  #write {
    margin-top: 0px;
    padding-top: 0px;
    border-color: transparent !important;
  }
  .typora-export * {
    -webkit-print-color-adjust: exact;
  }
  .typora-export #write {
    break-after: avoid;
  }
  .typora-export #write::after {
    height: 0px;
  }
  .is-mac table {
    break-inside: avoid;
  }
  .typora-export-show-outline .typora-export-sidebar {
    display: none;
  }
}
[contenteditable="true"]:active,
[contenteditable="true"]:focus,
[contenteditable="false"]:active,
[contenteditable="false"]:focus {
  outline: 0px;
  box-shadow: none;
}
.md-toc-inner:hover {
  text-decoration: underline;
}
@media screen and (max-width: 48em) {
  .md-toc-h3 .md-toc-inner {
    margin-left: 3.5em;
  }
  .md-toc-h4 .md-toc-inner {
    margin-left: 5em;
  }
  .md-toc-h5 .md-toc-inner {
    margin-left: 6.5em;
  }
  .md-toc-h6 .md-toc-inner {
    margin-left: 8em;
  }
}
@media print {
  .typora-export h1,
.typora-export h2,
.typora-export h3,
.typora-export h4,
.typora-export h5,
.typora-export h6 {
    break-inside: avoid;
  }
}
.md-fences-advanced:not(.md-focus) {
  padding: 0px;
  white-space: nowrap;
  border: 0px;
}
.md-fences-advanced:not(.md-focus) {
  background: inherit;
}
@media screen and (max-width: 1024px) {
  .typora-export-sidebar,
.typora-export-sidebar .outline-content {
    width: 240px;
  }
}
@media screen and (max-width: 800px) {
  .typora-export-sidebar {
    display: none;
  }
}
.outline-expander:hover::before {
  content: "";
}
.outline-label:hover {
  text-decoration: underline;
}
.outline-item:hover {
  border-color: rgb(245, 245, 245);
  background-color: var(--item-hover-bg-color);
}
.outline-item:hover {
  margin-left: -28px;
  margin-right: -28px;
  border-left: 28px solid transparent;
  border-right: 28px solid transparent;
}
.typora-export .outline-item:hover {
  margin-right: -8px;
  border-right: 8px solid transparent;
}
.typora-export .outline-expander:hover::before,
.typora-export .outline-item-open > .outline-item > .outline-expander::before {
  content: "−";
}
.typora-export-show-outline .outline-item-active > .outline-item .outline-label {
  font-weight: 700;
}
.cm-s-inner .cm-link,
.cm-s-inner.cm-link {
  color: rgb(0, 0, 204);
}
.cm-link {
  text-decoration: underline;
}
.cm-s-inner .CodeMirror-activeline-background {
  background: inherit;
}
.CodeMirror-focused div.CodeMirror-cursor {
  visibility: inherit;
}
@media print {
  .CodeMirror div.CodeMirror-cursor {
    visibility: hidden;
  }
}
h1:hover a.anchor,
h2:hover a.anchor,
h3:hover a.anchor,
h4:hover a.anchor,
h5:hover a.anchor,
h6:hover a.anchor {
  text-decoration: none;
}
@media screen and (min-width: 914px) {}
@media print {
  html {
    font-size: 13px;
  }
  table,
pre {
    page-break-inside: avoid;
  }
  pre {
    word-wrap: break-word;
  }
}
#write>h3.md-focus:before {
  left: -1.5625rem;
  top: .375rem;
}
#write>h4.md-focus:before {
  left: -1.5625rem;
  top: .285714286rem;
}
#write>h5.md-focus:before {
  left: -1.5625rem;
  top: .285714286rem;
}
#write>h6.md-focus:before {
  left: -1.5625rem;
  top: .285714286rem;
}
.on-focus-mode blockquote {
  border-left-color: rgba(85, 85, 85, 0.12);
}
.file-node-content:hover .file-node-icon,
.file-node-content:hover .file-node-open-state {
  visibility: visible;
}
</style><title>项目构建情况</title>
</head>
<body class="typora-export os-windows" style="box-sizing: border-box; margin: 0px; padding: 0px; height: auto; inset: 0px; font-size: 1rem; overflow-x: hidden; background: inherit; tab-size: 4; font-family: 'Open Sans','Clear Sans','Helvetica Neue',Helvetica,Arial,sans-serif; color: rgb(51, 51, 51); line-height: 1.6; padding-left: 30px; padding-right: 30px;"><div class="typora-export-content" style="box-sizing: border-box; margin-top: 0; margin-bottom: 0;">
<div id="write" class style="box-sizing: border-box; height: auto; width: inherit; word-break: normal; overflow-wrap: break-word; position: relative; white-space: normal; overflow-x: visible; max-width: 860px; margin: 0 auto; padding: 20px 30px 40px 30px; padding-top: 20px; padding-bottom: 100px;"><h1 id="项目构建情况" style="box-sizing: border-box; break-after: avoid-page; break-inside: avoid; orphans: 4; margin-top: 1rem; margin-bottom: 1rem; font-weight: bold; cursor: text; padding-bottom: .3em; font-size: 2.25em; line-height: 1.2; border-bottom: 1px solid #eee; color: black; width: inherit; position: relative;"><span style="box-sizing: border-box;">项目&lt;${PROJECT_NAME}&gt;构建情况</span></h1><h4 id="构建结果" style="box-sizing: border-box; break-after: avoid-page; break-inside: avoid; orphans: 4; margin-top: 1rem; margin-bottom: 1rem; font-weight: bold; line-height: 1.4; cursor: text; font-size: 1.25em; color: green; width: inherit; position: relative;"><span style="box-sizing: border-box;">构建结果</span></h4><h6 id="successful" style="box-sizing: border-box; break-after: avoid-page; break-inside: avoid; orphans: 4; margin-top: 1rem; margin-bottom: 1rem; font-weight: bold; line-height: 1.4; cursor: text; font-size: 1em; color: purple; width: inherit; position: relative;"><span style="box-sizing: border-box;">${BUILD_STATUS}</span></h6><h4 id="构建编号" style="box-sizing: border-box; break-after: avoid-page; break-inside: avoid; orphans: 4; margin-top: 1rem; margin-bottom: 1rem; font-weight: bold; line-height: 1.4; cursor: text; font-size: 1.25em; color: green; width: inherit; position: relative;"><span style="box-sizing: border-box;">构建编号</span></h4><h6 id="4" style="box-sizing: border-box; break-after: avoid-page; break-inside: avoid; orphans: 4; margin-top: 1rem; margin-bottom: 1rem; font-weight: bold; line-height: 1.4; cursor: text; font-size: 1em; color: purple; width: inherit; position: relative;"><span style="box-sizing: border-box;">${BUILD_NUMBER}</span></h6><h4 id="构建时间" style="box-sizing: border-box; break-after: avoid-page; break-inside: avoid; orphans: 4; margin-top: 1rem; margin-bottom: 1rem; font-weight: bold; line-height: 1.4; cursor: text; font-size: 1.25em; color: green; width: inherit; position: relative;"><span style="box-sizing: border-box;">构建时间</span></h4><h6 id="2022-07-07-234847-cst" style="box-sizing: border-box; break-after: avoid-page; break-inside: avoid; orphans: 4; margin-top: 1rem; margin-bottom: 1rem; font-weight: bold; line-height: 1.4; cursor: text; font-size: 1em; color: purple; width: inherit; position: relative;"><span style="box-sizing: border-box;">${BUILD_TIMESTAMP}</span></h6><h4 id="构建触发" style="box-sizing: border-box; break-after: avoid-page; break-inside: avoid; orphans: 4; margin-top: 1rem; margin-bottom: 1rem; font-weight: bold; line-height: 1.4; cursor: text; font-size: 1.25em; color: green; width: inherit; position: relative;"><span style="box-sizing: border-box;">构建触发</span></h4><h6 id="started-by-user-zhaoyafan" style="box-sizing: border-box; break-after: avoid-page; break-inside: avoid; orphans: 4; margin-top: 1rem; margin-bottom: 1rem; font-weight: bold; line-height: 1.4; cursor: text; font-size: 1em; color: purple; width: inherit; position: relative;"><span style="box-sizing: border-box;">${BUILD_CAUSE}</span></h6><h4 id="构建地址" style="box-sizing: border-box; break-after: avoid-page; break-inside: avoid; orphans: 4; margin-top: 1rem; margin-bottom: 1rem; font-weight: bold; line-height: 1.4; cursor: text; font-size: 1.25em; color: green; width: inherit; position: relative;"><span style="box-sizing: border-box;">构建地址</span></h4><h6 id="http1270018080jobautomation8" style="box-sizing: border-box; break-after: avoid-page; break-inside: avoid; orphans: 4; margin-top: 1rem; margin-bottom: 1rem; font-weight: bold; line-height: 1.4; cursor: text; font-size: 1em; color: purple; width: inherit; position: relative;"><a href="${BUILD_URL}" target="_blank" class="url" style="box-sizing: border-box; cursor: pointer; color: #4183C4; word-break: break-all;">${BUILD_URL}</a></h6><h4 id="构建详情" style="box-sizing: border-box; break-after: avoid-page; break-inside: avoid; orphans: 4; margin-top: 1rem; margin-bottom: 1rem; font-weight: bold; line-height: 1.4; cursor: text; font-size: 1.25em; color: green; width: inherit; position: relative;"><span style="box-sizing: border-box;">构建详情</span></h4><pre class="md-fences md-end-block ty-contain-cm modeLoaded" spellcheck="false" lang style="box-sizing: border-box; display: block; break-inside: avoid; text-align: left; overflow: visible; background: inherit; border: 1px solid #ddd; border-radius: 3px; font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 0.9em; margin-bottom: 15px; margin-top: 15px; padding: 0.2em 1em; padding-top: 8px; padding-bottom: 6px; background-color: #BBF1C4; width: inherit; white-space: normal; position: relative;"><div class="CodeMirror cm-s-inner cm-s-null-scroll CodeMirror-wrap" lang style="box-sizing: border-box; text-align: left; height: auto; position: relative; overflow: hidden; background: inherit;"><div style="box-sizing: border-box; overflow: hidden; position: relative; width: 3px; height: 0px; top: 9.2px; left: 4px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="box-sizing: border-box; color: inherit; font: inherit; position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true" style="box-sizing: border-box; background-color: rgb(255, 255, 255); position: absolute; z-index: 6; display: none; outline: 0px; right: 0px; bottom: 0px;"></div><div class="CodeMirror-gutter-filler" cm-not-content="true" style="box-sizing: border-box; background-color: rgb(255, 255, 255); position: absolute; z-index: 6; display: none; outline: 0px; left: 0px; bottom: 0px;"></div><div class="CodeMirror-scroll" tabindex="-1" style="overflow: auto hidden; z-index: 3; height: 100%; outline: 0px; position: relative; box-sizing: content-box; background: inherit; overflow-x: hidden;"><div class="CodeMirror-sizer" style="box-sizing: border-box; position: relative; margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="box-sizing: border-box; position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation" style="box-sizing: border-box; padding: 0px; cursor: text;"><div role="presentation" style="box-sizing: border-box; position: relative; outline: none;"><div class="CodeMirror-measure" style="box-sizing: border-box; position: absolute; width: 100%; height: 0px; overflow: hidden; visibility: hidden;"></div><div class="CodeMirror-measure" style="box-sizing: border-box; position: absolute; width: 100%; height: 0px; overflow: hidden; visibility: hidden;"></div><div style="box-sizing: border-box; position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation" style="box-sizing: border-box;"><div class="CodeMirror-activeline" style="box-sizing: border-box; position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground" style="box-sizing: border-box; position: absolute; inset: 0px; z-index: 0; background: inherit;"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="box-sizing: border-box; position: absolute; top: 0px; bottom: 0px; z-index: 4; left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation" style="box-sizing: border-box; break-inside: avoid; padding: 0px 4px; border-radius: 0px; border-width: 0px; background: 0px 0px; font-family: inherit; font-size: inherit; margin: 0px; color: inherit; z-index: 2; position: relative; overflow: visible; overflow-wrap: break-word; word-break: normal; border-right: none; width: inherit; white-space: pre-wrap;"><span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">${BUILD_LOG}</span></pre></div></div></div></div></div></div><div style="box-sizing: border-box; position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 22px;"></div><div class="CodeMirror-gutters" style="box-sizing: border-box; background-color: inherit; margin-right: 4px; background: inherit; white-space: nowrap; position: absolute; left: 0px; top: 0px; padding-bottom: 10px; z-index: 3; overflow-y: hidden; border-right: 1px solid #ddd; display: none; height: 22px;"></div></div></div></pre><p style="box-sizing: border-box; line-height: inherit; orphans: 4; margin-top: 1rem; margin-bottom: 1rem; margin: 0.8em 0; white-space: pre-wrap; width: inherit; position: relative;">&nbsp;</p></div></div>
</body>
</html>
6)点击保存完成设置;

此时构建任务已经创建完成,只要有构建就会发送邮件;

7)手动构建测试;

返回首页,点击”My Views“就能看到我们创建好的构建任务;

image-20220708125929268
image-20220708131207824
Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐