AWS Lambdaバージョン管理のススメ

『今日のゴミ出し』というAlexaスキルを公開しました。
[Alexaスキル - 今日のゴミ出し](https://www.amazon.co.jp/quo1987-%E4%BB%8A%E6%97%A5%E3%81%AE%E3%82%B4%E3%83%9F%E5%87%BA%E3%81%97/dp/B07BHTKYDQ/ref=sr_1_1?s=digital-skills&ie=UTF8&qid=1522574582&sr=1-1&keywords=%E4%BB%8A%E6%97%A5%E3%81%AE%E3%82%B4%E3%83%9F%E5%87%BA%E3%81%97)


初めてAlexaスキルを公開してから**失敗した！**と思ったことのひとつに、

**「Lambdaのモジュールにバージョンを付けていなかった」**

という点があります。

<br/>
Alexaスキルに限らず、普通に開発する人なら「何を今さら」という感じでしょうが、**「Lambdaとか雰囲気で使ってるんだよね。」**という私のような初学者に向けてAlexaスキル開発を例に取り、AWS Lambdaバージョン管理のススメをまとめます。

# Alexaスキル開発とAWS Lambda
なぜAlexaスキル開発時にAWS Lambdaのバージョン管理を推奨するのか。それはバージョン管理をしていない場合、

**公開後のアップデートが面倒臭くなるから**

です。

## Alexaスキル公開後の流れ
Alexaスキル開発ではデフォルトのエンドポイントにAWS Lambda関数のARNを指定します。

自分が開発したAlexaスキルは審査を通過すると自動的にストアに公開されます。それと同時に、スキルの開発バージョンが自動的に生成されます。

スキル公開後にAlexa Skill Kitコンソールを見ると**「公開バージョン」**と**「開発バージョン」**が表示さていることが分かります。  
<img width="904" alt="2018-04-01_18h33_51.png" src="https://qiita-image-store.s3.amazonaws.com/0/183744/e831c429-e0bc-0215-ebf1-e067a210275e.png">

公開バージョンは閲覧専用で、開発バージョンを使ってスキルをアップデートしていきます。

スキル公開直後、**開発バージョンには公開バージョンと同じエンドポイントが指定されています。**
<img width="626" alt="2018-04-01_18h48_35.png" src="https://qiita-image-store.s3.amazonaws.com/0/183744/7b4abb54-a969-e663-ae70-b31d54e5f65f.png">

## 開発バージョンだけLambdaを更新したい！
ではこの時**Lambdaモジュールを更新して開発バージョンにのみ更新を適用したい場合、どうしたら良いでしょう。**

……

Lambdaでバージョン管理をしていない場合、公開バージョンは常に最新のLambda関数を参照しているため、**Lambda関数を新規に作成するしかありません。**環境変数もテストパターンもそっくり同じものを作らなければならないので、とてつもなく面倒くさいです。（AWSコンソールを見る限り「既存の関数をコピーする」といったことはできない気がします。）

# AWS Lambdaのバージョン管理
この問題を解決するためにAWS Lambdaでバージョン管理します。

## バージョン管理の概要
具体的な手順の前にLambdaのバージョン管理について概要をさらっと記します。

AWS Lambdaのバージョン管理の要点は以下2つです。

- バージョンごとにARN（エンドポイント）が変わる
- 編集できるのは最新バージョン（$LATEST）のみ

### バージョンごとにARN（エンドポイント）が変わる
AlexaスキルのエンドポイントにはLambdaのARNを指定します。  
<img width="646" alt="2018-04-01_19h00_04.png" src="https://qiita-image-store.s3.amazonaws.com/0/183744/76cebca9-dd0f-d39c-5b3f-295d27e39333.png">

Lambdaでバージョンを発行すると**ARNがバージョンごとに一意になります。具体的には一番最後にバージョン番号が付与されます。**

例えば最新を示すバージョンであれば**「$LATEST」**が末尾に付きます。これは**バージョンを付けない場合と同意です。**
<img width="581" alt="2018-04-01_19h04_23.png" src="https://qiita-image-store.s3.amazonaws.com/0/183744/06bf20df-07e6-2b7c-6dd3-2ee94db17830.png">

一方で過去に発行したバージョンは末尾に**バージョン番号が付きます。**（以下の例では**バージョン「1」**）
<img width="548" alt="2018-04-01_19h04_34.png" src="https://qiita-image-store.s3.amazonaws.com/0/183744/85155f2f-7b16-6aa9-cfcd-d5d0566b009d.png">


これによって**公開中のスキルと開発中のスキルに同じLambda関数の異なるバージョンを使い分けることができます。**

### 編集できるのは最新バージョンのみ
Lambda関数の最新バージョンは`$LATEST`となり、**最新バージョンのみモジュールが更新可能**になります。通常のバージョンはコードはもちろん環境変数なども更新は行えず**読み取り専用**になります。

<img width="830" alt="2018-04-01_20h14_30.png" src="https://qiita-image-store.s3.amazonaws.com/0/183744/6c043c66-d7a9-36d0-eb35-152ee585f225.png">

<img width="826" alt="2018-04-01_20h14_47.png" src="https://qiita-image-store.s3.amazonaws.com/0/183744/8f134344-3689-6ef7-7456-25b0956983f3.png">

このためスキル申請のタイミングでLambdaのバージョンを発行しエンドポイントに設定することで**「誤って公開バージョンを変更してしまう」などを防ぐことができます。**

## 新しいバージョンを発行する
バージョンの発行はとても簡単です。

AWS Lambdaの関数コンソールのバージョンから`$LATEST`を選択し**「アクション」=>「新しいバージョンを発行」**をクリックします。
<img width="323" alt="2018-04-01_20h21_06.png" src="https://qiita-image-store.s3.amazonaws.com/0/183744/17952187-30b4-f04e-30bf-5d63d1a041c1.png">

ダイアログが表示されるので**「バージョンの説明」**を入力して**「発行」**を実行します。
<img width="629" alt="2018-04-01_20h24_46.png" src="https://qiita-image-store.s3.amazonaws.com/0/183744/4abbcaf8-40ec-04fb-3da8-e7adeb8eed12.png">

これで自動でバージョンが採番されます。
<img width="860" alt="2018-04-01_20h26_30.png" src="https://qiita-image-store.s3.amazonaws.com/0/183744/9b0d1d87-0efe-8729-6d72-9fd90ac661a8.png">

## 注意点
AWS Lambdaで新しいバージョンを発行すると、新バージョンの**「トリガー」がリセットされる**ようです。Alexaスキルで利用する場合は新バージョンで**「Alexa Skills Kit」**をトリガーに追加して保存しましょう。（トリガーの変更は可能）

<img width="813" alt="2018-04-01_20h33_17.png" src="https://qiita-image-store.s3.amazonaws.com/0/183744/1b36b0cd-a55d-79b8-911a-0c66afd5bcaa.png">

# まとめ（Alexaスキル開発の流れ）
ということでAlexaスキル開発を例にAWS Lmabdaのバージョン管理のススメでした。

Alexaスキル開発の流れでまとめると、

1. Alexaスキル開発
2. 公開申請手前でLambdaのバージョン発行
3. 発行されたバージョンでARNを修正し、スキルを公開申請する
4. 公開後の開発は最新バージョン（`$LATEST`）を使って1に戻る

という感じになります。

以上！