CodePipelineを使ってLambdaに自動デプロイ

# 概要
Lambdaの関数が増えてくると修正のたびにコンソールで修正したり、ローカルのPCで修正したソースをzipに固めてコンソールでアップする作業って結構大変ですよね！！
ってことでCodePipelineを使ってgitにpush（merge）されたタイミングでLmabdaにデプロイしたときの話を書いていきます。

## 処理の流れ
1. Lambdaに関数を登録（Hello World）
2. GithubにLambda用のコードをpush
3. CodePipelineのSourceでソースの取得
4. CodePipelineのBuildでテストの実行など（今回はテストの実行はしない）
5. CodePipelineのDeployでLambdaにデプロイ

## Lambdaに関数を登録
##### LambdaにHello Worldの関数を登録
関数の作成ボタンから関数の作成
<img width="1339" alt="スクリーンショット 2020-04-02 9.59.43.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525769/7a0414ef-b23b-da13-8b27-ad899592c4c3.png">
今回はpython3.8
<img width="1336" alt="スクリーンショット 2020-04-02 10.01.01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525769/5790c987-7518-8681-8e33-532ed66cee6b.png">
こんな感じ
<img width="1337" alt="スクリーンショット 2020-04-02 10.03.31.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525769/4a355633-0264-6763-e6fb-c756aea28fb2.png">

## Githubにリポジトリを作成とソースのpush
##### Githubに適当なリポジトリを作成しHello Worldを登録
先ほど作ったLambdaのコードをどうにかしてGitに登録
<img width="1338" alt="スクリーンショット 2020-04-02 10.42.30.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525769/4fe01526-c170-9710-6726-8c73d1b5192e.png">
<img width="1338" alt="スクリーンショット 2020-04-02 10.42.37.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525769/db46e3b3-882b-0646-92e1-bf5f3d86b9e3.png">

## CodePipelineのSourceでソースの取得
CodePipelineでパイプラインを作成する
<img width="1339" alt="スクリーンショット 2020-04-02 10.36.40.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525769/19d5627d-33ab-9bfe-a2f5-f206f31c7086.png">
パイプライン名を入力しあとはデフォルト
<img width="1339" alt="スクリーンショット 2020-04-02 10.46.02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525769/c89cfb2d-920f-76d5-b7a6-50ded8fa427a.png">
次にソースの追加
Githubを選んで接続後、リポジトリとブランチを選択
<img width="1293" alt="スクリーンショット 2020-04-02 10.46.50.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525769/6e096c46-b2cd-080f-cef5-f73165b16f4e.png">
次はビルド
CodeBuildを選択、ビルド用のプロジェクトを作ってないので「プロジェクトの作成」をクリック
<img width="1290" alt="スクリーンショット 2020-04-02 10.47.01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525769/281ab645-0047-d880-3a6f-ca353a4c1080.png">
ポップアップが開くので、色々入力
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525769/c07c17e2-a1ed-4689-8ab2-955df9b35c87.png" width="40%">
完了すると、プロジェクト名のところに勝手に入力される
<img width="1293" alt="スクリーンショット 2020-04-02 11.58.44.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525769/dbcee578-8c8c-5e84-d866-6b0be8058ee1.png">
最後デプロイですが、アプリケーションを作ってないので、一旦スキップする
<img width="1292" alt="スクリーンショット 2020-04-02 11.59.36.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525769/0b971ba4-32e2-2b2c-d9c0-b22df5c02660.png">
パイプラインが実行される
<img width="1294" alt="スクリーンショット 2020-04-02 12.00.56.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525769/4c361047-412e-e6bb-3870-7b6b1e91a07d.png">
Gitにbuildspec.ymlをあげてないので、Buildは失敗する、改めてbuildspec.ymlを作ってGitにpushする

```yaml:buildspec.yml
version: 0.2
  
phases:
  build:
    commands:
      - ls
artifacts:
  files:
    - "**/*"
```
ビルドも成功しました。コードテストも実行したいが今回は割愛
<img width="1333" alt="スクリーンショット 2020-04-02 12.26.36.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525769/d622d34c-39c0-5c32-d9a0-1d3e82fc7c6c.png">

## CodePipelineのDeployでLambdaにデプロイ
CodeDeployでアプリケーションを設定する
アプリケーションの作成をクリック
<img width="1335" alt="スクリーンショット 2020-04-03 17.07.14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525769/8834110c-e572-e5b2-d47d-44a85bd17940.png">
コンピューティングプラットフォームを「Lambda」にする
<img width="1334" alt="スクリーンショット 2020-04-03 17.07.28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525769/306954c6-277f-6697-5713-8ac3436b9532.png">
先ほど作ったアプリケーションでデプロイグループを作成する今回は「dev」としています
<img width="1331" alt="スクリーンショット 2020-04-03 17.07.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525769/f7ab76be-ce00-1326-5424-58df45de71bb.png">

今後はパイプラインに戻ってステージを追加する
<img width="1333" alt="スクリーンショット 2020-04-03 17.05.34.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525769/7c99d070-c5bb-8f0a-570d-bb050f995965.png">
デプロイ用のアクションお追加を行う、アプリケーション名とデプロイグループのところはCodeDeployで作った物を選択する
<img width="1333" alt="スクリーンショット 2020-04-03 17.09.27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525769/3694ac15-8d9d-70f1-05df-2a740bcd6d81.png">

appspec.ymlを追加する、ビルド時に動的に生成するため{{xxxx}}のように記載します


```yaml:appspec.yml
version: 0.0
Resources:
  - HelloWorld:
      Type: AWS::Lambda::Function
      Properties:
        Name: "HelloWorld"
        Alias: "dev"
        CurrentVersion: "{{CurrentVersion}}"
        TargetVersion: "{{TargetVersion}}"
```
参照：https://docs.aws.amazon.com/ja_jp/codedeploy/latest/userguide/reference-appspec-file-example.html#appspec-file-example-lambda

buildspec.ymlの変更を行う

```yaml:buildspec.yml
version: 0.2
  
phases:
  build:
    commands:
      - CurrentVersion=$(echo $(aws lambda get-alias --function-name HelloWorld --name dev | grep FunctionVersion | tail -1 |tr -cd "[0-9]"))
  post_build:
    commands:
      - ls
      - aws lambda publish-version --function-name HelloWorld
      - TargetVersion=$(echo $(aws lambda list-versions-by-function --function-name HelloWorld | grep Version | tail -1 | tr -cd "[0-9]"))
      - echo $CurrentVersion
      - echo $TargetVersion
      - sed -i -e "s/{{CurrentVersion}}/$CurrentVersion/g" appspec.yml
      - sed -i -e "s/{{TargetVersion}}/$TargetVersion/g" appspec.yml

artifacts:
  files:
    - "**/*"

```
buildspec.yml内でaws lambdaコマンドを実行するので、CodeBuildで使うロールにポリシーを追加する

```:iam
"lambda:PublishVersion"
"lambda:GetAlias"
```

Lambdaのaliasを作る
<img width="1332" alt="スクリーンショット 2020-04-03 18.18.28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525769/2559546a-4f34-c058-7559-972e15b6f354.png">
<img width="1334" alt="スクリーンショット 2020-04-03 18.18.40.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525769/aeb7637b-5a37-7d0b-6a0d-bef431be7baf.png">
変更をリリースするをクリックしてパイプラインを実行する
<img width="1289" alt="スクリーンショット 2020-04-03 18.29.40.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525769/1e44bd22-8bbb-86ca-9383-77ca79591b7c.png">

## 実行結果
失敗！！！！
<img width="1329" alt="スクリーンショット 2020-04-03 17.29.11.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525769/67b9c941-dfbc-72d0-39d6-6db2147a3040.png">
BundleType must be either yaml or json？？？？
<img width="1334" alt="スクリーンショット 2020-04-03 17.29.15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525769/aee099fc-5e7f-2bac-2b73-cb0fc573f774.png">
artifactの中にあるし、色々試したけど解決せずサポートに問い合わせると、artifactで保存されるファイルはzipで圧縮されるので、そうするとappspec.ymlが参照できないらしい
って無理じゃん！！！
現時点ではデプロイでCloudFormationを使うしかないということです、無駄足でした。

## 最後に
ここまでみて頂いた方ありがとうございます
ただデプロイしたいだけで、3日も溶かしてしまった、どうしてもこのやり方でやりたい方は
https://github.com/aws-samples/aws-serverless-workshop-greater-china-region/tree/master/Lab8A-CICD-CodePipeline
ここを参考にどうぞ、デプロイはCodeDeployじゃなくてLambdaを実行しているけどね・・・