简介
Jenkins流水线是一套插件,它支持实现和集成持续交付流水线到 Jenkins。流水线提供了一组可扩展的工具,用于通过流水线 DSL将简单到复杂的交付流水线建模为 "代码"。本文只是简单的介绍了下Jenkinsfile文件的编写,还有许多不足和可以优化改进的地方。
通过 Blue Ocean 创建
在上一篇Jenkins的简单使用文章中,已经介绍了使用blue ocean图形化创建pipeline。但是这种方式,创建出来的pipeline往往不符合我们的要求,直接写脚本的形式,可能更容易理解一点。所以本文主要介绍pipeline脚本的编写,再编写Jenkinsfile之前,最好先看看官方的教程,了解Jenkins的pipeline语法。
编写Jenkinsfile(pipeline脚本)
maven项目构建
先附上完整的pipeline脚本,然后再对其中的命令做对应的解释。而官方有的基础命令,则本文不再多做解释了,建议直接访问官网流水线语法参考 学习其中的命令
maven的pipeline
pipeline {
//设置环境变量
environment {
CI = 'true'
HAR_NAME = "test"
HAR_PASS = "Test12345"
SONARURL = "http://sonar.com"
SONARURL_token = "bb99xxxxxxx0bad5cf4"
CON_PROT = "8002"
TEST_ENV = "XXXX-test"
DEV_ENV = "XXXX-dev"
}
agent any
//设置构建的参数
parameters {
//设置环境部署参数
choice choices: ['test', 'dev', 'not'], description: '选择需要部署的环境,不需要部署则选择not', name: 'DEPLOY_TO'
//读取git的tag数据,该功能需要安装插件
listGitBranches branchFilter: 'origin/(.*)', credentialsId: 'gitlab', defaultValue: 'master', name: 'tag', quickFilterEnabled: false, remoteURL: 'http://gitlab.com.cn/xxx/xxx.git', selectedValue: 'NONE', sortMode: 'DESCENDING_SMART', tagFilter: '*', type: 'PT_TAG'
//设置钉钉的webhook
string defaultValue: 'https://oapi.dingtalk.com/robot/send?access_token=e706xxxf835279xxxx9453xxxxxx1561', description: '钉钉webhook通知地址', name: 'webhook', trim: false
//设置字符参数callphone,默认值是18677371111
string defaultValue: '18677371111', description: '通知人', name: 'callphone', trim: false
}
//设置构建需要用到的工具,该工具需要先在Jenkins中配置好
tools {
maven "maven3.5.4"
}
stages {
stage('构建') {
steps {
echo '开始构建'
//拉去git代码,需要先配置好相应凭据
git credentialsId: 'gitlab', url: 'http://gitlab.com.cn/xxx/xxx.git'
//切换分支
sh 'git checkout ${tag}'
//构建
sh 'mvn -DskipTests clean package'
echo '构建成功'
}
}
stage('代码扫描') {
steps {
echo '开始代码扫描'
sh 'mvn sonar:sonar -Dsonar.host.url=${SONARURL} -Dsonar.login=${SONARURL_token}'
echo '代码扫描结束'
}
}
stage('镜像构建') {
steps {
echo '构建镜像并上传到harbor'
script {
//登陆使用的凭据需要提前在Jenkins中添加好
def customImage = docker.build("harbor.com.cn/${HAR_NAME}/${JOB_NAME}:${env.GIT_BRANCH}-${env.BUILD_NUMBER}")
withDockerRegistry(credentialsId: 'har-test', url: 'http://harbor.com.cn') {
customImage.push("${env.GIT_BRANCH}-${env.BUILD_NUMBER}")
customImage.push("latest")
}
}
//这里为了节约空间,所以在上传到harbor之后,就删除本地的镜像
echo '删除本地镜像'
sh "docker image rm harbor.com.cn/${HAR_NAME}/${JOB_NAME}:${env.GIT_BRANCH}-${env.BUILD_NUMBER}"
}
}
stage('测试环境部署') {
//定义部署的节点机
agent { label "${TEST_ENV}" }
//定义该步骤不拉取代码
options { skipDefaultCheckout() }
//当构建参数为test的时候,才执行该步骤
when {
beforeAgent true
environment ignoreCase: true, name: 'DEPLOY_TO', value: 'test'
}
steps {
echo '开始环境部署'
//登陆harbor
sh "docker login -u ${HAR_NAME} -p ${HAR_PASS} harbor.com.cn"
//拉去镜像
sh "docker pull harbor.com.cn/${HAR_NAME}/${JOB_NAME}:latest"
//删除和停止原本的容器
sh '''if [ $(docker ps -aq --filter name=^/${JOB_NAME}$) ]; then docker stop ${JOB_NAME} && docker rm ${JOB_NAME};fi'''
//自动部署最新版本
sh '''docker run -d --name ${JOB_NAME} -p ${CON_PROT}:${CON_PROT} harbor.com.cn/${HAR_NAME}/${JOB_NAME}:latest --spring.profiles.active=test '''
echo '部署结束'
}
}
stage('接口测试') {
when {
branch 'master'
}
steps {
echo '开始接口测试'
sh '''
curl 'yapi.com'
'''
echo '接口测试结束'
}
}
}
post {
failure {
//钉钉通知,使用的是一个简单的shell脚本,传入相关参数即可
sh "ding.sh ${webhook} ${callphone} ${JOB_NAME} ${BUILD_ID} ${BUILD_TAG} ${esdb_tag} 失败"
}
success {
//钉钉通知
sh "ding.sh ${webhook} ${callphone} ${JOB_NAME} ${BUILD_ID} ${BUILD_TAG} ${esdb_tag} 失败"
}
}
}
dockerfile文件
上面的Jenkinsfile中,是构建为docker镜像的形式,所以需要一个dockerfile文件,通常像下面这个就可以了。设置了时区为中国时区。基础镜像也是使用alpine的,体积比较小。
FROM java:8-jdk-alpine
VOLUME /tmp
ADD /target/*.jar /app.jar
RUN apk --no-cache add tzdata && \
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
echo "Asia/Shanghai" > /etc/timezone
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar", "app.jar"]
ding.sh文件
构建完成之后,我们需要知道构建结果,就可以使用钉钉群的webhook功能,当然也有邮件、微信,qq等其他方式通知,这个就需要去自己探索了。这里给出上面Jenkinsfile中的ding.sh文件,里面需要修改下Jenkins地址为自己的。
#!/bin/sh
usage () {
echo "Usage: ding.sh [webhook] [cell-phone number] [JOB_NAME] [BUILD_ID] [BUILD_TAG] [deploy_env] [STATUS]";
echo " [webhook]: 钉钉聊天机器人webhook。";
echo " [cell-phone number]: 要@的成员手机号。";
echo " [JOB_NAME]: Jenkins的构建项目名";
echo " [BUILD_ID]: Jenkins的构建ID";
echo " [BUILD_TAG]: 构建的分支";
echo " [deploy_env]: 部署的环境";
echo " [STATUS]: 状态";
exit 1;
}
WEB_HOOK=$1
AT=$2
JOB_NAME=$3
BUILD_ID=$4
BUILD_TAG=$5
deploy_env=$6
STATUS=$7
TIME=$(date "+%Y-%m-%d %H:%M:%S")
shift 2
make(){
curl ${WEB_HOOK} -H "Content-type: application/json" -X POST -d "
{
"msgtype": 'markdown',
"markdown": {
"title":'持续集成机器人',
"text":'
# CI/CD机器人:构建${STATUS}\n\n 执行任务:代码扫描+构建+${deploy_env}环境部署\n\n 构建时间:${TIME} \n\n 项目名称:${JOB_NAME}\n\n 构建编号:${BUILD_ID} \n\n 构建版本:${BUILD_TAG}\n\n [点击查看](http://Jenkins.com/blue/organizations/jenkins/${JOB_NAME}/detail/${JOB_NAME}/${BUILD_ID})
@${AT}
'
},
"at": {
"atMobiles": [
"$AT"
],
"isAtAll": false
}
}"
}
make $@