継続は力なり

タイトル通り定期的な更新を心掛けるブログです。

AWS SAM と GitHub Actions を使った Lambda のデプロイフローの検証をしてみた

タダです.

業務で Lambda をデプロイを独自スクリプトと CodePipline,CodeBuild を使っていたのですが,開発チームとの相談を経て置き換えを図ろうとGitHub Actions を使ったデプロイフローを検証する機会があったのでこの記事に検証した内容をまとめます.

検証概要

Lambda のコードを管理しているリポジトリでは,以下のようなトップディレクトリ配下に関数ごとにディレクトリがあります.その中に AWS SAM のコードやアプリケーションのコードが入っているような構造になっているのですが,このコードが上位のブランチと差分があるものだけデプロイしたいと思い,検証しました.

.
├── README.md
├── lambdaA-functions
│   ├── README.md
│   ├── __init__.py
│   ├── xxx
│   │   ├── __init__.py
│   │   ├── app.py
│   │   └── requirements.txt
│   └── template.yaml
├── lambdaB-functions
│   ├── README.md
│   ├── __init__.py
│   ├── xxx
│   │   ├── __init__.py
│   │   ├── app.py
│   │   └── requirements.txt
│   └── template.yaml
└── lambdaC-functions
    ├── README.md
    ├── __init__.py
    ├── events
    │   └── event.json
    ├── xxx
    │   ├── __init__.py
    │   ├── app.py
    │   └── requirements.txt
    └── template.yaml

GitHub Actions の定義外観

GitHub Actions の定義としては以下のようなものにしました.

YAML の定義

on:
  pull_request:
    paths:
      - '**app.py'

env:
  TARGET_BRANCH: ${{ github.base_ref }}

jobs:
  sam-test:
    runs-on: ubuntu-latest
    steps:
      - name: 'Checkout'
        uses: actions/checkout@v2

     - name: 'Fetch'
        run: git fetch --depth 1 origin ${TARGET_BRANCH}

      - name: Set up Python ${{ matrix.python-version }}
        uses: actions/setup-python@v2
        with:
          python-version: '3.7'

      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install awscli
          pip install aws-sam-cli

      - name: Configure AWS credentials for prod
        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: ${{ secrets.AWS_REGION}}

      - name: Build & Deploy
        run: |
          for FILE in $(git diff origin/${TARGET_BRANCH} HEAD --diff-filter=AM --name-only -- "*app.py") ; do
            cd $(dirname ${FILE}); cd ../
            STACK_NAME=`pwd | awk -F "/" '{ print $NF }'`
            sam build --use-container
            sam package --template-file template.yaml --output-template-file packaged.yaml --s3-bucket ${{ secrets.AWS_SAM_BUCKET }} --region ${{ secrets.AWS_REGION}}
            sam deploy --template-file packaged.yaml --stack-name ${STACK_NAME} --s3-bucket ${{ secrets.AWS_SAM_BUCKET }} --region ${{ secrets.AWS_REGION}} --capabilities CAPABILITY_IAM
            cd ../
          done

処理の大枠

検証なのでプルリクのどんなイベントでもトリガーするようになっています.プルリクが走ったらpathで指定した AWS SAM のapp.pyに変更があるかをみるようにしています.

push および pull_request イベントを使用する場合、1 つ以上の変更されたファイルが paths-ignore にマッチしない場合や、1 つ以上の変更されたファイルが、設定された paths にマッチする場合にワークフローを実行するように設定できます。 タグへのプッシュに対して、パスのフィルタは評価されません。

docs.github.com

on:
  pull_request:
    paths:
      - '**app.py'

処理の中身ですが,デプロイにあたって予め, AWS CLIAWS SAM CLI を入れたり,クレデンシャル情報をsecrets設定から読み込む処理をしています.

jobs:
  sam-test:
    runs-on: ubuntu-latest
    steps:
      - name: 'Checkout'
        uses: actions/checkout@v2
      - name: Set up Python ${{ matrix.python-version }}
        uses: actions/setup-python@v2
        with:
          python-version: '3.7'

      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install awscli
          pip install aws-sam-cli

      - name: Configure AWS credentials for prod
        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: ${{ secrets.AWS_REGION}}

そして,肝心のビルドやデプロイ部分ですが,処理は上位ブランチと差分があるapp.pyファイルの1つ上の階層のディレクトリに移動してビルドとデプロイ処理が走るようにしています.この辺の差分をチェックする処理を@yutaka0m さんのブログを参考にさせていただきました! ありがとうございます 🙇‍♂️

     - name: 'Fetch'
        run: git fetch --depth 1 origin ${TARGET_BRANCH}
~中略~
      - name: Build & Deploy
        run: |
          for FILE in $(git diff origin/${TARGET_BRANCH} HEAD --diff-filter=AM --name-only -- "*app.py") ; do
            cd $(dirname ${FILE}); cd ../
            STACK_NAME=`pwd | awk -F "/" '{ print $NF }'`
            sam build --use-container
            sam package --template-file template.yaml --output-template-file packaged.yaml --s3-bucket ${{ secrets.AWS_SAM_BUCKET }} --region ${{ secrets.AWS_REGION}}
            sam deploy --template-file packaged.yaml --stack-name ${STACK_NAME} --s3-bucket ${{ secrets.AWS_SAM_BUCKET }} --region ${{ secrets.AWS_REGION}} --capabilities CAPABILITY_IAM
            cd ../
          done

参考記事

tech.yutaka0m.com

まとめ

AWS SAM と GitHub Actions を使った Lambda のデプロイフローを検証してみたのでその内容まとめてみました.GitHub Actions で変更したコードをデプロイできるようになったのでフロー切り替えに適用していきたいと思います.

関連記事

sadayoshi-tada.hatenablog.com