ASK CLI を使って Alexa Custom Skills をデプロイしよう (1) 設計 〜 環境構築

# はじめに

[TypeScript を使って Alexa Custom Skills を作ろう](https://qiita.com/daisukeArk/items/ac45f10d2fc8fe8bdc5a)の番外編もこれで最後となります。（たぶん）

１月末にASK CLIがベータ版を抜けたので、ずっと眠らせてたASK CLIを利用したCI/CD環境の構築を２回に分けてご紹介します。

ASK CLI を使って Alexa Custom Skills をデプロイしよう (1) 設計 〜 環境構築
ASK CLI を使って Alexa Custom Skills をデプロイしよう (2) buildspec作成 〜 デプロイ

# 前提

* TypeScriptを使っていること
* 既にカスタムスキル、Lambdaファンクション(us-east-1)が作成済みである。

# ASK CLI

Alexa Skills Kit Command Line Interfaceの略です。
コマンドラインでカスタムスキルの操作（作成、デプロイ、参照などなど）ができます。

ASK CLIを使ってCI/CD環境を作ってしまおうというのが本投稿の目的です。

# ASK CLIの課題

これから使っていこうってところで先に課題を書いてしまいます。
ちなみに私は以下の理由により、`ask deploy`によるデプロイは採用を見送っています。

1. Lambdaファンクションのリージョンを指定してデプロイできない
1. Lambdaのバージョニングとエイリアスが指定してデプロイできない
1. ~~ベータ版~~

特に２つ目については、かなり致命的だと思ってます。
１スキルはLiveとDevバージョンで構成されますが、DevのLambdaをそのまま更新してしまうとLiveに影響を与えてしまう可能性があります。
事前に手動でバージョニング、エイリアス設定を行えば回避できるでしょうが、それをやってしまうと本来やりたかったところが出来てないよね。そこも含めて自動化したいところです。

そんなことを考えつつも、そこらへんも含めて共有したいなぁと思って書いてます。
（ドキュメント見落としてる可能性もあるかもしれませんが。。。）

# CI/CDについて

簡単に言うと、コンピュータに任せられるとこはどんどん自動化して時間を節約しましょうってところでしょうか。
他のサイトでもっと詳しく正確な情報がある為、本投稿では細かい説明は割愛します。

参考
[継続的インテグレーション(CI) - aws.amazon.com](https://aws.amazon.com/jp/devops/continuous-integration/)
[継続デリバリー(CD) - aws.amazon.com](https://aws.amazon.com/jp/devops/continuous-delivery/)

# 必要なもの

インストール、アカウント作成方法等は、本投稿では割愛いたします。

* Node.js 4.5以上
* Node Package Manager(npm)
* AWS CLI
* ASK CLI
* Amazon Developer アカウント
* AWS アカウント
* LWA(Login With Amazon) 認可
* AWS 資格情報（アクセスキー）

以前投稿した [TypeScript を使って Alexa Custom Skills を作ろう (2) 環境構築](https://qiita.com/daisukeArk/items/f5cbc6065308ecd735b7) で`ASK CLI`のインストールも行っているので参考にしてください。

# 手動によるデプロイについて考える

CLIを使わずに、デプロイする場合を考えてみましょう。

1. ソースをローカルPCにクローンする。
2. 依存解決する。(npm install)
3. トランスパイルする。(tsc)
4. 単体テストする。
5. ソースファイルをZIP圧縮し、デプロイパッケージを作成する。
6. AWSマネジメントコンソールにログインする。
7. Lambdaにデプロイパッケージをアップロードする。
8. Amazon Developer Consoleにログインする。
9. ASK Developer Consoleでカスタムスキルのスキル構成情報を更新する。

以上の内容を図にするとこんな感じです。

![デプロイ手動.png](https://qiita-image-store.s3.amazonaws.com/0/228453/cf8a34f5-b19e-6c68-610c-a9056d1db73a.png)

この方法ではいくつか課題があります。

* Lambda／スキル構成情報を別々に適用する為、一時的にバージョンが同期されない。
* 適用が手動の為、オペミスが発生しやすい。
* デプロイパッケージを準備をする為に、担当者毎に環境構築する必要がある。
* とにかく毎回やるのがつらみ

こういう面倒なルーチンワークは自動化をしてしまいましょう。ずっと手動で続けるのツライよ。。。

# ASK CLIを使う構成を考える

何をトリガーにして自動化を行うかはいくつか候補がありますが、本投稿ではGitHubの`staging`ブランチへのプッシュをトリガーにします。

フローはこんな感じです。

1. ソースをローカルPCにクローンする
1. ソースの変更をプッシュする。
1. GitHubのプッシュをトリガーにCodePipelineが起動する。
1. CodeBuild起動。
    1. ASK CLI インストールする。
    1. AWS CLI コンフィグ設定する。
    1. 各種設定ファイルを準備する。
    1. 依存解決する。(npm install)
    1. トランスパイルする。(tsc)
    1. デプロイする。(ask deploy)

以上の内容を図にするとこんな感じです。

![デプロイ自動.png](https://qiita-image-store.s3.amazonaws.com/0/228453/d53ef9a2-1ca8-3455-a452-b972a231f0f1.png)

# CI/CD環境をつくろう

では、環境作成を進めていきましょう。

## CodePipelineの作成

### ステップ１

![cpl01.png](https://qiita-image-store.s3.amazonaws.com/0/228453/472d4a95-21cf-a938-ba0f-2dfd584ed41d.png)

### ステップ２

![cpl02.png](https://qiita-image-store.s3.amazonaws.com/0/228453/ca627389-100d-0fef-02ce-6b4e22c6fcf3.png)

### ステップ３

![cpl03.png](https://qiita-image-store.s3.amazonaws.com/0/228453/8eaf1ca7-4730-81fa-c03b-871443d2cb61.png)
![cpl04.png](https://qiita-image-store.s3.amazonaws.com/0/228453/c0445fa6-8cbd-6d28-76d6-f34e389f496a.png)
![cpl05.png](https://qiita-image-store.s3.amazonaws.com/0/228453/88f6b183-b263-c996-b289-e802abe9d949.png)
![cpl06.png](https://qiita-image-store.s3.amazonaws.com/0/228453/c0d64dbb-79f7-fc8b-63bf-b65fceb7b4f7.png)

### ステップ４

![cpl07.png](https://qiita-image-store.s3.amazonaws.com/0/228453/353ca30b-89e5-a85b-eef3-a7f7cd5e5d3b.png)

### ステップ５

![cpl08.png](https://qiita-image-store.s3.amazonaws.com/0/228453/8cab7d09-293f-4744-b432-886658daf4c2.png)

### ステップ６

![cpl09.png](https://qiita-image-store.s3.amazonaws.com/0/228453/e6535142-e017-2a6f-4f7b-af3b1688a47e.png)

### 完成！

![cpl10.png](https://qiita-image-store.s3.amazonaws.com/0/228453/e0fb8c4c-81ab-fee4-b29e-fbac6f9891cf.png)

初回は必ず失敗します。
ビルド仕様で選択した`buildspec.yml`を作成していない為です。

## CodeBuildのビルド仕様について考える

パイプラインを作成したので、あとはプッシュ後のビルドについて考えます。

[AWS CodeBuild のビルド仕様に関するリファレンス](https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/build-spec-ref.html)

### 前提条件

ASK CLIを使ってデプロイを実行するためには、以下が必要になります。

* Login With Amazon 認可トークン
* AWSアカウントの資格情報（アクセスキー）

前項で説明したフロー図では既に組み込んでいますが、設計する上で重要なことがあります。

> 機密情報、特に AWS アクセスキー ID とシークレットアクセスキーを格納する場合には、環境変数を使用しないことを強くお勧めします。環境変数は、AWS CodeBuild コンソールや AWS CLI などのツールを使用してプレーンテキストで表示できます。機密情報については、このセクションの後半で説明するように、parameter-store マッピングを代わりに使用することをお勧めします。

**Parameter Storeは必ず使いましょう**
**Parameter Storeは必ず使いましょう**

パラメータストアに格納する情報は以下の４つです。

* LWA アクセストークン
* LWA リフレッシュトークン
* AWS アクセスキー
* AWS シークレットキー

上記とは別にインパクトが小さいものは環境変数を利用します。
これらもASK CLI設定に必要です。

* ベンダーID
* スキルID
* Lambdaファンクション名

### ビルドフェーズ

CodeBuildには以下の４つのフェーズがあります。
それぞれのフェーズに合わせてやることを設定します。

| フェーズ | 概要 | やること |
| :-- | :-- | :-- |
| install | インストール | ask-cliインストール |
| pre-build | ビルド前処理 | AWSCLI設定、ASKCLI設定 |
| build | ビルド処理 | 依存解決、トランスパイル |
| post-build | ビルド後処理 | ごみファイル掃除、デプロイ |

## パラメータストアを作成する

### まずは、パラメータを暗号化する為のキーを作成しましょう。

IAM Management Console -> 暗号化キーで以下のキーを作成します。

* リージョン：~~東京リージョン~~ us-east-1(バージニア北部）
* エイリアス：AlexaEncryptionKey

### パラメータの作成

EC2 Management Console -> System Manager 共有リソース -> パラメータストアで以下のパラメータを作成します。

| 名前 | 種類 | キーID |
|:--|:--:|:--|
| alexa-aws-access-key-id | SecureString | alias/AlexaEncryptionKey |
| alexa-aws-secret-access-key | SecureString | alias/AlexaEncryptionKey |
| alexa-lwa-access-token | SecureString | alias/AlexaEncryptionKey |
| alexa-lwa-refresh-token | SecureString | alias/AlexaEncryptionKey |

### CodeBuildロールポリシーの編集

CodeBuildで作成した暗号化キー、パラメータを読取りできるようにCodeBuildへ割り当てられているロールへポリシーの追加を行います。


```json
{
    "Effect": "Allow",
    "Action": [
        "ssm:GetParameters"
    ],
    "Resource": [
        "arn:aws:ssm:us-east-1:{account-id}:parameter/alexa-aws-access-key-id",
        "arn:aws:ssm:us-east-1:{account-id}:parameter/alexa-aws-secret-access-key",
        "arn:aws:ssm:us-east-1:{account-id}:parameter/alexa-lwa-access-token",
        "arn:aws:ssm:us-east-1:{account-id}:parameter/alexa-lwa-refresh-token"
    ]
},
{
    "Effect": "Allow",
    "Action": [
        "kms:Decrypt"
    ],
    "Resource": [
        "arn:aws:kms:us-east-1:{account-id}:key/alias/AlexaEncryptionKey"
    ]
}
```

もう一息

### CodeBuild環境変数の設定

ASK CLI設定に必要な情報を環境変数へ以下の通り追加します。

| 名前 | 値 | タイプ |
|:--|:--|:--:|
| ALEXA_VENDOR_ID | {使用しているベンダーID} | プレーンテキスト |
| ALEXA_SKILL_ID | {使用しているスキルID} | プレーンテキスト |
| AWS_LAMBDA_FUNCTION_NAME | custom-skill-sample-to-convert | プレーンテキスト |

以上で環境構築は終わりです。

# まとめ

本投稿では、以下のことを行いました。

* ASK CLIを使ってどうデプロイしていくか
* 環境構築
    * CodePipeLine
    * 暗号化キー
    * パラメータストア
    * CodeBuild

次回はCodeBuildのビルド仕様に沿って、buildspec.ymlを作成しデプロイまでを行います。