公司最近准备分出一套人马去客户那里做驻场研发,这就涉及到代码库的统一管理。鉴于VSS在互联网上表现不好,而TFS配置又过于复杂,我们选择了SVN。考虑到代码的安全性及性能,我们决定在本地布署自己的SVN服务器,然后每个人安装TortoiseSVN作为客户端,并安装AnkhSVN插件配合Visual Studio使用,安装CruiseControl.NET进行自动化的每日构建,安装Redmine进行项目管理,安装BugFree进行bug管理。
1.VisualSVN,TortoiseSVN,AnkhSVN
我安装的版本是:VisualSVN2.1.9,TortoiseSVN-1.6.16.21511,AnkhSvn-2.1.10129。他们的安装过程都是傻瓜式的,无需多表,主要是安装好后需要进行几个位置的配置。
a).采用Http还是Https
这个选择的优缺点就不多表,其实是看具体的需要。
b).安全证书问题
安装完成后,如果采用Https方式,默认访问时会出现安全证书问题。这其实是因为默认使用的是“自签名证书”。安全证书的原理,简单来讲就是采用两个大素数A和B,用A加密的只能用B解密,用B加密的只能用A解密,此时称A为密钥,B为公钥或者B为密钥,A为公钥。这是一种典型的不对称加密。如果这对钥匙的提供者是公认的认证机构(如Verisign),那么各种主流浏览器就会认为它是安全的证书,反之就是非安全证书。显然,所谓“自签名证书”,就是指这个钥匙的提供者就是自己,在浏览器看来这当然就是典型的非安全证书了,会在最开始的页面显示一个警告。要想去除这个警告,有两种方法,***种当然就是把你的相关信息发给那些认证机构,让他们帮你生成安全证书。不过这个方案是需要花点银子滴。第二种方法就是手工把当前的“自签名证书”加入到受信任列表里去。这种方法简单易行,具体的方法与说明请自行google或者参见本文结尾的参考文章。
c).使用“锁定-编辑-解锁”模型
这个其实也是仁者见仁,智者见智的问题。只是对于我们而言,这个模型更加适合我们。但是SVN默认是“拷贝-修改-合并”模型,那如何进行变更呢?这就用到了SVN的自定义属性了。在SVN里是通过内置的属性“svn:needs-lock”实现“锁定-编辑-解锁”模型的。在这里只提一下具体操作,找到config文件,我的路径是:C:UsersljzforeverAppDataRoamingSubversionconfig。然后把enable-auto-props = yes前面的#号与空格删掉,然后在[auto-props]下面加一行* = svn:needs-lock=x。更加具体的操作与说明请自行google或者参见本文结尾的参考文章。这样,所有的文件在上传到SVN上后就自动进入“锁定-编辑-解锁”模型了。
d).关于"steal lock"
这个选项的初衷是为了增强灵活性,当一个文件被其它人锁定后,仍然可以用“偷”的方式将锁强行拿过来。不过这也是引起代码冲突的潜在原因之一,我们决定将其屏避掉。这里用到的技术就是hook script。hook script其实是一些脚本文件,在windows环境下就是一些bat脚本。每当svn做一些特定操作时,比如“锁定”,“提交”时,就会到指定目录下查找相关的hook script并执行它,达到对相应命令的预处理。我们这里是需要在锁定前检查用户在申请锁定文件时是否勾选了"steal lock",如果勾选了,则中断操作,提示用户这个选项已被系统禁止。放置这个hook script的目录是跟代码库路径是相关的,我的目录是:E:RepositoriesHWCHhooks。安装后默认里面已经有若干个模板,以tmpl为扩展名,比如pre-lock.tmpl就是锁定前做的预操作,post-commit.tmpl就是提交后做的预操作。我们在里面新建一个文件:pre-lock.bat,然后在里面输入以下内容:
- @echo off
- REM [1] REPOS-PATH (the path to this repository)
- REM [2] PATH (the path in the repository about to be locked)
- REM [3] USER (the user creating the lock)
- REM [4] COMMENT (the comment of the lock)
- REM [5] STEAL-LOCK (1 if the user is trying to steal the lock, else 0)
- setlocal
- ::svn对代码资源库路径与文件路径里的右小括号敏感,需要对其转义
- ::代码资源库路径
- set repos=%1
- set "repos=%repos:)=^)%"
- ::当前文件路径
- set repPath=%2
- set "repPath=%repPath:)=^)%"
- set userName=%3
- set isSteal=%5
- rem NO_STEALING
- ::如果没有被锁定,则直接跳走结束处理
- if /I '1'=='%isSteal%' goto NO_STEALING
- REM echo aaa >>d:\log.txt
- REM echo repos = %repos% >>d:\log.txt
- REM echo repPath = %repPath% >>d:\log.txt
- REM echo userName = %userName% >>d:\log.txt
- rem if the path has been locked, find the Owner.
- ::这里是处理重点
- ::通过svnlook lock %repos% %repPath%,命令获取锁信息,例如:
- :: UUID Token: opaquelocktoken:1707b1a0-8dd1-a94e-87d2-6569a115cd5c
- :: Owner: ljz
- :: Created: 2011-08-08 21:05:31 +0800 (周一, 08 八月 2011)
- :: Expires:
- :: Comment (1 line):
- ::通过findstr /r /n ".",将所有行的前面加上行号,前返回所有行,例如:
- :: 1:UUID Token: opaquelocktoken:1707b1a0-8dd1-a94e-87d2-6569a115cd5c
- :: 2:Owner: ljz
- :: 3:Created: 2011-08-08 21:05:31 +0800 (周一, 08 八月 2011)
- :: 4:Expires:
- :: 5:Comment (1 line):
- ::通过tokens=1,2,3 delims=: ,以:号与空格作为分隔符,将上述每一行分隔,并将前三段分别装入变量%%i,%%j,%%k
- ::通过if %%i == 2 set LockedName=%%k,把第二行分隔后的第三段装入变量LockedName,在这里,就是ljz
- for /f "tokens=1,2,3 delims=: " %%i in ('svnlook lock %repos% %repPath% ^|findstr /r /n "."') do (
- if %%i == 2 set LockedName=%%k
- )
- rem If we get no result from svnlook, there's no lock, allow the lock to happen.
- ::如果没有获取到锁定信息,则直接跳走结束处理
- if not defined LockedName goto OK_EXIT
- rem If the person locking matches the lock's owner, allow the lock to happen.
- rem But this one won't effect, the SVN don't care if the person matchs, they just don't allow relock.
- REM echo userName = %userName% >>d:\log.txt
- REM echo LockedName = %LockedName% >>d:\log.txt
- ::如果锁定人与当前用户同名,则直接跳走结束处理
- if /I '%LockedName%'=='%userName%' goto OK_EXIT
- rem Otherwise, we've got an owner mismatch, so return failure:
- :WRONG_PERSON
- echo the path has been locked by %LockedName%, Pls contact %LockedName% to unlock it.>&2
- goto ERROR_EXIT
- :NO_STEALING
- echo Stealing lock is not allowed at this server.>&2
- :ERROR_EXIT
- endlocal
- exit 1
- :OK_EXIT
- endlocal
- exit 0
2.CruiseControl.NET
我下载的版本是CruiseControl.NET-1.6.7981.1,安装完成后,主要通过配置安装目录下的ccnet.config文件来达到自动化构建。
a).配置文件
我的配置文件如下:
- <cruisecontrol xmlns:cb="urn:ccnet.config.builder">
- <!-- This is your CruiseControl.NET Server Configuration file. Add your projects below! -->
- <!--
- <project name="MyFirstProject" />
- -->
- <project name="SVNTest" >
- <!--公有参数-->
- <!--CC.net存放工作结果的目录-->
- <artifactDirectory>E:\project\SVNTest\artifactDir</artifactDirectory>
- <!--需要进行持续集成的项目的目录-->
- <workingDirectory >E:\project\SVNTest\workingDir</workingDirectory>
- <!--编译报告的网址-->
- <webURL>http://localhost/ccnet/server/local/ViewServerReport.aspx</webURL>
- <!--编译的版本号与日志文件名格式 -->
- <labeller type="dateLabeller"></labeller>
- <!--该触发器控制周一到周五的8点到24点的时间段内进行编译-->
- <!--在时间段内每900秒检查一次svn有无更新 ,如果有就取出并编译-->
- <!--在时间段内每晚上11点50分进行一次强制编译-->
- <!--但是目前有个问题,在周六与周日的23:59:59仍会编译一次,原因是我的时间段的结束时间写的是23:59:59。系统问题,无法解决-->
- <triggers>
- <multiTrigger operator="And">
- <triggers>
- <filterTrigger startTime="00:00:00" endTime="08:00:00">
- <trigger type="filterTrigger" startTime="00:00:00" endTime="23:59:59">
- <trigger type="intervalTrigger" seconds="900" />
- <weekDays>
- <weekDay>Saturday</weekDay>
- <weekDay>Sunday</weekDay>
- </weekDays>
- </trigger>
- </filterTrigger>
- <filterTrigger startTime="00:00:00" endTime="08:00:00">
- <trigger type="filterTrigger" startTime="00:00:00" endTime="23:59:59">
- <trigger type="scheduleTrigger" time="23:50:00" buildCondition="ForceBuild" />
- <weekDays>
- <weekDay>Saturday</weekDay>
- <weekDay>Sunday</weekDay>
- </weekDays>
- </trigger>
- </filterTrigger>
- </triggers>
- </multiTrigger>
- </triggers>
- <!-- 版本控制系统的类型 -->
- <sourcecontrol type="svn">
- <!-- SVN的地址 -->
- <trunkUrl>http://localhost:88/svn/HWCH/SVNTest/</trunkUrl>
- <!-- 把源代码检出到该目录 -->
- <workingDirectory>E:\project\SVNTest</workingDirectory>
- <!-- svn.exe所在路径 -->
- <executable>C:\Program Files\VisualSVN Server\bin\svn.exe</executable>
- <!-- 登录svn的用户名和密码 -->
- <username>ljz</username>
- <password>ljz</password>
- </sourcecontrol>
- <tasks>
- <!--采用VS进行编译-->
- <devenv>
- <solutionfile>E:\project\SVNTest\SVNTest.sln</solutionfile>
- <configuration>Debug</configuration>
- </devenv>
- </tasks>
- <publishers>
- <!--编译日志存放路径-->
- <!--<xmllogger logDir="E:\DailyBuild\Log\3\buildlogs" />-->
- <!-- 下面设置编译报告通过email通知相关人员 详细信息参考cc.net的帮助-->
- <!--<email from="admin@163.com" mailhost="smtp.163.com" mailhostUsername="admin" mailhostPassword="123" includeDetails="true">
- <users>
- <user name="dachuan" group="buildmaster" address="dachuan@163.com"/>
- </users>
- <groups>
- <group name="buildmaster" notification="always"/>
- </groups>
- </email>-->
- </publishers>
- </project>
- </cruisecontrol>
基本上照葫芦画瓢,就能把配置搞定。
b).服务器时间
我在测试cc.net从svn获取代码的时候,出现了一个这样子的错:failed:svn Check for modification。找了很久都没有找到原因,后来无意中改系统时间的时候才发现,原来我在测试triggers节点时,把系统时间改到昨天了,所以一定要记得,下一次获取代码的时间一定要晚于上一次获取代码的时间,不然cc.net就再也无法从svn获取***的代码了。
3.redmine
这是个著名的开源项目管理软件,这个就不多讲了,具体的请参看我之前的博文:项目管理软件之易度1.5,禅道2.0,redmine1.2(附redmine1.2的安装)
4.bugfree
这也是个著名的开源bug管理软件,下载***的Wamp环境,我的是WampServer2.1e,解压安装,然后下载***的bugfree,我的是bugfree2.1.3,解压后放在Wamp安装目录的www目录下,然后在浏览器地址栏里输入指定网址,按提示生成数据库,稍等几秒钟后就可以开始使用了。更详细的操作与说明请自行google或者参见本文结尾的参考文章。
***,下载个花生壳, 将域名动态绑定下,全世界就都可以使用公司本部的代码了~~~
参考的文章:
网站的安全证书有问题
将自签名证书用于Web服务安全性
命令行 Subversion 入门
TortoiseSVN有没有对资源的独占签出功能
AnkhSVN的自动加锁
用Hook Script阻止空日志信息提交到Subversion
分享Visual SVN Hook Script——检查提交时必须填写大于N个字符的日志信息
Hook Script to disable Break Lock in Tortoise SVN
SVN hooks(钩子)-禁止break lock及steal lock。(Windows dos-batch版)
bat set命令详解
BAT 批处理脚本 教程
DOS命令大全:Findstr命令详解
安装 VisualSVN-Server 和 TortoiseSVN 和 AnkhSVN 体会
原文链接:http://www.cnblogs.com/ljzforever/archive/2011/08/09/2132799.html
【编辑推荐】