この記事について
AWS Lambda関数を作成した際、VSCodeを使用している場合は拡張機能を使用してローカルからAWSへデプロイすることが可能です。
しかし、Lambda関数の変更回数が多くなったり、チーム開発を行う場合にはローカルからの手動デプロイは手間になったり俗人化を招くこととなります。
そこでこの記事では、GitHub Actionsを使用してGitHubの特定のブランチにpushされたLambda関数をAWSへ自動デプロイする仕組みについて説明したいと思います。
対象読者
- GitHubを使用してAWS Lambdaの開発を行っている方
- チーム開発などでAWS Lambdaの自動デプロイを行いたい方
環境
内容 | バージョン |
---|---|
.NET | 6.0.x |
.NET用のAmazon.Lambda.Toolsで下のコマンドで.NETプロジェクトを作成すると、以下のようなディレクトリ構成となります。
(プロジェクトファイルがSampleFunction/src/SampleFunction/SampleFunction.csproj
に存在する)
% dotnet new lambda.EmptyFunction --name SampleFunction
テンプレート "Lambda Empty Function" が正常に作成されました。
% cd SampleFunction
% tree SampleFunction
SampleFunction
├── src
│ └── SampleFunction
│ ├── Function.cs
│ ├── Readme.md
│ ├── SampleFunction.csproj
│ └── aws-lambda-tools-defaults.json
└── test
└── SampleFunction.Tests
├── FunctionTest.cs
└── SampleFunction.Tests.csproj
今回はこちらの構成を想定してワークフローを作成していきます。
参考:【VSCode, C#, AWS Lambda】C#で作成したLambda Functionをローカルで動作確認する - プロジェクトの作成
TL;DR
masterブランチにpushされた時のみGitHub Actionsのジョブを実行するようにしています。
name: Deploy to AWS Lambda
on:
push:
branches:
- master
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v2
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: Setup dotnet
uses: actions/setup-dotnet@v3
with:
dotnet-version: '6.0.x'
- name: Build
run: |
dotnet build ${GITHUB_WORKSPACE}/SampleFunction/src/SampleFunction/SampleFunction.csproj
(cd ${GITHUB_WORKSPACE}/SampleFunction/src/SampleFunction/bin/Debug/net6.0 && zip -r SampleFunction.zip .)
- name: Deploy
# デプロイ結果のoutputはターミナルに表示したくないため、いったんファイルに出力させてそのファイルをすぐ削除している
run: |
aws lambda update-function-code --function-name ${{ secrets.AWS_LAMBDA_FUNCTION_NAME }} --zip-file fileb://${GITHUB_WORKSPACE}/SampleFunction/src/SampleFunction/bin/Debug/net6.0/SampleFunction.zip --publish >> deploy.log
rm deploy.log
ジョブの内容
ジョブのstepsを5段階に分けましたが、それぞれの内容を順を追って見ていきましょう。
今回使用する環境はubuntuとするため、job.deploy.runs-on
にはubuntu-latest
を指定します。
# 前後省略
jobs:
deploy:
runs-on: ubuntu-latest
checkout
デプロイ前にプログラムコードのビルドが必要であるため、checkoutしてジョブの実行環境にソースコードを持ってきます。
GitHub Actionsにはactions/checkoutアクションが用意されており、今回は最新のv3を使用します。(actions/checkout@v3
)
# 前後省略
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
同じジョブのstep間のリソースは共有できるため、以降は別stepに分けて記述していきます。
AWS認証
今回はデプロイ先がAWS Lambdaであるため、デプロイ前にAWSユーザの認証が必要となります。
ルートユーザだと権限が強すぎるため、AWS IAMでLambda用のユーザを作成しておきます。
今回は、作成したユーザに「AWSLambda_FullAccess」「CloudWatchFullAccess」「CloudWatchEventsFullAccess」の許可ポリシーを割り当てております。(ユーザがLambdaへデプロイする権限があればカスタムの許可ポリシーなどでも良いです。)
参考:AWS アカウント での IAM ユーザーの作成
ユーザを作成したら、そのユーザのアクセスキーを発行します。作成したIAMユーザを選択して「アクセスキーを作成」から作成することが可能です。アクセスキーとシークレットアクセスキーを後ほど使うためためメモしておきましょう。
AWS認証は、専用のアクションaws-actions/configure-aws-credentialsが用意されているためこちらを使用します。
先ほど作成・メモしたアクセスキーとシークレットアクセスキーを使用するのですが、直接ymlファイルに記述してしまうとユーザ情報が外部に漏れてしまいます。漏洩を防ぐためGitHubのsecretsを使用します。
対象リポジトリで、Setting > Secrets and variables > Actionsと進みます。
キーの名前は任意で構いませんが、今回はアクセスキーをAWS_ACCESS_KEY_ID
、シークレットアクセスキーをAWS_SECRET_ACCESS_KEY
という名前でキーを登録します。
登録したキーをactionで使用します。
aws-actions/configure-aws-credentialsアクションでは、アクセスキー(aws-access-key-id
)・シークレットアクセスキー(aws-secret-access-key
)・Lambdaで使用するリージョン(aws-region
)を指定する必要があり、それぞれ以下のように指定することでGitHub ActionsでAWSの認証ができます。
# 前後省略
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v2
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ secrets.AWS_REGION }}
.NET環境のセットアップ
actionで.NET環境を整えていきましょう。actions/setup-dotnetアクションで.NET環境の構築ができます。
今回.NETのバージョンは6.0系を使用しているため、dotnet-version
には'6.0.x'
を指定します。
# 前後省略
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v2
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: Setup dotnet
uses: actions/setup-dotnet@v3
with:
dotnet-version: '6.0.x'
プログラムコードのビルド
.NET環境のセットアップを行ったため、dotnet build
コマンドで.NETプロジェクトのビルドができます。
引数でプロジェクトファイルの指定が必要ですが、checkoutした際のcheckout先ディレクトリパスは${GITHUB_WORKSPACE}
で取得できます。
参考:Learn GitHub Actions - Variables
環境のところでも記載したように、プロジェクトファイルはSampleFunction/src/SampleFunction/SampleFunction.csproj
に存在するため、ビルド先のパスは${GITHUB_WORKSPACE}/SampleFunction/src/SampleFunction/SampleFunction.csproj
指定とします。
またLambdaへのデプロイ時にはビルドしたものをzipファイルにして、zipファイルをデプロイしますが、zip
コマンドを使用する際には一度bin/Debug/net6.0
に移動してからzipファイルを作成します。
bin/Debug/net6.0
に移動せずにzipファイルを作成すると、${GITHUB_WORKSPACE}
直下のディレクトリからzipファイル化されてしまい、Lambdaにデプロイした際にエラーとなってしまいます。
参考:ディレクトリ内のファイルを zip ファイルにバックアップする
.NETプロジェクトをLambdaで動かすにはbin/Debug/net6.0
配下をデプロイする必要があります。
# 前後省略
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v2
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: Setup dotnet
uses: actions/setup-dotnet@v3
with:
dotnet-version: '6.0.x'
- name: Build
run: |
dotnet build ${GITHUB_WORKSPACE}/SampleFunction/src/SampleFunction/SampleFunction.csproj
(cd ${GITHUB_WORKSPACE}/SampleFunction/src/SampleFunction/bin/Debug/net6.0 && zip -r SampleFunction.zip .)
AWS Lambdaへデプロイ
いよいよLambdaへのデプロイです。
AWS CLIを使用できるため、aws lambda update-function-code
コマンドでLambda関数を更新します。(update-function-codeを使うには、AWS Lambdaの関数を事前に作成しておく必要があります。)
--function-name
で関数名を、--zip-file
で先ほど作成したzipファイルのパスを指定します。
ここで注意点です。コマンドが正常に実行されると、実行結果がJSON形式で表示されてしまいます。表示される実行結果の中には、環境変数やリージョンなど表示されたくない機密情報も表示されてしまいます。
publicリポジトリなどを使用している場合は、この情報がGitHub Actions上に表示されるのはあまりよろしくないため、>> deploy.log
を付けて一度ファイルに出力してGitHub Actions上に表示されないようにしています。
# 前後省略
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v2
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: Setup dotnet
uses: actions/setup-dotnet@v3
with:
dotnet-version: '6.0.x'
- name: Build
run: |
dotnet build ${GITHUB_WORKSPACE}/SampleFunction/src/SampleFunction/SampleFunction.csproj
(cd ${GITHUB_WORKSPACE}/SampleFunction/src/SampleFunction/bin/Debug/net6.0 && zip -r SampleFunction.zip .)
- name: Deploy
# デプロイ結果のoutputはターミナルに表示したくないため、いったんファイルに出力させてそのファイルをすぐ削除している
run: |
aws lambda update-function-code --function-name ${{ secrets.AWS_LAMBDA_FUNCTION_NAME }} --zip-file fileb://${GITHUB_WORKSPACE}/SampleFunction/src/SampleFunction/bin/Debug/net6.0/SampleFunction.zip --publish >> deploy.log
rm deploy.log
このジョブが実行されると、AWSの画面上でもLambda関数が更新されることが確認できます。
プログラムコードが変更された時のみ自動デプロイする
ここまでのGitHub Actionsの状態では、リポジトリ内のすべてのファイルの変更に対してジョブが実行されてしまいます。しかし、README.mdやymlファイル自体の変更では、プログラムコードのビルド結果は変わりません。
そのため、プログラムコードの変更時のみビルド・デプロイを行いたいものです。(プログラムコード以外の変更ではジョブを実行しない。)
次のように、push以下にpaths-ignore
を定義することで特定ファイルのpush時にはジョブを実行しないようにすることが可能です。逆にpush以下にpaths
を定義すると、特定ファイルのpush時のみジョブを実行することも可能です。
name: Deploy to AWS Lambda
on:
push:
branches:
- master
paths-ignore:
# mdファイルやGitHub Actionsのフローyml、vscode設定ファイル関連はpushしてもジョブ実行しないようにする
- '**/*.md'
- '.gitignore'
- '.github/**'
- '.vscode/**'
jobs:
# 以下省略