LoginSignup
14
12

More than 5 years have passed since last update.

fabricでデプロイ自動化

Last updated at Posted at 2017-10-04

ブログにも書いたので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
14
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
12