CircleCIを利用してAWS SAMで自動デプロイする(Python)

## 概要
AWS SAM + Pythonで開発したサーバーレスアプリケーションをCircleCIからデプロイする機会があったので、解説したいと思います。

下記の記事を参考にさせて頂きましたが、今回の設定では一部修正しないとうまく動作しない部分がありましたので、その点について記載したいと思います。
[CircleCI と GitHub で AWS SAM のサーバーレスアプリを自動デプロイしてみた （開発環境 & 本番環境） ｜ Developers.IO](https://dev.classmethod.jp/cloud/aws/aws-sam-auto-deploy-for-circleci/)

Pythonでの経験が少ないため、間違った記載がありましたらご指摘いただけると嬉しいです🙇‍♀️
普段はAWS SAM + Goを利用することが多いです。

## ソースコード
https://github.com/kobayashi-m42/aws-sam-circleci-deploy-sample

## 解説
CircleCIの設定ファイルはこんな感じで作成しました。

実行タイプにmachine(VM)を選択し、pipenvを利用した仮装環境でビルドとデプロイを行なっています。

```yaml:.circleci/config.yml
deploy_template: &deploy_template
  machine: true
  working_directory: ~/project/app
  steps:
    - checkout
    - run:
        name: install python 3.6.0
        command: |
          pyenv install 3.6.0
          pyenv global 3.6.0
    - run:
        name: sam build
        command: |
          pip install pipenv
          python -m venv venv
          source venv/bin/activate

          pipenv install

          make build
    - run:
        name: deploy AWS Key
        command: |
          source venv/bin/activate

          make package
          make deploy

version: 2.1

jobs:
  deploy-dev:
    <<: *deploy_template
  deploy-prd:
    <<: *deploy_template

workflows:
  version: 2.1
  aws-sam-deploy:
    jobs:
      - deploy-dev:
          context: aws-dev
          filters:
            branches:
              only:
                - /develop/
      - deploy-prd:
          context: aws-prd
          filters:
            branches:
              only: /master/

```

### Python仮装環境の構築
pipenvを利用して仮装環境を構築します。

pipenvについては下記の記事が参考になりましたので、掲載させて頂きます。
[Pipenvを使ったPython開発まとめ](https://qiita.com/y-tsutsu/items/54c10e0b2c6b565c887a)

仮装環境にAWS CLIとAWS SAM CLIを追加します。
CircleCIでもこの仮装環境を利用してAWS SAMのビルドとデプロイを行います。

```
$ pipenv install awscli
$ pipenv install aws-sam-cli
```

### ビルド
`sam build`コマンドを利用して、ビルドを行います。
[sam build - AWS Serverless Application Model](https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-build.html)

```
sam build --template template.yaml --use-container
```

今回は、オプションに`--use-container`を指定します。
このオプションを指定することで、Lambdaの動作環境と同等のコンテナ内でビルドすることができます。

サンプルのソースコードには追加していませんが、[Curator](https://github.com/elastic/curator)を利用する際に`--use-container`オプションを追加しなかった場合、ビルドでエラーとなりました。

[AWS SAM CLI、SAM ビルドコマンドを導入](https://aws.amazon.com/jp/about-aws/whats-new/2018/11/sam-cli-introduces-sam-build-command/)
> 関数がネイティブでコンパイルされたプログラムを持つパッケージに依存している場合は、SAM ビルドコマンドに --use-container フラグを指定することもできます。この --use-container フラグは、Lambda のような環境でローカルに関数をコンパイルするので、それらをクラウドにデプロイするときには正しいフォーマットになります。

### パッケージ&デプロイ
`sam package`、`sam deploy`コマンドを利用してデプロイを行います。
AWS SAMをデプロイするためには、事前にS3バケットを用意しておく必要があります。

### CircleCIの設定ファイル

ポイントは、下記の2点です。

- 実行タイプにmachine(VM)を選択
- コンテキストの使用して複数のAWSアカウントにデプロイを行う

詳細は`config.yml`をご確認ください。

#### 実行タイプにmachine(VM)を選択
`sam build`に`--use-container`オプションを追加しているため、コンテナ内でビルドが実行されます。

実行タイプに`Docker`を指定し、`setup_remote_docker`を設定することで、CircleCIでコンテナを使用することができると思ったのですが、ファイルをマウントすることができずにビルドが失敗してしまいました。そのため、machineを指定しています。

参考：[Docker コマンドの実行手順 - CircleCI](https://circleci.com/docs/ja/2.0/building-docker-images/)

#### 複数のAWSアカウントにデプロイを行う
開発環境を本番環境でAWSアカウントを分けているケースが多いと思います。
今回はCircleCIのContexts機能を利用することで、両方のアカウントにデプロイできるように設定を行なっています。

こちらの記事を参考にさせて頂きました。
[CircleCIで複数のAWSアカウントを扱う方法](https://qiita.com/kuedasmn/items/cac2c0bd2f5092bb033f)


## 参考記事
[CircleCI と GitHub で AWS SAM のサーバーレスアプリを自動デプロイしてみた （開発環境 & 本番環境） ｜ Developers.IO](https://dev.classmethod.jp/cloud/aws/aws-sam-auto-deploy-for-circleci/)
[Pipenvを使ったPython開発まとめ](https://qiita.com/y-tsutsu/items/54c10e0b2c6b565c887a)
[CircleCIで複数のAWSアカウントを扱う方法](https://qiita.com/kuedasmn/items/cac2c0bd2f5092bb033f)