Jenkins使用Pipeline脚本持续集成/持续部署

持续集成

配置

新建项目 -> 输入项目名 -> 选择Pipeline -> 创建

进入配置页面后,在Pipeline配置项中选择Pipeline script from SCM,配置好代码仓库地址就可以了。

Jenkins将会从代码仓库根目录的Jenkinsfile文件中读取Pipeline脚本代码并执行。

这样做的好处是Pipeline脚本的修改记录也将纳入代码仓库的管理。

脚本

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
#!groovy
pipeline {
//在任何可用的代理上执行Pipeline
agent any

//触发器
triggers {
//当依赖的项目执行完成后,触发执行本项目
upstream 'Dependency-Project'

//轮询检测代码仓库,有新代码则触发执行。使用cron表达式,每分钟检测一次。
pollSCM ignorePostCommitHooks: true, scmpoll_spec: '* * * * *'
}

options {
//保留10天构建记录
buildDiscarder(logRotator(daysToKeepStr: '10'))
//不允许并行执行
disableConcurrentBuilds()
}

//pipeline的各个阶段场景
stages {
stage('编译前的准备工作') {
steps {
echo "upgrade version......"
// 执行shell脚本
sh '''
./upgrade-version.sh
'''
}
}
stage('编译打包') {
steps {
echo "starting building......"
sh '''mvn clean install spotbugs:spotbugs pmd:pmd -Ptest'''
}
}
stage('静态检查') {
steps {
echo "starting codeAnalyze with checkstyle, findbugs, pmd......"
checkstyle canComputeNew: false, defaultEncoding: '', healthy: '80', pattern: '**/checkstyle-result.xml', thresholdLimit: 'normal', unHealthy: '40'
findbugs canComputeNew: false, defaultEncoding: '', excludePattern: '', healthy: '', includePattern: '', pattern: '**/spotbugsXml.xml', unHealthy: ''
pmd canComputeNew: false, defaultEncoding: '', healthy: '', pattern: '**/pmd.xml', unHealthy: ''
}
}
stage('构建归档 ') {
steps{
echo "starting archive artifacts......"
archiveArtifacts artifacts: 'target/*.jar', onlyIfSuccessful: true
}
}
stage('清理工作空间') {
steps {
cleanWs()
}
}
}
}

持续部署

配置

如果每次有代码更新都需要立即重新编译并部署到测试环境,可以在编译脚本最后添加部署stage。

但一般情况是由测试人员来判定什么时候部署哪些项目,所以会单独创建一个项目用于部署。

同样新建项目 -> 输入项目名 -> 选择Pipeline -> 创建

在配置页面设置好部署脚本的仓库路径。

脚本

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
#!groovy
pipeline {
//在任何可用的代理上执行Pipeline
agent any

//启动参数
parameters {
//choice下拉选择框
//Module1,Module2,Module3是Jenkins的编译项目名称,选择需要部署的模块。
choice(name:'projectName', choices: 'Module1\nModule2\nModule3',description: '项目模块名称')
//test-server-ip1,test-server-ip2是要部署的目标服务器地址。
choice(name:'deployServer', choices: 'test-server-ip1\ntest-server-ip2', description: '部署服务器地址')
//string文本输入框
//编译项目的构建编号
string(name:'buildNum', defaultValue: '', description: '构建编号', trim: true)
}

options {
//保留10天构建记录
buildDiscarder(logRotator(daysToKeepStr: '10'))
}

stages {
stage('拷贝构建文档') {
steps {
script {
if ( params.buildNum == '' ) {
//如果构建编号为空,则使用最新的一次构建。
echo "copy last successful artifact from $projectName ..."
copyArtifacts(projectName: "$projectName", selector: lastSuccessful())
} else {
//指定某一次构建,用户版本回退。
echo "copy #$buildNum artifact from $projectName ..."
copyArtifacts(projectName: "$projectName", selector: specific("$buildNum"))
}
}
}
}
stage('部署测试环境') {
steps {
echo "starting deploy to $deployServer ..."
sh '''
//删除旧的部署包
echo "Remove old package ..."
ssh root@$deployServer "
mkdir -p /opt/deploy/$projectName
cd /opt/deploy/$projectName
rm -rf $projectName.jar
exit
"
//上传新的部署包
if [ -f "target/$projectName.jar" ];then
echo "Upload new package ..."
scp target/$projectName-$projectVersion.jar root@$deployServer:/opt/deploy/$projectName/
fi
//执行重启脚本
echo "Restart application ..."
ssh root@$deployServer "
/opt/deploy/start.sh $projectName $projectName.jar
exit
"
'''
}
}
}
}