实战-jira集成gitlab,jenkins持续集成部署实现方案
一、概述
通常我们知道jira是软件项目流程管理工具,通过该工具,项目负责人可以分配人物给项目上的开发人员,开发人员随着开发的进度更新状态,进而反馈开发进度,项目的部署单独使用jenkins来实现。但是料想组内开发人员编写的代码能够通过jira一键发布打包,测试,合并到主分支,这样就更好。
二、jira自定义流程
2.1、自定义版本任务流程
每次有一个版本需求的时候,我们需要自定义一个版本,命名为版本任务。版本任务的流程大致有创建版本任务-集成部署与测试-DEV部署与测试-MST部署与测试-版本发布-版本验收-清理版本任务 这几个过程。
2.2、自定义集成任务流程
每个版本需求可以细分出来很多任务需求,分配给对应的后端开发人员,前段开发人员。此时,我们也需要根据版本任务来创建每个开发人员的集成任务。开发任务主要包括创建分支-集成开发与测试-集成合并-DEV测试与合并-MST测试与合并等状态。具体流程和以上版本任务创建类似。
三、jira集成gitlab
jira集成gitlab可以实现将git的commit信息上传到jira项目的问题中,方便管理人员或开发人员查阅。
3.1、gitlab中的配置
1、登录gitlab后台,进入需要配置的项目,再点击 Settings->Integrations->JIRA,如图:
2、配置jira信息,如图:
以上参数都需要配置:
Active、Trigger、Merge request:都勾上
Web URL:JIRA项目的基础URL
Web API URL:如果在JIRA中没有特殊配置API的URL,还是填上面的URL
Username:JIRA账户用户名
Enter new password: JIRA账户密码
Transition ID:此时填写的在JIRA中对应的流程关闭ID,此时填1371,如图:
3、填写完成后保存,若填写信息有误会保存失败。
4、测试在git中按照 jira任务编号+提交人+注释内容 的注释规范提交代码,jira中相关任务
下就会出现具体的提交信息:
3.2 、jira中的配置
若要进一步友好展示,可进行jira插件选择安装。
四、jira集成jenkins
4.1、jenkins中的配置
jenkins中需要安装的插件如下:
JIRA Integration for Jenkins
Jira Issue Updater
JIRA Pipeline Steps
JIRA plugin
JIRA Trigger Plugin
JiraTestResultReporter plugin
1、安装完 JIRA Trigger Plugin插件后,在系统管理->系统设置中,需要配置该插件和jira的关联:
4.2、jira中的配置
1、配置webhook,即网络钩子,jira->管理->系统->高级,找到WebHook:
2、创建webhook,点击保存即可。如图:
3、接口调试,通过访问 http://ip:20003/jenkins/jiratriggerwebhookreceiver/ ,可查看jenkins接口是的能调通,若出现下图,则表示可以调通:
asd
4、配置任务(版本任务和集成任务)
上面分别创建了JIRA的两个任务流程,每个任务流程的每个按钮都分别有个唯一的key值,通过jira点击相应的按钮,通过唯一的key可以触发jenkins的脚本进行唯一的构建。
以版本任务进行阐释:
JQL filter:指定触发对象,project=WUZ指的是jira中项目关键字为WUZ的项目,JQLfilter 包括:project、issue等
Comment pattern:jira备注中的comment,当用户在jira中添加指定备注时,会触发jenkins构建
Jenkins parameter:jenkins中的参数名称
Issue attribute path:jira issue中提取出得需要传给jenkins的属性值
注:JIRA filed ID 和 Custom Field ID 可通过http://120.79.168.18:20000/rest/api/2/field 地址查询
5、最后,只要修改jira的任务状态,就会触发jenkins自动构建,如图:
五、jenkins shell脚本编写
现在jira集成了jenkins,通过触发jira的button实现jenkins的自动构建,那么如果我们同时开发和部署多个项目,又该如何处理呢?
所以为了做到拓展性,我们直接通过shell脚本编写(重点讲解从检出代码到打包部署的过程)。
5.1、项目检出
可以根据JIRA上对应的不同项目名去检出对应的项目。
# git 检出任务分支
function check_out_code(){
code_path=$1
fixVersionName=$2
echo "fixVersionName:${fixVersionName}"
git clone http://$jenkins_name:$jenkins_password@gitlab.youxinsign.com/two/${project_name}.git $CLONE_ADDRESS
git clone http://$jenkins_name:$jenkins_password@gitlab.youxinsign.com/two/${msf_project_name}.git $MSF_CLONE_ADDRESS
if [ ! -d ${git_check_out_code_path} ];
then
echo "项目还没被检出"
git init
git checkout -b ${fixVersionName}
else
echo "项目已经被检出"
cd ${git_check_out_code_path}
#用代码库中的文件完全覆盖本地工作版本
existing_branch=`git branch -a`
echo "远程仓库存在的分支:${existing_branch}"
for(( i=0;i<${#existing_branch[@]};i++)) do
brachName=$(echo \"${existing_branch[i]}\" |sed 's/\"//g')
if [[ $brachName =~ ${fixVersionName} ]]
then
echo "更新分支:${fixVersionName}"
git reset --hard
git pull origin ${fixVersionName}
fi
done;
fi
}
5.2、项目构建
构建可以按模块构建,也可以构建整个项目
# gradle按照模块的构建,根据不同的模块进行模块构建
function get_deployed_module()
{
if [[ ${module_code} = "ADMIN" ]]
then
deployed_module='bee-core:bee_admin'
fi
if [[ ${module_code} = "CLIENT" ]]
then
deployed_module='bee-core:bee_client'
fi
if [[ ${module_code} = "API" ]]
then
deployed_module='bee-core:bee_api'
fi
if [[ ${module_code} = "TSK" ]]
then
deployed_module='bee-core:bee_taskserver'
fi
if [[ ${module_code} = "MSG" ]]
then
deployed_module='bee-core:bee_message'
fi
if [[ ${module_code} = "ORGAN" ]]
then
deployed_module='bee-core:bee_organ'
fi
if [[ ${module_code} = "ACT" ]]
then
deployed_module='bee-act:bee-act-admin'
fi
}
# gradle构建整个项目
function mvn_build()
{
cd ${build_based_path}
if [[ ${module_code} = "ALL" ]]
then
gradle clean
gradle bootRepackage
else
gradle :${deployed_module}:clean
gradle :${deployed_module}:bootRepackage
fi
echo -e "============Gradle构建完成=============="
}
5.3、项目部署
由于模块较多,现在就举例说明后台管理模块的部署。具体流程
1、kill -9 admin_pid
2、拷贝admin jar包到部署路径。
3、开启admin文件自动在服务器上传输(如果jenkins和jar包不在同一个服务器上则需要改流程)。
4、运行部署命令进行项目部署。
5、将部署成功的状态反馈到JIRA日志信息
#部署admin 模块
function deploy_admin_module()
{
jira_button_code=$1
echo -e "============开启自动化部署admin!=============="
#admin_pid=`ps -ef | grep ${admin_deploy_path}/${admin_archive_name} | grep -v grep | awk '{print $2}'`
admin_pid=$(ssh -p 5000 root@132.124.2.10"ps -ef | grep ${admin_deploy_path}/${admin_archive_name} | grep -v grep | awk '{print $2}'"| awk '{print $2}')
if [ -n "$admin_pid" ]
then
echo "admin_pid="$admin_pid
ssh -p 5000 root@132.124.2.10 "kill -9 ${admin_pid}"
fi
echo "开始拷贝admin jar包到部署路径..."
cp -f ${git_check_out_code_path}/src/${projectName}/${common_module}/${admin_module}/build/libs/${admin_archive_name} ${deploy_path}/${admin_module}
echo "开始启动程序..."
export BUILD_ID=dontKillMe
#sleep 30s
echo "开启admin文件自动在服务器上传输."
scp_put 132.124.2.10 root '*******&' ${deploy_path}/${admin_module} ${deploy_path}
if [ ${jira_button_code} = "B471" ];
then
excute "/usr/bin/nohup nohup java -jar ${admin_deploy_path}/${admin_archive_name} --spring.cloud.config.profile=master --spring.cloud.config.profile=master --spring.application.name=${admin_spring_application_name} --server.port=${admin_port} --eureka.client.service-url.defaultZone=http://${register_center_ip_adress}:${port}/eureka -Xms64m -Xmx512m -XX:MaxMetaspaceSize=512m -XX:CompressedClassSpaceSize=64m -Xss256k -Xmn8m -XX:InitialCodeCacheSize=4m -XX:ReservedCodeCacheSize=8m -XX:MaxDirectMemorySize=16m >/dev/null 2>&1 &"
else
excute "/usr/bin/nohup nohup java -jar ${admin_deploy_path}/${admin_archive_name} --spring.cloud.config.profile=dev --spring.cloud.config.profile=dev --spring.application.name=${admin_spring_application_name} --server.port=${admin_port} --eureka.client.service-url.defaultZone=http://${register_center_ip_adress}:${port}/eureka -Xms64m -Xmx512m -XX:MaxMetaspaceSize=512m -XX:CompressedClassSpaceSize=64m -Xss256k -Xmn8m -XX:InitialCodeCacheSize=4m -XX:ReservedCodeCacheSize=8m -XX:MaxDirectMemorySize=16m >/dev/null 2>&1 &"
fi
echo -e "============自动化部署admin成功!============"
echo -e '\n\n'
}
function get_rest_web_api_login()
{
echo "开始登录JIRA账户"
curl -c cookie.txt -d "os_username="${os_username}"&os_password="${os_password} -v ${login_api_uri}
cd ${cookie_file_path}
cookieContents=`cat ${cookie_file_path}/cookie.txt | awk -F "[JSESSIONID]" '/JSESSIONID/{print$0}'`
cookieContentsCutOut=$(echo $cookieContents | cut -d '/' -f 2)
JSESSIONID_STRING=$(echo ${cookieContentsCutOut} |tr -d " ")
JSESSIONID=${JSESSIONID_STRING:16}
echo "开始获取登录后的JSESSIONID"
echo "cookie文件中包含jSessionId的内容为:::::${cookieContents}"
echo "JIRA账户登录后的JSESSIONID的值为:::::${JSESSIONID}"
}
function get_jira_login_status()
{
echo "开始判断登录状态是否失效"
login_status_log=`curl --cookie JSESSIONID=${JSESSIONID} ${login_api_uri}`
echo "登录状态信息为....${login_status_log}"
if [[ ${login_status_log} =~ "errorMessages" ]]
then
echo "JIRA还未登录,开始登录"
curl -c cookie.txt -d "os_username="${os_username}"&os_password="${os_password} -v ${login_api_uri}
cd ${cookie_file_path}
cookieContents=`cat ${cookie_file_path}/cookie.txt | awk -F "[JSESSIONID]" '/JSESSIONID/{print$0}'`
cookieContentsCutOut=$(echo $cookieContents | cut -d '/' -f 2)
JSESSIONID_STRING=$(echo ${cookieContentsCutOut} |tr -d " ")
JSESSIONID=${JSESSIONID_STRING:16}
else
echo "JIRA已经登录"
fi
}
function add_post_build_comments()
{
commentCotents=$1
echo "JIRA_ISSUE_KEY[$JIRA_ISSUE_KEY]..."
echo "开始增加构建后的JIRA日志信息"
echo "add_post_build_comments参数:"$commentCotents
add_post_build_comments_status_result=`curl --cookie JSESSIONID=${JSESSIONID} --request POST --data '{"body": "'${commentCotents}'"}' --header 'Accept: application/json' --header 'Content-Type: application/json' ${issue_api_uri}/${JIRA_ISSUE_KEY}/comment`
echo "版本分支创建的结果:${add_post_build_comments_status_result}"
if [[ ${add_post_build_comments_status_result} =~ "errorMessages" ]]
then
echo "JIRA 版本分支构建JIRA日志信息增加失败"
else
echo "JIRA 版本分支构建JIRA日志信息增加成功"
fi
}
除此之前还有一键状态更新,一键代码合并等。
总结:虽然作为后端开发人员可能不太容易,因为脚本你没有运维人员熟悉。但是踏踏实实,一步一个脚印,会让你的知识更加全面。