Jenkins - 多个项目搭建
# Jenkins 构建的项目类型介绍
Jenkins 中自动构建项目的类型有很多,常用的有以下三种:
- 自由风格软件项目(FreeStyle Project)
- Maven 项目(Maven Project)
- 流水线项目(Pipeline Project)
每种类型的构建其实都可以完成一样的构建过程与结果,只是在操作方式、灵活度等方面有所区别,在实际开发中可以根据自己的需求和习惯来选择。(PS:个人推荐使用流水线类型,因为灵活度非常高)
# 自由风格项目构建
下面演示创建一个自由风格项目来完成项目的集成过程:
拉取代码 -> 编译 -> 打包 -> 部署
# 拉取代码
创建项目
配置源码管理,从 Gitlab 拉取代码
编译打包:构建 -> 添加构建步骤 -> Executor Shell
echo "开始编译和打包"
mvn clean package
echo "编译和打包结束"
2
3
部署:把项目部署到远程的 Tomcat 里面
安装 Deploy to container 插件
Jenkins 本身无法实现远程部署到 Tomcat 的功能,需要安装 Deploy to container 插件实现。
添加 Tomcat 用户凭证
添加构建后操作
选择 Deploy war/ear to a container。
点击
Build Now
,开始构建过程
看到 Finished:SUCCESS 代表部署成功后,然后可以访问项目
# Maven 项目构建
Maven 安装请看 Maven 安装和配置
安装 Maven Integration 插件
创建 Maven 项目
Git 配置
Maven 配置
配置项目
拉取代码和远程部署的过程和自由风格项目一样,只是「构建」部分不同。
# publish over ssh 配置
安装插件
在 Configure System 菜单里,往下来,添加一台目标服务器
修改配置
# 超时机制
输出命令时一定要注意不要让窗口卡主,不然 Jenkins 会认为认为一直没完成。
# shell 的日志输出
nohup java -jar /root/xxoo/demo*.jar > mylog.log 2>&1 &
# 数据流重定向
数据流重定向就是将某个命令执行后应该要出现在屏幕上的数据传输到其他地方
标准输入(stdin):代码为 0,使用<或<<;
标准输出(stdout):代码为 1,使用>或>>;
标准错误输出(stderr):代码为 2,使用 2> 或 2>>
> 覆盖写
- >> 追加写
# 运行前清理 jar
配置杀死之前运行的进程
#!/bin/bash
# 删除历史数据
rm -rf xxoo
appname=$1
# 获取传入的参数
echo "arg:$1"
# 获取正在运行的jar包pid
pid=`ps -ef | grep $1 | grep 'java -jar' | awk '{printf $2}'`
echo $pid
# 如果 pid 为空,提示一下,否则,执行 kill 命令
if [ -z $pid ];
# 使用 -z 做空值判断
then
echo "$appname not started"
else
kill -9 $pid
echo "$appname stoping...."
check=`ps -ef | grep -w $pid | grep java`
if [ -z $check ];
then
echo "$appname pid:$pid is stop"
else
echo "$appname stop failed"
fi
fi
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# 自动化部署到 Docker 容器中
Docker 启动命令示范
docker run -d -p 8080:8080 --name demo-out -v /root/jarfile/demo-1-0.0.1-SNAPSHOT.jar:/app.jar openjdk:11 java -jar app.jar
打包到容器内
- 准备一台测试服务器 Docker 环境
- 准备支持 JDK 的镜像
编写 Dockerfile
FROM openjdk:11
EXPOSE 8080
WORKDIR /root
ADD jarfile/demo*.jar /root/app.jar
ENTRYPOINT ["java","-jar","/root/app.jar"]
2
3
4
5
6
7
打包镜像
docker build -t demo .
重启服务
systemctl daemon-reload
systemctl restart docker
2
# Pipeline 流水线项目构建
# Pipeline 简介
概念
Pipeline,简单来说,就是一套运行在 Jenkins 上的工作流框架,将原来独立运行于单个或者多个节点的任务连接起来,实现单个任务难以完成的复杂流程编排和可视化的工作。
使用 Pipeline 有以下好处(来自翻译自官方文档)
- 代码:Pipeline 以代码的形式实现,通常被检入源代码控制,使团队能够编辑,审查和迭代其传送流程
- 持久:无论是计划内的还是计划外的服务器重启,Pipeline 都是可恢复的
- 可停止:Pipeline 可接收交互式输入,以确定是否继续执行 Pipeline
- 多功能:Pipeline 支持现实世界中复杂的持续交付要求。它支持 fork/join、循环执行,并行执行任务的功能
- 可扩展:Pipeline 插件支持其 DSL 的自定义扩展 ,以及与其他插件集成的多个选项
如何创建 Jenkins Pipeline 呢?
- Pipeline 脚本是由 Groovy 语言实现的,但是我们没必要单独去学习 Groovy
- Pipeline 支持两种语法:Declarative(声明式)和 Scripted Pipeline(脚本式)语法
- Pipeline 也有两种创建方法:可以直接在 Jenkins 的 Web UI 界面中输入脚本;也可以通过创建一个 Jenkinsfile 脚本文件放入项目源码库中(一般我们都推荐在 Jenkins 中直接从源代码控制(SCM)中直接载入 Jenkinsfile Pipeline 这种方法)
# 安装 Pipeline 插件
Manage Jenkins -> Manage Plugins -> 可选插件
安装插件后,创建项目的时候多了「流水线」类型。
# Pipeline 语法快速入门
# Declarative 声明式
创建一个流水线项目。
接着流水线 -> 选择 Hello World
模板
生成内容如下:
pipeline {
agent any
stages {
stage('Hello') {
steps {
echo 'Hello World'
}
}
}
}
2
3
4
5
6
7
8
9
10
stages:代表整个流水线的所有执行阶段。通常 stages 只有 1 个,里面包含多个 stage。
stage:代表流水线中的某个阶段,可能出现 n 个。一般分为拉取代码,编译构建,部署等阶段。
steps:代表一个阶段内需要执行的逻辑。steps 里面是 Shell 脚本,Git 拉取代码,SSH 远程发布等任意内容。
编写一个简单声明式 Pipeline:
pipeline {
agent any
stages {
stage('拉取代码') {
steps {
echo '拉取代码'
}
}
stage('执行构建') {
steps {
echo '执行构建'
}
}
stage('项目部署') {
steps {
echo '项目部署'
}
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
点击构建,可以看到整个构建过程
# Scripted Pipeline 脚本式
创建一个流水线项目
这次选择 Scripted Pipeline
模板
node {
def mvnHome
stage('Preparation') { // for display purposes
}
stage('Build') {
}
stage('Results') {
}
}
2
3
4
5
6
7
8
9
10
11
12
- Node:节点,一个 Node 就是一个 Jenkins 节点,Master 或者 Agent,是执行 Step 的具体运行环境,后续讲到 Jenkins 的 Master-Slave 架构的时候用到
- Stage:阶段,一个 Pipeline 可以划分为若干个 Stage,每个 Stage 代表一组操作,比如:Build、Test、Deploy,Stage 是一个逻辑分组的概念
- Step:步骤,Step 是最基本的操作单元,可以是打印一句话,也可以是构建一个 Docker 镜像,由各类 Jenkins 插件提供,比如命令:
sh 'make'
,就相当于我们平时 shell 终端中执行 make 命令 一样
编写一个简单的脚本式 Pipeline:
node {
def mvnHome
stage('拉取代码') { // for display purposes
echo '拉取代码'
}
stage('编译构建') {
echo '编译构建'
}
stage('项目部署') {
echo '项目部署'
}
}
2
3
4
5
6
7
8
9
10
11
12
构建结果和声明式一样。
来个例子:
拉取代码
pipeline {
agent any
stages {
stage('拉取代码') {
steps {
checkout([$class: 'GitSCM', branches: [[name: '*/master']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: '68f2087f-a034-4d39-a9ff-1f776dd3dfa8', url: 'git@192.168.66.100:itheima_group/web_demo.git']]])
}
}
}
}
2
3
4
5
6
7
8
9
10
编译打包
pipeline {
agent any
stages {
stage('拉取代码') {
steps {
checkout([$class: 'GitSCM', branches: [[name: '*/master']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: '68f2087f-a034-4d39-a9ff-1f776dd3dfa8', url: 'git@192.168.66.100:itheima_group/web_demo.git']]])
}
}
stage('编译构建') {
steps {
sh label: '', script: 'mvn clean package'
}
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
部署
pipeline {
agent any
stages {
stage('拉取代码') {
steps {
checkout([$class: 'GitSCM', branches: [[name: '*/master']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: '68f2087f-a034-4d39-a9ff-1f776dd3dfa8', url: 'git@192.168.66.100:itheima_group/web_demo.git']]])
}
}
stage('编译构建') {
steps {
sh label: '', script: 'mvn clean package'
}
}
stage('项目部署') {
steps {
deploy adapters: [tomcat8(credentialsId: 'afc43e5e-4a4e-4de6-984f-b1d5a254e434', path: '', url: 'http://192.168.66.102:8080')], contextPath: null,war: 'target/*.war'
}
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Pipeline Script from SCM
刚才我们都是直接在 Jenkins 的 UI 界面编写 Pipeline 代码,这样不方便脚本维护,建议把 Pipeline 脚本放在项目中(一起进行版本控制)
在项目根目录建立 Jenkinsfile 文件,把内容复制到该文件中
把 Jenkinsfile 上传到 Gitlab
在项目中引用该文件
然后构建项目即可。
# 常用的构建触发器
几种构建方式:
- 快照依赖构建:Build whenever a SNAPSHOT dependency is built
- 当依赖的快照被构建时执行本 job
- 触发远程构建 (例如,使用脚本)
- 远程调用本 job 的 restapi 时执行本 job
- job 依赖构建:Build after other projects are built
- 当依赖的 job 被构建时执行本 job
- 定时构建:Build periodically
- 使用 cron 表达式定时构建本 job
- 向 GitHub 提交代码时触发 Jenkins 自动构建:GitHub hook trigger for GITScm polling
- Github WebHook 出发时构建本 job
- 定期检查代码变更:Poll SCM
- 使用 cron 表达式定时检查代码变更,变更后构建本 job
# 触发远程构建
代码改动自动可以使用 GitLab 的 Webhook 回调钩子调起 Jenkins 的启动任务接口
在构建触发器中配置接口和 token
# job 依赖构建
创建 pre_job 流水线工程
配置需要触发的工程
# 定时构建
# Jenkins cron 表达式
标准 cron:https://crontab.guru
Jenkins cron 不是标准的 cron 表达式。
定时字符串从左往右分别为:分 时 日 月 周。
第一个 * 表示每个小时的第几分钟,取值 0 ~ 59
H * * * *
H:每小时执行一次
第二颗 * 表示小时,取值 0 ~ 23
15 * * * 表示每天下午 3 点
1 * * * 表示每天凌晨 1 点
第三颗 * 表示一个月的第几天,取值 1 ~ 31
- 1 5 * * 表示每月5日凌晨1点
第四颗 * 表示第几月,取值 1 ~ 12
- 15 5 1 * 表示每年几月执行
第五颗 * 表示一周中的第几天,取值 0 ~ 7,其中 0 和 7 代表的都是周日
"/"
表示每隔多长时间,比如 */10 * * * * 表示每隔 10 分钟
"H"
hash 散列值,以 job 名取值,获取到以 job 名为入参的唯一值,相同名称值也相同,这个偏移量会和实际时间相加,获得一个真实的运行时间
意义在于:不同的项目在不同的时间运行,即使配置的值是一样的,比如都是 15 * * * *
,表示每个小时的第 15 分钟开始执行任务,那么会造成同一时间内在 Jenkins 中启动很多 job,换成 H/15 * * * *
,那么在首次启动任务时,会有随机值参与进来,有的会在 17 分钟启动 有的会在 19 分钟启动,随后的启动时间也是这个值。这样就能错开相同 cron 值的任务执行了。
H 的值也可以设置范围:
H * * * *
:表示一小时内的任意时间*/10 * * * *
:每 10 分钟H/10 * * * *
:每 10 分钟,可能是 7,17,27,起始时间 hash,步长不变45 3 * * 1-6
:每个周一至周六,凌晨 3 点 45 执行 1 次45 3-5 * * 1-6
:每个周一至周六,凌晨 3 点 45 ,凌晨 4 点 45,凌晨 5 点 45 各执行 1 次H(40-48) 3-5 * * 1-6
:在 40 ~ 48 之间取值 其他同上45 3-5/2 * * 1-6
:每个周一至周六,凌晨 3 点 45 ,凌晨 5 点 45 各执行 1 次45 0-6/2 * * 1-6 * * 1-6
:0 点开始,每间隔 2 小时执行一次 0:45、2:45、4:45
# 轮询SCM
轮询 SCM,是指定时扫描本地代码仓库的代码是否有变更,如果代码有变更就触发项目构建。
注意:轮询 SCM 构建触发器,Jenkins 会定时扫描本地整个项目的代码,增大系统的开销,不建议使用。
# Git hook 自动触发构建
刚才我们看到在 Jenkins 的内置构建触发器中,轮询 SCM 可以实现 Gitlab 代码更新,项目自动构建,但是该方案的性能不佳。那有没有更好的方案呢?
有的。就是利用 Gitlab 的 Web Hook 实现代码 push 到仓库,立即触发项目自动构建。
# 安装 Gitlab Hook 插件
需要去插件商城安装两个插件:
- Gitlab Hook
- GitLab
# Jenkins 设置自动构建
如上图,设置完构建后,给了一个 WebHook URL 地址,我们需要把生成的 WebHook URL 配置到 Gitlab 中
# Gitlab 配置 webhook
开启 Web Hook 功能
使用 root 账户登录到后台,点击 Admin Area -> Settings -> Network
勾选 Allow requests to the local network from web hooks and services
在项目添加 Web Hook
点击项目 -> Settings -> Integrations
注意:以下设置必须完成,否则会报错!
Manage Jenkins -> Configure System
# Jenkins 的参数化构建
有时在项目构建的过程中,我们需要根据用户的输入动态传入一些参数,从而影响整个构建结果,这时我们可以使用参数化构建。
Jenkins 支持非常丰富的参数类型。
接下来演示通过输入 Gitlab 项目的分支名称来部署不同分支项目。
新建分支:v1,代码稍微改动下,然后提交到 Gitlab 上。
这时看到 Gitlab 上有一个两个分支:master 和 v1
# 在 Jenkins 添加字符串类型参数
# 改动 pipeline 流水线代码
点击左侧 Build with Parameters,输入分支名称,构建即可。构建完成后访问 Tomcat 查看结果
# 配置邮箱服务器发送构建结果
# 安装 Email Extension 插件
# Jenkins 设置邮箱相关参数
Manage Jenkins -> Configure System
设置邮件参数
设置 Jenkins 默认邮箱信息
# 准备邮件内容
在项目根目录编写 email.html,并把文件推送到 Gitlab,内容如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>${ENV, var="JOB_NAME"}-第${BUILD_NUMBER}次构建日志</title>
</head>
<body leftmargin="8" marginwidth="0" topmargin="8" marginheight="4"
offset="0">
<table width="95%" cellpadding="0" cellspacing="0"
style="font-size: 11pt; font-family: Tahoma, Arial, Helvetica, sans-serif">
<tr>
<td>(本邮件是程序自动下发的,请勿回复!)</td>
</tr>
<tr>
<td><h2>
<font color="#0000FF">构建结果 - ${BUILD_STATUS}</font>
</h2></td>
</tr>
<tr>
<td><br />
<b><font color="#0B610B">构建信息</font></b>
<hr size="2" width="100%" align="center" /></td>
</tr>
<tr>
<td>
<ul>
<li>项目名称 : ${PROJECT_NAME}</li>
<li>构建编号 : 第${BUILD_NUMBER}次构建</li>
<li>触发原因: ${CAUSE}</li>
<li>构建日志: <a
href="${BUILD_URL}console">${BUILD_URL}console</a></li>
<li>构建 Url : <a
href="${BUILD_URL}">${BUILD_URL}</a></li>
<li>工作目录 : <a
href="${PROJECT_URL}ws">${PROJECT_URL}ws</a></li>
<li>项目 Url : <a
href="${PROJECT_URL}">${PROJECT_URL}</a></li>
</ul>
</td>
</tr>
<tr>
<td><b><font color="#0B610B">Changes Since Last
Successful Build:</font></b>
<hr size="2" width="100%" align="center" /></td>
</tr>
编写Jenkinsfile添加构建后发送邮件
<tr>
<td>
<ul>
<li>历史变更记录 : <a
href="${PROJECT_URL}changes">${PROJECT_URL}changes</a></li>
</ul> ${CHANGES_SINCE_LAST_SUCCESS,reverse=true, format="Changes for
Build #%n:<br />%c<br />",showPaths=true,changesFormat="<pre>[%a]<br
/>%m</pre>",pathFormat=" %p"}
</td>
</tr>
<tr>
<td><b>Failed Test Results</b>
<hr size="2" width="100%" align="center" /></td>
</tr>
<tr>
<td><pre
style="font-size: 11pt; font-family: Tahoma, Arial, Helvetica,
sans-serif">$FAILED_TESTS</pre>
<br /></td>
</tr>
<tr>
<td><b><font color="#0B610B">构建日志 (最后 100行):</font></b>
<hr size="2" width="100%" align="center" /></td>
</tr>
<tr>
<td><textarea cols="80" rows="30" readonly="readonly"
style="font-family: Courier New">${BUILD_LOG,
maxLines=100}</textarea>
</td>
</tr>
</table>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# 编写 Jenkinsfile 添加构建后发送邮件
pipeline {
agent any
stages {
stage('拉取代码') {
steps {
checkout([$class: 'GitSCM', branches: [[name: '*/master']],doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [],userRemoteConfigs: [[credentialsId: '68f2087f-a034-4d39-a9ff-1f776dd3dfa8', url: 'git@192.168.66.100:itheima_group/web_demo.git']]])
}
}
stage('编译构建') {
steps {
sh label: '', script: 'mvn clean package'
}
}
stage('项目部署') {
steps {
deploy adapters: [tomcat8(credentialsId: 'afc43e5e-4a4e-4de6-984f-b1d5a254e434', path: '', url: 'http://192.168.66.102:8080')], contextPath: null, war: 'target/*.war'
}
}
}
post {
always {
emailext(
subject: '构建通知:${PROJECT_NAME} - Build # ${BUILD_NUMBER} -
${BUILD_STATUS}!',
body: '${FILE,path="email.html"}',
to: 'xxx@qq.com'
)
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
测试
PS:邮件相关全局参数参考列表:系统设置 -> Extended E-mail Notification -> Content Token Reference,点击旁边的 ? 号
# 代码审查 SonarQube
# SonaQube 简介
SonarQube 是一个用于管理代码质量的开放平台,可以快速的定位代码中潜在的或者明显的错误。目前支持 java,C#,C/C++,Python,PL/SQL,Cobol,JavaScrip,Groovy 等二十几种编程语言的代码质量管理与检测。
官网:https://www.sonarqube.org/
。
# 安装 SonarQube
在 MySQL 创建 sonar 数据库
下载 sonar 压缩包:https://www.sonarqube.org/downloads/
。
解压 sonar,并设置权限
yum install unzip
unzip sonarqube-6.7.4.zip # 解压
mkdir /opt/sonar # 创建目录
mv sonarqube-6.7.4/* /opt/sonar # 移动文件
useradd sonar #创建 sonar 用户,必须 sonar 用于启动,否则报错
chown -R sonar. /opt/sonar # 更改 sonar 目录及文件权限
2
3
4
5
6
修改 sonar 配置文件
vi /opt/sonarqube-6.7.4/conf/sonar.properties
# 内容如下:
sonar.jdbc.username=root sonar.jdbc.password=Root@123
sonar.jdbc.url=jdbc:mysql://localhost:3306/sonar?
useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true&useConfigs=
maxPerformance&useSSL=false
2
3
4
5
6
注意:sonar 默认监听 9000 端口,如果 9000 端口被占用,需要更改。
启动 sonar
cd /opt/sonarqube-6.7.4
su sonar ./bin/linux-x86-64/sonar.sh start # 启动
su sonar ./bin/linux-x86-64/sonar.sh status # 查看状态
su sonar ./bin/linux-x86-64/sonar.sh stop # 停止
tail -f logs/sonar.logs # 查看日志
2
3
4
5
访问 sonar:http://ip:port/
默认账户:admin/admin
创建 token
token 要记下来后面要使用:bb8b6c53d9d921e101343cef0395243e6c1dc8a3
# 实现代码审查
安装 SonarQube Scanner 插件
添加 SonarQube 凭证
Jenkins 进行 SonarQube 配置
Manage Jenkins -> Configure System -> SonarQube servers
Manage Jenkins -> Global Tool Configuration
SonaQube 关闭审查结果上传到 SCM 功能
在项目添加 SonaQube 代码审查(非流水线项目)
添加构建步骤:
# must be unique in a given SonarQube instance
sonar.projectKey=web_demo
# this is the name and version displayed in the SonarQube UI. Was mandatory
prior to SonarQube 6.1.
sonar.projectName=web_demo
sonar.projectVersion=1.0
# Path is relative to the sonar-project.properties file. Replace "\" by "/" on
Windows.
# This property is optional if sonar.modules is set.
sonar.sources=.
sonar.exclusions=**/test/**,**/target/**
sonar.java.source=1.8
sonar.java.target=1.8
# Encoding of the source code. Default is default system encoding
sonar.sourceEncoding=UTF-8
2
3
4
5
6
7
8
9
10
11
12
13
14
15
在项目添加 SonaQube 代码审查(流水线项目)
项目根目录下,创建 sonar-project.properties 文件
# must be unique in a given SonarQube instance
sonar.projectKey=web_demo
# this is the name and version displayed in the SonarQube UI. Was mandatory
prior to SonarQube 6.1.
sonar.projectName=web_demo
sonar.projectVersion=1.0
# Path is relative to the sonar-project.properties file. Replace "\" by "/" on
Windows.
# This property is optional if sonar.modules is set.
sonar.sources=.
sonar.exclusions=**/test/**,**/target/**
sonar.java.source=1.8
sonar.java.target=1.8
# Encoding of the source code. Default is default system encoding
sonar.sourceEncoding=UTF-8
2
3
4
5
6
7
8
9
10
11
12
13
14
15
修改 Jenkinsfile,加入 SonarQube 代码审查阶段
pipeline {
agent any
stages {
stage('拉取代码') {
steps {
checkout([$class: 'GitSCM', branches: [[name: '*/master']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: '68f2087f-a034-4d39-a9ff-1f776dd3dfa8', url: 'git@192.168.66.100:itheima_group/web_demo.git']]])
}
}
stage('编译构建') {
steps {
sh label: '', script: 'mvn clean package'
}
}
stage('SonarQube代码审查') {
steps{
script {
scannerHome = tool 'sonarqube-scanner'
}
withSonarQubeEnv('sonarqube6.7.4') {
sh "${scannerHome}/bin/sonar-scanner"
}
}
}
stage('项目部署') {
steps {
deploy adapters: [tomcat8(credentialsId: 'afc43e5e-4a4e-4de6-984f-b1d5a254e434', path: '', url: 'http://192.168.66.102:8080')], contextPath: null, war: 'target/*.war'
}
}
}
post {
always {
emailext(
subject: '构建通知:${PROJECT_NAME} - Build # ${BUILD_NUMBER} -
${BUILD_STATUS}!',
body: '${FILE,path="email.html"}',
to: '1014671449@qq.com'
)
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
到 SonarQube 的 UI 界面查看审查结果