How to Make a AutoBuild System with Git Server

Table of Content

今天给大家分享一下最近自己的成果, 折腾了一个autobuild系统, 如果您和我有同样的需求, 不妨跟随我一起搭建一个这样的系统, easy and simple, have fun :)

Why:

  事情是这样开始的, 我自己的项目放置在github上, 这是一个linux项目, 然而我所用来开发的机器是mac, 它不能用来编译所有的模块, 每次我都需要push提交之后, 再去server上pull下来, 然后编译看看结果, 这个过程我持续了一阵子之后再也忍受不了了, 我想要一个这样的系统:

1. 当我push提交之后, 他能实时的反馈给我编译的结果, 就像本地编译一样
2. 运行test unit, 并将结果实时反馈给我
3. 随后发送一封邮件到我的邮箱内, 包含编译结果以及test unit运行结果
4. 而这次的提交仅仅是为了测试集成的效果, 而不影响真正的版本库主干

How:

  目的明确后, 我想到了git hook, 这里面的hook有一个可以满足我的需求– post-receive, 这是一个server端的hook(shell脚本), 每当接收到applypatch后都会调用一次并将输出结果反馈给client, 接下来我们将开始利用这个hook搭建这套系统.

首先我们来看一下工作流程(如下图):

图1 WorkFlow

简单的描述一下这个流程, 相对还算清晰简洁, 找一台可以用作build的机器, 建立一个git bare repo 用于接受提交, a clone repo for update & build, 当你向这个repo push后, server收到commit会自动调用post-receive hook, 接下来你需要让这个hook脚本做4件事:

1. 定位到clone repo 目录中进行pull, 更新最后一次提交
2. 在build目录中执行make
3. 执行TestUnit
4. 将刚才输出的信息发送到指定邮箱

这个脚本完成上述4个步骤, 也就完成了我们制定的目标. 现在所有重点都在这个hook脚本内, 不过你是否有一个疑惑, 这些执行中的信息如何才能反馈给提交的client? 这个也是我最先想问的, 查了git hook的资料后, 发现post-receive执行时, 标准输出(stdout)和标准错误输出(stderr)都会被git-send-back给当前client, 所以这个传输问题我们可以不用担心,  我们只需要关心哪些信息我们需要收集, 哪些需要丢弃即可.

ToDo:

目标清楚了, 原理也清楚了, 接下来我会展示如何搭建一个git server ,以及如何编写这个git hook(post-receive),  到最后测试结果演示.

1. Git server:

搭建server很多文章中都有描述, 我稍微提炼一下, 做一个最精简的. 首先我们找一台机器(要有root or sudo权限)

1). mkdir -p git_repo/autobuild   ( git_repo为git server的根目录, autobuild为旗下的其中一个repo )
2). cd git_repo && git –bare init
3). sudo git daemon –verbose –export-all –base-path=gir_repo –enable=upload-pack –enable=upload-archive –enable=receive-pack    (这个可以做成一个shell 也可以把git daemon注册成service, 这个就不再这里过多讨论了 各有喜好)

完成上述3步后, 一个简单的git server就搭好了, 现在我们需要将其clone出来到一个目录中用于接下来做autobuild环境. (今后每次receive commit后我们都会到这个目录做一次git pull更新最后一次提交, 并进行后续操作)

比如 我们将其clone到一个名为”/test_env”的目录下:
git clone git://127.0.0.1/autobuild test_env

好了到此, 搭建git server并准备autobuild环境目录已经完成, 接下来我们开始编写post-receive hook了.

2. Post-receive Hook:

刚刚也提到了, 这个脚本就是我们今天的主角, 那么我们先回到git_repo/autobuild目录来, 在这里面, 我们可以看到hooks目录, 进去之后我们可以找到post-receive.sample 这个模板, 将其rename为post-receive, 并添加我们需要的工作流程:

一个简洁的例子, 内容如下:

mailfile='autobuild.txt'
email='xxx@xx.com'

unset GIT_DIR 

# 1. git pull
cd /git_repo/autobuild
git pull > $mailfile

# 2. build
make clean
make --no-print-directory 2>> $mailfile

# 3. run test unit
make run_test --no-print-directory >> $mailfile

# 4. output to stdout for echo back
cat $mailfile

# 5. send a email to yourself
mail -s "Autobuild `date`" $email < $mailfile

上面的例子仅仅完成了我们工作流程中的目标, 并没有进行任何排版工作, 为了使邮件的格式更加清晰, 你可以在其中放置更多的echo, 比如打上一些横线作为分割, 写上一些提示语句, 这个就看大家自己的喜好了, 我就不在这里赘赘的描述了 :), 接下来, 你需要将这个repo加入到你本地的git remote列表中(使用remote add命令添加), 每当你想要autobuild的时候, 就将当前branch push到这个remote repo中, 你会在push执行时得到上述我们提到的所有反馈(build info, run test unit, receive a email for backup). That’s All.

最后, 附上一个我的邮件信息格式, 以供参考:

2011年 11月 27日 星期日 23:04:46 EST
hi, This is a Autobuild message, please don't reply!
------------------------Update Info-------------------------------
Merge made by recursive.
 ftu/Makefile |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

------------------------Build Result------------------------------
No errors

------------------------Test Result-----------------------------------
( test -d test && cd test && make run_test )
(cd ../final_libraries/bin && ./test )
FINAL TEST UNIT START...

 <<<<<<< CASE NAME:test_list DESCRIBE:for test flist >>>>>>>
[ALL ASSERT PASSED -- 11/11]

 <<<<<<< CASE NAME:test_hash DESCRIBE:for test fhash set and get >>>>>>>
0--2717/2775
1--3238/4163
2--2769/2775
3--3272/4163
4--2742/2775
5--3284/4163
6--2751/2775
7--3260/4163
8--2741/2775
9--3226/4163
total count = 30000 max_size = 34690(cost 589730 byte) use ratio=1.00 avg len=3000
hash iter totoal=30000
hashforeach totoal=30000
[ALL ASSERT PASSED -- 30003/30003]

 <<<<<<< CASE NAME:test_hash_del DESCRIBE:for test hash_del method >>>>>>>
hash del complete
[ALL ASSERT PASSED -- 20000/20000]

 <<<<<<< CASE NAME:test_mem DESCRIBE:for test mempool alloc and free >>>>>>>
main tid=47601252718336
tid=47601254823680
tid=47601256924928
mempool init complete tid=47601254823680
tid=47601254823680 size=4 diff_time:155540usec | 155ms
tid=47601256924928 size=4 diff_time:183863usec | 183ms
tid=47601254823680 size=12 diff_time:153841usec | 153ms
tid=47601256924928 size=12 diff_time:146459usec | 146ms
tid=47601256924928 size=20 diff_time:146551usec | 146ms
tid=47601254823680 size=20 diff_time:170322usec | 170ms
tid=47601256924928 size=30 diff_time:144495usec | 144ms
tid=47601254823680 size=30 diff_time:152498usec | 152ms
tid=47601256924928 size=36 diff_time:148525usec | 148ms
tid=47601254823680 size=36 diff_time:152242usec | 152ms
tid=47601256924928 size=60 diff_time:136363usec | 136ms
tid=47601254823680 size=60 diff_time:136486usec | 136ms
tid=47601256924928 size=100 diff_time:139143usec | 139ms
tid=47601254823680 size=100 diff_time:148458usec | 148ms
tid=47601256924928 size=180 diff_time:155570usec | 155ms
tid=47601254823680 size=180 diff_time:137590usec | 137ms
tid=47601254823680 size=300 diff_time:147943usec | 147ms
tid=47601256924928 size=300 diff_time:154894usec | 154ms
tid=47601254823680 size=600 diff_time:147344usec | 147ms
tid=47601256924928 size=600 diff_time:155993usec | 155ms
tid=47601254823680 size=1000 diff_time:149958usec | 149ms
tid=47601256924928 size=1000 diff_time:146590usec | 146ms
tid=47601254823680 size=1200 diff_time:140344usec | 140ms
tid=47601256924928 size=1200 diff_time:157028usec | 157ms
tid=47601254823680 size=3000 diff_time:154509usec | 154ms
tid=47601256924928 size=3000 diff_time:159357usec | 159ms
tid=47601254823680 size=5000 diff_time:148422usec | 148ms
tid=47601256924928 size=5000 diff_time:147129usec | 147ms
tid=47601254823680 size=8202 diff_time:151623usec | 151ms
tid=47601256924928 size=8202 diff_time:153929usec | 153ms
tid=47601254823680 size=16394 diff_time:146452usec | 146ms
tid=47601256924928 size=16394 diff_time:141301usec | 141ms
tid=47601254823680 size=51200 diff_time:257559usec | 257ms
tid=47601254823680 total diff_time:2651372usec | 2651ms avg=155ms
tid=47601256924928 size=51200 diff_time:243754usec | 243ms
tid=47601256924928 total diff_time:2661121usec | 2661ms avg=156ms
[ALL ASSERT PASSED -- 52094510/52094510]

 <<<<<<< CASE NAME:test_realloc DESCRIBE:for test mempool realloc >>>>>>>
[ALL ASSERT PASSED -- 8/8]

 <<<<<<< CASE NAME:test_log DESCRIBE:for test log system >>>>>>>
log work thread start
read log info:[2011-11-27 23:04:55][debug]:log test final

find ptr=0x7fff5036ce2d
[ALL ASSERT PASSED -- 3/3]

 <<<<<<< CASE NAME:test_mbuf DESCRIBE:for test mbuf of mbuf_seek & rewind & realloc >>>>>>>
[ALL ASSERT PASSED -- 31/31]

 <<<<<<< CASE NAME:test_mbuf1 DESCRIBE:for test mbuf of mbuf_push & mbuf_pop >>>>>>>
[ALL ASSERT PASSED -- 90/90]

 <<<<<<< CASE NAME:test_timer DESCRIBE:for test ftimerfd >>>>>>>
[ALL ASSERT PASSED -- 4/4]

 <<<<<<< CASE NAME:test_fev DESCRIBE:for test fev for create register add del methods >>>>>>>
[ALL ASSERT PASSED -- 18/18]

 <<<<<<< CASE NAME:test_fev_listener DESCRIBE:for test fev listener >>>>>>>
test listener thread startup
wait for poll
net_conn:connect sucess fd = 6
[ALL ASSERT PASSED -- 5/5]

 <<<<<<< CASE NAME:test_fev_buff DESCRIBE:for test fev buff >>>>>>>
wait for poll
net_conn:connect sucess fd = 6
read size=12, read_str=hello final
main recv str=hi final
evbuff error
error happened haha
[ALL ASSERT PASSED -- 22/22]

 <<<<<<< CASE NAME:test_fev_conn DESCRIBE:for test fev asynchronous connect >>>>>>>
main tid=47601252718336
wait for poll
accept sucessful
tid=47601256924928
[ALL ASSERT PASSED -- 2/2]

--------------------------------------
TOTAL CASE 13, PASS 13, FAILED 0

Best Regards! Final Autobuild Team

Comments are closed.