AWS Chalice を CodePipeline によってデプロイする

# はじめに

[AWS Chalice](https://github.com/aws/chalice) ではコマンドラインベースのデプロイ手段が提供されている。

https://aws.github.io/chalice/quickstart.html

こちらの `chalice` のサブコマンドを見てみると `generate-pipeline` というサブコマンドが存在することが分かる。 この内容から、CodePipeline を使って Chalice をデプロイすることができそうだったので、どのような手順でデプロイが行われるのかを調べた。

```bash
$ pipenv run chalice --version
chalice 1.27.3, python 3.9.10, linux 5.15.0-60-generic

$ pipenv run chalice --help
Usage: chalice [OPTIONS] COMMAND [ARGS]...

Options:
  --version             Show the version and exit.
  --project-dir TEXT    The project directory path (absolute or
                        relative).Defaults to CWD
  --debug / --no-debug  Print debug logs to stderr.
  --help                Show this message and exit.

Commands:
  delete
  deploy
  dev                Development and debugging commands for chalice.
  gen-policy
  generate-models    Generate a model from Chalice routes.
  generate-pipeline  Generate a cloudformation template for a starter CD...
  generate-sdk
  invoke             Invoke the deployed lambda function NAME.
  local
  logs
  new-project
  package
  url
```

# 実装の確認

`generate-pipeline` サブコマンドは以下のページで説明されている。

https://aws.github.io/chalice/topics/cd.html

こちらを確認すると、CodePipeline を構築するための CloudFormation リソースを出力してくれる。 生成された json ファイルを読み、その概略をまとめると以下の様になる

- 生成される CodePipeline は Source -> Build -> Deploy の３段構えになる
- Source: CodeCommit or Github のリポジトリを選択可能
- Build: clone したリソースから `chalice package` および `aws cloudformation package` を行い、実行可能な CloudFormation ファイルを生成して、これを後続で参照するアーティファクトとして次工程に引き渡す
- Deploy: Build で生成された CloudFormation 用のファイルを実行する

重要なのは Chalice で想定されている CI/CD の方法は **Build フェーズで CloudFormation 用のリソースを生成して、これを Deploy フェーズで反映する** ということである。 ここを抑えていれば、`generate-pipeline` を利用することなく既存の CodePipeline のデプロイスクリプトの中に組み込むことが可能となる。

## CodeBuild の具体例

Git プロジェクトの直下に `chalice` というディレクトリが存在する場合 (Git のプロジェクトルートで `chalice new-project chalice` を実行した場合)、例えば以下のような buildspec.yaml を利用することでデプロイ用の CloudFormation ファイル `package.yaml` を生成して、後続フェーズに渡すことができる。

```buildspec.yaml
version: 0.2
env:
  variables:
    S3_BUCKET: "<CloudFormation で利用するソースコードをアップロードする S3 バケット>"
    S3_PREFIX: chalice-package
phases:
  pre_build:
    commands:
      - echo "start environment setup"
      - pipenv install
      - pipenv requirements
  build:
    commands:
      - echo "start build"
      - cd chalice
      - pipenv run chalice package build
      - cd ..
  post_build:
    commands:
      - echo "output build result"
      - aws cloudformation package --template-file chalice/build/sam.json --s3-bucket ${S3_BUCKET} --s3-prefix ${S3_PREFIX} --output-template-file package.yaml
artifacts:
  files:
    - package.yaml
```

## Deploy フェーズの設定例

Deployフェーズのアクションの１つとして、以下の様なアクションを追加する。

![SnapCrab_NoName_2023-2-22_0-50-36_No-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502582/7cd3df30-db17-9c43-9164-2cb2ec69c394.png)

ここでは Build フェーズで生成されるアーティファクトは BuildArtifact なので、この中の package.yaml を利用するように設定している。

また、Chalice の設定次第では IAM Role / Policy を生成・変更することがある。 この機能によって IAM に変更を加える場合は `CAPABILITY_IAM` (IAMリソースの生成) および `CAPABILITY_AUTO_EXPAND` (ネスト処理の許可) が必要になる。

## Build/Deploy フェーズの補足

これらを実行する IAM Role についてはここでは取り扱わないため、必要なものを適時付与すること。

# 終わりに

Chalice が提供している CI/CD の具体的な方法について見ていった。 最近のフレームワークの中には AWS CloudFormation でデプロイ用スクリプトを生成してくれるものもあるように思うが、そのような場合もこれと同様の方法でパイプラインを構築できるだろう。