以往博主在部署springboot项目时,用的jar包方式启动,大致只需要经过以下stage

  • 拉取代码
  • mvn构建
  • 单元测试
  • 部署jar包
  • 通知

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
pipeline {
agent any
environment {
branch = 'master'
scmUrl = 'ssh://git@myScmServer.com/repos/myRepo.git'
serverPort = '8080'
developmentServer = 'dev-myproject.mycompany.com'
// javaopt = ''
}
stages {
stage('checkout git') {
steps {
git branch: branch, credentialsId: 'GitCredentials', url: scmUrl
}
}

stage('build') {
steps {
sh 'mvn clean package -DskipTests=true'
}
}

stage ('test') {
steps {
parallel (
"unit tests": { sh 'mvn test' },
"integration tests": { sh 'mvn integration-test' }
)
}
}

stage('deploy development'){
steps {
// 通过Spring Boot Actuator来停止服务
httpRequest httpMode: 'POST', url: "http://${developmentServer}:${serverPort}/shutdown", validResponseCodes: '200,408'
sshagent(['RemoteCredentials']) {
sh "scp target/*.jar root@${developmentServer}:/opt/jenkins-demo-${BUILD_ID}.jar"
sh "ssh root@${developmentServer} nohup java -Dserver.port=${serverPort} -jar /opt/jenkins-demo-${BUILD_ID}.jar &"
}
retry (3) {
sleep 5
httpRequest url:"http://${developmentServer}:${serverPort}/health", validResponseCodes: '200', validResponseContent: '"status":"UP"'
}
}
}
}
post {
failure {
mail to: 'team@example.com', subject: 'Pipeline failed', body: "${env.BUILD_URL}"
}
}
}

看着deploy stage那段代码复用程度很高,得找个方式将其抽离为共享库,后面pipeline只需要提供两个参数server、port即可,所以抽离出来ss部署方式的deploy方法,所以我们的共享库工程如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
mkdir ssh-deploy/{src,vars,resources}
cat >ssh-deploy/vars/deploy.groovy<<-'EOF'
def call(def server, def port) {
// 通过Spring Boot Actuator来停止服务
httpRequest httpMode: 'POST', url: "http://${server}:${port}/shutdown", validResponseCodes: '200,408'
sshagent(['RemoteCredentials']) {
sh "scp target/*.jar root@${server}:/opt/jenkins-demo-${BUILD_ID}.jar"
sh "ssh root@${server} nohup java -Dserver.port=${port} -jar /opt/jenkins-demo-${BUILD_ID}.jar &"
}
retry (3) {
sleep 5
httpRequest url:"http://${server}:${port}/health", validResponseCodes: '200', validResponseContent: '"status":"UP"'
}
}
EOF

# 将上述代码创建为sshdeploy仓库,并提交到远程仓库中,略
# https://gitlab.xadocker.cn/devops-jenkins-shared-library/ssh-deploy.git

最后博主的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
library identifier: 'ssh-deploy@master', retriever: modernSCM([
$class: 'GitSCMSource',
remote: 'https://github.com/devops-ws/jenkins-shared-library',
traits: [[$class: 'jenkins.plugins.git.traits.BranchDiscoveryTrait']]
])

pipeline {
agent any
environment {
branch = 'master'
scmUrl = 'ssh://git@myScmServer.com/repos/myRepo.git'
serverPort = '8080'
developmentServer = 'dev-myproject.mycompany.com'
// javaopt = ''
}
stages {
stage('checkout git') {
steps {
git branch: branch, credentialsId: 'GitCredentials', url: scmUrl
}
}

stage('build') {
steps {
sh 'mvn clean package -DskipTests=true'
}
}

stage ('test') {
steps {
parallel (
"unit tests": { sh 'mvn test' },
"integration tests": { sh 'mvn integration-test' }
)
}
}

stage('deploy development'){
steps {
deploy(developmentServer, serverPort)
}
}
}
post {
failure {
mail to: 'team@example.com', subject: 'Pipeline failed', body: "${env.BUILD_URL}"
}
}
}

如果单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
library identifier: 'ssh-deploy@master', retriever: modernSCM([
$class: 'GitSCMSource',
remote: 'https://github.com/devops-ws/jenkins-shared-library',
traits: [[$class: 'jenkins.plugins.git.traits.BranchDiscoveryTrait']]
])

pipeline {
agent any
environment {
branch = 'master'
scmUrl = 'ssh://git@myScmServer.com/repos/myRepo.git'
serverPort = '8080'
developmentServer = 'dev-myproject.mycompany.com'
stagingServer = 'staging-myproject.mycompany.com'
productionServer = 'production-myproject.mycompany.com'
// javaOpt = ''
// jarName = ''
}
stages {
stage('checkout git') {
steps {
git branch: branch, credentialsId: 'GitCredentials', url: scmUrl
}
}

stage('build') {
steps {
sh 'mvn clean package -DskipTests=true'
}
}

stage ('test') {
steps {
parallel (
"unit tests": { sh 'mvn test' },
"integration tests": { sh 'mvn integration-test' }
)
}
}

stage('deploy development'){
steps {
deploy(developmentServer, serverPort)
}
}
stage('deploy staging'){
steps {
deploy(stagingServer, serverPort)
}
}
stage('deploy production'){
steps {
deploy(productionServer, serverPort)
}
}
}
post {
failure {
mail to: 'team@example.com', subject: 'Pipeline failed', body: "${env.BUILD_URL}"
}
}
}