Deployerのrsyncでcapistranoのvia copyっぽいこと

[PHP Advent Calendar 2016](http://qiita.com/advent-calendar/2016/php)の21日目 兼
[Fusic Advent Calendar 2016](http://qiita.com/advent-calendar/2016/fusic)の21日目の記事です。

魔の三連休が目の前まで迫っているこの頃、孤独な夜の過ごし方を模索しているtutidaです
[Fusic Advent Calendar 2016](http://qiita.com/advent-calendar/2016/fusic)では2回目の投稿です
（1回目 [Controllerから簡単にJSに変数を渡したい in CakePHP3](http://qiita.com/tutida/items/66ed280782c5d22cf432)

皆さん、デプロイどうしてますか？

今年の頭あたりまでデプロイはもっぱらcapistranoでしたが、最近はDeployerをよく使ってます
php環境にrubyを入れなくて済むのでかなり楽です。~~コンテナ使えば？とかは置いといて~~

今回は最近お気に入りのDeployerでcapistranoのvia copyっぽいことをしてみます
例として CakePHP3 を扱います

## Deployer
Deployer - Deployment tool for PHP　[Packagist](https://packagist.org/packages/deployer/deployer) / [GitHub](https://github.com/deployphp/deployer) / [Document] (https://deployer.org/docs)

Documentが充実しているのと、
recipeという各フレームワークごとのDeployの雛形やslack通知のための雛形などが用意されているので、
細かい調整などをあまりしない場合はコーディング量が少なくて済みます

## Install
色々なやり方がありますが、composerで取得する方が便利なのでその方法で紹介します
今回はユーザディレクトリにdeoloyerを設置する場合

recipeをinstallする場合は、deployerとrecipeのメジャーバージョンは合わせておきましょう

```console
$ mkdir ~/deploy
$ vi ~/deploy/composer.json
$ cd ~/deploy
$ composer install
$ vendor/bin/dep init
```

```composer.json
{
    "name": "name",
    "description": "description",
    "type": "project",
    "require": {
        "deployer/deployer": "*",
        "deployphp/recipes": "*"
    }
}
```

```console
-rw-rw-r--  1 tutida tutida   236 12月 10 21:03 composer.json
-rw-rw-r--  1 tutida tutida 65820 12月 10 21:05 composer.lock
-rw-rw-r--  1 tutida tutida 65820 12月 10 21:05 deploy.php
drwxrwxr-x 18 tutida tutida  4096 12月 10 21:05 vendor
```

## 基本的な使い方
基本的な使い方は公式やすでに紹介していただいている記事もあるので割愛
[Deployer-Documentaion](https://deployer.org/docs)
[Deployer-Recipes](https://deployer.org/recipes)
[Deployerを使ってデプロイしてみたら想像以上に楽だった](http://qiita.com/ritukiii/items/ce1876b85c5bed68c93b)

## Rsync で via copy っぽいこと in CakePHP3
`deploy.php`を編集
ホストの指定したディレクトリの中身を、デプロイ先の指定したディレクトリにコピーするタスクを追加しましょう
~~本当はdeployごとに新規にローカルで`git pull`したほうがいいですね~~

DeployerのRecipeの中に`rsync.php`というコマンドが用意されているのでそれを使用します
`recipe/cakephp.php`の`deploy:update_code`が`git pull`をしているTaskなのでそこを`rsync`に変更したのみです


```deploy.php
<?php
require 'recipe/common.php';
require 'vendor/deployer/deployer/recipe/cakephp.php';
require 'vendor/deployphp/recipes/recipes/rsync.php';


##########################################################################################
### server

server('hoge_procution', 'IPアドレス', 22)
    ->user('ログインユーザ')
    ->stage('procution') // ステージ（グループみたいなもの
    ->identityFile('~/.ssh/id_rsa.pub', '~/.ssh/id_rsa', 'pass phrase'); // 鍵の設定
    ->env('rsync_src', '/root/var/www/html/blog')    // rsync元（ホスト
    ->env('deploy_path', '/root/var/www/html/blog'); // rsync先（デプロイ先

##########################################################################################

##########################################################################################
###Cconfigration

/**
 * rsysc task configration
 */
set('rsync',[
    'exclude' => [
        '.git',
        '.gitignore',
        'README.md',
        'composer.json',
        'composer.lock',,
        'logs/*',
        'tmp/*'
    ], // コピー時に必要ないものを上記に記載
    'exclude-file' => false,
    'include'      => [],
    'include-file' => false,
    'filter'       => [],
    'filter-file'  => false,
    'filter-perdir'=> false,
    'flags'        => 'rzp', // Recursive, with compress, and keep permission (rsynのオプション
    'options'      => ['delete'],
    'timeout'      => 60,
]);

/**
 * shared dirs configration
 */
set('shared_dirs', ['logs', 'tmp']);
set('shared_files', []);


##########################################################################################

##########################################################################################
### Tasks

/**
 * Confirm
 */
task('ask_deploy_user', function () {
    $rsync_src = env('rsync_src');
    $answer = askConfirmation("{$rsync_src}の内容をデプロイします. よろしいでしょうか？", false);
    if (!$answer) {
        exit();
    }
})->desc('Confirm');

task('deploy', [
    'deploy:prepare',            // make deploy dirs
    'deploy:release',            // make reseases dir
    'rsync',                     // rsysc
    'deploy:shared',             // shared dir
    'deploy:configure',          // set configure files
    'deploy:init',               // plugin load
    'deploy:run_migrations',     // run migration
    'deploy:symlink',            // symlink to current
    'cleanup',                   // delete releases
])->desc('Deploy tasks');

before('deploy', 'ask_deploy_user');
after('deploy', 'success');
after('deploy', 'current');
after('rollback', 'current');

##########################################################################################
```

あとは、 Deployerをインストールしたディレクトリ、今回は`~/deploy`でdeployコマンドを実行

```console
$ cd ~/deploy

// ステージ production をdeploy
$ vendor/bin/dep deploy production
/root/var/www/html/blogの内容をデプロイします. よろしいでしょうか？ [y/N] y
✔ Ok
✔Executing task deploy:prepare
✔Executing task deploy:release
✔Executing task rsync
✔Executing task deploy:shared
✔Executing task deploy:configure
✔Executing task deploy:init
✔Executing task deploy:run_migrations
✔Executing task deploy:symlink
✔Executing task cleanup
➤ Executing task success
Successfully deployed!
✔ Ok
➤ Executing task current
Current release: 20161220130422
✔ Ok
```

## まとめ
capistranoのvia copyと同等の動きとは言えませんが、僕のケースで使う上ではrsyncで十分です

`->stage()`を使えば複数台構成のデプロイも簡単だし、
recipeが充実してい点や、独自タスクの追加のしやすさ、シンプルに書ける点等々から
今後はDeployerを中心に使っていこうかと思っています。

皆さんもDeployerでDeployしてみましょう！