Publish PyPI Package to Lambda Layer #2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Publish PyPI Package to Lambda Layer | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| package_version: | |
| description: 'Package version to download' | |
| required: true | |
| type: string | |
| layer_version: | |
| description: 'Layer version' | |
| required: true | |
| type: string | |
| python_version: | |
| description: 'Python version' | |
| required: true | |
| default: 'ALL' | |
| type: choice | |
| options: ['ALL', '3.10', '3.11', '3.12', '3.13'] | |
| architecture: | |
| description: 'Architecture' | |
| required: true | |
| default: 'ALL' | |
| type: choice | |
| options: ['ALL', 'x86_64', 'aarch64'] | |
| region: | |
| description: 'AWS region' | |
| required: true | |
| default: 'ALL' | |
| type: choice | |
| # Only non opt-in regions included for now | |
| options: ['ALL', 'us-east-1', 'us-east-2', 'us-west-1', 'us-west-2', 'ap-south-1', 'ap-northeast-1', 'ap-northeast-2', 'ap-northeast-3', 'ap-southeast-1', 'ap-southeast-2', 'ca-central-1', 'eu-central-1', 'eu-west-1', 'eu-west-2', 'eu-west-3', 'eu-north-1', 'sa-east-1'] | |
| confirm: | |
| description: 'Type "Create Lambda Layer {PyPI version}-layer{layer version}" to confirm publishing the layer' | |
| required: true | |
| type: string | |
| jobs: | |
| validate: | |
| runs-on: ubuntu-latest | |
| permissions: {} | |
| steps: | |
| - name: Validate confirmation | |
| run: | | |
| CONFIRM="${{ inputs.confirm }}" | |
| EXPECTED="Create Lambda Layer ${{ inputs.package_version }}-layer${{ inputs.layer_version }}" | |
| if [ "$CONFIRM" != "$EXPECTED" ]; then | |
| echo "Confirmation failed. You must type exactly '$EXPECTED' to proceed." | |
| exit 1 | |
| fi | |
| echo "Confirmation validated" | |
| package-and-upload: | |
| needs: validate | |
| runs-on: ubuntu-latest | |
| strategy: | |
| matrix: | |
| python-version: ${{ inputs.python_version == 'ALL' && fromJson('["3.10", "3.11", "3.12", "3.13"]') || fromJson(format('["{0}"]', inputs.python_version)) }} | |
| architecture: ${{ inputs.architecture == 'ALL' && fromJson('["x86_64", "aarch64"]') || fromJson(format('["{0}"]', inputs.architecture)) }} | |
| region: ${{ inputs.region == 'ALL' && fromJson('["us-east-1", "us-east-2", "us-west-1", "us-west-2", "ap-south-1", "ap-northeast-1", "ap-northeast-2", "ap-northeast-3", "ap-southeast-1", "ap-southeast-2", "ca-central-1", "eu-central-1", "eu-west-1", "eu-west-2", "eu-west-3", "eu-north-1", "sa-east-1"]') || fromJson(format('["{0}"]', inputs.region)) }} | |
| permissions: | |
| id-token: write | |
| steps: | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| - name: Configure AWS credentials | |
| uses: aws-actions/configure-aws-credentials@v6 | |
| with: | |
| role-to-assume: ${{ secrets.STRANDS_LAMBDA_LAYER_PUBLISHER_ROLE }} | |
| aws-region: ${{ matrix.region }} | |
| - name: Create layer directory structure | |
| run: | | |
| mkdir -p layer/python | |
| - name: Download and install package | |
| run: | | |
| pip install strands-agents==${{ inputs.package_version }} \ | |
| --python-version ${{ matrix.python-version }} \ | |
| --platform manylinux2014_${{ matrix.architecture }} \ | |
| -t layer/python/ \ | |
| --only-binary=:all: | |
| - name: Create layer zip | |
| run: | | |
| cd layer | |
| zip -r ../lambda-layer.zip . | |
| - name: Upload to S3 | |
| run: | | |
| PYTHON_VERSION="${{ matrix.python-version }}" | |
| ARCH="${{ matrix.architecture }}" | |
| REGION="${{ matrix.region }}" | |
| LAYER_NAME="strands-agents-py${PYTHON_VERSION//./_}-${ARCH}" | |
| ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text) | |
| BUCKET_NAME="strands-layer-${ACCOUNT_ID}-${{ secrets.STRANDS_LAMBDA_LAYER_BUCKET_SALT }}-${REGION}" | |
| LAYER_KEY="$LAYER_NAME/${{ inputs.package_version }}/layer${{ inputs.layer_version }}/lambda-layer.zip" | |
| aws s3 cp lambda-layer.zip "s3://$BUCKET_NAME/$LAYER_KEY" --region "$REGION" | |
| echo "Uploaded layer to s3://$BUCKET_NAME/$LAYER_KEY" | |
| publish-layer: | |
| needs: package-and-upload | |
| runs-on: ubuntu-latest | |
| strategy: | |
| matrix: | |
| python-version: ${{ inputs.python_version == 'ALL' && fromJson('["3.10", "3.11", "3.12", "3.13"]') || fromJson(format('["{0}"]', inputs.python_version)) }} | |
| architecture: ${{ inputs.architecture == 'ALL' && fromJson('["x86_64", "aarch64"]') || fromJson(format('["{0}"]', inputs.architecture)) }} | |
| region: ${{ inputs.region == 'ALL' && fromJson('["us-east-1", "us-east-2", "us-west-1", "us-west-2", "ap-south-1", "ap-northeast-1", "ap-northeast-2", "ap-northeast-3", "ap-southeast-1", "ap-southeast-2", "ca-central-1", "eu-central-1", "eu-west-1", "eu-west-2", "eu-west-3", "eu-north-1", "sa-east-1"]') || fromJson(format('["{0}"]', inputs.region)) }} | |
| permissions: | |
| id-token: write | |
| steps: | |
| - name: Configure AWS credentials | |
| uses: aws-actions/configure-aws-credentials@v6 | |
| with: | |
| role-to-assume: ${{ secrets.STRANDS_LAMBDA_LAYER_PUBLISHER_ROLE }} | |
| aws-region: ${{ matrix.region }} | |
| - name: Publish layer | |
| run: | | |
| PYTHON_VERSION="${{ matrix.python-version }}" | |
| ARCH="${{ matrix.architecture }}" | |
| REGION="${{ matrix.region }}" | |
| LAYER_NAME="strands-agents-py${PYTHON_VERSION//./_}-${ARCH}" | |
| ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text) | |
| REGION_BUCKET="strands-layer-${ACCOUNT_ID}-${{ secrets.STRANDS_LAMBDA_LAYER_BUCKET_SALT }}-${REGION}" | |
| LAYER_KEY="$LAYER_NAME/${{ inputs.package_version }}/layer${{ inputs.layer_version }}/lambda-layer.zip" | |
| DESCRIPTION="PyPI package: strands-agents v${{ inputs.package_version }} (Python $PYTHON_VERSION, $ARCH)" | |
| # Set compatible architecture based on matrix architecture | |
| if [ "$ARCH" = "x86_64" ]; then | |
| COMPATIBLE_ARCH="x86_64" | |
| else | |
| COMPATIBLE_ARCH="arm64" | |
| fi | |
| LAYER_OUTPUT=$(aws lambda publish-layer-version \ | |
| --layer-name $LAYER_NAME \ | |
| --description "$DESCRIPTION" \ | |
| --content S3Bucket=$REGION_BUCKET,S3Key=$LAYER_KEY \ | |
| --compatible-runtimes python${{ matrix.python-version }} \ | |
| --compatible-architectures $COMPATIBLE_ARCH \ | |
| --region "$REGION" \ | |
| --license-info Apache-2.0 \ | |
| --output json) | |
| LAYER_ARN=$(echo "$LAYER_OUTPUT" | jq -r '.LayerArn') | |
| LAYER_VERSION=$(echo "$LAYER_OUTPUT" | jq -r '.Version') | |
| echo "Published layer version $LAYER_VERSION with ARN: $LAYER_ARN in region $REGION" | |
| aws lambda add-layer-version-permission \ | |
| --layer-name $LAYER_NAME \ | |
| --version-number $LAYER_VERSION \ | |
| --statement-id public \ | |
| --action lambda:GetLayerVersion \ | |
| --principal '*' \ | |
| --region "$REGION" | |
| echo "Successfully published layer version $LAYER_VERSION in region $REGION" |