由於專案需要在幾個桌面環境建構發行包 (distribution packages), 不久也想在 Raspberry Pi 上面進行 , 需要一個可以在不同平台環境上自動執行建置工作的軟體 。 基於過去比較與使用的經驗 , 山姆鍋選擇了 Buildbot 來進行這項工作 。

選擇 Buildbot 主要考量 :

  1. 對於主機的要求較低

    只需要基本 Python 執行環境 , 有網路連接便可運作 。 而 Python 本身跨平台的特性 , 使得 Buildbot 也容易支援不同的系統環境 。

  2. 參與者可以貢獻主機

    這點尤其對於需要支援多種用戶環境的專案更重要 。Buildbot 的 slaves 可以在防火牆之後 , 這樣的架構讓參與者相對容易可以貢獻自己的主機來協助專案建置的工作 。

Buildbot 是一套以 Python 開發的持續整合 (continuous integration) 伺服器軟體 , 對於 Buildbot 的介紹可以參考官方文件 :http://docs.buildbot.net/current/manual/introduction.html 。 本文假設您已經了解何謂 「 持續整合 (continuous integration)」 以及 Buildbot 的基本概念 。

安裝 Buildbot Master

建立虛擬環境

雖然不是必須 , 但這裏山姆鍋假設使用 virtualenv 來設定 Buildbot master 跟 slave 的執行環境 。

virtualenv bbenv-master

安裝 Buildbot master 套件

pip install buildbot

之前的經驗 , 如果會遇到問題大多跟 twisted 這個套件有關 , 不過新版已經比較少遇到問題了 。

設定 Master 基本環境

buildbot create bb-master

會建立 bb-master 這個目錄 , 在其中建立相關必要檔案 。

修改 Master 設定

根據 Slave 數量 、 種類以及要建置的專案修改設定 。 由於是實際例子 , 這裏山姆鍋共有三個 slaves 以及一個專案需要建置 。 Master 設定主要由 bb-master 中的 master.cfg' 檔案決定 , 而這個檔案通常以 Buildbot 提供的 `master.cfg.sample 作為基礎來修改 。

底下列出跟 master.cfg.sample 比較主要修改的內容 。

設定 Slaves 使用的登入名稱跟密碼 :

c['slaves'] = [
    buildslave.BuildSlave("macosx-slave", "pass1234"),
    buildslave.BuildSlave("win7x64-slave", "pass1234"),
    buildslave.BuildSlave("ubuntux64-slave", "pass1234")]

從名稱可以猜測這個專案在 Windows 7, Ubuntu, OS X 上 各有一個 slave。

設定使用輪詢方式偵測代碼更動 :

c['change_source'].append(changes.GitPoller(
    'https://github.com/eavatar/eavatar-me.git',
    workdir='gitpoller-workdir', branch='master',
    pollinterval=300))

由於這個例子 master 跟 slave 都在本地主機執行 , 並沒有設定使用 Webhook。 關於 Webhook 的使用說明 , 請參考 :http://docs.buildbot.net/0.8.10/manual/cfg-statustargets.html#change-hooks

設定當代碼有變動時的處置方式 , 在 Buildbot 這是由 Schedulers 物件決定 :

c['schedulers'].append(schedulers.SingleBranchScheduler(
                        name="all",
                        change_filter=util.ChangeFilter(branch='master'),
                        treeStableTimer=None,
                        builderNames=["macosx_packer", "ubuntux64_packer", "win7x64_packer"]))
c['schedulers'].append(schedulers.ForceScheduler(
                        name="force",
                        builderNames=["macosx_packer", "ubuntux64_packer", "win7x64_packer"]))

這裡的範例設定當變動是發生在 master 這個分支 (branch) 或者手動強制執行時 , 啟動 "macosx_packer", "ubuntux64_packer", "win7x64_packer" 這幾個 Builders。

設定 Builders:

c['builders'].append(
    util.BuilderConfig(name="macosx_packer",
    slavenames=["macosx-slave"],
    factory=factory))

c['builders'].append(
    util.BuilderConfig(name="ubuntux64_packer",
    slavenames=["ubuntux64-slave"],
    factory=factory))

c['builders'].append(
    util.BuilderConfig(name="win7x64_packer",
    slavenames=["win7x64-slave"],
    factory=factory))

Builder 物件決定構建的工作要由哪些 slaves 執行以及構建該使用的步驟 ( 由 BuildFactory 物件定義 )。 一個 Builder 物件可以將工作指派給多個 slave, 而一個 slave 可以同時承接來自不同 builder 物件的工作 。

設定 BuildFactory:

BuildFactory 定義當 Slave 要實際建構專案時須執行的步驟 , 山姆鍋通常使用 ShellCommand 來呼叫外部程式進行建構工作 , 如範例所示 :

factory.addStep(steps.Git(repourl='https://github.com/eavatar/eavatar-me.git', mode='incremental'))
factory.addStep(steps.ShellCommand(command=["git", "submodule", "init"]))
factory.addStep(steps.ShellCommand(command=["git", "submodule", "update"]))
factory.addStep(steps.ShellCommand(command=["pip", "install", "-r", "requirements.txt"]))

第一個步驟是取出專案原始碼 , 除了 Git, Builbot 也支援常見的版本管理系統 。 其它內容已經被刪減 , 實際上需要根據不同的專案修改 。

基本安全認證

為了限制只有特定使用者可以管理 Buildbot, 設定網頁管理介面需要做身份認證 , 在 master.cfg 設定當中 , 找到 authz_cfg , 在其中修改 auth 成如下 ,

authz_cfg=authz.Authz(
    auth=auth.BasicAuth([("username","password")]),
    ...

記得將 usernamepassword 改成您要使用的登入名稱跟密碼 。

啟動 Master

設定完成後 , 需要先啟動 master, 在設定 slave 時需要用到 。

將目前目錄改到 bb-master 後 , 使用指令 :

buildbot start

如果看到 The buildmaster appears to have (re)started correctly 而沒有其它錯誤訊息 ,master 應該有正確執行了 , 如果有 tail 工具程式的話 , 可以使用下列指令檢視執行紀錄 :

tail -f twisted.log

開啟另一個終端機視窗 , 準備安裝 Buildbot slave。

安裝 Buildbot Slave

在擔任 Buildbot slave 的主機上 , 按照以下步驟安裝與設定 :

virtualenv bbenv-slave

安裝 Slave 套件

pip install buildbot-slave

通常在這裡階段 , 山姆鍋也會同時安裝專案建構所需的大部份系統以及應用套件 , 主要理由是 :

  1. 套件可能無法自動安裝
  2. 套件安裝需要耗費時間

設定 Slave 環境

buildslave create-slave <basedir> <master> <name> <passwd>

其中 ,

  • <basedir> 是 slave 的工作目錄

    本文假設此目錄為 bb-slave

  • <master> 是 master 對外的網址

    這個跟安裝所在的主機位址跟使用的 port 有關 , 如果只需要從本地連結的話 , 可以使用 : localhost:9989

  • <name>

    此 slave 在 master 中的登入名稱 。

  • <passwd>

    此 slave 登入 master 時使用的密碼 。

啟動 Slave

上述步驟都完成後 , 將更換當前目錄到 bb-slave, 使用下列指令啟動 slave:

buildslave start

安裝其它 Slaves

其它平台使用同樣的方式設定 , 但使用不同的登入名稱跟密碼 。

觸動專案建置

基本上 , 觸動專案建置的方式有下列三種 :

  1. 使用者手動

    也就是透過網頁介面 , 強制 Buildbot 建置專案 。 此方法適用在測試專案建置步驟 , 這種代碼沒有更動的情況下 , 讓 Buildbot 無條件執行建置動作 。

  2. 代碼庫輪詢

    透過輪詢方式 ,Buildbot 定時監控代碼庫 (code repository), 如果有更動則建置相對應的專案 。

  3. Webhook 驅動

    有些代碼庫的代管服務可以透過 webhook 機制在代碼有更動時即時通知 Buildbot 或其它外部系統 。 這種方法會比第二種方法更即時 , 但需要 Buildbot master 放在公開的主機上 , 或透過 ngrok 這種轉接服務 。

Buildbot 網頁介面

在撰寫專案構建步驟時 , 常需要手動觸動建構工作 , Buildbot 預設的網頁介面位址為 : http://localhost:8010, 需要根據連線的來源將 localhost 更換為其它網址 。

如果您有設定需要登入的話 , 要透過網頁介面管理 Buildbot, 需要先登入 。

結語

誠然 , 有更好用的 CI 軟體或服務 , 但對於需要在各種不同用戶平台上進行編譯 、 測試與打包工作的專案 , Buildbot 也很適合 。 例如 : 需要支援多種作業系統的 Chromium 瀏覽器便利用 Buildbot 的這個特性在不同平台建置 。 另外 , Buildbot 的架構設計讓專案參與者可以方便貢獻自己的電腦或裝置 來作為 Slaves。

要說 Buildbot 的主要缺點的話 , 那應該就是 : 設定檔對一般使用者不是那麼友善 , 需要了解不少概念 。