對(duì)于大部分的公司來說,搭建一套自動(dòng)化發(fā)版流程是必備的。自動(dòng)化發(fā)版的優(yōu)勢(shì):
- 節(jié)省溝通成本。讓項(xiàng)目,測(cè)試,軟件能更高效的運(yùn)轉(zhuǎn)。
- 節(jié)約人力,沒有自動(dòng)化發(fā)版,手動(dòng)發(fā)版的效率不忍直視。
對(duì)于沒有自動(dòng)化,或者自動(dòng)化程度不高的中小公司,低效帶來的人力成本是容易被忽視的,但是的確存在的。
自動(dòng)化發(fā)版可以自動(dòng)到什么程度,取決于團(tuán)隊(duì)對(duì)規(guī)則的執(zhí)行力,脫離了執(zhí)行力,再好的工具也是擺設(shè)。
一套完整的自動(dòng)化發(fā)版流程如下圖所示,本文重點(diǎn)介紹第一部分的實(shí)現(xiàn)。第二部分主要是一些Jenkins的郵件配置和releasenote的自動(dòng)生成腳本。

這套流程使用的工具:
bug管理工具: redmine
編譯工具: Jenkins服務(wù)器
版本服務(wù)器: ubuntu服務(wù)器
redmine/jira/mantis/禪道等bug/項(xiàng)目管理的優(yōu)缺點(diǎn),不做過多的討論,對(duì)于中心公司最關(guān)鍵的就是開源,免費(fèi)。開源可定制,免費(fèi)不花錢。
編譯服務(wù)器使用大名鼎鼎的Jenkins,如果jenkins都不知道,可以自行百度一下。
版本服務(wù)器沒有過多要求,就是存放服務(wù)器,使用ubuntu/windows系統(tǒng)都可以。這里使用ubuntu主要是因?yàn)閖enkins連接ubuntu使用ssh方式登錄,拷貝,更便捷。
一. redmine觸發(fā)Jenkins自動(dòng)編譯流程。
規(guī)則:計(jì)劃發(fā)布版本鏈接的問題,全部解決后redmine自動(dòng)觸發(fā)jenkins編譯
優(yōu)點(diǎn):redmine自動(dòng)觸發(fā)Jenkins編譯,無需額外人員手動(dòng)發(fā)布,多項(xiàng)目的發(fā)版,這套規(guī)則很實(shí)用。
具體步驟:
1. 項(xiàng)目管理人員:
1. 在redmine上建立對(duì)應(yīng)的project。
2. 建立計(jì)劃發(fā)布版本如 IOT_PCBA_V001_20200101。

2. 測(cè)試人員:
測(cè)試將所有需要在IOT_PCBA_V001_20200101版本解決的問題關(guān)聯(lián)到該目標(biāo)版本。

3. 開發(fā)人員:
開發(fā)人員提交bug,fix后更新redmine/JIRA的狀態(tài)到已解決。
腳本會(huì)定時(shí)檢測(cè)IOT_PCBA_V001_20200101版本的所有問題解決狀態(tài),當(dāng)所有問題是已經(jīng)解決,則開啟編譯。
具體實(shí)現(xiàn)自動(dòng)化觸發(fā)編譯腳本:
腳本實(shí)現(xiàn):python
1.設(shè)定一個(gè)定時(shí)器,定時(shí)查詢r(jià)edmine 計(jì)劃發(fā)布版本的問題狀態(tài)。
*/10 * * * * python /home/ubuntu/xl/auto-build/main.py
2.定時(shí)查詢r(jià)edmine各個(gè)計(jì)劃版本的問題解決狀態(tài),選擇服務(wù)器,觸發(fā)jenkins上的jobs編譯。
實(shí)現(xiàn)的主要步驟以及代碼:
- 查詢數(shù)據(jù)庫中計(jì)劃發(fā)布版本鏈接的問題是否解決
- 使用jenkins插件連接enkins服務(wù)器
- redmine的當(dāng)前版本的build字段是1,則說明已經(jīng)編譯了,無需再次編譯
- 尋找空閑服務(wù)器
- jenkins服務(wù)器開始編譯
- 更新redmine build字段,避免下次輪詢?cè)俅尉幾g
import jenkins
def Build(self, sqlite):
``` 1. 查詢數(shù)據(jù)庫中計(jì)劃發(fā)布版本鏈接的問題是否解決```
info_list = sqlite.GetBuildInfo()
if info_list == None or len(info_list) <= 0:
return
```2. 使用jenkins插件連接enkins服務(wù)器```
server = jenkins.Jenkins(contast.JENKINS_URL,
username=contast.JENKINS_USERNAME, password=contast.JENKINS_PASSWORD)
print server
print server.jobs_count()
for info in info_list:
param = {'versionname':None, 'buildtype': None, 'versionid':None }
param['buildtype'] = info['buildtype']
identifier = info['identifier']
param['versionname'] = info['versionname']
logging.debug('Build State:' + info['build'])
```3. redmine的當(dāng)前版本的build字段是1,則說明已經(jīng)編譯了,無需再次編譯```
if info['build'] == '1':return
logging.debug('Trigger Build! identifier:%s, %s' %(identifier, param))
```4. 尋找空閑服務(wù)器```
item = self.GetFreeServer(identifier)
if item == None:
logging.debug("Please Check Your Server,Maybe You Don't Config!!");
return
```5. jenkins服務(wù)器開始編譯```
server.build_job(item, param)
'''update version build states, don't build next time'''
version_id = info['versionid']
```6.更新redmine build字段,避免下次輪詢?cè)俅尉幾g```
sqlite.UpdateBuildField(version_id)