AWS Lambda Layersを自動更新するGitHub Actions

# はじめに

あの若干面倒なAWS LambdaのLayersをGithubActionsで自動更新するプロセスを組みましたので参考にしていただければ!!（備忘録も兼ねて）

また、本記事内ではアクセスキーとシークレットキーを使った認証ではなく、OIDC認証で実施していますので以下の記事を参考にしていただければ問題ないかと思います。

https://qiita.com/frei_aqua/items/c284a1249dac84c881cb

# 前提
- Python
- Pipenv環境
- Lambda関数を作成済み
- Layersも紐づけ済み（設定オプション的に紐づけもコマンドで行けそうか？要検証）

# 本体

お急ぎの方もいるかと思いますので先にymlを貼っておきます。

```yaml
name: Layer Update

on:
  push:
    branches:
      - main
    paths:
      - "Pipfile"

env:
  REGION_NAME: your-region
  FUNCTION_NAME: 対象のfuntion_name
  LAYERS_NAME: 対象のlayer_name
  LAYERS_ARN: 対象のlayer ARN
  LAMBDA_EXECUTION_ROLE: 更新用ロールARN
  
jobs:
  deploy:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: read

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
        
      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.10"
          
      - name: Configure aws credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: ${{ env.LAMBDA_EXECUTION_ROLE }}
          role-session-name: githubaction
          aws-region: ${{ env.REGION_NAME }}

      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install pipenv

      - name: Generate Layer.zip
        run: |
          pipenv lock
          mkdir python
          PIP_TARGET=python/ pipenv install --system
          zip -r Layer.zip python/
      
      - name: Publish new layer version
        id: publish_layer
        run: |
          LAYER_VERSION=$(aws lambda publish-layer-version \
            --layer-name ${{ env.LAYERS_NAME }} \
            --zip-file fileb://Layer.zip \
            --query 'Version' \
            --output text)
          echo "LAYER_VERSION=${LAYER_VERSION}" >> $GITHUB_OUTPUT

      - name: Update Lambda function configuration
        run: |
          aws lambda update-function-configuration \
          --function-name ${{ env.FUNCTION_NAME }} \
          --layers ${{ env.LAYERS_ARN }}:${{ steps.publish_layer.outputs.LAYER_VERSION }}

```

# ワークフローの詳細説明

## トリガー設定
mainブランチのPipfileが変更されたときに実行されます。
こちらは各々適宜調整

```yml
on:
  push:
    branches:
      - main
    paths:
      - "Pipfile"
```

# 環境変数
修正対応が必要そうなのはこの部分のみ。各々の環境変数を設定
```yml
env:
  REGION_NAME: your-region
  FUNCTION_NAME: 対象のfuntion_name
  LAYERS_NAME: 対象のlayer_name
  LAYERS_ARN: 対象のlayer ARN
  LAMBDA_EXECUTION_ROLE: 更新用ロールARN
```

LAMBDA_EXECUTION_ROLEについてはLambdaへのデプロイロールと同じものでよいかと思います。適宜調整してください

ロールのポリシー（パーミッション）については[以下](#ロールのポリシー設定)

# Pythonバージョン
こちらも適宜調整
```yml
    - name: Set up Python
    uses: actions/setup-python@v5
    with:
      python-version: "3.10"
```

# OIDC認証
詳細は記事上部に引用した記事を参照
```yml
  - name: Configure aws credentials
    uses: aws-actions/configure-aws-credentials@v4
    with:
      role-to-assume: ${{ env.LAMBDA_EXECUTION_ROLE }}
      role-session-name: githubaction
      aws-region: ${{ env.REGION_NAME }}
```

# 依存関係
Pipenvで依存関係を一括管理しています。
こちらも環境によって調整してください。


```yml
  - name: Install dependencies
    run: |
      python -m pip install --upgrade pip
      pip install pipenv

  - name: Generate Layer.zip
    run: |
      pipenv lock
      mkdir python
      PIP_TARGET=python/ pipenv install --system
      zip -r Layer.zip python/
```

下記でpythonディレクトリ内にライブラリをインストールします。
```bash
PIP_TARGET=python/ pipenv install --system
```

ライブラリインストール後zip化
```bash
zip -r Layer.zip python/
```

# Layersデプロイ
次ステップで最新のLayersバージョンが必要なのでechoする必要があります。
```yaml
  - name: Publish new layer version
    id: publish_layer
    run: |
      LAYER_VERSION=$(aws lambda publish-layer-version \
        --layer-name ${{ env.LAYERS_NAME }} \
        --zip-file fileb://Layer.zip \
        --query 'Version' \
        --output text)
      echo "LAYER_VERSION=${LAYER_VERSION}" >> $GITHUB_OUTPUT
```

# Layersバージョン書き換え
```yaml
  - name: Update Lambda function configuration
    run: |
      aws lambda update-function-configuration \
      --function-name ${{ env.FUNCTION_NAME }} \
      --layers ${{ env.LAYERS_ARN }}:${{ steps.publish_layer.outputs.LAYER_VERSION }}
```

# ロールのポリシー設定
必要な権限としては以下
対象リソースの設定も忘れずに…
``` yml
lambda:PublishLayerVersion #Layersのpublish
lambda:GetLayerVersion #Layersの取得
lambda:UpdateFunctionConfiguration #Lambdaの設定変更
```
# まとめ
これでPipfileが更新されるたびに自動的にAWS Lambda Layersが更新されLambdaへの紐づきも最新化されます。
依存関係の管理に集中でき、Layersの手動更新による煩わしさからの解放～