AWS Amplify ConsoleでCIを頑張った話

先日の[JAWS-UG横浜 #16 DevOps](https://jawsug-yokohama.connpass.com/event/125095/)で発表させてもらった内容の技術的な部分。

[AWS Amplify Console](https://aws.amazon.com/jp/amplify/console/)はCD（継続的デリバリ）に特化したサービスに現在見えるが、以下のことを自前で実施してみました。

1. 単体試験（[unittest](https://docs.python.org/ja/3/library/unittest.html)）がAmplify Console上で自動実施できるようにする
2. シナリオ試験（[Karate](https://github.com/intuit/karate)）がAmplify Console上で自動実施できるようにする
3. 1, 2で実施した結果がHTMLでレポート出力され、ブラウザから表示可能なようにする（Amplify Consoleはビルド時に毎回インスタンスが割り当てられるので、ローカルに出力したものは基本的に破棄される）
4. 上記が実施可能なamplify.ymlを作成する

# 結果
適用したamplify.ymlとサンプルアプリを以下にコミットしてあります。

https://github.com/kojiisd/cognito-user-manager

# どんなアプリか？
CIの対象としたアプリはCognitoのユーザ管理を簡単に実施できるWebサービスです。（Cognitoって承認とかユーザ削除とか、面倒なので）まだ作り途中ですが、ある程度機能が揃っていて画面もサーバサイドもしっかり実装されているので、こいつをCIしていきます。

クライアントはAngular 7、サーバはPython3.7のAWS Lambdaで実装しています。

![スクリーンショット 2019-05-25 15.47.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102769/8bc6da0a-4429-6ddc-2944-3023fbc127b6.png)

# 単体試験とシナリオ試験をAmplify Console上で行えるようにする
amplify.ymlの編集がキモになるわけですが、Amplify Consoleは勝手にビルドマシンが用意されるため、色々とインストールが必要になります。

## 事前準備
CI/CDを行うために足りないものをインストールしていきます。（手抜きで全ての処理をpreBuildに含んでいます。）

### AWS認証設定
Serverless Frameworkでサーバ側をデプロイする仕組みにしていますが、デプロイ用の権限はデフォルトでは用意されていないため、自前で用意します。

```yml
- mkdir  -p ~/.aws
- echo "[${SLS_AWS_ACCOUNT_ID}]" > ~/.aws/credentials
- echo "aws_access_key_id = ${ACCESS_KEY}" >>  ~/.aws/credentials
- echo "aws_secret_access_key = ${SECRET_KEY}" >>  ~/.aws/credentials
```

### unittest実行用にPython、Pipのインストール
Pythonはデフォルトのリポジトリだと3.4系までしかない？のでそれをインストールします。またunittestをHTML形式でレポート出力できるようにPyUnitReportをインストールします。

```yml
- yum update python34 -y
- yum -y install python34
- python3 --version
- curl https://bootstrap.pypa.io/get-pip.py | python3
- pip3 -V
- pip3 install -r requirements_test.txt -t libs
- python3 tests/test_user_handler.py
```

PyUnitReportはrequirements_test.txtい記載しています。

```
pyunitreport==0.1.4
```

### Karate実行用にJavaとMavenのインストール
KarateはMaven, Gradleで実行が可能ですが、今回はMavenで実行します。

```yml
- yum install -y java-1.8.0-openjdk-devel.x86_64
- yum install -y apache-maven
```

### Node.jsのDaemon化のためにforeverをインストール
本当は```ng e2e```コマンドでKarateが実行されるようにしたかったのですが、手抜きで```ng serve```を実施してその内容をDaemon化できるようにします。そのためにはforeverというツールがよさそうです。

```yml
- npm install -g forever
```

# それぞれ単体試験とシナリオ試験を実行する
ここまでで事前準備が済んだので、実際に単体試験とシナリオ試験を実施してみます。またその結果をHTMLレポートとして出力しているので、S3の特定のバケットにアップロードします。

設定は以下のようになります。

```yml
# unittestによる単体試験とその結果のHTML出力、S3へのアップロード
- python3 tests/test_user_handler.py
- ls reports/html_report/ > file_path.txt
- aws s3 cp reports/html_report/`cat file_path.txt` s3://${REPORT_BUCKET}/index.html --profile=${SLS_AWS_ACCOUNT_ID}
:
:
# Karateによるシナリオ試験とその結果のHTML出力、S3へのアップロード
- mvn clean test
- ls target/
- cd target/surefire-reports/
- aws s3 cp ./ s3://${REPORT_BUCKET}/karate/ --recursive --profile=${SLS_AWS_ACCOUNT_ID}
- aws s3 cp ../karate.log s3://${REPORT_BUCKET}/karate/karate.log --profile=${SLS_AWS_ACCOUNT_ID}

```
それぞれS3には必要ファイルが出力されるため、確認をすると、バッチリ試験結果が出力されていました。

PyUnitReportによる単体試験結果
![スクリーンショット 2019-06-01 17.40.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102769/146b8f6e-0d60-a03e-b8dc-7c8752876398.png)

Karateによるシナリオ試験結果
![スクリーンショット 2019-06-01 17.41.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102769/0206a651-196f-576d-ac75-d4d1c7a95627.png)


# まとめ
AWS Amplify Console自体はまだまだCD感の強いサービスですが、カスタマイズすることで一応CIっぽさを出すこともできました。とりあえず1本Amplify Console上で通るものをGitHubに置いているので、興味ある人は中身を見てもらえればと思います。