fabric
supervisor
Python3
デプロイ

fabricでデプロイ自動化

More than 1 year has passed since last update.

ブログにも書いたのでfabricでデプロイ自動化

独学マンなので、書き方等ご指摘頂けますと幸いです。


背景


  • python3.6で書かれたjobを、ec2上に構築


  • shceduleでスケジューリング


  • supervisorでdaemon化

までできていた。デプロイ作業を失敗しそうなので、自動化した時の備忘録。自動デプロイツールとしてfabricを利用。

ちなみに現状、fabric本家はpython3系をサポートいません。参考: FabricのPython3への対応についてそのためforkされたprojectから、インストールする必要があります。

pip3 install fabric3

ディレクトリ構成はこんな感じ。シンプル。

...

├── fabfile
│   ├── __init__.py # module読み込み
│   ├── deploy.py # 基本処理の記述
│   ├── envs.py # 基本設定を記述
...


基本処理の記述


fabfile/deploy.py

from fabric.api import run, abort, env, cd, local

from fabric.decorators import task

class LocalHandler(object):
"""localでのデプロイ周りの処理"""

def push(self):
"""localの変更をgithubへpushする
commitまではされている想定
"""

self.__check_has_commited()
self.__check_on_master()
self.__update_requirements()
local('git push origin master')

def __update_requirements(self):
"""requirements.txtをupdateするスクリプト"""
req_txt = 'requirements.txt'
local('pip freeze > {}'.format(req_txt))
res = local('git ls-files -m', capture=True)
if res == req_txt:
local('git add {}'.format(req_txt))
local('git commit -m "update requirements.txt"')

def __check_has_commited(self):
"""変更がちゃんとcommitされているかを確認"""
res = local('git ls-files -m', capture=True)
if res:
abort('there are some diff on git supervised files')

def __check_on_master(self):
"""master branchにいるか確認"""
branch = local('git rev-parse --abbrev-ref HEAD', capture=True)
if branch != 'master':
abort('you should call this on master branch')

class RemoteHandler(object):

def pull(self):
"""master branchに移動してソースコードの更新"""
with cd(env.app_path):
self.__check_no_change()
run('git checkout master')
run("git pull origin master")

def restart_daemon(self):
"""svcを使って、restartさせる"""
self.__install_required_package()
res = run('supervisorctl restart {}'.format(env.daemon_name))
if res.failed:
abort('REMOTE: fail restart daemon {}'.format(env.daemon_name))
return res

def __install_required_package(self):
req_txt = 'requirements.txt'
with cd(env.app_path):
run('pip3 install -r {}'.format(req_txt))

def __check_no_change(self):
"""変更がちゃんとcommitされているかを確認"""
res = run('git ls-files -m')
if res:
abort('REMOTE: there are some diff on git supervised files')

@task
def deploy():
LocalHandler().push()
rh = RemoteHandler()
rh.pull()
res = rh.restart_daemon()
if res.succeeded:
print("SUCCESS!! WELL DONE")
else:
print("TRY ONcE MORE :D")



基本設定を記述


fabfile/envs.py

from fabric.api import env

from fabric.decorators import task

@task
def production():
""" 本番 """
env.environment = "production"
env.app_path = '/path/to/project_root'
env.daemon_name = 'supervisor daemon_name'
env.user = 'ec2-user'
env.hosts = ['host_name']
env.key_filename = '~/.ssh/key.pem'



module読み込み

このままだと、プロジェクトルートからfabricのタスクを呼べない。init.pyにimport書いてモジュール化する。


fabfile/__init__.py

from fabfile.envs import production

from fabfile.deploy import deploy


実際に自動デプロイをする

下記のコマンドをローカルで叩く。

$ fab production deploy