Automate your Lambda function builds and deployments using popular CI/CD platforms. These examples show how to build and deploy Lambda functions with Powertools for AWS with proper cross-platform compatibility and deploy them reliably.

## GitHub Actions

**GitHub Actions** provides a powerful, integrated CI/CD platform that runs directly in your GitHub repository. It offers excellent integration with AWS services, supports matrix builds for testing multiple configurations, and provides a rich ecosystem of pre-built actions.

```
name: Deploy Lambda with AWS Lambda Deploy Action

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

env:
  AWS_REGION: us-east-1
  PYTHON_VERSION: '3.13'

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8  # v5.0.0

    - name: Set up Python
      uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
      with:
        python-version: ${{ env.PYTHON_VERSION }}

    - name: Install dependencies
      run: |
        pip install aws-lambda-powertools[all] pytest pytest-cov

    - name: Run tests
      run: |
        pytest tests/ --cov=src/ --cov-report=xml

    - name: Upload coverage to Codecov
      uses: codecov/codecov-action@v4
      with:
        file: ./coverage.xml

  deploy:
    needs: test
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'

    steps:
    - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8  # v5.0.0

    - name: Set up Python
      uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
      with:
        python-version: ${{ env.PYTHON_VERSION }}

    - name: Prepare deployment directory
      run: |
        # Create deployment directory with dependencies
        mkdir -p deploy/

        # Install dependencies with Linux-compatible wheels
        pip install \
          --platform manylinux2014_x86_64 \
          --target deploy/ \
          --implementation cp \
          --python-version ${{ env.PYTHON_VERSION }} \
          --only-binary=:all: \
          --upgrade \
          aws-lambda-powertools[all] pydantic requests

        # Copy application code
        cp -r src/* deploy/

    - name: Configure AWS credentials
      uses: aws-actions/configure-aws-credentials@209f2a4450bb4b277e1dedaff40ad2fd8d4d0a4c # v4.3.0
      with:
        role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}
        aws-region: ${{ env.AWS_REGION }}

    - name: Deploy to Lambda
      uses: aws-actions/aws-lambda-deploy@246115fccc1ad110c97f729696574d09eb5c690d
      with:
        function-name: powertools-lambda-function
        code-artifacts-dir: deploy/
        handler: app.lambda_handler
        runtime: python3.13
        environment: '{"POWERTOOLS_SERVICE_NAME":"powertools-app","POWERTOOLS_METRICS_NAMESPACE":"MyApp","POWERTOOLS_LOG_LEVEL":"INFO"}'
        timeout: 30
        memory-size: 512
        role: ${{ secrets.LAMBDA_EXECUTION_ROLE_ARN }}
```

```
name: Multi-Environment Lambda Deployment

on:
  push:
    branches: [main, develop, staging]

jobs:
  deploy:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        include:
          - branch: develop
            environment: dev
            function-suffix: -dev
            memory: 256
            timeout: 30
            log-level: DEBUG
          - branch: staging
            environment: staging
            function-suffix: -staging
            memory: 512
            timeout: 45
            log-level: INFO
          - branch: main
            environment: prod
            function-suffix: -prod
            memory: 1024
            timeout: 60
            log-level: INFO

    steps:
    - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8  # v5.0.0
      if: github.ref == format('refs/heads/{0}', matrix.branch)

    - name: Set up Python
      if: github.ref == format('refs/heads/{0}', matrix.branch)
      uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
      with:
        python-version: '3.13'

    - name: Prepare deployment with uv (fast)
      if: github.ref == format('refs/heads/{0}', matrix.branch)
      run: |
        # Install uv for fast dependency management
        pip install uv

        # Create deployment directory
        mkdir -p deploy-${{ matrix.environment }}/

        # Install dependencies with uv (much faster than pip)
        uv pip install \
          --target deploy-${{ matrix.environment }}/ \
          --python-version 3.13 \
          --platform manylinux2014_x86_64 --only-binary=:all: \
          aws-lambda-powertools[all] pydantic requests

        # Copy application code
        cp -r src/* deploy-${{ matrix.environment }}/

    - name: Configure AWS credentials
      if: github.ref == format('refs/heads/{0}', matrix.branch)
      uses: aws-actions/configure-aws-credentials@209f2a4450bb4b277e1dedaff40ad2fd8d4d0a4c # v4.3.0
      with:
        role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}
        aws-region: us-east-1

    - name: Deploy to Lambda
      if: github.ref == format('refs/heads/{0}', matrix.branch)
      uses: aws-actions/aws-lambda-deploy@246115fccc1ad110c97f729696574d09eb5c690d # v1.0.1
      with:
        function-name: powertools-app${{ matrix.function-suffix }}
        code-artifacts-dir: deploy-${{ matrix.environment }}/
        handler: app.lambda_handler
        runtime: python3.13
        environment: '{"ENVIRONMENT":"${{ matrix.environment }}","POWERTOOLS_SERVICE_NAME":"powertools-app-${{ matrix.environment }}","POWERTOOLS_METRICS_NAMESPACE":"MyApp/${{ matrix.environment }}","POWERTOOLS_LOG_LEVEL":"${{ matrix.log-level }}"}'
        timeout: ${{ matrix.timeout }}
        memory-size: ${{ matrix.memory }}
        role: ${{ secrets.LAMBDA_EXECUTION_ROLE_ARN }}
        tags: '{"Environment":"${{ matrix.environment }}","Project":"powertools-demo","ManagedBy":"github-actions"}'
```

```
name: Simple Lambda Deployment from Source

on:
  push:
    branches: [main]

env:
  AWS_REGION: us-east-1

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8  # v5.0.0

    - name: Set up Python
      uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
      with:
        python-version: '3.13'

    - name: Install dependencies
      run: |
        # Simple pip install - the action handles the rest
        pip install --platform manylinux2014_x86_64 --only-binary=:all: \
        --python-version 3.13 -r requirements.txt -t src-deploy/

    - name: Configure AWS credentials
      uses: aws-actions/configure-aws-credentials@209f2a4450bb4b277e1dedaff40ad2fd8d4d0a4c # v4.3.0
      with:
        role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}
        aws-region: ${{ env.AWS_REGION }}

    - name: Deploy to Lambda
      uses: aws-actions/aws-lambda-deploy@246115fccc1ad110c97f729696574d09eb5c690d
      with:
        function-name: powertools-simple-function
        code-artifacts-dir: src-deploy/  # Deploy from current directory
        handler: app.lambda_handler
        runtime: python3.13
        environment: '{"POWERTOOLS_SERVICE_NAME":"powertools-simple","POWERTOOLS_METRICS_NAMESPACE":"MyApp","POWERTOOLS_LOG_LEVEL":"INFO"}'
        timeout: 30
        memory-size: 512
        role: ${{ secrets.LAMBDA_EXECUTION_ROLE_ARN }}
        dry-run: false  # Set to true for validation without deployment
```

```
name: Deploy Lambda via S3

on:
  push:
    branches: [main]

env:
  AWS_REGION: us-east-1
  S3_BUCKET: my-lambda-deployments-bucket

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8  # v5.0.0

    - name: Set up Python
      uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
      with:
        python-version: '3.13'

    - name: Prepare deployment directory
      run: |
        mkdir -p lambda-package/

        # Install Powertools and dependencies
        pip install \
          --platform manylinux2014_x86_64 \
          --target lambda-package/ \
          --implementation cp \
          --python-version 3.13 \
          --only-binary=:all: \
          aws-lambda-powertools[all] pydantic requests

        # Copy source code
        cp -r src/* lambda-package/

    - name: Configure AWS credentials
      uses: aws-actions/configure-aws-credentials@209f2a4450bb4b277e1dedaff40ad2fd8d4d0a4c # v4.3.0
      with:
        role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}
        aws-region: ${{ env.AWS_REGION }}

    - name: Deploy to Lambda via S3
      uses: aws-actions/aws-lambda-deploy@246115fccc1ad110c97f729696574d09eb5c690d # v1.0.1
      with:
        function-name: powertools-s3-function
        code-artifacts-dir: lambda-package/
        handler: app.lambda_handler
        runtime: python3.13
        s3-bucket: ${{ env.S3_BUCKET }}
        s3-key: deployments/powertools-function-${{ github.sha }}.zip
        environment: '{"POWERTOOLS_SERVICE_NAME":"powertools-s3","POWERTOOLS_METRICS_NAMESPACE":"MyApp","POWERTOOLS_LOG_LEVEL":"INFO"}'
        timeout: 30
        memory-size: 512
        role: ${{ secrets.LAMBDA_EXECUTION_ROLE_ARN }}
        publish: true  # Publish a new version
```

```
name: Deploy with Different Build Tools

on:
  push:
    branches: [main]

jobs:
  deploy-poetry:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8  # v5.0.0

    - name: Set up Python
      uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
      with:
        python-version: '3.13'

    - name: Install Poetry
      run: pip install --upgrade pip poetry

    - name: Build with Poetry
      run: |
        # Create deployment directory
        mkdir -p poetry-deploy/

        # Export and install dependencies
        poetry export -f requirements.txt --output requirements.txt --without-hashes
        pip install --platform manylinux2014_x86_64 --only-binary=:all: \
        --python-version 3.13 -r requirements.txt -t poetry-deploy/

        # Copy source code
        cp -r src/* poetry-deploy/

    - name: Configure AWS credentials
      uses: aws-actions/configure-aws-credentials@209f2a4450bb4b277e1dedaff40ad2fd8d4d0a4c # v4.3.0
      with:
        role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}
        aws-region: us-east-1

    - name: Deploy Poetry build
      uses: aws-actions/aws-lambda-deploy@246115fccc1ad110c97f729696574d09eb5c690d
      with:
        function-name: powertools-poetry-function
        code-artifacts-dir: poetry-deploy/
        handler: app.lambda_handler
        runtime: python3.13
        environment: '{"POWERTOOLS_SERVICE_NAME":"powertools-poetry","POWERTOOLS_METRICS_NAMESPACE":"MyApp","POWERTOOLS_LOG_LEVEL":"INFO"}'
        role: ${{ secrets.LAMBDA_EXECUTION_ROLE_ARN }}

  deploy-uv:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8  # v5.0.0

    - name: Set up Python
      uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
      with:
        python-version: '3.13'

    - name: Build with uv (fastest)
      run: |
        # Install uv
        pip install uv

        # Create deployment directory
        mkdir -p uv-deploy/

        # Install dependencies with uv (much faster)
        uv pip install \
          --target uv-deploy/ \
          --python-version 3.13 \
          --platform manylinux2014_x86_64 --only-binary=:all: \
          aws-lambda-powertools[all] pydantic requests

        # Copy source code
        cp -r src/* uv-deploy/

    - name: Configure AWS credentials
      uses: aws-actions/configure-aws-credentials@209f2a4450bb4b277e1dedaff40ad2fd8d4d0a4c # v4.3.0
      with:
        role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}
        aws-region: us-east-1

    - name: Deploy uv build
      uses: aws-actions/aws-lambda-deploy@246115fccc1ad110c97f729696574d09eb5c690d # v1.0.1
      with:
        function-name: powertools-uv-function
        code-artifacts-dir: uv-deploy/
        handler: app.lambda_handler
        runtime: python3.13
        environment: '{"POWERTOOLS_SERVICE_NAME":"powertools-uv","POWERTOOLS_METRICS_NAMESPACE":"MyApp","POWERTOOLS_LOG_LEVEL":"INFO"}'
        role: ${{ secrets.LAMBDA_EXECUTION_ROLE_ARN }}
```

## AWS CodeBuild

**AWS CodeBuild** is a fully managed build service that compiles source code, runs tests, and produces deployment packages. It integrates seamlessly with other AWS services and provides consistent build environments with automatic scaling.

```
version: 0.2

env:
  variables:
    PYTHON_VERSION: "3.14"
    POWERTOOLS_VERSION: "3.18.0"
  parameter-store:
    FUNCTION_NAME: "/lambda/powertools-app/function-name"

phases:
  install:
    runtime-versions:
      python: $PYTHON_VERSION
    commands:
      - echo "Installing build dependencies..."
      - pip install --upgrade pip
      - pip install uv poetry  # Install fast package managers

  pre_build:
    commands:
      - echo "Pre-build phase started on $(date)"
      - echo "Python version: $(python --version)"
      - echo "Installing application dependencies..."

      # Use uv for fast dependency installation
      - uv venv build-env
      - source build-env/bin/activate
      - uv pip install aws-lambda-powertools[all]==$POWERTOOLS_VERSION
      - uv pip install pydantic requests

  build:
    commands:
      - echo "Build started on $(date)"
      - echo "Creating deployment package..."

      # Create optimized deployment package
      - mkdir -p package/
      - cp -r build-env/lib/python*/site-packages/* package/
      - cp -r src/* package/

      # Remove unnecessary files to reduce package size
      - find package/ -name "*.pyc" -delete
      - find package/ -name "__pycache__" -type d -exec rm -rf {} + 2>/dev/null || true
      - find package/ -name "tests" -type d -exec rm -rf {} + 2>/dev/null || true
      - find package/ -name "*.dist-info" -type d -exec rm -rf {} + 2>/dev/null || true

      # Create deployment ZIP
      - cd package && zip -r ../lambda-deployment.zip . && cd ..

      # Show package info
      - echo "Package size: $(du -sh lambda-deployment.zip)"
      - echo "Package contents:"
      - unzip -l lambda-deployment.zip | head -20

  post_build:
    commands:
      - echo "Build completed on $(date)"
      - echo "Deploying Lambda function..."

      # Deploy to Lambda
      - aws lambda update-function-code \
          --function-name $FUNCTION_NAME \
          --zip-file fileb://lambda-deployment.zip \
          --region $AWS_DEFAULT_REGION

      # Update environment variables
      - aws lambda update-function-configuration \
          --function-name $FUNCTION_NAME \
          --environment Variables="{
            POWERTOOLS_SERVICE_NAME=powertools-codebuild,
            POWERTOOLS_METRICS_NAMESPACE=MyApp/CodeBuild,
            POWERTOOLS_LOG_LEVEL=INFO
          }" \
          --region $AWS_DEFAULT_REGION

      - echo "Deployment completed successfully!"

artifacts:
  files:
    - lambda-deployment.zip
  name: lambda-deployment-$(date +%Y-%m-%d-%H-%M-%S)

cache:
  paths:
    - 'build-env/**/*'  # Cache virtual environment for faster builds
```

## Best Practices for CI/CD

1. **Use Linux runners** (ubuntu-latest) to ensure Lambda compatibility
2. **Cache dependencies** to speed up builds (uv, poetry cache, pip cache)
3. **Run tests first** before building deployment packages
4. **Use matrix builds** to test multiple Python versions or configurations
5. **Implement proper secrets management** with GitHub Secrets or AWS Parameter Store
6. **Add deployment gates** for production environments
7. **Monitor deployment success** with CloudWatch metrics and alarms

> [!TIP]
>
> **Performance Optimization**
>
> - Use **uv** for fastest dependency installation in CI/CD
> - **Cache virtual environments** between builds when possible
> - **Parallelize builds** for multiple environments
> - **Use container images** for complex dependencies or large packages
