我們項目在開發過程中使用了Jenkins構建Windows版本,為了通過自動觸發使構建的版本保持最新,可以采用的方法如下:
- Jenkins Poll SCM:設置Jenkins定時檢查變更,在SVN版本號有變更的情況下執行構建;
- Jenkins Remote Trigger + SVN Post Commit Hook:配置SVN倉庫的Post Commit Hook,在提交完成后觸發Jenkins遠程構建;
顯然,第二種方法更可取一些。但是在公司內配置SVN Server Hooks需要申請權限和訪問規則。
幸好,我們使用的TortoiseSVN支持客戶端鈎子腳本(Hook Scripts)。
客戶端鈎子腳本的類型和參數
TortoiseSVN的客戶端鈎子腳本支持以下幾種類型:
我們需要的是Post-commit類型的腳本。在腳本執行的時候,TortoiseSVN會傳遞的參數信息如下:
這些參數的意義如下:
其中,PATH指向的文件包含了本次提交影響到的所有文件的路徑,ERROR指向的文件包含了本次提交的錯誤信息。這兩個參數是我們需要關心的。
Post-commit腳本
我們使用的腳本如下:
HOOKS/POST_COMMIT_HOOK.BAT
Python腳本的封裝,內容如下:
1
2
|
set current_path=%~dp0
python.exe %current_path%\post_commit_hook.py %*
|
HOOKS/POST_COMMIT_HOOK.PY
實際的鈎子腳本,內容如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import sys
import os
from shutil import copyfile
import json
import urllib2
if len(sys.argv) < 2:
sys.exit()
current_path = os.path.dirname(os.path.abspath(__file__))
with open(current_path + '/post_commit.log','w') as f:
f.write(str(sys.argv[1:]))
if len(sys.argv) < 7:
sys.exit()
path = sys.argv[1]
depth = sys.argv[2]
message_file = sys.argv[3]
revision = sys.argv[4]
error = sys.argv[5]
cwd = sys.argv[6]
#copyfile(path, current_path + '/path.tmp')
#copyfile(message_file, current_path + '/message_file.tmp')
#copyfile(error, current_path + '/error.tmp')
# if error is not empty, the commit should not success
try:
if os.stat(error).st_size > 0:
print "[INFO] error happened"
sys.exit()
except OSError:
# no such file, which should not happen
print "[ERROR] no error file"
sys.exit()
# if files include source files or project files, trigger ci build
source_extensions = ['.h', '.cpp', '.cc', '.c', '.vcxproj', '.vcxproj.filters']
def SourcePath(file_path):
for extension in source_extensions:
if file_path.endswith(extension):
return True
return False
source_changed = False
with open(path) as f:
for line in f:
if SourcePath(line.strip()):
source_changed = True
break;
if not source_changed:
print "[INFO] source not changed"
sys.exit()
print "[INFO] source changed"
jenkins_job_url = 'http://USER:USER_API_TOKEN@JENKINS_URL/job/JOB_NAME/buildWithParameters?token=TOKEN_NAME&cause=svn-post-commit'
req = urllib2.Request(jenkins_job_url )
response = urllib2.urlopen(req)
print "[INFO] response = " + str(response)
|
鈎子腳本的主要工作如下:
1. 判斷本次提交是否出錯,如果有錯誤,說明提交未成功,退出腳本;
2. 遍歷本次提交影響到的所有文件,如果包括源代碼文件(‘.h’, ‘.cpp’, ‘.cc’, ‘.c’),或者項目配置文件(‘.vcxproj’, ‘.vcxproj.filters’),則說明需要觸發構建,否則退出腳本;
3. 調用jenkins_job_url觸發構建。
JENKINS JOB URL
鈎子腳本中jenkins_job_url
的定義如下:
1
|
jenkins_job_url = 'http://USER:USER_API_TOKEN@JENKINS_URL/job/JOB_NAME/buildWithParameters?token=TOKEN_NAME&cause=svn-post-commit'
|
其中的變量含義分別如下:
USER/USER_API_TOKEN
Jenkins用戶名和對應的API TOKEN。
JENKINS_URL
Jenkins的訪問路徑。
JOB_NAME
項目名稱。
TOKEN_NAME
在項目的遠程構建中設置的身份驗證,需要啟用觸發遠程構建的選項。
設置鈎子腳本
打開TortoiseSVN設置界面,選擇鈎子腳本:
點擊增加,打開設置鈎子腳本界面:
進行以下設置:
- 設置鈎子類型為提交之后;
- 設置工作副本路徑為trunk目錄;
- 設置執行的命令行為post_commit_hook.bat;
- 選中運行時隱藏腳本和總是執行這些腳本選項,不要選中等待腳本運行結束選項。
驗證構建
在提交版本后,檢查Jenkins中是否觸發了構建。如果成功觸發了構建,控制台輸出應該如下: