CI環境が欲しければCircle CIなりTravis CIなりを使うのが一般的だが、クローズドなリポジトリを運用している場合は自前で立てる必要がある。
よくあるのはJenkinsなのだろうが、今回はリポジトリがmercurialかつFlaskのプロジェクトが対象だったので、なんとなくPythonで揃えてBuildbotを選択してみた。
- ことはじめ
- 設定ファイル
Buildbotの仕様
Buildbot Basicsを読んでもらえばわかるのだが、BuildbotはMasterとWorkerのふたつで構成される。
MasterはTwistedで書かれているようで、リポジトリへのポーリングやWorkerへの依頼、Webインターフェイスなどをこなす。WorkerはMasterから依頼されて実際のビルド処理やテストなどを行う。
チュートリアル
試しにMasterとWorkerを作って連携するところまで試してみよう。
ここでは、作成直後に記述されているGithub上の buildbot/hello-world で構築する。
やり方はFirst Runにあるのでそちらを参照にしつつ、今回は手頃なEC2インスタンス(Ubuntu)上に構築してみた。
Docker環境がある人は手っ取り早くFirst Buildbot run with Dockerをどうぞ。
Master作成
適当なvirtualenvを立ててpipで導入。
$ virtualenv buildbot -p python3
$ source buildbot/bin/activate
$ pip install --upgrade pip
$ pip install 'buildbot[bundle]'
必要なのは python3
, virtualenv
, python3-dev
と、あとデフォルトだとSQLiteなので sqlite
くらいだろうか。
導入次第、適当なディレクトリに移ってMasterを作ってみる。
$ buildbot create-master master
mkdir /home/ubuntu/sites/master
creating /***/***/master/master.cfg.sample
creating database (sqlite:///state.sqlite)
buildmaster configured in /***/***/master
$ cp master/master.cfg.sample master/master.cfg
お好みで設定ファイル master/master.cfg
を修正。
masterディレクトリと同じ階層に移動し、Master開始。
$ buildbot start master
Following twistd.log until startup finished..
The buildmaster appears to have (re)started correctly.
これで、 localhost:8010
にMasterが立つ。見てみるとこんな感じ。
もしnginxなどで外部に80番で出したい場合、/ws
でWebsocket通信しているのでそこだけ注意。また、 /sse/
は一応バッファリングしない方が良い。
server {
listen 80;
listen [::]:80;
server_name subdomain.domain.tld;
proxy_set_header HOST $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-Host $host;
location / {
proxy_pass http://localhost:8010;
}
location /sse/ {
proxy_buffering off;
proxy_pass http://localhost:8010/sse/;
}
location /ws {
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass http://localhost:8010/ws;
proxy_read_timeout 6000s;
}
}
Worker作成
次にWorkerの構築。
Masterの環境にも buildbot-worker
は導入されているので同じvirtualenvを用いても良いのだが、実運用だとWorkerにしか入れないパッケージなどもありそうなのでvirtualenvを新規作成。
$ virtualenv worker -p python3
$ source worker/bin/activate
$ pip install --upgrade pip
$ pip install buildbot-worker
Workerはテストを行う側なので、テストプロジェクト内で使われている runtests
を導入。
$ pip install setuptools-trial
Workerを構築する前に、Master側の master.cfg
の以下を確認(必要ならば修正)しておく。
これがMasterとWorkerが会話するためのユーザとパスワードになる。
####### WORKERS
# The 'workers' list defines the set of recognized workers. Each element is
# a Worker object, specifying a unique worker name and password. The same
# worker name and password must be configured on the worker.
c['workers'] = [worker.Worker("example-worker", "pass")]
example-worker
がユーザ、pass
がパスワードとなる。
同じく接続先の確認。
# 'protocols' contains information about protocols which master will use for
# communicating with workers. You must define at least 'port' option that workers
# could connect to your master with this protocol.
# 'port' must match the value configured into the workers (with their
# --master option)
c['protocols'] = {'pb': {'port': 9989}}
ポート 9989
の定義のみなのでこのままローカル(無指定だと規定値の9989
)で繋ぐ。
$ buildbot-worker create-worker worker localhost example-worker pass
mkdir /***/***/worker
mkdir /***/***/worker/info
Creating info/admin, you need to edit it appropriately.
Creating info/host, you need to edit it appropriately.
Not creating info/access_uri - add it if you wish
Please edit the files in /***/***/worker/info appropriately.
worker configured in /***/***/worker
では、Masterと同じくWorkerも走らせる。
$ buildbot-worker start worker
Following twistd.log until startup finished..
The buildbot-worker appears to have (re)started correctly.
lsof
あたりで確認すると次のようになってるはず。
$ lsof -i
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
python3 xxxx user 00u IPv4 yyyyy 0t0 TCP *:8010 (LISTEN)
python3 xxxx user 00u IPv4 yyyyy 0t0 TCP *:9989 (LISTEN)
python3 xxxx user 00u IPv4 yyyyy 0t0 TCP localhost:9989->localhost:37564 (ESTABLISHED)
buildbot- xxxx user 00u IPv4 yyyyy 0t0 TCP localhost:37564->localhost:9989 (ESTABLISHED)
この段階で既に master/master.cfg
で定義されているリポジトリに対して gitpoller
がポーリングを仕掛け始めているはず。
ビルド実行
ポーリング先に変更があればビルドが走るわけだが、今回はGitHub上の公開リポジトリなので変更を発生させるのも面倒なので、強制的にビルドを走らせてみる。
Builds / Builders の中を見てみると、
既に runtests
というビルダーが存在するので、これを強制的にビルドする。
適当に入力(空で良い)して実行すると、ビルド経過が次々と出てきた後でビルド結果が表示される。
これが、実際はポーリングで変更を感知した都度実施されると思えばいい。
認証の追加
Master側に組み込みの認証を設定してみよう。
設定は c['www']['auth']
と c['www']['authz']
で行う。
# minimalistic config to activate new web UI
c['www'] = dict(port=8010,
plugins=dict(waterfall_view={}, console_view={}, grid_view={}))
の下あたりから追加。
追加ユーザーは今回はテストのため埋め込みで Ponapalt/Nullpo とした。
c['www'] = dict(port=8010,
plugins=dict(waterfall_view={}, console_view={}, grid_view={}))
c['www']['authz'] = util.Authz(
allowRules = [
util.AnyEndpointMatcher(role="admins")
],
roleMatchers = [
util.RolesFromUsername(roles=['admins'], usernames=['Ponapalt'])
]
)
c['www']['auth'] = util.UserPasswordAuth([('Ponapalt','Nullpo')])
これで reconfig
すると右上にログイン項目が増えてアクセス制限がかかる。
チュートリアルとしてはこんな感じだろうか。
次 → Buildbotの設定ファイル