歡迎大家前往騰訊云+社區,獲取更多騰訊海量技術實踐干貨哦~
本文由angel_郁發表于云+社區專欄
介紹
Buildbot是一個基于Python的持續集成系統,用于自動化軟件構建,測試和發布過程。
在本教程中,我們將演示如何設置持續集成系統以自動測試對存儲庫的新更改。我們將使用一個簡單的Node.js應用程序來演示測試過程和必要的配置。為了將我們的測試環境與Buildbot主機隔離,我們將創建一個Docker鏡像作為Buildbot worker運行。然后,我們將配置Buildbot主服務器以觀察GitHub存儲庫的更改,每次檢測到新的更改時自動進行測試。
準備
要學習本教程,您需要:
- 一個具有至少1 GB的RAM的Ubuntu16.04服務器,并包括一個可以使用sudo命令的非root 用戶。
另外,在開始本教程之前需要完成以下內容:
如何在Ubuntu上安裝Buildbot
安裝Nginx
在Ubuntu上使用SSL來保護Nginx
給Buildbot加上SSL,使用Nginx做反向代理
搭建Docker環境
在GitHub中使用fork示例存儲庫
在我們開始配置Buildbot之前,我們將看一下我們將用于本教程的示例存儲庫。
在您的Web瀏覽器中,訪問我們將用于演示的GitHub上的hello hapi應用程序。這個應用程序是一個簡單的“hello world”程序,帶有一些單元和集成測試,用hapi編寫的一個Node.js Web框架。
由于此示例用于演示各種持續集成系統,您可能會注意到一些文件用于為其他系統定義管道。對于Buildbot,我們將在服務器上而不是在存儲庫中定義構建步驟。
稍后,我們將在我們的存儲庫中為Buildbot設置webhook,以便更改將自動觸發新測試。現在,我們需要創建自己的存儲庫分支。
單擊屏幕右上角的Fork按鈕:
GitHub fork 按鈕
如果您是GitHub組織的成員,可能會詢問您在哪里使用fork存儲庫:
哪里使用fork存儲庫
選擇帳戶或組織后,存儲庫的副本將添加到您的帳戶中:
存儲庫的副本將添加到您的帳戶
您將在Buildbot配置中使用fork的URL。現在我們有了一個存儲庫URL,我們可以開始配置Buildbot了。
為Buildbot設置Docker
我們將從設置Docker開始,以便Buildbot使用它來執行構建。首先,我們需要配置Docker和Buildbot之間的訪問。之后,我們需要創建一個Docker鏡像以用于我們的容器。
為Buildbot配置Docker訪問
我們需要允許Buildbot和Docker在幾個不同的級別進行通信。
首先,我們需要確保Buildbot進程可以訪問Docker守護程序。我們可以通過將做到這一點buildbot用戶的docker組:
$ sudo usermod -aG docker buildbot
下次重新啟動Buildbot主服務器時,這個新組將可用于Buildbot,我們稍后會這樣做。
我們還需要確保Buildbot知道如何與Docker通信。由于Buildbot是用Python編寫的,它利用docker-py
Python包而不是直接發出Docker命令。
您可以輸入以下命令安裝docker-py
:
$ sudo -H pip install docker-py
最后,我們需要打開從容器到主機系統和外部世界的網絡訪問。我們可以通過在防火墻中允許docker0
的接口例外來實現此目的。
通過輸入以下內容允許從docker0
界面訪問流量:
$ sudo ufw allow in on docker0
Buildbot和Docker現在應該能夠有效地相互通信。
創建一個Docker鏡像以用作Buildbot Worker
接下來,我們將創建一個Docker容器,用作Buildbot worker來運行我們的測試。Buildbot可以動態啟動Docker容器以用作worker,但首先需要使用包含的一些Buildbot worker組件構建容器。
幸運的是,Buildbot項目提供了一個基本的Buildbot worker映像,該鏡像已經配置了所有特定于Buildbot的需求。我們只需要將此鏡像用作基礎并安裝我們項目所需的其他依賴項。
在我們的例子中,我們將使用的示例應用程序是Node.js應用程序,因此我們需要確保Node.js在鏡像上可用。
要定義我們的鏡像,請創建并打開Dockerfile在主目錄中調用的文件:
$ nano ~/Dockerfile
在這個文件中,我們使用了基于Buildbot worker的鏡像FROM buildbot/buildbot-worker:master
。之后,我們可以切換到root
用戶安裝Node.js
,然后切換回buildbot用戶運行實際命令:
?/ Dockerfile
FROM buildbot/buildbot-worker:masterUSER root
RUN curl -sL https://deb.nodesource.com/setup_8.x | bash -
RUN apt-get install -y nodejs
USER buildbot
完成后保存并關閉文件。
一旦我們擁有了Dockerfile
,我們就可以從中構建我們的鏡像。我們將調用鏡像npm-worker
來明確我們安裝的額外依賴項:
$ docker build -t npm-worker - < ~/Dockerfile
Docker將根據我們在其中列出的命令開始構建您的鏡像Dockerfile
。它將下拉基本鏡像及其依賴層,安裝Node.js
,然后將生成的環境保存到一個名為npm-worker
的鏡像中。
配置Buildbot主服務器
現在我們有了Docker鏡像,我們可以配置Buildbot主機來使用它。
因為我們正在定義一個全新的構建過程,并且因為到目前為止我們對主配置的定制很少,所以我們將從頭開始配置。為避免丟失當前信息,我們將原始文件移動到備份文件:
$ sudo mv /home/buildbot/master/master.cfg /home/buildbot/master/master.cfg.bak
顯示備份文件的配置,以便我們可以復制一些重要值以在新配置中使用:
$ sudo cat /home/buildbot/master/master.cfg.bak
我們要轉移到新配置的重要部分是用戶憑據和權限。在輸出中查找c['www']['authz']
和c['www']['auth']
開頭的配置部分:
. . .
c['www']['authz'] = util.Authz(allowRules = [util.AnyEndpointMatcher(role="admins")],roleMatchers = [util.RolesFromUsername(roles=['admins'], usernames=['Sammy'])]
)
c['www']['auth'] = util.UserPasswordAuth({'Sammy': 'Password'})
. . .
將這些行復制并保存在某處,以便以后可以引用它們。我們將這些詳細信息添加到我們的新Buildbot主配置中,以保留我們的用戶和身份驗證設置。
現在,創建一個新master.cfg
文件,我們可以在其中重新定義Buildbot實例的行為:
$ sudo nano /home/buildbot/master/master.cfg
我們將在此文件中定義新的Buildbot主配置。
設置基本項目配置
Buildbot配置文件實際上是一個Python模塊,它以犧牲一些復雜性為代價提供了極大的靈活性。
我們將從一些基本配置開始。將以下行粘貼到您的文件中:
/home/buildbot/master/master.cfg
# -*- python -*-
# ex: set filetype=python:
from buildbot.plugins import *c = BuildmasterConfig = {}# Basic config
c['buildbotNetUsageData'] = None
c['title'] = "Hello Hapi"
c['titleURL'] = "https://github.com/your_github_name/hello_hapi"
c['buildbotURL'] = "https://buildmaster_domain_name/"
c['protocols'] = {'pb': {'port': 9989}}
該文件的頂部包含一些注釋,許多文本編輯器能夠解釋這些注釋以正確應用語法高亮顯示。然后,我們從buildbot.plugins
包中導入所有內容,以便我們可以使用工具來構建配置。
Buildbot配置全部由名為BuildmasterConfig
的字典定義,因此我們將此變量設置為空字典以啟動。
我們創建一個名為c
的速記變量,設置為同一個字,以減少整個文件中所需的輸入量。
下面的配置中需要注意的一些事項:
buildbotNetUsageData
設置為None
。如果要向開發人員報告使用情況數據,請將其更改為字符串"basic"
。title
和titleURL
反映項目的名稱和GitHub的倉庫。使用指向您自己的fork的鏈接。buildbotURL
設置為Buildbot主服務器的SSL安全域名。記得從https://
開始并以尾部斜杠/
結束。與我們的上一個配置不同,該
protocol
定義并不會和本地主機綁定。我們需要通過Docker橋接網絡docker0
允許來自Docker容器的連接。
配置Docker Worker
接下來,我們需要定義我們的Docker worker。Buildbot將根據需要使用Docker來配置工作人員。為此,它需要知道如何連接到Docker以及使用哪個映象。
將以下內容粘貼到文件的底部:
/home/buildbot/master/master.cfg
. . .# Workers
c['workers'] = []
c['workers'].append(worker.DockerLatentWorker("npm-docker-worker", None,docker_host='unix://var/run/docker.sock',image='npm-worker',masterFQDN='buildmaster_domain_name'))
該c['workers'] =[]
行演示了我們在完成配置時將使用的基本約定。我們將配置字典中的鍵設置為空列表。然后,我們將元素附加到列表以實現實際配置。這使我們可以在以后添加其他元素。
為了定義我們的worker,我們創建一個worker.DockerLatentWorker
實例并將其追加到worker
列表中。我們將此工作者命名為npm-docker-worker
,以便稍后在配置中引用它。然后我們將docker_host
設置為Docker的套接字位置,并提供我們創建的Docker鏡像的名稱(在我們的例子中為npm-worker)。我們將masterFQDN
設置為Buildbot master的域名,以確保容器可以到達主服務器,而不管服務器的內部主機名設置如何。
配置調度程序
接下來,我們將定義一個調度程序。Buildbot使用調度程序根據從變更源或更改掛鉤收到的更改來決定何時以及如何運行構建(稍后我們將配置更改掛鉤)。
將以下配置粘貼到文件的底部:
/home/buildbot/master/master.cfg
. . .# Schedulers
c['schedulers'] = []
c['schedulers'].append(schedulers.SingleBranchScheduler(name="hello_hapi",change_filter=util.ChangeFilter(project='your_github_name/hello_hapi', branch='master'),treeStableTimer=3,builderNames=["npm"]))
我們使用相同的方法將配置附加到空列表中。在這種情況下,我們附加一個schedulers.SingleBranchScheduler
實例。這允許我們在存儲庫中觀察單個分支,并簡化了配置。
我們將調度程序命名為“hello_hapi”以正確識別它。然后我們定義一個更改過濾器。來自不同來源的許多不同變更集可以交給調度程序。更改過濾器定義一組標準,用于確定此特定調度程序是否應處理相關更改。在我們的例子中,我們根據項目名稱進行過濾,這將由GitHub webhook和我們希望觀看的分支報告。
接下來,我們將treeStableTimer設置為3秒,該treeStableTimer確定等待其他更改的時間量。這有助于防止Buildbot為與密切相關的更改排隊許多小型構建。最后,我們定義當更改符合我們的條件時應該使用的構建器的名稱(我們將暫時定義此為構建器)。
為Node.js項目配置構建工廠
接下來,我們將配置一個用于處理Node.js項目的構建工廠。構建工廠負責定義構建或在我們的案例測試中應該采取的步驟。它通過定義util.BuildFactory
實例然后添加應執行的順序步驟來完成此操作。
將以下內容粘貼到文件的底部:
/home/buildbot/master/master.cfg
. . .# Build Factories
npm_f = util.BuildFactory()
npm_f.addStep(steps.GitHub(repourl='git://github.com/your_github_name/hello_hapi.git', mode='full', method='clobber'))
npm_f.addStep(steps.ShellCommand(command=["npm", "install"]))
npm_f.addStep(steps.ShellCommand(command=["npm", "test"]))
首先,我們定義一個名為npm_f的構建工廠。我們添加的第一步是steps.GitHub
實例。在這里,我們設置應該下拉到構建器中的存儲庫。我們設置mode
為“full”
和method“clobber”
以在每次提取新代碼時完全清理我們的存儲庫。
我們添加的第二個和第三個步驟是steps.ShellCommand
對象,它們定義在構建期間在存儲庫中運行的shell命令。在我們的例子中,我們需要運行npm install
以收集項目的依賴項。之后,我們需要運行npm test
以運行我們的測試套件。在大多數情況下,建議將命令定義為一個list (["npm","install"])
,以防止shell對命令中的元素應用不需要的擴展。
配置構建器
一旦我們有一個添加了步驟的構建工廠,我們就可以設置一個構建器。構建器將我們已定義的許多元素綁定在一起,以確定構建的執行方式。
將以下配置粘貼到文件的底部:
/home/buildbot/master/master.cfg
. . .# Builders
c['builders'] = []
c['builders'].append(util.BuilderConfig(name="npm",workernames=["npm-docker-worker"],factory=npm_f))
我們將一個util.BuilderConfig
對象附加到builders
列表中。請記住,我們的構建工廠名為npm_f
,我們的Docker工作者稱為npm-docker-worker
,我們定義的調度程序將把任務傳遞給名為npm的worker。。我們的構建器定義了這些元素之間的關系,以便我們的調度程序的更改將導致構建工廠步驟在Docker worker中執行。
配置數據庫和Web界面
最后,我們可以配置數據庫和Web界面設置。與之前的許多項目不同,這兩個設置被定義為字典而不是列表。該db
字典只指向/home/buildbot/master
目錄中已有的state.sqlite
文件。www
詞典包含大量額外配置。
將以下內容粘貼到文件的底部。將您從原始Buildbot主配置中復制的身份驗證信息替換為以下身份驗證塊:
/home/buildbot/master/master.cfg
. . .# Database
c['db'] = { 'db_url': "sqlite:///state.sqlite",}# Web Interface
c['www'] = dict(port=8010, plugins=dict(waterfall_view={}, console_view={}))# Auth info copied from the original configuration
c['www']['authz'] = util.Authz(allowRules = [util.AnyEndpointMatcher(role="admins")],roleMatchers = [util.RolesFromUsername(roles=['admins'], usernames=['Sammy'])]
)
c['www']['auth'] = util.UserPasswordAuth({'Sammy': 'Password'})
# End of auth info copied from the original configuration# GitHub webhook receiver
c['www']['change_hook_dialects'] = {'github': {'secret': 'your_secret_value','strict': True,}
}
在定義數據庫設置之后,我們創建一個www
字典,該字典首先定義要偵聽的端口以及要包含在Web UI中的一些視圖。接下來,我們添加從先前的Buildbot配置文件中提取的身份驗證要求。
最后,我們在www
字典中定義了一個名為change_hook_dialects
的字典。我們使用它來定義一個GitHub更改掛鉤,它將偵聽來自GitHub的webhook消息。為您的機密選擇一個安全密碼,GitHub將使用該密碼來驗證它將發送的消息。
完成后,保存并關閉文件。
重新啟動Buildbot Master以應用新配置
此時,我們已經完全重新配置了Buildbot主進程。我們需要重新啟動Buildbot主進程來實現更改。
在我們這樣做之前,檢查我們的文件是否有重要的語法錯誤。由于我們從頭開始重建配置,因此我們很可能會引入一些錯誤。
輸入以下命令檢查文件的語法:
$ sudo buildbot checkconfig /home/buildbot/master
該命令將報告它找到的任何問題。如果未找到任何錯誤,您將收到如下消息:
Config file is good!
如果報告了任何錯誤,請仔細閱讀錯誤消息,以便更好地了解錯誤。再次打開配置文件以嘗試解決任何問題。
如果不再出現任何錯誤,請輸入以下命令重新啟動Buildbot主服務:
$ sudo systemctl restart buildbot-master
輸入以下命令檢查操作是否成功:
$ sudo systemctl status buildbot-master
● buildbot-master.service - BuildBot master serviceLoaded: loaded (/etc/systemd/system/buildbot-master.service; enabled; vendor preset: enabled)Active: active (running) since Tue 2017-06-27 19:24:07 UTC; 2s agoMain PID: 8298 (buildbot)Tasks: 2Memory: 51.7MCPU: 1.782sCGroup: /system.slice/buildbot-master.service└─8298 /usr/bin/python /usr/local/bin/buildbot start --nodaemonJun 27 19:24:07 bb5 systemd[1]: Started BuildBot master service
如果服務能夠成功重新啟動,則會將其標記為活動狀態。
在示例存儲庫中創建GitHub Webhook
現在Buildbot配置了一個Web端點來接受GitHub webhook帖子,我們可以為我們的fork配置一個webhook。
在Web瀏覽器中,導航到示例項目存儲庫的fork:
https://github.com/your_github_user/hello_hapi
單擊“設置”選項卡以查看項目設置。在設置頁面的左側菜單中,單擊Webhooks(GitHub可能會提示您在此過程中重新輸入密碼以確認您的身份):
項目設置
單擊右側的“ 添加webhook”按鈕以添加新的webhook。
下面的頁面將包含一個用于定義webhook的表單。在Payload URL字段中,添加項目的GitHub更改的URL。這是通過指定https://
協議,然后是Buildbot master的域名,然后是/change_hook/github
構建的。
將內容類型設置為application/x-www-form-urlencoded
。在“密碼”字段中,輸入您在Buildbot主配置文件中選擇的秘密密碼。您可以選中“Just push”事件觸發器,勾選“Active”復選框:
添加新的webhook
完成后,單擊“ 添加webhook”按鈕。
您將返回到項目的webhooks索引,在該索引中將顯示您的新webhook。如果刷新幾次,則應在webhook旁邊顯示綠色復選標記圖標,表示郵件已成功傳輸:
webhooks索引
如果您看到紅色的X,請再次單擊webhook,然后向下滾動到Recent Deliveries部分。如果您單擊failed delivery,可以獲得有關出現問題的更多信息。
測試Webhook
現在我們已經有了webhook,我們可以測試以確保當我們對存儲庫進行更改時,Buildbot會被警告,觸發Docker中的構建,并且能夠成功執行測試套件。
在GitHub fork的主頁面中,單擊綠色“克隆或下載”按鈕左側的“ 創建新文件 ”按鈕:
創建新文件
在隨后的屏幕上,創建dummy_file
并填寫一些文本:
dummy_file
完成后,單擊頁面底部的“ 提交新文件”按鈕。
接下來,訪問您的Buildbot Web界面,如果您尚未通過身份驗證,請登錄。
根據您提交dummy_file
到存儲庫后的時間長度,您可能會看到正在進行的構建,如下所示:
Buildbot 正在構建
如果構建已經完成,則它將位于“最近構建”部分中:
構建完成
我們定義的構建器名稱“npm”用于標記構建。在該示例中,我們還可以從先前的主配置中看到較早的樣本構建器運行。
無論進度如何,單擊構建器名稱和內部版本號鏈接以訪問構建詳細信息頁面。此視圖包含有關所執行的構建的信息。我們添加到構建工廠的每個步驟都將顯示在其自己的部分中:
構建詳細信息
如果單擊某個步驟,將顯示該命令的輸出。如果出現問題,這可以幫助調試:
調試輸出
在上面的輸出中,我們可以驗證Buildbot是否在我們的測試套件中成功運行了三個測試。
如果構建未成功完成,您可能希望檢查的其他一些區域是構建詳細信息頁面上的其他選項卡以及/home/buildbot/master/twistd.log
文件。
調整Buildbot服務
在我們完成之前,我們應該對我們的Buildbot服務進行一些調整。
目前,我們為不再使用的工作人員定義了buildbot-worker
服務(我們的Docker工作程序在需要時自動啟動)。
我們應該停止并禁用old worker。
要停止正在運行的服務并禁止它在引導時啟動,請輸入:
$ sudo systemctl stop buildbot-worker
$ sudo systemctl disable buildbot-worker
Removed symlink /etc/systemd/system/buildbot-master.service.wants/buildbot-worker.service.
上面的輸出結果表明工作人員下次啟動時不會啟動。要驗證服務是否不再運行,請輸入:
$ sudo systemctl status buildbot-worker
● buildbot-worker.service - BuildBot worker serviceLoaded: loaded (/etc/systemd/system/buildbot-worker.service; disabled; vendor preset: enabled)Active: inactive (dead)Jun 27 21:12:48 bb6 systemd[1]: Started BuildBot worker service.
Jun 27 21:55:51 bb6 systemd[1]: Stopping BuildBot worker service...
Jun 27 21:55:51 bb6 systemd[1]: Stopped BuildBot worker service.
我們應該做的最后一件事是在Buildbot主服務和Docker守護進程之間建立一個soft依賴項。由于Buildbot主服務無法在沒有Docker的情況下配置new workers,因此我們應該定義此要求。
打開/ etc / systemd / system
目錄中的buildbot-master.service
文件以調整服務文件:
$ sudo nano /etc/systemd/system/buildbot-master.service
在[Unit]
部分中,將docker.service
添加到network.target
項之后的After指令中。添加另一個名為docker.service
的Wants
指令。Wants建立了一個軟依賴,而After
指令建立了起始順序:
/etc/systemd/system/buildbot-master.service
[Unit]
Description=BuildBot master service
After=network.target docker.service
Wants=docker.service[Service]
User=buildbot
Group=buildbot
WorkingDirectory=/home/buildbot/master
ExecStart=/usr/local/bin/buildbot start --nodaemon[Install]
WantedBy=multi-user.target
完成后保存并關閉文件。
重新加載systemd守護程序和服務以立即應用配置:
$ sudo systemctl daemon-reload
$ sudo systemctl restart buildbot-master
現在應該在Docker可用之后啟動Buildbot主進程。
結論
在本教程中,我們將Buildbot配置為使用webhooks監聽對GitHub存儲庫的更改。收到更改后,Buildbot會根據自定義Docker鏡像啟動容器以測試新提交。Docker鏡像包含一個Buildbot工作器實例以及測試項目代碼所需的依賴項。這允許Buildbot在對存儲庫進行更改時根據需要動態啟動Buildbot worker。
參考文獻:《How To Set Up Continuous Integration with Buildbot on Ubuntu 16.04》
問答
騰訊云服務器?
相關閱讀
教你從0到1搭建小程序音視頻
教你快速搭建一場發布會直播方案
移形換影 - 短視頻色彩特效背后的故事
此文已由作者授權騰訊云+社區發布,原文鏈接:https://cloud.tencent.com/developer/article/1178239?fromSource=waitui
歡迎大家前往騰訊云+社區或關注云加社區微信公眾號(QcloudCommunity),第一時間獲取更多海量技術實踐干貨哦~
海量技術實踐經驗,盡在云加社區! https://cloud.tencent.com/developer?fromSource=waitui