1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

GitHub Actions の AWS Lambdaデプロイ用のアクション (aws-actions/aws-lambda-deploy)

Last updated at Posted at 2025-09-02

はじめに

表題の最新のアップデートについて試してみたいと思います。

何ができるようになったの?

AWS Lambda が GitHub Actions と直接連携して、Lambda 関数を自動デプロイできるようになりました!

これまでの問題点

GitHub から Lambda 関数をデプロイするには、複雑なカスタムスクリプトや AWS CLI を書く必要がありました。

そのため、開発者が以下のようなことを手動で設定する必要があった。

  • 関数コードのパッケージ化
  • AWS IAM 権限の設定
  • エラーハンドリング

新機能で何が変わった?

GitHub Actions ワークフローで宣言するだけで簡単になった

デプロイ方式

ZIP ファイルとコンテナイメージの両方をサポート

使い方の例

GitHub Actions の設定ファイル(.github/workflows/deploy.yml)に以下のように記載:

.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 を作成します:

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 を作成します:

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 を作成します:

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 に移動し、以下のシークレットを追加します:

  1. AWS_ROLE_ARN: arn:aws:iam::<AWS アカウント ID>:role/GitHubActionsRole
  2. LAMBDA_FUNCTION_NAME: arn:aws:iam::<AWS アカウント ID>:role/lambda-execution-role

サンプルアプリケーションの準備

適当なサンプルアプリケーションを準備しておきます。

./src/lambda_function.py
./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 の設定が必須となります。

github/workflows/deploy-lambda.yml
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 を確認してみます。
スクリーンショット 2025-09-03 0.59.21.png

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/・・・・・・・
    }
}
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?