本文将介绍如何实现 SVN 与 Jenkins 的双向打通,实现 DevOps 价值流的快速流转。
1. 前言
京东研发效能专家石雪峰在其极客时间专栏《DevOps实战笔记》中表明的”对于 DevOps 来说,真正的难点不在于工具本身,而在于如何基于整个研发流程将工具串联打通,把它们结合在一起,发挥出最大的优势。”,对此笔者是非常认同的,因此在基于【DEVOPS】基于Jenkins + Ansible 实现 Windows 环境下自动化打包部署构建部门内部的完整研发运维流水线时,笔者就将工具和平台的打通作为最高优先级的任务。
本文将介绍如何实现作为源代码管理工具的 SVN,以及作为流水线平台的 Jenkins 之间的双向打通,提供一站式解决方案,抛砖引玉。
惯例:为什么不用 GitLab + Jenkins?一言难尽!
2. SVN 向 Jenkins 的打通
按照流水线执行的先后顺序,我们首先讨论 SVN 向 Jenkins 打通的方案。
关于这一步的实现思路,我们最终是借助【DevOps】SVN集成Checkstyle实现代码自动静态检查 和 【DevOps】SVN集成PMD实现代码自动静态检查中使用的SvnChecker来完成这一步操作。具体思路如下:
-
绑定 SVN 服务端的 post-commit 阶段。
-
仿造 SvnChecker 实现 CheckStyle 检查的思路,扩展出相应的 TriggerJenkinsJob.py(脚本放置位置等原理性内容可以参见 【DevOps】SVN集成PMD实现代码自动静态检查 )。
以下列出关键性内容:
1、首先是 SvnChecker 的配置文件svncheckerconfig.ini 。
[Default]
#Separated with comma (",")
Main.PostCommitChecks=TriggerJenkinsJob
# =================================================== TriggerJenkinsJob
#Path of java executable to run Java command
TriggerJenkinsJob.Java=java
#In case of failures, where should Subversionchecker redirect the errors
TriggerJenkinsJob.FailureHandlers=Console
TriggerJenkinsJob.SuccessHandlers=Console
#
TriggerJenkinsJob.IgnoreFiles=
2、然后当然就是我们核心的TriggerJenkinsJob.py文件了。
from modules import Process
import collections
def run(transaction, config):
check = config.getArray("TriggerJenkinsJob.CheckFiles", [".*\.java"])
ignore = config.getArray("TriggerJenkinsJob.IgnoreFiles", [])
files = transaction.getFiles(check, ignore)
java = config.getString("TriggerJenkinsJob.Java")
# transaction.getCommitMsg()
# transaction.getRevision()
# transaction.getUserID()
# files : c:/windows/servic~2/networ~1/appdata/local/temp/tmpoa188k/xxxx/trunk/src/main/java/com/xxxx/filter/Struts2Filter.java
if len(files) <= 0 :
return ("", 0)
files = [transaction.getFile(oneFile[0]) for oneFile in files.iteritems() if oneFile[1] in ["A", "U", "UU", "D"]]
filepath = files[0]
jenkinsInfo = getMatchedJenkinsInfo(filepath)
if jenkinsInfo is None:
return ("no matched Jenkins task", 0)
jenkinsJobName = jenkinsInfo[0]
command = "%s -jar F:/xxxxx/jenkins-cli.jar -s http://xxxx.16.3.250:9527/ -auth JenkinsCLI:JenkinsCLI build %s -p NOTICED_USER=%s -p BUILD_TRIGGER_CAUSE=AUTO -c" % (java, jenkinsJobName, transaction.getUserID())
try:
Process.execute(command)
except Process.ProcessException, e:
msg = "Jenkins CLI errors found:\n\n"
msg += e.output + "\n"
return (msg, 1)
return ("", 0)
def getMatchedJenkinsInfo(tempfileFullPath):
mappings = getMapping()
for k,v in mappings.items():
if k in tempfileFullPath:
return v
return None
def getMapping():
SVN_BASE_PATH = "https://172.16.3.3:xxxx/svn/"
d1=collections.OrderedDict() # 这里我们可以将映射表设置为有序
# 因为历史原因,我们的SVN目录的建立并不规范,所以这里我们采取建立映射表的方式来确定当前SVN提交对应的Jenkins任务.
# 这里的:
# key: svn地址中的关键字, 可以唯一性地标识当前SVN URL.
# value[0]: 对应的Jenkins Job Name ; value[1]: SVN URL; 用于可能的后期扩展.
d1["xxxx"] = ["xxxx", SVN_BASE_PATH + "xxxx/xx/trunk"]
return d1
关于以上脚本中的 jenkins-cli.jar,读者可以自行从自己搭建的 Jenkins 服务上下载。
以上配置安装到位之后,提交代码之后将呈现如下效果:
3. Jenkins 向 SVN 的打通
介绍了 SVN 向 Jenkins 的价值流动之后,接下来让我们看看反向操作。 这一步我们的实现思路是在 Jenkins Pipeline 的 post 阶段通过调用 Svn Commandline 将 Jenkins 执行流水线中产生的关键性日志信息反写回对应的 SVN 仓库。 在目前的实现中,我们所写入的关键性信息直接复用了【DEVOPS】基于Jenkins + Ansible实现Windows环境下自动化打包部署 中创建的meta-info.md文件。
mkdir -p doc/jenkins_build
cp meta-info.md doc/jenkins_build/jenksin_build_{BUILD_NUMBER}.md
svn add doc/jenkins_build/jenksin_build_{BUILD_NUMBER}.md
svn commit -m "Auto Commit by Jenkin for build id ${BUILD_NUMBER}" --non-interactive --trust-server-cert --username Jenkins --password Jenkins --no-auth-cache
4. 最佳实践
讲完了实现方法之后,最后再补充一些在实际应用中的最佳实践。
-
分别建立专门的账户来进行对应的自动化操作。例如笔者这里的为Jenkins建立的帐号JenkinsCLI 和为SVN建立的账户 Jenkins。
-
价值流的打通只是第一步,**将流动被中断视为最高处理优先级**才是我们追求的目标。
5. Links
-
https://blog.csdn.net/lqzkcx3/article/details/103477780
-
https://blog.csdn.net/lqzkcx3/article/details/103958695
-
极客时间专栏《DevOps实战笔记》—— 京东研发效能专家-石雪峰
来源:https://blog.csdn.net/lqzkcx3/article/details/109675368?utm_source=app