Jenkins任务:创建任务发布新的war包-war_release

综述:本文将介绍如何在Jenkins上创建和运行发布新的war包的任务,主要包括:“新建Jenkins任务”、“选择构建一个maven项目,输入任务名”、“配置任务”、“运行Jenkins任务”、“查看运行日志”。

正文:

1、新建Jenkins任务

2、选择构建一个maven项目,输入任务名

3、配置任务

(1)源码管理

选择Subversion,Repository URL填写$CURRENT_ReleaseUrlSVNNbr,Credentials填写登录svn的账号密码

Check-out Strategy选择Use 'svn update' as much as posible,with 'svn revert' before update

(2)构建触发器

勾选Build whenever a SNAPSHOT dependency is built 

(3)构建环境

不用选择

(4)Pre Steps

选择Execute Windows batch command

批处理命令填写

SET CURRENT_JenkinsTask=war_release

call D:\BXERP\trunk\src\jenkins\war_release\war_release_preBuildSteps.py

call D:\BXERP\trunk\src\jenkins\Common\updateConfig.py

exit 0

设置了当前任务名为war_release,调用了war_release_preBuildSteps.py

主要的逻辑:1、检查准备好的发布新版本的文件夹是否有pre_steps.bat,如果有则执行2、检查文件夹的release.sql文件是否准备好3、关闭tomcat 4、备份数据库5、执行准备好的sql命令release.sql 6、修改login.jsp文件里的版本号7、关闭QueenService服务,修改helper.properties中的SVN版本号,然后重启QueenService

代码如下

war_release_preBuildSteps.py

# coding=utf-8

"""

case1: release成功

case2: release失败>重新release(特别注意:如果release失败需要rollback时,sql使用此次备份成功的sql文件,war包拿上一次release成功的war包进行rollback)

case3: 之前有无成功release(目前保证每次release的文件夹都是成功的,故可略过该case)

case4: 之前有无release过(暂不考虑该case)

"""




import time

import os

import subprocess

# 引用自定义的模块

import sys

sys.path.append('D:/BXERP/trunk/src/jenkins/Common')       #引用的自定义模块不与该python文件在同一目录时,需要指定路径

from bxUtility import printInfo

from bxUtility import closeTomcat

from bxUtility import replaceLine




# 需要从jenkins的环境变量读取的参数:文件夹路径、现使用场、版本号

CURRENT_ReleaseNO = os.getenv("CURRENT_ReleaseNO")  #示例:CURRENT_ReleaseNO=00004_v1_0_r691_r691

CURRENT_Env = os.getenv("CURRENT_Env")

CURRENT_ReleaseNbrVersionNO = os.getenv("CURRENT_ReleaseNbrVersionNO")

# 此次release放置输出文件的总路径

CURRENT_ReleasePath = 'D:/Release/' + CURRENT_ReleaseNO

# DB备份的文件夹路径

CURRENT_DbBackupPath = CURRENT_ReleasePath + '/backup'

# DB的备份

CURRENT_Time = time.strftime('%Y%m%d%H%M%S', time.localtime(time.time()))

DB_BackupFile = CURRENT_DbBackupPath + '/' + CURRENT_Time + '.sql'

# 要执行的BAT文件

PATH_BatToRelease = 'D:/BXERP/trunk/release/' + CURRENT_ReleaseNO + '/BAT/pre_steps.bat'

# 要Release的SQL文件

PATH_SqlToRelease = 'D:/BXERP/trunk/release/' + CURRENT_ReleaseNO + '/' + CURRENT_Env + '/release'

FILE_SqlToRelease = PATH_SqlToRelease + '/release.sql'

# 找不到release.sql时的特殊提示

errTag = '~~~~~~XXXXXXXX~~~~~~~~~~~~~XXXX~~~~~~~~~~XXXX~~~~~~~~~';

# 要修改的login.jsp的路径

FILE_LoginJsp = "D:/Jenkins/workspace/war_release/src/main/webapp/WEB-INF/admin/login.jsp"

# 要修改的QueenService的helper.properties的路径

FILE_HelperProperties = "D:/QueenService/Bin/helper.properties"




def dbBackup():

         """

         备份db(sql)

         """

         os.system('cd D:/wamp/bin/mysql/mysql5.6.17/bin')

         (errCode, errMsg) = subprocess.getstatusoutput('mysqldump --no-defaults --login-path=root --default-character-set=gb2312 -R --hex-blob -A>' + DB_BackupFile)

         print ('备份DB的错误码=' + str(errCode));

         print ('备份DB的错误信息=' + str(errMsg));

         if (errCode == 0):

                   printInfo('备份DB成功!', 0)

         else:

                   printInfo ('备份DB失败!' + errTag, errCode)




try:

         # 检查要执行

         if os.path.exists(PATH_BatToRelease):       

                   printInfo('pre_steps.bat文件存在,正在执行...', 0)

                   os.system(PATH_BatToRelease)

                   printInfo('pre_steps.bat文件存在,执行完毕', 0)

         else:

                   printInfo('pre_steps.bat文件不存在,将不执行此文件', 0)

        

         # 检查release.sql是否已准备好

         if os.path.exists(PATH_SqlToRelease):

                   Files = os.listdir(PATH_SqlToRelease)

                   if 'release.sql' in Files:

                            printInfo('release.sql文件存在。', 0)

                   else:

                            printInfo('release.sql文件不存在,这将令Release只会更新WAR,这极可能是错误的。' + errTag, 5)

         else:

                   printInfo(PATH_SqlToRelease + '路径不存在!' + errTag, 5)

        

         # 关闭tomcat

         closeTomcat(60)  #参数为等待的时间(s),每10秒会检查一次,直到超过等待的时间

        

         # 备份DB

         print ('正在建立数据库备份...');

         if os.path.exists(CURRENT_ReleasePath):

                   Files = os.listdir(CURRENT_DbBackupPath)

                   for i in range(len(Files)):

                            suffixName = os.path.splitext(Files[i])[1]

                            print('suffixName:' + suffixName);

                            if '.sql' == suffixName:

                                     fileName = os.path.basename(Files[i]);

                                     print('重命名fileName:' + fileName);

                                     os.rename(CURRENT_DbBackupPath + '/' + fileName, CURRENT_DbBackupPath + '/' + fileName + '.BuildFailed');

                   dbBackup()

         else:

                   os.makedirs(CURRENT_DbBackupPath)

                   dbBackup()

        

         # 执行准备的release.sql文件

         print ('顺序执行release中的所有SQL文件...');

         print ('当前登录本机的账户是:' + os.getlogin());

         (errCode, errMsg) = subprocess.getstatusoutput('mysql --login-path=root <' + FILE_SqlToRelease)

         print ('执行release.sql的错误码=' + str(errCode));

         print ('执行release.sql的错误信息=' + str(errMsg));

         if (errCode == 0):

                   printInfo('执行release.sql成功!', 0)

         else:

                   printInfo('执行release.sql失败!' + errTag, errCode)




         # update D:/BXERP

         (errCode, errMsg) = subprocess.getstatusoutput('svn update D:/BXERP')

         if (errCode == 0):

                   printInfo('update D:/BXERP成功!', 0)

         else:

                   printInfo('update D:/BXERP失败!' + errTag, errCode)




         # 修改配置文件夹中的login.jsp

         keyword = '<input type="hidden" id="CURRENT_ReleaseNbrVersionNO" value="'

         newLine = '                    <input type="hidden" id="CURRENT_ReleaseNbrVersionNO" value="' + CURRENT_ReleaseNbrVersionNO + '" />' + '\n'

         replaceLine(FILE_LoginJsp, keyword, newLine, "utf-8", 1)

        

         keyword2 = '<h4 style="font-size:15px; line-height:16px; margin-bottom: 15px;">v1.0.0</h4>'

         newLine2 = '<h4 style="font-size:15px; line-height:16px; margin-bottom: 15px;">v' + CURRENT_ReleaseNbrVersionNO + '</h4>' + '\n'

         replaceLine(FILE_LoginJsp, keyword2, newLine2, "utf-8", 1)




         # 关闭QueenService

         (errCode, errMsg) = subprocess.getstatusoutput('net stop QueenService')

         if (errCode == 0):

                   printInfo('关闭QueenService成功!', 0)

         else:

                   printInfo('关闭QueenService失败!' + errTag, errCode)




         # 修改D:\QueenService\Bin\helper.properties中的SVN版本号  CURRENT_ReleaseNO=00004_v1_0_r691_r691

         keyword = 'SvnVersionNO='

         newLine = 'SvnVersionNO=' + CURRENT_ReleaseNO.split('_')[-1].split('r')[-1] + '\n'

         replaceLine(FILE_HelperProperties, keyword, newLine, "utf-8", 1)

        

         # 启动QueenService

         (errCode, errMsg) = subprocess.getstatusoutput('net start QueenService')

         if (errCode == 0):

                   printInfo('启动QueenService成功!', 0)

         else:

                   printInfo('启动QueenService失败!' + errTag, errCode)

except Exception as e:

         printInfo('出现异常:' + str(e), 1)

else:

         os._exit(0)

 

调用的updateConfig.py和common.py可以查看”更新配置文件脚本updateConfig.py”和“”公共脚本common.py”文章

(5)Build

Root POM填写pom.xml,Goals and options 填写clean package -DskipTests

(6)Post Steps

选择Run regardless of build result

选择Execute Windows batch command

批处理命令填写

@echo off

echo 修改前的BUILD_ID=%BUILD_ID%

call D:\BXERP\trunk\src\jenkins\war_release\war_release_postBuildSteps.py

echo 如果不重新设置build id,会导致.py脚本启动的tomcat进程因jenkins build结束而被杀死

SET BUILD_ID='AnotherID'

echo 修改后的BUILD_ID=%BUILD_ID%

调用了war_release_postBuildSteps.py

主要完成的逻辑:1、备份war包 。2、删除tomcat下旧的war包、项目nbr文件夹和Root文件夹。 3复制Jenkins构建出来的war包到tomcat下。 4重启tomcat。5、访问项目首页验证版本号是否正确。6、release成功后压缩配置文件

代码如下

war_release_postBuildSteps.py
 # coding=utf-8




import shutil

import time

import os

import zipfile

import urllib.request

from bs4 import BeautifulSoup

# 引用自定义的模块

import sys

sys.path.append('D:/BXERP/trunk/src/jenkins/Common')       #引用的自定义模块不与该python文件在同一目录时,需要指定路径

from bxUtility import printInfo

from bxUtility import startTomcat




# 需要从jenkins的环境变量读取的参数:release版本号、nbr版本号、nbr登录页网址、现使用场、当前使用的TableCreate源代码文件夹目录(v1.0 or v1.1)

CURRENT_ReleaseNO = os.getenv("CURRENT_ReleaseNO")  #示例:CURRENT_ReleaseNO=00004_v1_0_r691_r691

CURRENT_ReleaseNbrVersionNO = os.getenv("CURRENT_ReleaseNbrVersionNO")

CURRENT_ReleaseNbrHomeUrl = os.getenv("CURRENT_ReleaseNbrHomeUrl")

CURRENT_Env = os.getenv("CURRENT_Env")

CURRENT_SrcDirOfTableCreate = os.getenv("CURRENT_SrcDirOfTableCreate")

# 当前时间,参与war包命名

CURRENT_Time = time.strftime('%Y%m%d%H%M%S', time.localtime(time.time()))

# 此次release放置文件的总路径

CURRENT_ReleasePath = 'D:/Release/' + CURRENT_ReleaseNO

# war备份的文件夹路径

CURRENT_WarBackupPath = CURRENT_ReleasePath + '/backup'

# 当前release出的war包,备份到哪个目录

FILE_WarBackup = CURRENT_WarBackupPath + '/bxb_' + CURRENT_Env + '_' + CURRENT_ReleaseNbrVersionNO + '_' + CURRENT_Time + '.war'

# 相关的操作文件和路径

FILE_WarPath = 'D:/Tomcat/webapps/nbr.war'

FILE_NbrPath = 'D:/Tomcat/webapps/nbr'

FILE_RootPath = 'D:/Tomcat/webapps/ROOT'




try:

         # 备份war包,这里没有判断文件夹是否存在,是因为在war_release_preBuildSteps.py中已经判断了

         print ('正在备份war包...');

         Files = os.listdir(CURRENT_WarBackupPath)

         for i in range(len(Files)):

                   suffixName = os.path.splitext(Files[i])[1]

                   print('suffixName:' + suffixName);

                   if '.war' == suffixName:

                            fileName = os.path.basename(Files[i]);

                            print('重命名fileName:' + fileName);

                            os.rename(CURRENT_WarBackupPath + '/' + fileName, CURRENT_WarBackupPath + '/' + fileName + '.BuildFailed');

         shutil.copy('D:/Jenkins/workspace/war_release/target/nbr.war', FILE_WarBackup)

         printInfo('备份war包完毕。', 0)




         # 删除旧的nbr.war

         print ('正在删除Tomcat下旧的nbr.war...');

         if os.path.exists(FILE_WarPath):

                   os.remove(FILE_WarPath)

                   printInfo('删除Tomcat下旧的nbr.war完毕。', 0)

         else:

                   printInfo('找不到旧war包:' + FILE_WarPath + '。', 0)




         # 删除旧的nbr文件夹

         print ('正在删除Tomcat下旧的nbr文件夹...');

         if os.path.exists(FILE_NbrPath):

                   shutil.rmtree(FILE_NbrPath)

                   printInfo('删除Tomcat下旧的nbr文件夹完毕。', 0)

         else:

                   printInfo('找不到旧nbr文件夹:' + FILE_NbrPath + '。', 0)

        

         # 删除旧ROOT文件夹

         print ('正在删除旧ROOT文件夹...');

         if os.path.exists(FILE_RootPath):

                   shutil.rmtree(FILE_RootPath)

                   printInfo('删除Tomcat下旧的ROOT文件夹成功。', 0)

         else:

                   printInfo('找不到旧ROOT文件夹:' + FILE_RootPath + '。', 0)




         # 复制并移动新构建好的war包

         print ('正在将jenkins构建后的war包复制到Tomcat下...');

         Files = os.listdir(CURRENT_WarBackupPath)

         for i in range(len(Files)):

                   if os.path.splitext(Files[i])[1] == '.war':

                            shutil.copy(CURRENT_WarBackupPath + '/' + os.path.splitext(Files[i])[0] + os.path.splitext(Files[i])[1], FILE_WarPath)

                            printInfo('将jenkins构建后的war包复制到D:/tomcat/webapps/nbr.war成功。', 0)

        

         # 重启tomcat

         startTomcat(300, CURRENT_ReleaseNbrHomeUrl, CURRENT_SrcDirOfTableCreate)




         # 获取页面版本号进行验证

         print ('正在打开nbr网址' + CURRENT_ReleaseNbrHomeUrl + ',获取版本号进行验证...');

         html = urllib.request.urlopen(CURRENT_ReleaseNbrHomeUrl)

         response = html.read()

         response = BeautifulSoup(response, 'html.parser')

         nbrVersionNO = response.find('input', id='CURRENT_ReleaseNbrVersionNO')["value"]

         print ('当前web前端的版本号=' + nbrVersionNO);

         if nbrVersionNO == CURRENT_ReleaseNbrVersionNO:

                   printInfo('网页的版本号与jenkins设置的版本号一致。', 0)

         else:

                   printInfo('网页的版本号与Jenkins设置的版本号不一致。', 3)

        

         # release成功后压缩配置文件

         dirpath = "D:/NbrConfigFile"  # 要压缩的文件夹

         outFullName = CURRENT_WarBackupPath +'/NbrConfigFile.zip'  # 压缩后要放置的文件夹路径

         zip = zipfile.ZipFile(outFullName,"w",zipfile.ZIP_DEFLATED)

         for path,dirnames,filenames in os.walk(dirpath):

                   # 去掉目标跟路径,只对目标文件夹下边的文件及文件夹进行压缩

                   fpath = path.replace(dirpath,'')

                   for filename in filenames:

                            zip.write(os.path.join(path,filename),os.path.join(fpath,filename))

         zip.close()

         printInfo('D:/NbrConfigFile中的配置文件备份成功。', 0)

except Exception as e:

         printInfo('出现异常:' + str(e), 1)

else:

         printInfo('Release成功!', 0)

         os._exit(0)

 

(7)保存,在主页面可以看到刚创建好的任务

4、运行Jenkins任务

点击Build Now按钮开始运行任务

5、查看运行日志

在左下方可以看到运行中的任务,点击”控制台输出”可以查看日志

posted @ 2022-08-29 19:42  Boxin-kim  阅读(519)  评论(0)    收藏  举报
Web Analytics
Guang Zhou Boxin