デプロイツールに Fabric を選んだ理由

すべて以下エントリーの受け売り。せっかく自分でまとめるので良い感じに変更しようと思ったけど元エントリーが良すぎてほぼ同じ内容のエントリーになった。

[複数プロジェクトを抱えるチームでのデプロイ自動化](http://deeeet.com/writing/2014/10/30/fabric/)

# Fabric を選んだ理由

もともとはシェルスクリプトで自動化されてた。大きな問題はなかったけど、シェルスクリプトが得意な人がメンテするという感じになってたのでもっと気軽にだれでも修正できるようにしたかった。
Capistrano とどっちにするかという問題は今いる会社が Python メインで Ruby さわれる人がほぼいないので消去法で Fabric を選択。

# 戦略

元のエントリーにも書いてあるけど、Fabric でめんどくさいのはベースのフレームワークがないので自分で一から書かないとダメなところ。最小のフレームワークを作ってチームに提供することにした。

```
├── README.md
├── lib
│   ├── git.py
│   └── hipchat.py
├── projectA
│   ├── README.md
│   ├── config
│   │   ├── common.py
│   │   ├── develop.py
│   │   ├── production.py
│   │   └── staging.py
│   └── fabfile.py
├── projectB
├── projectC
```

プロジェクト毎にディレクトリを作って、共通化できるものは lib ディレクトリで管理するようにする。元エントリと違うのは common ディレクトリが lib という名前に変わってるのと、環境毎に異なる設定を config ディレクトリで吸収するようにした。（やっぱり common に戻そうかな。。）

# 用語の統一

属人性を排除するためにプロジェクトが異なってもインターフェースは統一する。

_ノーマルなデプロイ_

```
fab -H host1,host2 develop deploy
```

_ブランチを指定したデプロイ_

```
fab -H host1,host2 develop deploy:feat/ABC
```

_ロールバック_

```
fab -H host1,host2 develop rollback
```


# 環境依存ファイル

Fabric 標準の load_settings() だと文字列しか扱えなかったので、以下のようにして辞書とかリストも使えるようにした。ちょっとコード量は増えたけど拡張性は高くなった。

fabfile.py

```
@task
def develop(user='vagrant'):
    """開発環境"""
    config.develop.develop(user)

@task
def staging(user=''):
    """ステージング環境"""
    config.staging.staging(user)

@task
def production(user=''):
    """本番環境"""
    config.production.production(user)

@task
def deploy():
    """デプロイする"""
    ここに処理を書く
```

config/develop.py

```
def develop(user='vagrant'):
    """開発環境"""
    env.environment = 'develop'
    env.user = user
    …
    …
```


# 優しさ

[失敗する前提でデプロイする - hitode909の日記](http://hitode909.hatenablog.com/entry/2014/02/01/154226)

ほんと丸パクリで申し訳ないけど、この通りにしたいと思う。マニュアル見る運用はできるだけ少なくしたい。

## 慌てないように

ロールバックコマンドを教えてあげる

```
ヒント：戻すときは以下のコマンドを実行しましょう
fab -H host1,host2 production rollback
```

## 迷わせない

[必要ない事は出力しない](http://blog.masu-mi.me/2015/04/11/fabric_tips.html#id5)

デプロイする人が次に何をすればいいか画面のログを見ればわかるようにしたい。はじめてデプロイする人でも迷わないぐらいがいい。

## fab -l

Fabric の標準コマンド。きちんとコメントを書いて利用者に安心して使ってもらう。

```
% fab -l
Available commands:

    deploy      デプロイする
    develop     開発環境
    production  本番環境
    rollback    ロールバックする
    staging     ステージング環境
```

## わかりやすい README.md を書く

Confluence に書くのもいいけど GIT で管理するようなものなら README に書いて Confluence へはリンクを貼るようにしたい。

[わかりやすいREADME.mdを書く](http://deeeet.com/writing/2014/07/31/readme/)


```
Name
====

Overview

## Description

## Demo

## VS. 

## Requirement

## Usage

## Install

## Contribution

## Licence

[MIT](https://github.com/tcnksm/tool/blob/master/LICENCE)

## Author

[tcnksm](https://github.com/tcnksm)

```

社内プロジェクトの場合は以下も書く

```
## Document

## Ticket

## Deploy

## Test
```

> これらを書くことで初めてプロジェクトに参加したメンバーが迷うことがなくなる．レポジトリのみで全てが完結すればよいが，歴史のあるプロジェクトはドキュメントが各地に散っていることがある．長くそのプロジェクトに関わっているメンバーであれば問題ないが，新しく参加したメンバーには負担になる．どんなメンバーであってもスムーズにプロジェクトに参加できるように整備しておきたい．

# まとめ

Consul とか Capistrano も使ってみたかったけど現状の問題をスムーズに解決しようと思うとこんな形になった。この仕組が一年後に生き残ってるかが楽しみ。

# 心残り

テストも書けそうだったけどそこまで時間をとれなかった。以下は参考リンク。

https://github.com/fabric/fabric/tree/master/tests
http://www.obeythetestinggoat.com/unit-testing-fabric-deployment-scripts.html

Fabric 標準で以下みたいなライブラリもあったりする。

```
class FabricTest(object):
    """
    Nose-oriented test runner which wipes state.env and provides file helpers.
    """
```



# 参考

- [Welcome to Fabric’s documentation!](http://fabric-ja.readthedocs.org/ja/latest/index.html)
- [複数プロジェクトを抱えるチームでのデプロイ自動化](http://deeeet.com/writing/2014/10/30/fabric/)
- [失敗する前提でデプロイする - hitode909の日記](http://hitode909.hatenablog.com/entry/2014/02/01/154226)
- [必要ない事は出力しない](http://blog.masu-mi.me/2015/04/11/fabric_tips.html#id5)
- [Fabric デプロイツールのPythonicな書き方](http://www.ianlewis.org/jp/fabric-pythonic)
- [コマンドラインツールについて語るときに僕の語ること](http://deeeet.com/talking/2014/08/31/yapc-2014/)