AWS Lambda関数をGithubで管理・デプロイさせよう

## 入る前に

こんにちは、
アプリケーションエンジニアのキムです。
現在、自分が配属されてるチームでは複数のAWS Lambda関数を運用してます。

AWSが提供しているバージョン管理も有効に使っていますが、Lambdaコードをもっと細かく管理したい意見が多くなり、主にLambdaを生産してる私さえ必要性を感じているので、この機会にGithubに移住させてみたいと思います。

どうせGithub上での管理する以上、現在運用中のアプリケーションと同様に、PR・コードレビューが正常に完了してから自動的にdeployされてほしいという気持ちがあったので、今回の作業を実行することになりました。

## 頼みの言葉

様々な試みの末、手作業で作られたコードです。 とても粗雑かもしれませんので、修正案について良い意見がありましたらコメントをお願いします。
Github marketplaceで気に入りのActionsが特になかったのでこのような感じになりました。
今後良いActionsがマーケットに登場するようになったらアクション内容についても共有していただければ嬉しいです。

## やりたいこと

やりたい作業は簡単です。
- AWSアカウント内で使用中の複数のLambda関数をすべてGithub上での管理
- Mergeされる場合、新しいバージョンへのdeploy
    - リポジトリ全体がdeployされるのではなく、今回作業された関数のみ

この2つを満足させるアクションが今のところ見られなかったので作業を始めることになりました。
タスクは、以前にも共有したことのあるGithubActionsを活用し、トリガーはbranchに対するmerge行為、PRがmergeされてcloseになるケースが発生した場合を想定しています。

Github Actionsの処理の中、Linux上でawsコマンドを利用する方法で進めました。
私が調査によると現時点でのGithub Marketplaceでよく共有されてるActionsはほぼ1レポジトリ＝1関数または特定関数を指定するように設定するのが多くて(私の認識が間違っていたら申し訳ありません)私たちが望む2番目の条件を果たすアクションを見つけることができませんでした。

#### 状況を整理すると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76353/31a7f253-4bc4-9613-a2b0-924ff3b9be20.png)

このような運用構成を望んでいました。
複数のファイルをアップデートしても対応可能な状況に対応したかったのです（あえて）

## 実行
```yaml
name: Deploy作業
on:
  pull_request:
    branches:
      - develop
      - stage
      - master
    types: [closed]

jobs:
  deploy:
    if: github.event.pull_request.merged == true
    runs-on: ubuntu-latest
    environment:
      name: ${{ github.ref }}
    steps:
      - name: Checkout
        uses: actions/checkout@v3
      - uses: jitterbit/get-changed-files@v1
        id: files
        with:
          format: space-delimited

      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ap-northeast-1

      - name: Python Setup
        uses: actions/setup-python@v3
        with:
          python-version: '3.9'

      ## pipでawscliをInstall
      ## 1. 変更が発生した、ファイル一覧をForでLoopさせながら、特定拡張子を取得
      ## 2. .py（現コード）を発見　→　ファイル名を lambda_function.pyに変更（現状運用中の関数のファイル名）
      ## 3. 該当ファイルをzipファイルとして圧縮し、指定AWSアカウントにアップロード
      - name: Lambda Build & Update
        run: |
          pip3 install awscli 
          for changed_file in ${{ steps.files.outputs.added_modified }}; do
            if [[ ${changed_file##*.} == "py" ]]; then
              cp `echo ${changed_file}` lambda_function.py && ls -al
              zip -r package.zip lambda_function.py
              aws lambda update-function-code --function-name `echo ${changed_file} | sed 's/src\///g' | sed 's/\.py//g'` --zip-file fileb://package.zip --publish
            fi
          done
```

上記の流れを以下のように実行しました。
できるだけ多様なファイル拡張子を指定するように設定してみました。 大きな意味はなさそうです。
一度に複数の関数に対する作業が発生する可能性がある状況を考慮したため、このような流れを選択しました。

加えて、私達の場合AWSが2つのアカウントが存在します。
ひとつはテスト環境用のアカウント、またプロダクションのアカウントです。
したがって、GithubActionsを実行させる際にも、どのブランチに止まるかによって、アカウント情報を[Github Envrionments](https://docs.github.com/ja/actions/deployment/targeting-different-environments/using-environments-for-deployment)を活用して分けておきました。
簡単に言えば、ブランチが
- develop →　開発環境
- master　→　プロダクション環境

を選択してデプロイさせます。

## 仕上げ

今回はLambda関数を管理するアクションを作ってみました。
以前から必要な機能だったが思ったより余裕がない見たら思ったより時間が長くかかったようです。

私はビジネス開発と共にこのようなチーム内開発に役立つ多様なサポートをする作業になぜかもう少し意欲が先立つ方です。 その他にも、アプリケーションのパフォーマンス状況チェックやアプリケーションロギング管理、AWS費用確認など、より面白いテーマで意味のある結果を作り出すことができれば、関連ポスティングを作成できるよう努力します。

私の経験が誰かに役に立てば嬉しいです。 みんな楽しい開発をしてください:)