GitHubActionsでLambdaとLambdaレイヤーの構築をしていて躓いた。

# はじめに
今回はGitHubActionsを利用してLambdaとLambdaレイヤーを構築します。
LambdaとLambdaレイヤーを紐づける際に上手くいかなかった箇所や解決方法を備忘録として残していきたいと思います。

# 目次
・つまづいたところ
・解決方法
・事前準備
・LambdaレイヤーのCloudFormation
・LambdaのCloudFormation
・Lambdaレイヤー構築のGithubActions
・Lambda構築のGithubActions
・動作確認
・最後に
・参考

# つまづいたところ
Lambdaレイヤーを複数のLambdaに紐づけることとなり、
GitHubActionsでLambdaレイヤーとLambdaのCFnテンプレートを分けて構築することになりました。
そのため、Lambdaを構築する際にLambdaレイヤーの情報をテンプレート外から取得することになったのですが、Outputsで対応した際にバージョンまで取得することができず、躓いてしまいました。

# 解決方法
デプロイをGitHubActionsを活用していたため、バージョンを取得してくるときにAWS CLIの下記コマンドを活用してバージョン情報を取得し、デプロイ時にパラメータとして渡すことで解決しました。
```
LATEST_LAYER_VERSION=$(aws lambda list-layer-versions --layer-name pj-ogataro-dev-layer --output json | jq -r '(.LayerVersions | sort_by(.Version) | reverse)[0].Version')
```

次章から実際のテンプレートファイルを紹介します。

#　事前準備
LambdaレイヤーとLambdaのコードはS3から取得してくるので事前に構築してください。
S3の構築は以前の記事を参考に作成してください。
https://qiita.com/ogataro/items/71dd28babfcdf6410a3c

# LambdaレイヤーのCloudFormation
Lambdaレイヤー構築のCloudFormationが下記になります
node_modulesなどは別途対応をお願いします。

```yaml:LambdaLayer.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  Lambda package layer deployment

#------------------------------------------------------------#
#Parameters
#------------------------------------------------------------#
Parameters:
  PJPrefix:
    Description: Project Name
    Type: String
    Default: pj-ogataro
    AllowedPattern: ^[a-zA-Z0-9\-]*$
  Environment:
    Description: Environment Name
    Type: String
    Default: dev
    AllowedPattern: ^[a-zA-Z0-9\-]*$
#------------------------------------------------------------#
#Resources
#------------------------------------------------------------#
Resources:
  ###Lambdaレイヤー
  LambdaLayer:
    Type: 'AWS::Lambda::LayerVersion'
    Properties:
      LayerName: !Sub '${PJPrefix}-${Environment}-layer'
      CompatibleRuntimes:
        - nodejs20.x
      Content:
        S3Bucket: !Sub '${PJPrefix}-${Environment}-storage'
        S3Key: layer/layer_lambda.zip
```

# LambdaのCloudFormation
LambdaとIAMロールを作成します
Parametersに`LayerVer`としてLambdaレイヤーのバージョンを変数として宣言しておきます。

また、index.mjsは下記サイトを参考にお願いします。

https://qiita.com/ogataro/items/2e57c8bda6c2af69187b

```yaml:Lambda.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  Lambda Deployment

#------------------------------------------------------------#
#Parameters
#------------------------------------------------------------#
Parameters:
  PJPrefix:
    Description: Project Name
    Type: String
    Default: pj-ogataro
    AllowedPattern: ^[a-zA-Z0-9\-]*$
  Environment:
    Description: Environment Name
    Type: String
    Default: dev
    AllowedPattern: ^[a-zA-Z0-9\-]*$
  LayerVer:
    Description: Layer Version
    Type: String
    Default: 1

#------------------------------------------------------------#
#Resources
#------------------------------------------------------------#
Resources:
  ###IAMロール
  IAMRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub '${PJPrefix}-${Environment}-lambdaRole'
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action: sts:AssumeRole
      ManagedPolicyArns:
           - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole

  ###Lambdaファンクション
  LambdaFunction:
    Type: AWS::Lambda::Function
    Properties:
      FunctionName: !Sub '${PJPrefix}-${Environment}-lambda'
      Runtime: nodejs20.x
      Handler: index.handler
      Layers:
        - !Sub 'arn:aws:lambda:ap-northeast-1:${AWS::AccountId}:layer:${PJPrefix}-${Environment}-layer:${LayerVer}'
      Code:
        S3Bucket: !Sub '${PJPrefix}-${Environment}-storage'
        S3Key: lambda/lambda.zip
      Role: !Ref IAMRole
```

# Lambdaレイヤー構築のGitHubActions
Lambdaレイヤーを構築する際のGitHubActionsが下記になり、こちらを実行します。
working-directoryや`AWSAccountID`などは適宜変更してください。

```yaml:Deploy-Layer.yaml
name: Deploy-Layer

on: workflow_dispatch

permissions:
  id-token: write
  contents: read
jobs:
  aws-deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: aws-actions/configure-aws-credentials@v1-node16
        with:
          role-to-assume: arn:aws:iam::{AWSAccountID}:role/{IAMRole}
          aws-region: ap-northeast-1

      #Lambda アップロード用パッケージ
      - name: Create ZIP Archive LambdaLayer-NodeJs-Package
        run: zip -r layer_lambda.zip nodejs # packageをZIPに圧縮
        working-directory: ./2_Lambda

      - name: S3 FileUpload LambdaLayer-NodeJs-Package
        run: aws s3 cp layer_lambda.zip s3://pj-ogataro-dev-storage/layer/ #zipファイルをS3にアップ
        working-directory: ./2_Lambda

      #Lambda 共通パッケージレイヤー作成用Yaml実行
      - name: AWS Cloudformation Development SubApp-PatentTag LambdaLayer-NodeJs-Package
        run: aws cloudformation deploy --stack-name Deployment-LayerLambda --template-file LayerLambda.yaml
        working-directory: ./2_Lambda
```

# Lambda構築のGitHubActions
Lambdaを構築する際のGitHubActionsが下記になり、こちらを実行します。
Lambdaレイヤーの最新バージョン取得のところで、レイヤーの最新バージョン取得と共にGitHubActionsの変数に入れています。
その変数をデプロイ時に、 `--parameter-overrides`でパラメータに上書きし、最新バージョンを取得できるようにします。

```yaml:Deploy-Lambda.yaml
name: Deploy-Lambda

on: workflow_dispatch

permissions:
  id-token: write
  contents: read
jobs:
  aws-deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: aws-actions/configure-aws-credentials@v1-node16
        with:
          role-to-assume: arn:aws:iam::405529072556:role/repo-qiita-role
          aws-region: ap-northeast-1
      #Lambdaコード アップロード
      - name: Create ZIP Archive LambdaCode
        run: zip -r lambda.zip index.mjs # コードをZIPに圧縮
        working-directory: ./2_Lambda

      - name: S3 FileUpload LambdaCode
        run: aws s3 cp lambda.zip s3://pj-ogataro-dev-storage/lambda/ #zipファイルをS3にアップ
        working-directory: ./2_Lambda

      #Lambda Layerの最新バージョン取得
      - name: AWS LayerVersion Get
        run: |
          LATEST_LAYER_VERSION=$(aws lambda list-layer-versions --layer-name pj-ogataro-dev-layer --output json | jq -r '(.LayerVersions | sort_by(.Version) | reverse)[0].Version')
          echo "LATEST_LAYER_VERSION: $LATEST_LAYER_VERSION"
        working-directory: ./2_Lambda

      #Lambda デプロイ実行
      - name: AWS Cloudformation Development Lambda
        run: |
          aws cloudformation deploy --stack-name Lambda --template-file Lambda.yaml --parameter-overrides Environment=dev LayerVer=$LATEST_LAYER_VERSION
        working-directory: ./2_Lambda
```

# 最後に
こちらでGitHubActionsを使ってLambdaとLambdaレイヤーを構築する手順は完了です。
参考になれば、幸いです。

# 参考サイト
Lambda

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html

AWS CLI (Layerバージョンを取得) 

https://docs.aws.amazon.com/cli/latest/reference/lambda/list-layer-versions.html