设为首页 收藏本站
云服务器等爆品抢先购,低至4.2元/月
查看: 1826|回复: 0

[经验分享] SVN怎么触发Jenkins自动构建

[复制链接]

尚未签到

发表于 2018-9-16 08:51:10 | 显示全部楼层 |阅读模式
  通常,有几种方式可以在SVN仓库发生改变时触发Jenkins进行构建。第一种是,Jenkins主动轮询SVN仓库;第二种是,在SVN客户端(如TortoiseSVN)创建客户端hooks来触发构建;第三种是,在SVN服务器端,创建仓库hooks来触发构建。而我所要介绍的就是这第三种。
  在http://svnbook.red-bean.com/en/1.5/svn.reposadmin.create.html#svn.reposadmin.create.hooks这里可以找到如何创建仓库hooks的指导说明。
  现在假设,我有一个仓库名为"auto_everything",在SVN管理页面的版本库列表中也可以看到:
DSC0000.jpg

  登录到SVN服务器上,找到该仓库所在目录(可以用find命令搜一下):
DSC0001.jpg

  在该仓库目录下,有一个hooks目录,默认情况下该目录下有一些模板文件(.tmpl文件):
DSC0002.jpg

  SVN的仓库hooks的原理是这样的:当你对该仓库执行一些操作时,比如创建一个新的revision版本或修改一个未版本化的属性,就会触发hooks目录下的相应程序。操作的事件(或时间节点)是跟程序文件名相对应的。举个例子,post-commit,代表,你往该仓库提交完成后,如果此时hooks目录下有一个叫做post-commit的程序文件的话,该程序就会被触发执行。该程序文件可以是任意可执行的程序,比如shell脚本、python脚本、二进制程序等,它需要有可执行权限。
  SVN在执行该hooks文件时,同时会传入三个参数:该仓库的路径(REPOS)、修订版本号(REV)、事务名称(TXN_NAME,这个不知道什么鬼,不过也用不上)。在https://wiki.jenkins.io/display/JENKINS/Subversion+Plugin这里可以找到利用post-commit hook来触发Jenkins执行的示例脚本。
  #!/bin/sh
  REPOS="$1"                                         # 本仓库的目录路径
  REV="$2"                                            # 版本修订号
  UUID=`svnlook uuid $REPOS`
  /usr/bin/wget \
  --header "Content-Type:text/plain;" \
  --post-data "`svnlook changed --revision $REV $REPOS`" \
  --output-document "-" \
  --timeout=2 \
  http://server/subversion/${UUID}/notifyCommit?rev=$REV
  注一:出于安全考虑,SVN在调用hooks程序时是不传入任何环境变量的,包括PATH路径。所以,如果为了方面书写命令,我们我们需要自己设置PATH路径:
  svn_dir=/home/svn/csvn                                                            # SVN安装目录
  export PATH=$svn_dir/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
  注二:注意到rev=$REV参数,这是告诉Jenkins签出该hook程序所报告的那个版本号。如果你的job定义了多个subversion模块位置,这可能会导致签出代码不一致 - 因此那种情况下就推荐你省去 '?rev=$REV' ,这会使得Jenkins签出最新版本的代码。
  注三:为了让Jenkins中的job可以被触发,job需要被显式地配置为启用SCM轮询才行,未启用SCM轮询选项的job将不会被post-commit hook所触发。下图为在job中启用SCM轮询的示例:
DSC0003.jpg

  注四:为了让上面的脚本可以正常工作,Jenkins需要允许匿名用户有读取权限。在"系统管理"→"全局安全配置"中,可以启用:
DSC0004.jpg

  当然,通常我们的Jenkins会有更加严格的访问权限控制,我们不会这么做。后面会介绍。
  注五:如果Jenkins启用了跨站点请求伪造防护(默认启用)选项,那么上面的请求会返回一个403错误("No valid crumb was included")。在"系统管理"→"全局安全配置"中,可以看到跨站点请求伪造防护是否有启用:
DSC0005.jpg

  为了避免该问题,请求所需的crumb可以从URL地址http://server/crumbIssuer/api/xml (或/api/json)获取到。可以通过在wget请求中添加类似于下面的代码来解决:
  --header `wget -q --output-document - \
  'http://server/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,":",//crumb)'`
  注六:由于wget在给定的超时时间内访问不成功时,它默认会尝试最多20次,--timeout=2在一个性能较差的SVN服务器上可能会导致Jenkins扫描仓库非常多次,进一步减慢了SVN服务器,然后使用Jenkins不响应。对该问题的可能的解决办法是增加超时时间,减小重试次数(如--retries=3),或者在wget命令最后面添加2>&1 &来异步地调用wget(因此忽略了所有的通信错误)。
  timeout值太低会导致你的commit操作hang住并抛出502错误(如果你是在一个proxy后面)或post-commit错误。增加超时值,直到你不再看到wget重试,应该可以修复这个问题。
  考虑到上面总总情况,实际生产环境中,我建议按照如下操作步骤进行。
  1、 首先,在Jenkins中,不要允许匿名用户有读取权限。相反,我们可以登录进去,在用户的设置界面("用户"→ 选择某个用户 →"设置"),找到用户的API Token并记下来,我们后面在程序中可以通过该token来访问Jenkins。你使用的是哪个用户的token,程序就具有那个用户的访问权限。
DSC0006.jpg

DSC0007.jpg

  2、 保持跨站点请求伪造防护为启用。在"系统管理"→"全局安全配置"中,可以设置:
DSC0008.jpg

  3、 对于需要被post-commit hook所触发的job,要启用它的"Poll SCM"选项:
DSC0009.jpg

  4、 在SVN服务器上,所选仓库的hooks目录中,创建程序文件post-commit:
  [root@gw ~]# cd /home/svn/csvn/data/repositories/auto_everything/hooks
  [root@gw hooks]# touch post-commit
  [root@gw hooks]# chown svn:svn post-commit                          # 跟SVN的httpd程序的所属用户相同
  [root@gw hooks]# chmod 755 post-commit                             # 需要有可执行权限
  我们使用python来编写该程序:
  [root@gw hooks]# vim post-commit
  #!/usr/bin/env python
  # -*- coding: utf-8 -*-
  import urllib2, sys, os, base64, json
  # 本仓库的目录路径
  repos_path = sys.argv[1]
  # 版本修订号
  revision = sys.argv[2]
  # svnlook命令所在路径
  svnlook = '/home/svn/csvn/bin/svnlook'
  # Jenkins的地址
  baseurl = 'http://172.31.2.8:8080'
  # Jenkins用户和用户的api token
  user_id = 'admin'
  api_token = '0e5127a9b050097b14e72b1485cf5e39'
  def my_urlopen(url, data=None, header={ }):
  request = urllib2.Request(url, data)
  base64string = base64.encodestring('%s:%s' % (user_id, api_token)).replace('\n', '')
  header['Authorization'] = 'Basic %s' % base64string
  for key in header:
  request.add_header(key, header[key])
  try:
  response = urllib2.urlopen(request)
  except urllib2.URLError as e:
  print '[Exception URLError]:', e
  sys.exit(1)
  else:
  result = response.read( )
  finally:
  if 'response' in vars( ):
  response.close( )
  return result
  def main( ):
  # 获取uuid值
  command = r'%s uuid %s' % (svnlook, repos_path)
  with os.popen(command) as f:
  uuid = f.read( ).strip( )
  # 获取仓库变更信息
  command = r'%s changed --revision %s %s' % (svnlook, revision, repos_path)
  with os.popen(command) as f:
  data = f.read( ).strip( )
  # 获取crumb
  url = r'%s/crumbIssuer/api/json' % baseurl
  crumb_dict = json.loads(my_urlopen(url))
  # 触发Jenkins
  url = r'%s/subversion/%s/notifyCommit?rev=%s' % (baseurl, uuid, revision)
  header={'Content-Type':'text/plain', 'charset':'UTF-8', crumb_dict['crumbRequestField']:crumb_dict['crumb']}
  my_urlopen(url, data, header)
  main( )
  这样就设置好了。可以找一个项目的文件夹,在里面随便新建一个问题,然后提交。如果SVN的post-commit有触发Jenkins进行构建的话,在Jenkins管理页面中就可以看到有job在运行了,在Jenkins的系统日志中也会产生类似下面的信息:
  [root@gw ~]# tail -n 100 -f /opt/jenkins/jenkins.log
  Jun 25, 2018 9:03:17 AM jenkins.scm.impl.subversion.SubversionSCMSource$ListenerImpl onNotify
  INFO: Received post-commit hook from 7c771039-8f78-4126-8c20-220196ed6f6c for revision 21 on paths [example-pipeline/test.txt]
  Jun 25, 2018 9:03:17 AM jenkins.scm.impl.subversion.SubversionSCMSource$ListenerImpl onNotify
  INFO: No subversion consumers for UUID 7c771039-8f78-4126-8c20-220196ed6f6c
  Jun 25, 2018 9:03:18 AM hudson.triggers.SCMTrigger$Runner run
  INFO: SCM changes detected in example-pipeline. Triggering  #4
  Jun 25, 2018 9:03:33 AM org.jenkinsci.plugins.workflow.job.WorkflowRun finish
  INFO: example-pipeline #4 completed: SUCCESS
  实际生产环境中,一个SVN仓库可能会存放有多个项目,对应多个Jenkins job。但经过测试,发现没有任何问题。当我们将修改提交到SVN仓库中时,只有那些文件有变动的项目对应的job才会被触发。这可能是Jenkins有检查,每一次变动都涉及到哪些文件,跟现有job的SVN源码路径是否匹配,如果有匹配到,才会触发这个job。不过需要注意的是,不管是新增文件还是删除文件,只要项目文件发生变动,都会触发项目的job进行自动构建的。


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-584365-1-1.html 上篇帖子: jenkins构建shell或者python脚本中含有远程登录复制会报错解决办法 下篇帖子: jenkins邮件端口配置
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表