jenkins使用记录转自https://my.oschina.net/sanpeterguo/blog/197931
【背景】:部门在搞持续集成,使用jenkins作为核心调度,要再其基础上进行二次封装,所以需要研究下jenkins的api。笔者主要负责搭建平台,在研究用法也花费了些时间,本文主要做个简要的记录,希望能为各位朋友节省时间。
【环境】:(默认读者已经具备了基本的持续集成经验和jenkins用法)
2. 系统Suse
3. Tomcat 6.0.37
4. Java 1.6.0_26
【API介绍】
Jenkins提供了html、json、python API,实质都是以http get/post方式调用的。查看http://www.xxx.xxx/jenkins/api/ 即可得到相应的说明,如图:
【API实践】
1.创建
curl -X POST http://www.xxx.xxx/jenkins/createItem?name=JavaStd --user peterguo:peterguo --data-binary "@javastd.config.xml" -H "Content-Type: text/xml"
2.禁用
curl -X POST http://www.xxx.xxx/jenkins/job/JavaStd/disable --user peterguo:peterguo
3.启用
curl -X POST http://www.xxx.xxx/jenkins/job/JavaStd/enable --user peterguo:peterguo
4.删除
curl -X POST http://www.xxx.xxx/jenkins/job/JavaStd/doDelete --user peterguo:peterguo
5.获取项目描述
curl -X GET http://www.xxx.xxx/jenkins/job/JavaStd/description --user peterguo:peterguo
6.获取配置文件
curl -X GET http://www.xxx.xxx/jenkins/job/JavaStd/config.xml --user peterguo:peterguo
7.触发SCM检查
curl -X GET http://www.xxx.xxx/jenkins/job/JavaStd/polling --user peterguo:peterguo
8.普通触发
curl -X GET http://www.xxx.xxx/jenkins/job/JavaStd/build --user peterguo:peterguo
9.带参数触发
curl -X GET "http://www.xxx.xxx/jenkins/job/helloworld-freestyle/buildWithParameters?bAllTest=&Choices=2&strParam=abc" --user peterguo:peterguo
10.带文件触发
curl -X POST "http://localhost:8080/job/Demo/buildWithParameters?assertMethod=online" -F "input=@atest.txt"
11.参数和补丁触发
curl -X POST "http://www.xxx.xxx/jenkins/job/helloworld-freestyle/buildWithParameters?bAllTest=&Choices=2&strParam=abc" --user peterguo:peterguo -F "action=upload" -F "patch.diff=@OtherTest.java.patch"
注:带补丁触发需要先安装补丁插件,并设置项目的补丁参数
【通过Python-curl库调用】
提供python使用pycurl调用的例子片段,实际和curl调用一样,优点是易整合。
import pycurl
url = "http://10.129.145.112:8081/jenkins/job/helloworld-freestyle/config.xml"
crl = pycurl.Curl()
crl.setopt(pycurl.VERBOSE,1)
crl.setopt(pycurl.FOLLOWLOCATION, 1)
crl.setopt(pycurl.MAXREDIRS, 5)
crl.setopt(pycurl.USERPWD, "peterguo:peterguo") crl.setopt(pycurl.CONNECTTIMEOUT, 60)
crl.setopt(pycurl.TIMEOUT, 300)
crl.setopt(pycurl.HTTPPROXYTUNNEL,1)
crl.fp = StringIO.StringIO() crl.setopt(pycurl.URL, url)
crl.setopt(crl.WRITEFUNCTION, crl.fp.write)
crl.perform()
ret = crl.fp.getvalue()
【通过Python-jenkinsapi库调用】
这里给出代码
from jenkinsapi.jenkins import Jenkins class CJenkinsAPI():
'''
均采用同步设置超时机制
创建项目:输入:configid planid
创建任务:输入:configid planid 返回:返回码 msg buildid 额外动作:不写SQL
查询任务:输入:configid planid taskid 返回:返回码 msg buildid 额外动作:结束更新SQL(包括成功或失败),未结束则不处理
终止任务:输入:configid planid taskid 返回:返回码 msg buildid 额外动作:终止成功写SQL '''
__doc__ = '''Usage: \t\tCJenkinsAPI.createProject\t\tCJenkinsAPI.triggerBuild\t\t''' _strConfigTemplatePath = ""
_strConfigDataPath = "" def __init__(self):
import pycurl
pass def __del__(self):
pass @staticmethod
def createProject(nPlanId, strConfigId):
'''
Return:返回码/返回信息
先根据配置文件生成项目
'''
#用于测试
nPlanId = 14
strConfigId = "D1057406" #返回
nRet, strMsg, nBuild = 0, "", 0 #配置文件模版
strConfigTemplate = CJenkinsAPI._strConfigTemplatePath + "/config.template.xml" #用planID和配置ID作为项目名
strProjectName = "P%d-%s" % (nPlanId, strConfigId ) #访问数据库拿到构建节点IP和SVN
strBuildNodeIP = ""
strProjectSVN = "" oProxy = CSqlProxy("10.129.145.112", "ci_test", "ci_test", "ci_plat")
#SVN从t_build_plan中取
lSelectRet = CSqlProxy.selectFromTable(oProxy.m_oCon, "t_build_plan", ["f_svn"], " where f_plan_id='%d' " % nPlanId)
strProjectSVN = lSelectRet[0]["f_svn"]
#配置信息从t_ci_config中取
lSelectRet = CSqlProxy.selectFromTable(oProxy.m_oCon, "t_ci_config", ["f_node_ip", "f_run_param"], " where f_config_id='%s' " % strConfigId)
strBuildNodeIP = lSelectRet[0]["f_node_ip"]
strRunParam = lSelectRet[0]["f_run_param"]
oProxy.close() strNodeFlag = {True:"", False:"slave_"}["10.129.145.112" in strBuildNodeIP]
dReplaceInfo = {"PROJ_DESC" : "This is generate by Ci-plat, with plan_id[%d] and config_id[%s]" % (nPlanId, strConfigId),\
"SVN_URL" : strProjectSVN.replace("http://tc-svn.tencent.com", "svn://172.27.198.49:8081"),\
"BUILD_NODE_IP" : strNodeFlag + strBuildNodeIP,\
"BUILD_SCRIPT" : '''sh build.sh %s ''' % strRunParam, \
"JUNIT_TEST_PATH" :"target/surefire-reports/*.xml", \
"COVERAGE_PATH" :"target/site/cobertura/", \
} #利用模版生成配置文件
oConf = CCiConfig(strConfigTemplate, dReplaceInfo)
strCurConfigXml = CJenkinsAPI._strConfigDataPath + "/" + strProjectName + ".config.xml"
oConf.dump2file(strCurConfigXml) strCommand = 'curl -X POST http://10.129.145.112:8081/jenkins/createItem?name=%s --user peterguo:peterguo --data-binary "@%s" -H "Content-Type: text/xml"' % (strProjectName, strCurConfigXml)
nRet = os.system(strCommand)
strMsg = {True:"SucceedCreate,Url:", False:"FailedCreate,Url:"}[nRet==0]
print "%d|%s|%d" % (nRet, tran2UTF8(strMsg)+"[http://10.129.145.112:8081/jenkins/job/%s]" % strProjectName, nBuild) @staticmethod
def triggerBuild(nPlanId, strConfigId):
'''
Return:
触发前先更新配置文件,使用远程脚本
触发前获取要出发的编号
'''
#返回
nRet, strMsg, nBuild = 0, "", 0 #配置文件模版
strConfigTemplate = CJenkinsAPI._strConfigTemplatePath + "/config.template.xml" #用planID和配置ID作为项目名
strProjectName = "P%d-%s" % (nPlanId, strConfigId ) #访问数据库拿到构建节点IP和SVN
strBuildNodeIP = ""
strProjectSVN = "" oProxy = CSqlProxy("10.129.145.112", "ci_test", "ci_test", "ci_plat")
#SVN从t_build_plan中取
lSelectRet = CSqlProxy.selectFromTable(oProxy.m_oCon, "t_build_plan", ["f_svn"], " where f_plan_id='%d' " % nPlanId)
strProjectSVN = lSelectRet[0]["f_svn"]
#配置信息从t_ci_config中取
lSelectRet = CSqlProxy.selectFromTable(oProxy.m_oCon, "t_ci_config", ["f_node_ip", "f_run_param"], " where f_config_id='%s' " % strConfigId)
strBuildNodeIP = lSelectRet[0]["f_node_ip"]
strRunParam = lSelectRet[0]["f_run_param"]
oProxy.close() strNodeFlag = {True:"", False:"slave_"}["10.129.145.112" in strBuildNodeIP]
dReplaceInfo = {"PROJ_DESC" : "This is generate by Ci-plat, with plan_id[%d] and config_id[%s]" % (nPlanId, strConfigId),\
"SVN_URL" : strProjectSVN.replace("http://tc-svn.tencent.com", "svn://172.27.198.49:8081"),\
"BUILD_NODE_IP" : strNodeFlag + strBuildNodeIP,\
"BUILD_SCRIPT" : '''sh build.sh %s ''' % strRunParam, \
"JUNIT_TEST_PATH" :"target/surefire-reports/*.xml", \
"COVERAGE_PATH" :"target/site/cobertura/", \
} #利用模版生成配置文件
oConf = CCiConfig(strConfigTemplate, dReplaceInfo)
strCurConfigXml = CJenkinsAPI._strConfigDataPath + "/" + strProjectName + ".config.xml"
oConf.dump2file(strCurConfigXml) #更新配置文件
strCommand = 'curl -X POST http://10.129.145.112:8081/jenkins/job/%s/config.xml --user peterguo:peterguo --data-binary "@%s" -H "Content-Type: text/xml"' % (strProjectName, strCurConfigXml)
nRet = os.system(strCommand)
strMsg += {True:"更新配置成功", False:"更新配置失败"}[nRet==0] #获取下一次构建编号
nBuild = Jenkins("http://10.129.145.112:8081/jenkins","peterguo","peterguo")[strProjectName.encode("utf8")].get_next_build_number() #触发构建
strCommand = 'curl -X POST http://10.129.145.112:8081/jenkins/job/%s/build --user peterguo:peterguo ' % (strProjectName)
nRet = os.system(strCommand)
strMsg = {True:"SucceedTrigger,Url:", False:"FailedTrigger,Url:"}[nRet==0]
print "%d|%s|%d" % (nRet, tran2UTF8(strMsg)+"[http://10.129.145.112:8081/jenkins/job/%s/%d]" % (strProjectName, nBuild), nBuild ) @staticmethod
def infoBuild(nPlanId, strConfigId, nTaskId):
'''
Return:
'''
strProjectName = "P%d-%s" % (nPlanId, strConfigId )
oProxy = CSqlProxy("10.129.145.112", "ci_test", "ci_test", "ci_plat")
strWhere = " where f_task_id='%d' " % int(nTaskId)
lSelectRet = CSqlProxy.selectFromTable(oProxy.m_oCon, "t_build_task", ["f_build_id"], strWhere)
oProxy.close()
nBuildId = int(lSelectRet[0]["f_build_id"]) oCurBuild = Jenkins("http://10.129.145.112:8081/jenkins","peterguo","peterguo")[strProjectName.encode("utf8")].get_build(nBuildId)
bRunning = oCurBuild.is_running()
if bRunning == True:
print "1|Running|%d" % nBuildId
return #最重要更新的数据
dResult2Sql = {} #取测试用例结果的个数信息
if oCurBuild.has_resultset():
dResult = oCurBuild.get_actions()
else:
dResult = {"failCount":0, "totalCount":0, "skipCount":0} oDeltaDur = oCurBuild.get_duration()
oBuildBegin = utc2LocalDatetime(oCurBuild.get_timestamp())
oBuildEnd = oBuildBegin + oDeltaDur
dResult2Sql["f_case_fail"] = dResult['failCount']
dResult2Sql["f_case_total"] = dResult['totalCount']
dResult2Sql["f_case_skip"] = dResult['skipCount']
dResult2Sql["f_build_duration"] = "%.3f" % (oDeltaDur.days * 24 * 60 + oDeltaDur.seconds / 60.0)
dResult2Sql["f_build_url"] = oCurBuild.baseurl
dResult2Sql["f_build_result"] = {True:0, False:1}[oCurBuild.is_good()]
dResult2Sql["f_task_status"] = TASK_DONE
dResult2Sql["f_build_time"] = oBuildBegin.strftime("%Y-%m-%d %H:%M:%S")
dResult2Sql["f_build_end"] = oBuildEnd.strftime("%Y-%m-%d %H:%M:%S")
dResult2Sql["f_msg_info"] = tran2GBK("任务完成,收集数据完成") #任务已经完成,需要入库相关数据,更新相关状态
oProxy = CSqlProxy("10.129.145.112", "ci_test", "ci_test", "ci_plat")
strWhere = " where f_task_id='%d' " % int(nTaskId)
CSqlProxy.updateValueToDBTable(oProxy.m_oCon, "t_build_task", dResult2Sql.keys(), dResult2Sql.values(), strWhere)
oProxy.close()
#for item in dResult2Sql.items():
# print item[0], str(item[1])
print "%d|%s|%d" % (0, "SucceedUpdated", nBuildId) @staticmethod
def stopBuild(nPlanId, strConfigId, nTaskId):
'''
Return:
'''
strProjectName = "P%d-%s" % (nPlanId, strConfigId )
oProxy = CSqlProxy("10.129.145.112", "ci_test", "ci_test", "ci_plat")
strWhere = " where f_task_id='%d' " % int(nTaskId)
lSelectRet = CSqlProxy.selectFromTable(oProxy.m_oCon, "t_build_task", ["f_build_id"], strWhere)
oProxy.close()
nBuildId = int(lSelectRet[0]["f_build_id"]) oCurBuild = Jenkins("http://10.129.145.112:8081/jenkins","peterguo","peterguo")[strProjectName.encode("utf8")].get_build(nBuildId)
bRunning = oCurBuild.is_running()
if bRunning == False:
print "2|AlreadyStopped|%d" % nBuildId
return #触发停止命令
oCurBuild.stop() #等停止
oCurBuild.block_until_complete() #最重要更新的数据
dResult2Sql = {} #取测试用例结果的个数信息
if oCurBuild.has_resultset():
dResult = oCurBuild.get_actions()
else:
dResult = {"failCount":0, "totalCount":0, "skipCount":0} oDeltaDur = oCurBuild.get_duration()
oBuildBegin = utc2LocalDatetime(oCurBuild.get_timestamp())
oBuildEnd = oBuildBegin + oDeltaDur
dResult2Sql["f_case_fail"] = dResult['failCount']
dResult2Sql["f_case_total"] = dResult['totalCount']
dResult2Sql["f_case_skip"] = dResult['skipCount']
dResult2Sql["f_build_duration"] = "%.3f" % (oDeltaDur.days * 24 * 60 + oDeltaDur.seconds / 60.0)
dResult2Sql["f_build_url"] = oCurBuild.baseurl
dResult2Sql["f_build_result"] = {True:0, False:1}[oCurBuild.is_good()]
dResult2Sql["f_task_status"] = TASK_ABORTED
dResult2Sql["f_build_time"] = oBuildBegin.strftime("%Y-%m-%d %H:%M:%S")
dResult2Sql["f_build_end"] = oBuildEnd.strftime("%Y-%m-%d %H:%M:%S")
dResult2Sql["f_msg_info"] = tran2GBK("TaskStopped") #任务已经完成,需要入库相关数据,更新相关状态
oProxy = CSqlProxy("10.129.145.112", "ci_test", "ci_test", "ci_plat")
strWhere = " where f_task_id='%d' " % int(nTaskId)
CSqlProxy.updateValueToDBTable(oProxy.m_oCon, "t_build_task", dResult2Sql.keys(), dResult2Sql.values(), strWhere)
oProxy.close()
#for item in dResult2Sql.items():
# print item[0], str(item[1]) print "%d|%s|%d" % (1, tran2UTF8("SucceedStopped"), nBuildId) @staticmethod
def deleteProject(nPlanId, strConfigId):
'''
Return:返回码/返回信息 curl -X POST http://10.129.145.112:8081/jenkins/job/JavaStd/doDelete --user peterguo:peterguo
'''
strProjectName = "P%d-%s" % (nPlanId, strConfigId )
strCommand = 'curl -X POST http://10.129.145.112:8081/jenkins/job/%s/doDelete --user peterguo:peterguo' % (strProjectName)
CColorPrint.colorPrintStr("CMD:[%s]" % strCommand, "green") nRet = os.system(strCommand)
strMsg = {True:"SucceedDeleted", False:"FailedDeleted"}[nRet==0]
print nRet, tran2UTF8(strMsg), 0
jenkins使用记录转自https://my.oschina.net/sanpeterguo/blog/197931的更多相关文章
- selenium定位元素(本内容从https://my.oschina.net/flashsword/blog/147334处转载)
注明:本内容从https://my.oschina.net/flashsword/blog/147334处转载. 在使用selenium webdriver进行元素定位时,通常使用findElemen ...
- https://my.oschina.net/huangyong/blog/161419
https://my.oschina.net/huangyong/blog/161419
- https://my.oschina.net/reesechou/blog/492265
https://my.oschina.net/reesechou/blog/492265
- Echarts 的 Java 封装类库 转自 https://my.oschina.net/flags/blog/316920
转自: https://my.oschina.net/flags/blog/316920 Echarts 的 Java 封装类库:http://www.oschina.net/p/echarts-ja ...
- linux svn 中文 https://my.oschina.net/VASKS/blog/659236
https://my.oschina.net/VASKS/blog/659236 设置服务器: export LC_ALL=zh_CN.UTF-8长久之计, echo export LC_ALL=zh ...
- python和scrapy的安装【转:https://my.oschina.net/xtfjt1988/blog/364577】
抓取网站的代码实现很多,如果考虑到抓取下载大量内容scrapy框架无疑是一个很好的工具.Scrapy = Search+Pyton.下面简单列出安装过程.PS:一定要按照Python的版本下载,要不然 ...
- c3p0的几种使用方式(原文地址: https://my.oschina.net/liangtee/blog/101047)
package com.c3p0.test; import java.sql.Connection; import java.sql.SQLException; import java.beans.P ...
- python学习笔记之读取配置文件【转自https://my.oschina.net/u/3041656/blog/793467】
[转自https://my.oschina.net/u/3041656/blog/793467] 最近在接触利用python来写测试框架,本人也是个刚接触python,所以是个小菜鸟,今天开始,一点点 ...
- https://www.oschina.net/project/lang/19/java
https://www.oschina.net/project/lang/19/java
随机推荐
- echart--如何将echart的配置项,放到webpack中(CHARTTEMPLATE时)
1.假如,我们已经写好了组件,我们需要把它放入到一个环境中去 2.首先在index.html中,我们需要写一个dom结构 3.新建一个,chart.js文件(这个里面放组件的代码) 1>开始创建 ...
- 863D - Yet Another Array Queries Problem(思维)
原题连接:http://codeforces.com/problemset/problem/863/D 题意:对a数列有两种操作: 1 l r ,[l, r] 区间的数字滚动,即a[i+1]=a[i] ...
- fengmiantu3
- Flask中的实例化配置
也就是在app=Flask(__name__)括号中的参数 1.static_folder = 'static', # 静态文件目录的路径 默认当前项目中的static目录 2.static_url_ ...
- Flask中的路由配置
在Flask中也同样有django中的路由配置只不过没有djngo那么严格主要的参数有一下六个记住常用的就可以了 1.endpoint 反向生成url地址标志,默认视图函数名 2.methods ...
- Delphi XE2 之 FireMonkey 入门(11) - 控件居中、旋转、透明
RotationAngle.RotationCenter.Opacity 属性继承自 TControl(FMX.Types), 这些新属性成了控件的基本功能. 先在 HD 窗体上添加 TRectang ...
- 阶段1 语言基础+高级_1-3-Java语言高级_04-集合_06 Set集合_1_HashSet集合介绍
特点:不允许有重复的记录,无序的集合 set不允许重复.接口中没有索引.所以方法和Collection中的方法是一样的,没有带索引的方法 因为Set的方法和Collection都是一样的.所以这里不再 ...
- Prometheus Alertmanager Grafana 监控警报
Prometheus Alertmanager Grafana 监控警报 #node-exporter, Linux系统信息采集组件 #prometheus , 抓取.储存监控数据,供查询指标 #al ...
- SoapUI乱码问题处理方法
前言 每个工具都会有一些意想不到的“坑”,SoapUI也不例外.无论是参数或者响应报文,大家可能都遇到过乱码问题,这里记录一下几种解决乱码的方法. 一.修改显示字体 在File>>> ...
- Python解决ModuleNotFoundError: No module named 'Queue'的问题
我们知道Python2和Python3两个版本之间,有些不兼容的地方,Python3中引入Queue会报出这个问题. Python3中要这样引入: import queue Python2中要这样引入 ...