Young Kbt blog Young Kbt blog
首页
  • java基础

    • Java基础
    • Java集合
    • Java反射
    • JavaJUC
    • JavaJVM
  • Java容器

    • JavaWeb
  • Java版本新特性

    • Java新特性
  • SQL 数据库

    • MySQL
    • Oracle
  • NoSQL 数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • ActiveMQ
    • RabbitMQ
    • RocketMQ
    • Kafka
  • 进阶服务

    • Nginx
  • Spring
  • Spring Boot
  • Spring Security
  • 设计模式
  • 算法
  • 知识
  • 管理

    • Maven
    • Git
  • 部署

    • Linux
    • Docker
    • Jenkins
    • Kubernetes
  • 进阶

    • TypeScript
  • 框架

    • React
    • Vue2
    • Vue3
  • 轮子工具
  • 项目工程
  • 友情链接
  • 本站

    • 分类
    • 标签
    • 归档
  • 我的

    • 收藏
    • 关于
    • Vue2-Admin (opens new window)
    • Vue3-Admin(完善) (opens new window)
GitHub (opens new window)

Shp Liu

朝圣的使徒,正在走向编程的至高殿堂!
首页
  • java基础

    • Java基础
    • Java集合
    • Java反射
    • JavaJUC
    • JavaJVM
  • Java容器

    • JavaWeb
  • Java版本新特性

    • Java新特性
  • SQL 数据库

    • MySQL
    • Oracle
  • NoSQL 数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • ActiveMQ
    • RabbitMQ
    • RocketMQ
    • Kafka
  • 进阶服务

    • Nginx
  • Spring
  • Spring Boot
  • Spring Security
  • 设计模式
  • 算法
  • 知识
  • 管理

    • Maven
    • Git
  • 部署

    • Linux
    • Docker
    • Jenkins
    • Kubernetes
  • 进阶

    • TypeScript
  • 框架

    • React
    • Vue2
    • Vue3
  • 轮子工具
  • 项目工程
  • 友情链接
  • 本站

    • 分类
    • 标签
    • 归档
  • 我的

    • 收藏
    • 关于
    • Vue2-Admin (opens new window)
    • Vue3-Admin(完善) (opens new window)
GitHub (opens new window)
  • 版本管理 - Maven

  • 开发管理 - Git

  • 操作系统 - Linux

  • 容器部署 - Docker

  • 持续集成 - Jenkins

    • Jenkins - 介绍
    • Jenkins - 安装和配置
    • Jenkins - 多个项目搭建
      • Jenkins 构建的项目类型介绍
      • 自由风格项目构建
        • 拉取代码
      • Maven 项目构建
        • publish over ssh 配置
        • 超时机制
        • shell 的日志输出
        • 数据流重定向
        • 运行前清理 jar
        • 自动化部署到 Docker 容器中
      • Pipeline 流水线项目构建
        • Pipeline 简介
        • 安装 Pipeline 插件
        • Pipeline 语法快速入门
        • Declarative 声明式
        • Scripted Pipeline 脚本式
        • Pipeline Script from SCM
      • 常用的构建触发器
        • 触发远程构建
        • job 依赖构建
        • 定时构建
        • Jenkins cron 表达式
        • 轮询SCM
      • Git hook 自动触发构建
        • 安装 Gitlab Hook 插件
        • Jenkins 设置自动构建
        • Gitlab 配置 webhook
      • Jenkins 的参数化构建
        • 在 Jenkins 添加字符串类型参数
        • 改动 pipeline 流水线代码
      • 配置邮箱服务器发送构建结果
        • 安装 Email Extension 插件
        • Jenkins 设置邮箱相关参数
        • 准备邮件内容
        • 编写 Jenkinsfile 添加构建后发送邮件
      • 代码审查 SonarQube
        • SonaQube 简介
        • 安装 SonarQube
        • 实现代码审查
    • Jenkins - DevOps
  • 容器管理 - kubernetes

  • 工具
  • 持续集成 - Jenkins
Young Kbt
2022-08-24
目录

Jenkins - 多个项目搭建

  • Jenkins 构建的项目类型介绍
  • 自由风格项目构建
    • 拉取代码
  • Maven 项目构建
    • publish over ssh 配置
    • 运行前清理 jar
    • 自动化部署到 Docker 容器中
  • Pipeline 流水线项目构建
    • Pipeline 简介
    • 安装 Pipeline 插件
    • Pipeline 语法快速入门
  • 常用的构建触发器
    • 触发远程构建
    • job 依赖构建
    • 定时构建
    • 轮询SCM
  • Git hook 自动触发构建
    • 安装 Gitlab Hook 插件
    • Jenkins 设置自动构建
    • Gitlab 配置 webhook
  • Jenkins 的参数化构建
    • 在 Jenkins 添加字符串类型参数
    • 改动 pipeline 流水线代码
  • 配置邮箱服务器发送构建结果
    • 安装 Email Extension 插件
    • Jenkins 设置邮箱相关参数
    • 准备邮件内容
    • 编写 Jenkinsfile 添加构建后发送邮件
  • 代码审查 SonarQube
    • SonaQube 简介
    • 安装 SonarQube
    • 实现代码审查

# Jenkins 构建的项目类型介绍

Jenkins 中自动构建项目的类型有很多,常用的有以下三种:

  • 自由风格软件项目(FreeStyle Project)
  • Maven 项目(Maven Project)
  • 流水线项目(Pipeline Project)

每种类型的构建其实都可以完成一样的构建过程与结果,只是在操作方式、灵活度等方面有所区别,在实际开发中可以根据自己的需求和习惯来选择。(PS:个人推荐使用流水线类型,因为灵活度非常高)

# 自由风格项目构建

下面演示创建一个自由风格项目来完成项目的集成过程:

拉取代码 -> 编译 -> 打包 -> 部署

# 拉取代码

创建项目

image-20220824211135877

配置源码管理,从 Gitlab 拉取代码

image-20220824211234599

编译打包:构建 -> 添加构建步骤 -> Executor Shell

echo "开始编译和打包"
mvn clean package
echo "编译和打包结束"
1
2
3

部署:把项目部署到远程的 Tomcat 里面

安装 Deploy to container 插件

Jenkins 本身无法实现远程部署到 Tomcat 的功能,需要安装 Deploy to container 插件实现。

image-20220824211453420

添加 Tomcat 用户凭证

image-20220824211613981

添加构建后操作

image-20220824211647897

选择 Deploy war/ear to a container。

image-20220824211833243

点击 Build Now,开始构建过程

看到 Finished:SUCCESS 代表部署成功后,然后可以访问项目

# Maven 项目构建

Maven 安装请看 Maven 安装和配置

安装 Maven Integration 插件

image-20220824212108573

创建 Maven 项目

image-20220824212405007

Git 配置

image-20220726213303821

image-20220726213505879

Maven 配置

image-20220726214239888

配置项目

拉取代码和远程部署的过程和自由风格项目一样,只是「构建」部分不同。

image-20220824212640023

# publish over ssh 配置

安装插件

在 Configure System 菜单里,往下来,添加一台目标服务器

image-20220726223917263

image-20220726223937722

修改配置

image-20220727165700419

# 超时机制

输出命令时一定要注意不要让窗口卡主,不然 Jenkins 会认为认为一直没完成。

# shell 的日志输出

nohup java -jar /root/xxoo/demo*.jar > mylog.log 2>&1 &
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
1
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
1

打包到容器内

  1. 准备一台测试服务器 Docker 环境
  2. 准备支持 JDK 的镜像

编写 Dockerfile

FROM openjdk:11
EXPOSE 8080

WORKDIR /root

ADD jarfile/demo*.jar /root/app.jar
ENTRYPOINT ["java","-jar","/root/app.jar"]
1
2
3
4
5
6
7

打包镜像

docker build -t demo .
1

重启服务

systemctl daemon-reload
systemctl restart docker
1
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 -> 可选插件

image-20220824214117009

安装插件后,创建项目的时候多了「流水线」类型。

image-20220824214152563

# Pipeline 语法快速入门

# Declarative 声明式

创建一个流水线项目。

接着流水线 -> 选择 Hello World 模板

image-20220824214308996

生成内容如下:

pipeline {
	agent any
    stages {
        stage('Hello') {
			steps {
				echo 'Hello World'
			}
		}
	}
}
1
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 '项目部署'
            }
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

点击构建,可以看到整个构建过程

image-20220824214701107

# Scripted Pipeline 脚本式

创建一个流水线项目

这次选择 Scripted Pipeline 模板

image-20220824214831757

node {
	def mvnHome
	stage('Preparation') { // for display purposes
	
	}
    stage('Build') {
    
    }
    stage('Results') {
    
    }
}
1
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 '项目部署'
    }
}
1
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']]])
            }
    	}
    }
}
1
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'
        	}
    	}
    }
}
1
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'
            }
        }
    }
}
1
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 文件,把内容复制到该文件中

image-20220824215530979

把 Jenkinsfile 上传到 Gitlab

在项目中引用该文件

image-20220824215844982

然后构建项目即可。

# 常用的构建触发器

几种构建方式:

  • 快照依赖构建: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

image-20220728170250273

# job 依赖构建

创建 pre_job 流水线工程

image-20220824220230181

配置需要触发的工程

image-20220824220059611

# 定时构建

# Jenkins cron 表达式

标准 cron:https://crontab.guru

Jenkins cron 不是标准的 cron 表达式。

image-20220824220425684

定时字符串从左往右分别为:分 时 日 月 周。

第一个 * 表示每个小时的第几分钟,取值 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 到仓库,立即触发项目自动构建。

image-20220824224334708

# 安装 Gitlab Hook 插件

需要去插件商城安装两个插件:

  • Gitlab Hook
  • GitLab

# Jenkins 设置自动构建

image-20220824221433052

如上图,设置完构建后,给了一个 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

image-20220824221753355

在项目添加 Web Hook

点击项目 -> Settings -> Integrations

image-20220824221854166

注意:以下设置必须完成,否则会报错!

Manage Jenkins -> Configure System

image-20220824221939944

# Jenkins 的参数化构建

有时在项目构建的过程中,我们需要根据用户的输入动态传入一些参数,从而影响整个构建结果,这时我们可以使用参数化构建。

Jenkins 支持非常丰富的参数类型。

image-20220824222139731

接下来演示通过输入 Gitlab 项目的分支名称来部署不同分支项目。

新建分支:v1,代码稍微改动下,然后提交到 Gitlab 上。

这时看到 Gitlab 上有一个两个分支:master 和 v1

# 在 Jenkins 添加字符串类型参数

image-20220824222248901

image-20220824222320736

# 改动 pipeline 流水线代码

image-20220824222338616

点击左侧 Build with Parameters,输入分支名称,构建即可。构建完成后访问 Tomcat 查看结果

image-20220824222456560

# 配置邮箱服务器发送构建结果

# 安装 Email Extension 插件

image-20220824222523705

# Jenkins 设置邮箱相关参数

Manage Jenkins -> Configure System

image-20220824222541900

设置邮件参数

image-20220824222814684

设置 Jenkins 默认邮箱信息

image-20220824222912160

# 准备邮件内容

在项目根目录编写 email.html,并把文件推送到 Gitlab,内容如下:

image-20220824222931295

<!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>项目名称&nbsp;:&nbsp;${PROJECT_NAME}</li>
                        <li>构建编号&nbsp;:&nbsp;第${BUILD_NUMBER}次构建</li>
                        <li>触发原因:&nbsp;${CAUSE}</li>
                        <li>构建日志:&nbsp;<a
                                          href="${BUILD_URL}console">${BUILD_URL}console</a></li>
                        <li>构建&nbsp;&nbsp;Url&nbsp;:&nbsp;<a
                                                             href="${BUILD_URL}">${BUILD_URL}</a></li>
                        <li>工作目录&nbsp;:&nbsp;<a
                                                href="${PROJECT_URL}ws">${PROJECT_URL}ws</a></li>
                        <li>项目&nbsp;&nbsp;Url&nbsp;:&nbsp;<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="&nbsp;&nbsp;&nbsp;&nbsp;%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>
1
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'
            )
        }
    }
}
1
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

测试

image-20220824223417896

PS:邮件相关全局参数参考列表:系统设置 -> Extended E-mail Notification -> Content Token Reference,点击旁边的 ? 号

image-20220824223601765

# 代码审查 SonarQube

# SonaQube 简介

SonarQube 是一个用于管理代码质量的开放平台,可以快速的定位代码中潜在的或者明显的错误。目前支持 java,C#,C/C++,Python,PL/SQL,Cobol,JavaScrip,Groovy 等二十几种编程语言的代码质量管理与检测。

官网:https://www.sonarqube.org/。

# 安装 SonarQube

在 MySQL 创建 sonar 数据库

image-20220824223824294

下载 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 目录及文件权限
1
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
1
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 # 查看日志
1
2
3
4
5

访问 sonar:http://ip:port/

image-20220824224046627

默认账户:admin/admin

创建 token

image-20220824224205948

token 要记下来后面要使用:bb8b6c53d9d921e101343cef0395243e6c1dc8a3

# 实现代码审查

image-20220824224429061

安装 SonarQube Scanner 插件

image-20220824224445252

添加 SonarQube 凭证

image-20220824224616989

Jenkins 进行 SonarQube 配置

Manage Jenkins -> Configure System -> SonarQube servers

image-20220824224703870

Manage Jenkins -> Global Tool Configuration

image-20220824224829822

SonaQube 关闭审查结果上传到 SCM 功能

image-20220824224924875

在项目添加 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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

在项目添加 SonaQube 代码审查(流水线项目)

项目根目录下,创建 sonar-project.properties 文件

image-20220824225055625

# 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
1
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'
            )
    	}
    }
}
1
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 界面查看审查结果

image-20220824225353461

编辑此页 (opens new window)
#Jenkins
更新时间: 2023/10/23, 10:58:52
Jenkins - 安装和配置
Jenkins - DevOps

← Jenkins - 安装和配置 Jenkins - DevOps→

最近更新
01
技术随笔 - Element Plus 修改包名 原创
11-02
02
Reactor - 扩展性
11-02
03
Reactor - 最佳实践
11-02
更多文章>
Theme by Vdoing | Copyright © 2021-2024 Young Kbt | blog
桂ICP备2021009994号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式