【小ネタ】GitHub ActionsでLambda Layerをデプロイするときに困った話
目次
はじめに
こんにちは、CloudBuildersのsugawaraです。
先日、GitHub ActionsでLambdaとCDKのコードを自動デプロイしようとしたとき、Lambda Layerのデプロイ部分でちょっとつまってしまいました。今回はそのときの話を小ネタとして書いていきたいと思います。これを読んでいただき、自分のようなミスをしないようにしていただければと思います。
さきに結論
今回の件で自分が学んだのは下記の2点です。(ここを読んで理解納得できれば次節以降は読まなくて大丈夫だと思います!)
- Lambda LayerをGitHub Actionsのワークフロー内でzip化し、CDKのコードとともにデプロイする場合、zipファイルをアーティファクトとしてGitHub Actions上へアップロードする必要がある。
- アーティファクトはワークフロー間では渡すことができないため、ジョブ間で渡す(ダウンロードする)ようにする。
やりたいこと
- GitHub ActionsでCDKのコードとその一部であるLambdaのコードを自動デプロイする
- Lambda用のワークフロー内でLambda Layerはzip化する
実行環境
$ node --version
v20.12.2
$ cdk --version
2.138.0 (build 6b41c8b)
$ aws --version
aws-cli/2.13.25 Python/3.11.5 Linux/5.10.16.3-microsoft-standard-WSL2 exe/x86_64.ubuntu.22 prompt/off
当初の構成
ディレクトリ構成
.github/workflows配下のワークフローファイルはLambdaとCDKの2つを作成していました。また、infrastructure配下にはCDKのコード、lambda配下にはLambda(Node.js)とLambda Layerのコードを配置しています。
.
├── README.md
├── .github/workflows
│ ├── lambda.yml
│ └── infrastructure.yml
├── infrastructure
│ ├── bin
│ │ └── infrastructure.ts
│ ├── cdk.context.json
│ ├── cdk.json
│ ├── lib
│ │ └── infrastructure-stack.ts
│ ├── node_modules
│ ├── package-lock.json
│ └── package.json
└── lambda
├── lambda-layer
│ └── nodejs
└── src
└── samplecode
ワークフローファイル
独立した2つのワークフローファイルを作成し、それぞれは異なるトリガーで起動するようにしていました。簡単にまとめると、下記のようになります。
- GitHubにCDKのコードの更新がプッシュされたら、CDK用のワークフローが起動する。
- GitHubにLambdaのコードの更新がプッシュされたら、Lambda用のワークフローが起動する。問題がなければ、次にCDK用のワークフローが起動する。
↓↓Lambda用のワークフローファイル
name: "Lambda Build and Test"
on:
push:
branches:
- develop
paths:
- "lambda/**/*.mjs"
- ".github/**/lambda.ya?ml"
workflow_dispatch:
defaults:
run:
working-directory: lambda/src
shell: bash
jobs:
build-test-deploy:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: actionlint
uses: actions/checkout@v4
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
cache: npm
cache-dependency-path: ./lambda/src/package-lock.json
cache-dependency-path: lambda/lambda-layer/nodejs/package-lock.json
- name: Setup dependencies
run: npm ci
working-directory: lambda/lambda-layer/nodejs
- name: Run Unit Tests
run: npm test
- name: Build
run: npm run build
↓↓CDK用のワークフローファイル
name: "CI/CD for CDK"
on:
push:
branches:
- develop
paths:
- "infrastructure/**"
- ".github/**/infra.ya?ml"
pull_request:
branches:
- main
workflow_dispatch:
workflow_run:
workflows: ["Lambda Build and Test"]
types:
- completed
defaults:
run:
working-directory: infrastructure
shell: bash
permissions:
id-token: write
contents: read
jobs:
build-test-deploy:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: actionlint
uses: actions/checkout@v4
- name: Checkout repository code
uses: actions/checkout@v4
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.AWS_IAM_ROLE_ARN }}
aws-region: ap-northeast-1
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
cache: npm
cache-dependency-path: ./infrastructure/package-lock.json
- name: Setup dependencies
run: npm ci
- name: Bootstrap CDK
run: npx cdk bootstrap
- name: Build
run: npm run build
- name: CDK Diff Check
run: npx cdk diff
- name: CDK Deploy
if: github.ref == 'refs/heads/develop'
run: npx cdk deploy --require-approval never
なお、AWSへのデプロイはGitHub ActionsのOpenID Connect用のIAMロールを作成して実行しています。OIDCについては下記の記事をご参照ください。
また、GitHub Actionsの学習についても記事を書いていますので、こちらも見ていただけると嬉しいです。
問題点と改善案
実際にワークフローを起動してみると、CDK用のワークフロー上でLambda Layerのzipファイルを取得できずにエラーに。
GitHubのActionsタブで確認してみると、LambdaのワークフローではLambda Layerがzip化されてGitHub上にアーティファクトとしてアップロードされていることは確認できました。しかし、CDK用のワークフロー上では、アップロードされたzipファイルのダウンロード時にNot Foundのエラーが出ているということがわかりました。
公式ドキュメントにてアーティファクトを見てみると、同一のワークフロー内なら別のジョブへアーティファクトを渡すことができるとわかりました。つまり、そもそも別ワークフローには渡せないということでした。
最終的な構成
ディレクトリ構成
2つのワークフローは統合して1つのワークフローに修正しました。
.
├── README.md
├── .github/workflows
│ └── cicd.yml ## ここを修正して一元化
├── infrastructure
│ ├── bin
│ │ └── infrastructure.ts
│ ├── cdk.context.json
│ ├── cdk.json
│ ├── lib
│ │ └── infrastructure-stack.ts
│ ├── node_modules
│ ├── package-lock.json
│ └── package.json
└── lambda
├── lambda-layer
│ └── nodejs
└── src
└── samplecode
ワークフローファイル
別々のワークフローだったものを2つのジョブに修正することで、アーティファクトをアップロード&ダウンロードできるようにしています。
name: "CI/CD for Lambda and CDK"
on:
push:
branches:
- develop
paths:
- "lambda/**/*.mjs"
- "infrastructure/**"
- ".github/**.yml"
pull_request:
branches:
- main
workflow_dispatch:
defaults:
run:
shell: bash
permissions:
id-token: write
contents: read
jobs:
build-lambda-and-lambda-layer:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: actionlint
uses: actions/checkout@v4
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
- name: Setup dependencies
run: npm ci
working-directory: ./lambda/lambda-layer/nodejs
- name: Package Lambda Layer
run: zip -r layer.zip nodejs
working-directory: ./lambda/lambda-layer
- name: Upload Lambda Layer Artifact
uses: actions/upload-artifact@v4
with:
name: lambda-layer
path: ./lambda/lambda-layer/layer.zip
- name: Build Lambda
run: npm run build
working-directory: ./lambda/src
- name: Test
run: npm test
deploy-cdk:
runs-on: ubuntu-latest
timeout-minutes: 20
needs: build-lambda-and-lambda-layer
steps:
- name: actionlint
uses: actions/checkout@v4
- name: Checkout repository code
uses: actions/checkout@v4
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.AWS_IAM_ROLE_ARN }}
aws-region: ap-northeast-1
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
cache: npm
cache-dependency-path: ./infrastructure/package-lock.json
- name: Setup dependencies for CDK
run: npm ci
working-directory: ./infrastructure
- name: Download Lambda Layer Artifact
uses: actions/download-artifact@v4
with:
name: lambda-layer
path: ./lambda/lambda-layer
- name: Bootstrap CDK
run: npx cdk bootstrap
working-directory: ./infrastructure
- name: Build CDK
run: npm run build
working-directory: ./infrastructure
- name: CDK Diff Check
run: npx cdk diff
working-directory: ./infrastructure
- name: CDK Deploy
if: github.ref == 'refs/heads/develop'
run: npx cdk deploy --require-approval never
working-directory: ./infrastructure
上記に修正することで、問題なくLambda Layerも含めてCDKのデプロイができるようになりました。
おわりに
今回は実際にGitHub Actionsで自分がつまづいたことを記事にしました。今回の失敗からアーティファクトやワークフロー、ジョブについての理解がちょっと深まりました。やはり自分でやってみるのことが一番学びにつながりますね。
まだまだ上記のワークフローファイルは改善の余地があるので、引き続き学習を進めたいと思います。