CircleCIの特徴は1環境であれば無料でCI環境が利用出来る点です。環境構築が完了すると、GitHubのcommit毎にCIコンテナが立ち上がり定義した自動テストがコンテナ上で実行されるようになります。本投稿では、Python3.5とFlaskで構築したWebサーバをCircleCI上で稼働させて、requestsを使ってコンテナ上のWebサーバにアクセスしてHTTP Statusコード200が返却されることを試験しています。
2時間で構築するCI環境の動作フロー
Python3.5 + Flaskで構築されたWebサーバを試験する
CircleCI上でPythonのWebフレームワークであるFlaskを利用したWebサーバを立ち上げて、HTTPのエンドポイントにアクセスしてHTTP Statusを確認する簡単な試験を行うのが本記事です。
jenkins職人問題へのCircleCIの考え方
jenkins職人問題 というのは私の狭い観測範囲内で言われている一般的でない造語です。どんな問題かというと、PJにCI環境としてjenkinsを投入すると、だいたいにおいてjenkins職人が発生して魔改造が進み便利になる一方で、jenkinsでしかdeploy出来ないのにjenkins環境が破損したときに職人しか直せない。という問題が往々に発生してしまうことです。jenkinsが必須インフラになってしまい本番環境並みに落ちないことを要求されるようになる段階で割と悲劇が起きることが多いと思います。jenkinsクラスタには出来れば関わりたくないと尊敬する先輩が言っていました。
CircleCIでは、CI環境に関する情報が 全てcircle.ymlに集約されるため、この問題が発生しません。また1台のJenkinsにSDKを詰め込みすぎる問題も、試験毎に別途コンテナを生成する仕組みのため発生しません。
CircleCI 構築手順書
1. GitHubのアカウントを所持すること
2. CircleCIのSign Upページでユーザ登録する
3. GitHubのリポジトリを選択して登録する
4.CircleCI上でHelloWorldする
リポジトリのトップディレクトリに circle.yml
を作成して次のように記述してcommitしましょう。commitした瞬間にhookされて自動でCircleCI上で試験が始まります。
test:
override:
- pwd ~
- ifconfig
- echo HelloWorld
- exit 0
5. CircleCI上でPython3.5環境を構築する
CircleCIが対応しているPythonのバージョンについては、こちらの公式ドキュメントを参照してください。commitしたら自動で試験が走る。
machine:
python:
version: 3.5.0
test:
override:
- pwd ~
- ifconfig
- echo HelloWorld
- exit 0
6. pipで環境構築する
pipとはRubyで言うGem, パッケージ管理システムです。CicleCIの標準手法では、リポジトリのトップディレクトリに requirements.txt
にパッケージ名とバージョンを列挙します。詳細は公式ドキュメント Pythonの項を参照すると良いです。
machine:
python:
version: 3.5.0
dependencies:
pre:
- pip install -r ./requirements.txt
test:
override:
- pwd ~
- ifconfig
- echo HelloWorld
- exit 0
Flask==0.10.1
Flask-Script==2.0.5
pytz==2015.7
redis==2.10.5
requests==2.9.1
six==1.10.0
SQLAlchemy==1.0.11
gunicorn==19.4.5
pytest==2.8.5
7. バックグラウンドでrunserverする
バックグラウンドで実行する理由は、並列(Parallel)実行させないとrunserverの終了待ちで処理が止まって試験が終わらなくなるからです。
pythonスクリプトをCircleCI上で稼働させるためには、chmodでの権限の付与とPYTHONPATHの設定が必要です。Flaskなのにmanage.pyなのはFlask-Scriptでカスタマイズした影響です。Django経験者にはFlask-Script便利。サーバが稼働しているかの疎通確認はtest:override:
内でcurlコマンドを書くと便利です。
machine:
python:
version: 3.5.0
dependencies:
pre:
- chmod -R 777 ./example
- pip install -r ./requirements.txt
- export PYTHONPATH="/home/ubuntu/flask_template/example/application"
- python ./application/manage.py runserver:
background: true
- sleep 5
test:
override:
- pwd ~
- ifconfig
- echo HelloWorld
- curl http://127.0.0.1/example
- exit 0
8. テストを通す
py.testでテスト書きます。HttpStatusを確認するだけの単純なものです。今回はサンプルなので内容は同じ
■ py.test用のコード
# -*- coding: utf-8 -*-
from __future__ import absolute_import, unicode_literals
import requests
def test_example():
host = "127.0.0.1:5000"
url = 'http://{}/example/'.format(host)
print(url)
response = requests.get(url)
print(response.text)
assert response.status_code == 200
assert "Error" not in response.text
machine:
python:
version: 3.5.0
dependencies:
pre:
- chmod -R 777 ./example
- pip install -r ./requirements.txt
- export PYTHONPATH="/home/ubuntu/flask_template/example/application"
- python ./application/manage.py runserver:
background: true
- sleep 5
test:
override:
- pwd ~
- ifconfig
- echo HelloWorld
- curl http://127.0.0.1/example
- py.test ./example/tests/test_example.py
- exit 0
commitしてテストが通れば作業完了
9. 結果をHipChatに通知させる
Project Settings > Notifications page. で通知先を設定できます。公式ドキュメントのnotifyを読むと判りやすいかと
この記事で扱っていない範囲
mysqlは試していないので今後試したいです。公式ドキュメントのデータベース設定
CircleCI触ってみた感想
最初は理屈がわからず学習コスト重くはじめの一歩が大変でした。公式ドキュメントが充実していて大変良いと思いました。PythonのWebフレームワークをテストするという限定的な用途ですと、誰かが頑張って設定ファイル書けば、それを参考にして量産できそうだなと感じました。