CircleCIからServerless Frameworkのデプロイを実行する

## これからこの記事のタイトルにあることを試そうという方へ
この記事で紹介されている方法は、2018年9月1日以降動作しなくなります。
これはCircleCIのアップデートのよるもので、本記事で紹介している方法はversion1の方法のためです。

v1終了するぜというお知らせ：https://circleci.com/blog/sunsetting-1-0/
マイグレーション方法：https://circleci.com/docs/2.0/migrating-from-1-2/

CircleCI 2でServerless Frameworkのデプロイをされたい方は、こちらの記事をご覧ください。
[CircleCI 2.0でServerless Frameworkのプロジェクトをデプロイする](https://wp-kyoto.net/deploy-serverless-project-by-circleci-2/)

## 経緯
「APIはServerless FWでデプロイするでー」
「フロントエンドはS3なー」
「devDependenciesのパッケージ増えたから、デプロイ前に消しといてなー」
「間違えて本番にデプロイしないようにステージの確認しっかりね」

＿人人人人人人＿
＞　めんどい　＜
￣Y^Y^Y^Y^Y￣

## 計画
- 手でコマンドうつから事故る
- 開発環境へのデプロイくらい自動化したい
- CircleCIから`sls deploy`すればええやん

## 想定

clientディレクトリにS3へアップするファイルが、srcディレクトリ内にServerless FW用のスクリプトが配置されている。

```
├── serverless.yml
├── ci
│   └── deploy_dev.sh
├── circle.yml
├── client
│   ├── css
│   ├── img
│   ├── index.html
│   └── js
├── src
│   └── api1.js
└── tests
```

## 結果

```circleci.yml
---
machine:
  node:
    version: 4.3

dependencies:
  override:
    - npm install

test:
  override:
    - npm test
    - npm run lint

deployment:
  dev:
    branch: dev
    commands:
      - ./ci/deploy_dev.sh
```

```ci/deploy_dev.sh
#!/bin/bash
npm install -g serverless
cd ~/${CIRCLE_PROJECT_REPONAME}
npm prune --production
serverless deploy --stage dev --region us-east-1
cd client
aws s3 sync ./ s3://YOUR_BACKET_NAME_HERE --delete --exclude '*.DS_Store'
```

## ハマったところ
### Serverless Frameworkはグローバルインストール
devDependenciesでServerless Frameworkを入れてるので、`npm prune --production`してしまうと`./node_modules/serverless/bin/serverless`は動かない。
かといってLambdaに同梱する必要もないものなので、`npm install -g serverless`で対応しています。

必要に応じてバージョン指定とかもすればいいかなと。


### serverless.ymlのあるディレクトリに移動する
`cd ~/${CIRCLE_PROJECT_REPONAME}`でリポジトリ内のディレクトリに移動しないと以下のようなエラーでCIがコケます。

```
 Serverless Error ---------------------------------------
 
     This command can only be run inside a service directory
```

### slsコマンドはリージョンを指定する
CircleCIだと`AWS Permissions`でクレデンシャル情報を設定していると思いますが、これだけだとリージョンが指定されてないのでやっぱりデプロイがコケます。

`--region us-east-1`をつけてやってください。

### CircleCIに設定しているIAMロールに要注意

CircleCIに設定しているIAMロールに権限が足りないと、これもまたデプロイ失敗します。
できるだけきっちり設定しておいたほうがいいと思いますが、とりあえずIAMユーザー部分だけ最低限にしたバージョンは以下。

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Stmt9999999998000",
            "Effect": "Allow",
            "Action": [
                "iam:GetRole",
                "iam:CreateRole",
                "iam:DeleteRole",
                "iam:PutRolePolicy",
                "iam:DeleteRolePolicy",
                "iam:PassRole"
            ],
            "Resource": [
                "*"
            ]
        },
        {
            "Sid": "Stmt9999999999000",
            "Effect": "Allow",
            "Action": [
                "s3:*",
                "lambda:*",
                "cloudformation:*",
                "apigateway:*"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}
```


## 終わりに
master or releaseブランチあたりに対しても同様のことを行うことで、本番デプロイの自動化も可能とは思います。
「目視確認後にリリースしたい」とか「リリースのタイミングはこちらで決めたい」という場合は、AWS CodePipelineの手動承認機能とCode Buildで設定してみてください。

参考：https://aws.amazon.com/jp/about-aws/whats-new/2016/07/aws-codepipeline-adds-manual-approval-actions/