軟件開(kāi)發(fā)項(xiàng)目管理實(shí)踐之駐場(chǎng)研發(fā)
公司最近準(zhǔn)備分出一套人馬去客戶那里做駐場(chǎng)研發(fā),這就涉及到代碼庫(kù)的統(tǒng)一管理。鑒于VSS在互聯(lián)網(wǎng)上表現(xiàn)不好,而TFS配置又過(guò)于復(fù)雜,我們選擇了SVN??紤]到代碼的安全性及性能,我們決定在本地布署自己的SVN服務(wù)器,然后每個(gè)人安裝TortoiseSVN作為客戶端,并安裝AnkhSVN插件配合Visual Studio使用,安裝CruiseControl.NET進(jìn)行自動(dòng)化的每日構(gòu)建,安裝Redmine進(jìn)行項(xiàng)目管理,安裝BugFree進(jìn)行bug管理。
1.VisualSVN,TortoiseSVN,AnkhSVN
我安裝的版本是:VisualSVN2.1.9,TortoiseSVN-1.6.16.21511,AnkhSvn-2.1.10129。他們的安裝過(guò)程都是傻瓜式的,無(wú)需多表,主要是安裝好后需要進(jìn)行幾個(gè)位置的配置。
a).采用Http還是Https
這個(gè)選擇的優(yōu)缺點(diǎn)就不多表,其實(shí)是看具體的需要。
b).安全證書(shū)問(wèn)題
安裝完成后,如果采用Https方式,默認(rèn)訪問(wèn)時(shí)會(huì)出現(xiàn)安全證書(shū)問(wèn)題。這其實(shí)是因?yàn)槟J(rèn)使用的是“自簽名證書(shū)”。安全證書(shū)的原理,簡(jiǎn)單來(lái)講就是采用兩個(gè)大素?cái)?shù)A和B,用A加密的只能用B解密,用B加密的只能用A解密,此時(shí)稱A為密鑰,B為公鑰或者B為密鑰,A為公鑰。這是一種典型的不對(duì)稱加密。如果這對(duì)鑰匙的提供者是公認(rèn)的認(rèn)證機(jī)構(gòu)(如Verisign),那么各種主流瀏覽器就會(huì)認(rèn)為它是安全的證書(shū),反之就是非安全證書(shū)。顯然,所謂“自簽名證書(shū)”,就是指這個(gè)鑰匙的提供者就是自己,在瀏覽器看來(lái)這當(dāng)然就是典型的非安全證書(shū)了,會(huì)在最開(kāi)始的頁(yè)面顯示一個(gè)警告。要想去除這個(gè)警告,有兩種方法,***種當(dāng)然就是把你的相關(guān)信息發(fā)給那些認(rèn)證機(jī)構(gòu),讓他們幫你生成安全證書(shū)。不過(guò)這個(gè)方案是需要花點(diǎn)銀子滴。第二種方法就是手工把當(dāng)前的“自簽名證書(shū)”加入到受信任列表里去。這種方法簡(jiǎn)單易行,具體的方法與說(shuō)明請(qǐng)自行g(shù)oogle或者參見(jiàn)本文結(jié)尾的參考文章。
c).使用“鎖定-編輯-解鎖”模型
這個(gè)其實(shí)也是仁者見(jiàn)仁,智者見(jiàn)智的問(wèn)題。只是對(duì)于我們而言,這個(gè)模型更加適合我們。但是SVN默認(rèn)是“拷貝-修改-合并”模型,那如何進(jìn)行變更呢?這就用到了SVN的自定義屬性了。在SVN里是通過(guò)內(nèi)置的屬性“svn:needs-lock”實(shí)現(xiàn)“鎖定-編輯-解鎖”模型的。在這里只提一下具體操作,找到config文件,我的路徑是:C:UsersljzforeverAppDataRoamingSubversionconfig。然后把enable-auto-props = yes前面的#號(hào)與空格刪掉,然后在[auto-props]下面加一行* = svn:needs-lock=x。更加具體的操作與說(shuō)明請(qǐng)自行g(shù)oogle或者參見(jiàn)本文結(jié)尾的參考文章。這樣,所有的文件在上傳到SVN上后就自動(dòng)進(jìn)入“鎖定-編輯-解鎖”模型了。
d).關(guān)于"steal lock"
這個(gè)選項(xiàng)的初衷是為了增強(qiáng)靈活性,當(dāng)一個(gè)文件被其它人鎖定后,仍然可以用“偷”的方式將鎖強(qiáng)行拿過(guò)來(lái)。不過(guò)這也是引起代碼沖突的潛在原因之一,我們決定將其屏避掉。這里用到的技術(shù)就是hook script。hook script其實(shí)是一些腳本文件,在windows環(huán)境下就是一些bat腳本。每當(dāng)svn做一些特定操作時(shí),比如“鎖定”,“提交”時(shí),就會(huì)到指定目錄下查找相關(guān)的hook script并執(zhí)行它,達(dá)到對(duì)相應(yīng)命令的預(yù)處理。我們這里是需要在鎖定前檢查用戶在申請(qǐng)鎖定文件時(shí)是否勾選了"steal lock",如果勾選了,則中斷操作,提示用戶這個(gè)選項(xiàng)已被系統(tǒng)禁止。放置這個(gè)hook script的目錄是跟代碼庫(kù)路徑是相關(guān)的,我的目錄是:E:RepositoriesHWCHhooks。安裝后默認(rèn)里面已經(jīng)有若干個(gè)模板,以tmpl為擴(kuò)展名,比如pre-lock.tmpl就是鎖定前做的預(yù)操作,post-commit.tmpl就是提交后做的預(yù)操作。我們?cè)诶锩嫘陆ㄒ粋€(gè)文件:pre-lock.bat,然后在里面輸入以下內(nèi)容:
- @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對(duì)代碼資源庫(kù)路徑與文件路徑里的右小括號(hào)敏感,需要對(duì)其轉(zhuǎn)義
- ::代碼資源庫(kù)路徑
- set repos=%1
- set "repos=%repos:)=^)%"
- ::當(dāng)前文件路徑
- set repPath=%2
- set "repPath=%repPath:)=^)%"
- set userName=%3
- set isSteal=%5
- rem NO_STEALING
- ::如果沒(méi)有被鎖定,則直接跳走結(jié)束處理
- 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.
- ::這里是處理重點(diǎn)
- ::通過(guò)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):
- ::通過(guò)findstr /r /n ".",將所有行的前面加上行號(hào),前返回所有行,例如:
- :: 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):
- ::通過(guò)tokens=1,2,3 delims=: ,以:號(hào)與空格作為分隔符,將上述每一行分隔,并將前三段分別裝入變量%%i,%%j,%%k
- ::通過(guò)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.
- ::如果沒(méi)有獲取到鎖定信息,則直接跳走結(jié)束處理
- 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
- ::如果鎖定人與當(dāng)前用戶同名,則直接跳走結(jié)束處理
- 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,安裝完成后,主要通過(guò)配置安裝目錄下的ccnet.config文件來(lái)達(dá)到自動(dòng)化構(gòu)建。
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" >
- <!--公有參數(shù)-->
- <!--CC.net存放工作結(jié)果的目錄-->
- <artifactDirectory>E:\project\SVNTest\artifactDir</artifactDirectory>
- <!--需要進(jìn)行持續(xù)集成的項(xiàng)目的目錄-->
- <workingDirectory >E:\project\SVNTest\workingDir</workingDirectory>
- <!--編譯報(bào)告的網(wǎng)址-->
- <webURL>http://localhost/ccnet/server/local/ViewServerReport.aspx</webURL>
- <!--編譯的版本號(hào)與日志文件名格式 -->
- <labeller type="dateLabeller"></labeller>
- <!--該觸發(fā)器控制周一到周五的8點(diǎn)到24點(diǎn)的時(shí)間段內(nèi)進(jìn)行編譯-->
- <!--在時(shí)間段內(nèi)每900秒檢查一次svn有無(wú)更新 ,如果有就取出并編譯-->
- <!--在時(shí)間段內(nèi)每晚上11點(diǎn)50分進(jìn)行一次強(qiáng)制編譯-->
- <!--但是目前有個(gè)問(wèn)題,在周六與周日的23:59:59仍會(huì)編譯一次,原因是我的時(shí)間段的結(jié)束時(shí)間寫(xiě)的是23:59:59。系統(tǒng)問(wèn)題,無(wú)法解決-->
- <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>
- <!-- 版本控制系統(tǒng)的類型 -->
- <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進(jìn)行編譯-->
- <devenv>
- <solutionfile>E:\project\SVNTest\SVNTest.sln</solutionfile>
- <configuration>Debug</configuration>
- </devenv>
- </tasks>
- <publishers>
- <!--編譯日志存放路徑-->
- <!--<xmllogger logDir="E:\DailyBuild\Log\3\buildlogs" />-->
- <!-- 下面設(shè)置編譯報(bào)告通過(guò)email通知相關(guān)人員 詳細(xì)信息參考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>
基本上照葫蘆畫(huà)瓢,就能把配置搞定。
b).服務(wù)器時(shí)間
我在測(cè)試cc.net從svn獲取代碼的時(shí)候,出現(xiàn)了一個(gè)這樣子的錯(cuò):failed:svn Check for modification。找了很久都沒(méi)有找到原因,后來(lái)無(wú)意中改系統(tǒng)時(shí)間的時(shí)候才發(fā)現(xiàn),原來(lái)我在測(cè)試triggers節(jié)點(diǎn)時(shí),把系統(tǒng)時(shí)間改到昨天了,所以一定要記得,下一次獲取代碼的時(shí)間一定要晚于上一次獲取代碼的時(shí)間,不然cc.net就再也無(wú)法從svn獲取***的代碼了。
3.redmine
這是個(gè)著名的開(kāi)源項(xiàng)目管理軟件,這個(gè)就不多講了,具體的請(qǐng)參看我之前的博文:項(xiàng)目管理軟件之易度1.5,禪道2.0,redmine1.2(附redmine1.2的安裝)
4.bugfree
這也是個(gè)著名的開(kāi)源bug管理軟件,下載***的Wamp環(huán)境,我的是WampServer2.1e,解壓安裝,然后下載***的bugfree,我的是bugfree2.1.3,解壓后放在Wamp安裝目錄的www目錄下,然后在瀏覽器地址欄里輸入指定網(wǎng)址,按提示生成數(shù)據(jù)庫(kù),稍等幾秒鐘后就可以開(kāi)始使用了。更詳細(xì)的操作與說(shuō)明請(qǐng)自行g(shù)oogle或者參見(jiàn)本文結(jié)尾的參考文章。
***,下載個(gè)花生殼, 將域名動(dòng)態(tài)綁定下,全世界就都可以使用公司本部的代碼了~~~
參考的文章:
網(wǎng)站的安全證書(shū)有問(wèn)題
將自簽名證書(shū)用于Web服務(wù)安全性
命令行 Subversion 入門
TortoiseSVN有沒(méi)有對(duì)資源的獨(dú)占簽出功能
AnkhSVN的自動(dòng)加鎖
用Hook Script阻止空日志信息提交到Subversion
分享Visual SVN Hook Script——檢查提交時(shí)必須填寫(xiě)大于N個(gè)字符的日志信息
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 體會(huì)
原文鏈接:http://www.cnblogs.com/ljzforever/archive/2011/08/09/2132799.html
【編輯推薦】