sshしてgit pullするのが面倒なのでwercker+pm2でdeployしよう

# デプロイサーバの役割

> デプロイとは、主にネットワークを通じて提供されるWebアプリケーションなどのシステム開発工程において、システムを利用可能な状態にすることである。
[こちらより引用](http://www.weblio.jp/content/%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4)

よくあるのがこんな構成で踏み台サーバにシェルスクリプトやCapistranoが仕掛けられていて、
各サーバA,B,Cにログインして`git pull origin master`とかするやつです。
最近だとansibleとかも使う会社もあるみたいです。

<img width="261" alt="スクリーンショット 2017-04-19 15.11.46.png" src="https://qiita-image-store.s3.amazonaws.com/0/87900/7e3af0d2-90a1-6e3a-2c99-2b35d358ca5d.png">

他にも見かけるのが上記の踏み台サーバがjenkinsおじさんとかdrone.ioだったりする構成です。
またクラウドでは、Githubと連携できるCircleCIやTravisCIなんてのもあります。

そこで今回紹介するのはCircleCIやTravisCIの競合の**[wercker](http://www.wercker.com/)**です。
ここではHello-worldをConoha VPSに展開できるようにしてみます。

つまりこんなイメージです。
<img width="540" alt="スクリーンショット 2017-04-19 15.40.02.png" src="https://qiita-image-store.s3.amazonaws.com/0/87900/19faaf97-50da-571e-9039-7f1b912b61bc.png">

ちなみにwerckerの料金は個人で使う分には基本的に無料と言っていいレベルだと思います。
http://www.wercker.com/pricing

# 環境
## 開発
- Mac
- Node.js v7.9.0
- pm2 2.4.5
- git 2系

## デプロイするサーバ
- Conoha VPS (CentOS7)
- Node.js v7.9.0
- [pm2](https://github.com/Unitech/pm2) 2.4.5
- git [2系(RHEL系のyumだと1系しか入りません)](https://blacksaildivision.com/git-latest-version-centos)

※pm2はCapistranoのようなものです

# テスト用プロジェクトを作成
おなじみのNode.jsのExpressでサンプルプロジェクトを作成します。

```bash
$ npm install -g express 
$ npm install -g express-generator
$ express hello-world 
...
$ cd hello-world
```

# pm2用のデプロイファイルを作成
```bash
$ npm install -g pm2
$ pm2 ecosystem
```

## ecosystem.config.jsを編集
```bash
$ cat ecosystem.config.js
```

```js
var user = encodeURIComponent(process.env.GITHUB_USER);
var password = encodeURIComponent(process.env.GITHUB_PASSWORD);
var keyPath = process.env.SSH_PRIVATE_KEY_PATH || "~/.ssh/id_rsa";

module.exports = {
  /**
   * Application configuration section
   * http://pm2.keymetrics.io/docs/usage/application-declaration/
   */
  apps : [

    // First application
    {
      name      : "hello-world",
      script    : "npm",
      args      : "start",
      env: {
        PORT: 3000
      },
      env_production : {
        NODE_ENV: 'production',
      }
    }
  ],

  /**
   * Deployment section
   * http://pm2.keymetrics.io/docs/usage/deployment/
   */
  deploy : {
    production : {
      "key"  : keyPath,
      "user" : "ichiwa",
      "host" : [process.env.HOST],
      "ref"  : "origin/master",
      "repo" : "https://"+user+":"+password+"@github.com/ichiwa/hello-world-pm2-wercker.git",
      "ssh_options" : "StrictHostKeyChecking=no",
      "path" : "/home/ichiwa/hello-world-pm2-wercker",
      "post-setup" : "npm install",
      "post-deploy" : "pm2 restart ecosystem.config.js --env production"
    }
  }
};
```

historyに残ったりとか問題がありますが、werckerを経由しなくてもこのコマンドでローカルマシンからVPSにデプロイは可能です。

```bash
$ SSH_PRIVATE_KEY_PATH="~/.ssh/id_rsa" GITHUB_USER=XXX GITHUB_PASSWORD=XXX HOST=XXX pm2 deploy ecosystem.config.js production update 
```

つまりこれをwerckerにやってもらうイメージです。

※蛇足ですが、pm2ではデプロイ先を複数指定できます。 

```js
"host" : ["XXX.XXX.XXX.XXX", "YYY.YYY.YYY.YYY", "ZZZ.ZZZ.ZZZ.ZZZ"],
```
## wercker.ymlの作成
```bash
$ cat wercker.yml 
```

```yml
box: node

build:
  steps:
    - npm-install
    - npm-test
    - script:
        name: echo nodejs information
        code: |
          echo "node version $(node -v) running"
          echo "npm version $(npm -v) running"

setup-production:
  steps:
    - mktemp:
        envvar: SSH_PRIVATE_KEY_PATH
    - create-file:
        name: Create private key
        filename: $SSH_PRIVATE_KEY_PATH
        content: $SSH_PRIVATE
        overwrite: true
        hide-from-log: true
    - script:
        name: Install pm2 package
        code: npm install -g pm2
    - script:
        name: Setup production
        code: |
          pm2 deploy ecosystem.config.js production setup

deploy-production:
  steps:
    - mktemp:
        envvar: SSH_PRIVATE_KEY_PATH
    - create-file:
        name: Create private key
        filename: $SSH_PRIVATE_KEY_PATH
        content: $SSH_PRIVATE
        overwrite: true
        hide-from-log: true
    - script:
        name: Install pm2 package
        code: npm install -g pm2
    - script:
        name: Deploy production
        code: |
          pm2 deploy ecosystem.config.js production update
```

## werckerのPipeline

上記のファイルで指定されているPipelineは 
- `build`
- `setup-production`
- `deploy-production`
の３つです。

`build`はデフォルトであるPipelineです。 `npm test`を実行します。

`setup-production`は秘密鍵を作成して、`pm2 setup`コマンドでソースを配置しています。※初回に一度だけ
実行後に`ecosystem.config.js`の`post-setup`で指定されたコマンド`npm install`が実行されます。

`deploy-production`も同様に`pm2 update`コマンドでソースを更新しています。基本的にブランチが更新されたらこれを使ってデプロイしていきます。
`ecosystem.config.js`の`post-deploy`で指定されたコマンド`pm2 restart ecosystem.config.js --env production`が実行され、プロセスが再起動されます。

これでローカルマシンですべきことは完了です。
Githubにあげておきます。
[デモソース](https://github.com/ichiwa/hello-world-pm2-wercker)

# wercker にて

※werckerにはすでにGithubと紐付いたアカウントがある前提で勧めます。

## Application作成から要点のみ説明
- Repositoryは先程作ったものを選択
![Screenshot 2017-04-18_17-39-17.png](https://qiita-image-store.s3.amazonaws.com/0/87900/52ccfac8-d243-d0e5-9408-af7f8ad5705e.png)
- 作成後、すでにwercker.ymlはあるのでビルドする。
![Screenshot 2017-04-18_17-40-56.png](https://qiita-image-store.s3.amazonaws.com/0/87900/df32f5b1-fb55-76a0-770e-15d29815fd4c.png)
- その後、Workflows→Add new Pipeline
![Screenshot 2017-04-18_17-45-09.png](https://qiita-image-store.s3.amazonaws.com/0/87900/04f5a81a-51b7-097e-46a3-2ac04a2f3e71.png)
- `setup-production`と`deploy-production`を作成する
![Screenshot 2017-04-19_16-38-24.png](https://qiita-image-store.s3.amazonaws.com/0/87900/5656fdf7-83cd-e371-676f-9f6cd5a054aa.png)
- Environmentから使う環境変数を追加する(認証鍵はGenerate SSH Keysから作る)
![Screenshot 2017-04-18_18-34-55.png](https://qiita-image-store.s3.amazonaws.com/0/87900/f103365d-e2a6-ce1f-fe33-6772bba7540d.png)

# デプロイするVPSにて

## werckerで作成した認証鍵を追加する
```bash
$ vi ~/.ssh/authorized_keys
werckerで作成した公開鍵をコピペする

$ chmod 644 ~/.ssh/authorized_keys
```
`~/.ssh`がない場合は鍵を作成しておく

```bash
$ ssh-keygen
```
これでwerckerの秘密鍵でログインができるようになる。

# werckerに戻る

## デプロイしてみる

1. すでに成功しているRunsからデプロイするビルドを選ぶ。
2. Actions→`setup-production`を実行する。(初回だけ)

その後はAction→`deploy-production`でデプロイができるようになる。
![Screenshot 2017-04-19_16-51-49.png](https://qiita-image-store.s3.amazonaws.com/0/87900/a5a93b35-8591-ff51-38ee-86d491f72808.png)

おしまい
# 最後に
ここでやったのは本番へのデプロイだけですが、各Pipelineはつなげることもできるため、Buildが成功したら、開発環境へ自動デプロイみたいなこともHOSTとか変更したりすればできます。
本番へ自動デプロイするのは商用サービスではしないと思うので、あえてそうはしていません。

そういえば最近、[OracleがWerckerを買った](https://www.oracle.com/corporate/acquisitions/wercker/index.html)みたいですね、、、
Oracleのことだから料金が上がるかもですね（偏見）

### ハマった話
最初はubuntu(debian系)でやったから正常に動いたと思って安心していたら、
centos(RHEL系)でやったらなぜか３つくらい前のコミットをデプロイするという
yumのGit(1系)のバグに出くわしてハマりました... orz
https://github.com/Unitech/pm2/issues/2623