はじめに
表題の最新のアップデートについて試してみたいと思います。
何ができるようになったの?
AWS Lambda が GitHub Actions と直接連携して、Lambda 関数を自動デプロイできるようになりました!
これまでの問題点
GitHub から Lambda 関数をデプロイするには、複雑なカスタムスクリプトや AWS CLI を書く必要がありました。
そのため、開発者が以下のようなことを手動で設定する必要があった。
- 関数コードのパッケージ化
- AWS IAM 権限の設定
- エラーハンドリング
新機能で何が変わった?
GitHub Actions ワークフローで宣言するだけで簡単になった
デプロイ方式
ZIP ファイルとコンテナイメージの両方をサポート
使い方の例
GitHub Actions の設定ファイル(.github/workflows/deploy.yml
)に以下のように記載:
name: Deploy Lambda Function
on:
push:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Deploy to Lambda
uses: aws-actions/aws-lambda-deploy@v1
with:
function-name: my-lambda-function
runtime: python3.9
handler: lambda_function.lambda_handler
設定できるパラメータは GitHub を参照して下さい。
やってみた
GitHub Actions 用 と Lambda 用の AWS IAM の設定
OIDC 認証を使用して GitHub Actions が Lambda 関数をデプロイできるようにするための AWS IAM ロールとポリシーを作成します。
1: GitHub OIDC アイデンティティプロバイダーの作成
AWS IAM で OIDC アイデンティティプロバイダーを作成します:
aws iam create-open-id-connect-provider \
--url https://token.actions.githubusercontent.com \
--client-id-list sts.amazonaws.com \
--thumbprint-list 6938fd4d98bab03faadb97b34396831e3780aea1 \
--thumbprint-list 1c58a3a8518e8759bf075b76b750d4f2df264fcd
2: Lambda デプロイ用 IAM ポリシーの作成
ポリシーファイル lambda-deploy-policy.json
を作成します:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "LambdaFunctionAccess",
"Effect": "Allow",
"Action": [
"lambda:UpdateFunctionCode",
"lambda:UpdateFunctionConfiguration",
"lambda:GetFunction",
"lambda:CreateFunction",
"lambda:TagResource",
"lambda:UntagResource",
"lambda:ListTags",
"lambda:PublishVersion",
"lambda:GetFunctionConfiguration"
],
"Resource": "arn:aws:lambda:*:*:function:*"
},
{
"Sid": "IAMRoleAccess",
"Effect": "Allow",
"Action": [
"iam:PassRole"
],
"Resource": "arn:aws:iam::*:role/lambda-execution-role*"
},
{
"Sid": "LogsAccess",
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents",
"logs:DescribeLogGroups",
"logs:DescribeLogStreams"
],
"Resource": "arn:aws:logs:*:*:*"
}
]
}
ポリシーを作成します:
aws iam create-policy \
--policy-name GitHubActionsLambdaDeployPolicy \
--policy-document file://lambda-deploy-policy.json
3: GitHub Actions 用 IAM ロールの作成
信頼ポリシーファイル github-actions-trust-policy.json
を作成します:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::<AWS アカウント ID>:oidc-provider/token.actions.githubusercontent.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
},
"StringLike": {
"token.actions.githubusercontent.com:sub": "repo:<GITHUB ユーザー名>/<リポジトリ名>:*"
}
}
}
]
}
ロールを作成します:
aws iam create-role \
--role-name GitHubActionsRole \
--assume-role-policy-document file://github-actions-trust-policy.json
4: ポリシーをロールにアタッチ
ポリシーをロールにアタッチします:
aws iam attach-role-policy \
--role-name GitHubActionsRole \
--policy-arn arn:aws:iam::<AWS アカウント ID>:policy/GitHubActionsLambdaDeployPolicy
5: Lambda 実行ロールの作成
Lambda実行ロール用の信頼ポリシー lambda-trust-policy.json
を作成します:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
Lambda実行ロールを作成します:
aws iam create-role \
--role-name lambda-execution-role \
--assume-role-policy-document file://lambda-trust-policy.json
aws iam attach-role-policy \
--role-name lambda-execution-role \
--policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
GitHub シークレットの設定
GitHubリポジトリで、Settings > Secrets and variables > Actions に移動し、以下のシークレットを追加します:
-
AWS_ROLE_ARN:
arn:aws:iam::<AWS アカウント ID>:role/GitHubActionsRole
-
LAMBDA_FUNCTION_NAME:
arn:aws:iam::<AWS アカウント ID>:role/lambda-execution-role
サンプルアプリケーションの準備
適当なサンプルアプリケーションを準備しておきます。
./src/lambda_function.py
import json
import logging
logger = logging.getLogger()
logger.setLevel(logging.INFO)
def lambda_handler(event, context):
"""
AWS Lambda function handler for a simple API Gateway integration
"""
logger.info(f"Received event: {json.dumps(event)}")
# Get method and path from event
http_method = event.get('httpMethod', 'GET')
path = event.get('path', '/')
# Simple routing
if path == '/' and http_method == 'GET':
return handle_health_check()
elif path == '/hello' and http_method == 'GET':
return handle_hello(event)
elif path == '/hello' and http_method == 'POST':
return handle_create_hello(event)
else:
return handle_not_found()
def handle_health_check():
"""Health check endpoint"""
return {
'statusCode': 200,
'headers': {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
},
'body': json.dumps({
'message': 'Lambda function is healthy',
'status': 'OK'
})
}
def handle_hello(event):
"""GET /hello endpoint"""
query_params = event.get('queryStringParameters') or {}
name = query_params.get('name', 'World')
return {
'statusCode': 200,
'headers': {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
},
'body': json.dumps({
'message': f'Hello, {name}!',
'timestamp': context_timestamp()
})
}
def handle_create_hello(event):
"""POST /hello endpoint"""
try:
body = json.loads(event.get('body', '{}'))
name = body.get('name', 'Anonymous')
return {
'statusCode': 201,
'headers': {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
},
'body': json.dumps({
'message': f'Hello created for {name}!',
'data': body,
'timestamp': context_timestamp()
})
}
except json.JSONDecodeError:
return {
'statusCode': 400,
'headers': {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
},
'body': json.dumps({
'error': 'Invalid JSON in request body'
})
}
def handle_not_found():
"""404 handler"""
return {
'statusCode': 404,
'headers': {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
},
'body': json.dumps({
'error': 'Not Found',
'message': 'The requested resource was not found'
})
}
def context_timestamp():
"""Get current timestamp"""
from datetime import datetime, timezone
return datetime.now(timezone.utc).isoformat().replace('+00:00', 'Z')
GitHub Actions の設定ファイルの作成
### Lambda 関数のデプロイ ###
が今回の表題の AWS Lambda の GitHub Actions の記載です。なお、今回はまだ Lambda が存在していないため、role
の設定が必須となります。
name: Deploy AWS Lambda Function
# トリガー: push, pull_request
on:
push:
branches:
- main
pull_request:
branches:
- main
# 環境変数
env:
PYTHON_VERSION: '3.13'
AWS_REGION: 'ap-northeast-1'
# ジョブ定義
jobs:
# テストジョブ
test:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install pytest boto3 moto
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
- name: Run tests
run: |
python -m pytest tests/ -v || echo "No tests found - skipping test execution"
# デプロイジョブ
deploy:
needs: test
runs-on: ubuntu-latest
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
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: ${{ env.PYTHON_VERSION }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
if [ -f requirements.txt ]; then pip install -r requirements.txt -t ./dist/; fi
- name: Copy source code to dist directory
run: |
mkdir -p dist
cp -r src/* dist/
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
aws-region: ${{ env.AWS_REGION }}
### Lambda 関数のデプロイ ###
- name: Deploy Lambda Function
uses: aws-actions/aws-lambda-deploy@v1
with:
function-name: sample-lambda-function
code-artifacts-dir: ./dist
handler: lambda_function.lambda_handler
runtime: python3.13
memory-size: 128
timeout: 30
environment: '{"ENVIRONMENT":"production","LOG_LEVEL":"INFO"}'
role: ${{ secrets.AWS_LAMBDA_EXECUTION_ROLE }}
dry-run-deploy:
needs: test
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
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: ${{ env.PYTHON_VERSION }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
if [ -f requirements.txt ]; then pip install -r requirements.txt -t ./dist/; fi
- name: Copy source code to dist directory
run: |
mkdir -p dist
cp -r src/* dist/
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
aws-region: ${{ env.AWS_REGION }}
- name: Dry Run Lambda Deployment
uses: aws-actions/aws-lambda-deploy@v1
with:
function-name: sample-lambda-function
code-artifacts-dir: ./dist
handler: lambda_function.lambda_handler
runtime: python3.13
memory-size: 128
timeout: 30
function-description: "Sample Lambda function deployed via GitHub Actions"
environment: '{"ENVIRONMENT":"staging","LOG_LEVEL":"DEBUG"}'
dry-run: true
動作確認
git に push して動作を確認してみます。
git add .
git commit -m "Initial Lambda function"
git push origin main
GitHub リポジトリの Actions を確認してみます。
AWS CLI で AWS Lambda が作成されていることも確認しておきます。
aws lambda get-function --function-name sample-lambda-function
{
"Configuration": {
"FunctionName": "sample-lambda-function",
"FunctionArn": "arn:aws:lambda:ap-northeast-1:123456789012:function:sample-lambda-function",
"Runtime": "python3.13",
"Role": "arn:aws:iam::123456789012:role/lambda-execution-role",
"Handler": "lambda_function.lambda_handler",
"CodeSize": 991,
"Description": "",
"Timeout": 30,
"MemorySize": 128,
"LastModified": "2025-09-02T15:34:14.000+0000",
"CodeSha256": "Ls5gUV3Z/GFl8s9pxDskLdoPCb1dj1vizJs7y4Mz9pU=",
"Version": "$LATEST",
"Environment": {
"Variables": {
"ENVIRONMENT": "production",
"LOG_LEVEL": "INFO"
}
},
"TracingConfig": {
"Mode": "PassThrough"
},
"RevisionId": "24c13f99-7a19-492f-96a1-35e380e7afb2",
"State": "Active",
"LastUpdateStatus": "Successful",
"PackageType": "Zip",
"Architectures": [
"x86_64"
],
"EphemeralStorage": {
"Size": 512
},
"SnapStart": {
"ApplyOn": "None",
"OptimizationStatus": "Off"
},
"RuntimeVersionConfig": {
"RuntimeVersionArn": "arn:aws:lambda:ap-northeast-1::runtime:6b9e6bdace
9349e61d853adcfe031f7dbe39dd1762b0b2fcd6532dc5792399ca"
},
"LoggingConfig": {
"LogFormat": "Text",
"LogGroup": "/aws/lambda/sample-lambda-function"
}
},
"Code": {
"RepositoryType": "S3",
"Location": "https://awslambda-ap-ne-1-tasks.s3.ap-northeast-1.amazonaws.co
m/snapshots/・・・・・・・
}
}