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
随机推荐
- linux运维、架构之路-Kubernetes集群部署
一.kubernetes介绍 Kubernetes简称K8s,它是一个全新的基于容器技术的分布式架构领先方案.Kubernetes(k8s)是Google开源的容器集群管理系统(谷歌内部 ...
- 面试题常考&必考之--js中的call()和apply()
apply: 接受两个参数,第一个参数是要绑定给this的值,第二个参数是一个参数数组.当第一个参数为null.undefined的时候,默认指向window. call: 第一个参数是要绑定给thi ...
- 微信小程序支付功能讲解
前言:虽然小程序做过很多,但是一直觉得微信支付功能很是神秘,现在终于有机会接触心里还是有点小激动的,经过一番折腾发现支付也不过如此,在此记录下支付功能的实现过程 小程序的官方文档介绍到发起微信支付即调 ...
- 【bzoj3162】独钓寒江雪
*题目描述: *题解: 树哈希+组合数学.对于树的形态相同的子树就一起考虑. *代码: #include <cstdio> #include <cstring> #includ ...
- python list 插入元素
https://www.jb51.net/article/57923.htm List 是 Python 中常用的数据类型,它一个有序集合,即其中的元素始终保持着初始时的定义的顺序(除非你对它们进行排 ...
- sh_06_个人信息
sh_06_个人信息 """ 姓名:小明 年龄:18 岁 性别:是男生 身高:1.75 米 体重:75.0 公斤 """ # 在 Pytho ...
- jq和js用法:入口写法
jq和js入口写法demo: <!DOCTYPE html> <html lang="en"> <head> <meta charset= ...
- 我的"开发工具箱"
我使用的IDEA插件 Free Mybatis plugin Alibaba Java Coding Guidelines 我的IDEA开发配置 配置Maven Runner -DarchetypeC ...
- daemon(守护、服务员)-t1.setDaemon(true) - 设置为守护线程
daemon(守护.服务员)t1.setDaemon(true) - 设置为守护线程 class KTV extends Thread{ public void run(){ try { Thread ...
- GMM demo
# GMM model # // library(mvtnorm) ) n1 = n2 = mu1 = c(,) mu2 = c(-,-) sigma1 = matrix(c(,.,.,),nrow= ...