From df32f9f1a56c7e7cebfe4f262260b225d90d8599 Mon Sep 17 00:00:00 2001 From: Dean Schmigelski Date: Wed, 10 Sep 2025 18:05:39 -0400 Subject: [PATCH 01/31] feat: add update-docs --- .github/workflows/publish-lambda-layer.yml | 186 +++++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 .github/workflows/publish-lambda-layer.yml diff --git a/.github/workflows/publish-lambda-layer.yml b/.github/workflows/publish-lambda-layer.yml new file mode 100644 index 000000000..8384e0fae --- /dev/null +++ b/.github/workflows/publish-lambda-layer.yml @@ -0,0 +1,186 @@ +name: Publish PyPI Package to Lambda Layer + +on: + workflow_dispatch: + inputs: + package_version: + description: 'Package version to download' + required: true + type: string + python_version: + description: 'Python version' + required: false + default: '3.12' + type: choice + options: ['3.10', '3.11', '3.12', '3.13'] + architecture: + description: 'Architecture' + required: false + default: 'x86_64' + type: choice + options: ['x86_64', 'aarch64'] + region: + description: 'AWS region' + required: false + default: 'us-east-1' + type: choice + # Only non opt-in regions included for now + options: ['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" to confirm publishing the layer' + required: true + type: string + +env: + IS_FULL_DEPLOY: ${{ !inputs.python_version && !inputs.architecture && !inputs.region }} + +jobs: + publish-layer: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ${{ inputs.python_version && fromJson(format('["{}"', inputs.python_version)) || fromJson('["3.10", "3.11", "3.12", "3.13"]') }} + architecture: ${{ inputs.architecture && fromJson(format('["{}"', inputs.architecture)) || fromJson('["x86_64", "aarch64"]') }} + region: ${{ inputs.region && fromJson(format('["{}"', inputs.region)) || 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"]') }} + + outputs: + layer-version: ${{ env.LAYER_VERSION }} + permissions: + id-token: write + contents: read + + steps: + - name: Validate confirmation + run: | + CONFIRM="${{ inputs.confirm }}" + if [ "$CONFIRM" != "Create Lambda Layer" ]; then + if [[ "$CONFIRM" =~ ^(x86_64|aarch64|3\.[0-9]+|[a-z]+-[a-z]+-[0-9]+)$ ]]; then + echo "Error: You entered '$CONFIRM' which looks like an architecture, Python version, or region." + echo "Please type exactly 'Create Lambda Layer' to confirm." + else + echo "Confirmation failed. You must type exactly 'Create Lambda Layer' to proceed." + fi + exit 1 + fi + echo "Confirmation validated" + + - name: Checkout current repository + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v4 + 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 layer to S3 and publish + run: | + PYTHON_VERSION="${{ matrix.python-version }}" + ARCH="${{ matrix.architecture }}" + REGION="${{ matrix.region }}" + LAYER_NAME="strands-agents-py${PYTHON_VERSION//./_}-${ARCH}" + BUCKET_NAME="strands-agents-lambda-layers-$(aws sts get-caller-identity --query Account --output text)-${REGION}" + LAYER_KEY="$LAYER_NAME/v${{ inputs.package_version }}/lambda-layer.zip" + + if ! aws s3api head-bucket --bucket "$BUCKET_NAME" 2>/dev/null; then + if [ "$REGION" = "us-east-1" ]; then + aws s3api create-bucket --bucket "$BUCKET_NAME" --region "$REGION" + else + aws s3api create-bucket --bucket "$BUCKET_NAME" --region "$REGION" --create-bucket-configuration LocationConstraint="$REGION" + fi + fi + + aws s3 cp lambda-layer.zip "s3://$BUCKET_NAME/$LAYER_KEY" --region "$REGION" + echo "Uploaded layer to s3://$BUCKET_NAME/$LAYER_KEY" + + DESCRIPTION="PyPI package: strands-agents v${{ inputs.package_version }} (Python $PYTHON_VERSION, $ARCH)" + + LAYER_OUTPUT=$(aws lambda publish-layer-version \ + --layer-name $LAYER_NAME \ + --description "$DESCRIPTION" \ + --content S3Bucket=$BUCKET_NAME,S3Key=$LAYER_KEY \ + --compatible-runtimes python${{ matrix.python-version }} \ + --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" + + if [ "${{ env.IS_FULL_DEPLOY }}" = "true" ] && [ "$REGION" = "us-east-1" ] && [ "$PYTHON_VERSION" = "3.10" ] && [ "$ARCH" = "x86_64" ]; then + echo "LAYER_VERSION=$LAYER_VERSION" >> $GITHUB_ENV + fi + + update-docs: + if: ${{ env.IS_FULL_DEPLOY == 'true' }} + needs: publish-layer + runs-on: ubuntu-latest + steps: + - name: Checkout docs repository + uses: actions/checkout@v4 + with: + repository: ${{ github.repository_owner }}/docs + token: ${{ secrets.GITHUB_TOKEN }} + path: docs + + - name: Update lambda layers documentation + run: | + cd docs + LAYER_VERSION="${{ needs.publish-layer.outputs.layer-version }}" + NEW_ROW="| $LAYER_VERSION | [${{ inputs.package_version }}](https://pypi.org/project/strands-agents/${{ inputs.package_version }}) | \`arn:aws:lambda:{REGION}:856699698935:layer:strands-agents-{VERSION}-{ARCHITECTURE}:$LAYER_VERSION\` |" + + sed -i "//a\$NEW_ROW" docs/user-guide/deploy/lambda-layers.md + + - name: Create Pull Request + run: | + cd docs + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + + BRANCH="update-lambda-layers-${{ inputs.package_version }}" + git checkout -b "$BRANCH" + git add docs/user-guide/deploy/lambda-layers.md + git commit -m "Update lambda layers with version ${{ inputs.package_version }}" + git push origin "$BRANCH" + + gh pr create \ + --title "Update lambda layers documentation for v${{ inputs.package_version }}" \ + --body "Automated update to add new lambda layer version ${{ inputs.package_version }}" \ + --head "$BRANCH" \ + --base main + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file From 6c5a7e2061f9bd411b85a1593a9062a091327574 Mon Sep 17 00:00:00 2001 From: Dean Schmigelski Date: Wed, 10 Sep 2025 18:17:21 -0400 Subject: [PATCH 02/31] remove default --- .github/workflows/publish-lambda-layer.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/publish-lambda-layer.yml b/.github/workflows/publish-lambda-layer.yml index 8384e0fae..fbbf6626a 100644 --- a/.github/workflows/publish-lambda-layer.yml +++ b/.github/workflows/publish-lambda-layer.yml @@ -10,19 +10,16 @@ on: python_version: description: 'Python version' required: false - default: '3.12' type: choice options: ['3.10', '3.11', '3.12', '3.13'] architecture: description: 'Architecture' required: false - default: 'x86_64' type: choice options: ['x86_64', 'aarch64'] region: description: 'AWS region' required: false - default: 'us-east-1' type: choice # Only non opt-in regions included for now options: ['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'] From 423f7297a515821eeadb1521b80f9feee8a39b0a Mon Sep 17 00:00:00 2001 From: Dean Schmigelski Date: Wed, 10 Sep 2025 18:24:29 -0400 Subject: [PATCH 03/31] change name --- .github/workflows/publish-lambda-layer.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish-lambda-layer.yml b/.github/workflows/publish-lambda-layer.yml index fbbf6626a..0cff92daf 100644 --- a/.github/workflows/publish-lambda-layer.yml +++ b/.github/workflows/publish-lambda-layer.yml @@ -1,4 +1,4 @@ -name: Publish PyPI Package to Lambda Layer +name: Publish Lambda Layer on: workflow_dispatch: From a871ca50ff7e19278772704fa84cb182b1239253 Mon Sep 17 00:00:00 2001 From: Dean Schmigelski Date: Wed, 10 Sep 2025 18:30:56 -0400 Subject: [PATCH 04/31] fix --- .github/workflows/publish-lambda-layer.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish-lambda-layer.yml b/.github/workflows/publish-lambda-layer.yml index 0cff92daf..46b8b4244 100644 --- a/.github/workflows/publish-lambda-layer.yml +++ b/.github/workflows/publish-lambda-layer.yml @@ -143,7 +143,7 @@ jobs: fi update-docs: - if: ${{ env.IS_FULL_DEPLOY == 'true' }} + if: ${{ !inputs.python_version && !inputs.architecture && !inputs.region }} needs: publish-layer runs-on: ubuntu-latest steps: From 7acdab475c3f93db743a0ea21bcc8ad0f2680a2f Mon Sep 17 00:00:00 2001 From: Dean Schmigelski Date: Wed, 10 Sep 2025 18:36:01 -0400 Subject: [PATCH 05/31] use all --- .github/workflows/publish-lambda-layer.yml | 25 ++++++++++++---------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/.github/workflows/publish-lambda-layer.yml b/.github/workflows/publish-lambda-layer.yml index 46b8b4244..6868e6191 100644 --- a/.github/workflows/publish-lambda-layer.yml +++ b/.github/workflows/publish-lambda-layer.yml @@ -9,36 +9,39 @@ on: type: string python_version: description: 'Python version' - required: false + required: true + default: 'ALL' type: choice - options: ['3.10', '3.11', '3.12', '3.13'] + options: ['ALL', '3.10', '3.11', '3.12', '3.13'] architecture: description: 'Architecture' - required: false + required: true + default: 'ALL' type: choice - options: ['x86_64', 'aarch64'] + options: ['ALL', 'x86_64', 'aarch64'] region: description: 'AWS region' - required: false + required: true + default: 'ALL' type: choice # Only non opt-in regions included for now - options: ['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'] + 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" to confirm publishing the layer' required: true type: string env: - IS_FULL_DEPLOY: ${{ !inputs.python_version && !inputs.architecture && !inputs.region }} + IS_FULL_DEPLOY: ${{ inputs.python_version == 'ALL' && inputs.architecture == 'ALL' && inputs.region == 'ALL' }} jobs: publish-layer: runs-on: ubuntu-latest strategy: matrix: - python-version: ${{ inputs.python_version && fromJson(format('["{}"', inputs.python_version)) || fromJson('["3.10", "3.11", "3.12", "3.13"]') }} - architecture: ${{ inputs.architecture && fromJson(format('["{}"', inputs.architecture)) || fromJson('["x86_64", "aarch64"]') }} - region: ${{ inputs.region && fromJson(format('["{}"', inputs.region)) || 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"]') }} + python-version: ${{ inputs.python_version == 'ALL' && fromJson('["3.10", "3.11", "3.12", "3.13"]') || fromJson(format('["{}"', inputs.python_version, ']')) }} + architecture: ${{ inputs.architecture == 'ALL' && fromJson('["x86_64", "aarch64"]') || fromJson(format('["{}"', 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('["{}"', inputs.region, ']')) }} outputs: layer-version: ${{ env.LAYER_VERSION }} @@ -143,7 +146,7 @@ jobs: fi update-docs: - if: ${{ !inputs.python_version && !inputs.architecture && !inputs.region }} + if: ${{ inputs.python_version == 'ALL' && inputs.architecture == 'ALL' && inputs.region == 'ALL' }} needs: publish-layer runs-on: ubuntu-latest steps: From 8ae7c71084bfb22d767daf6d956d4dc7824bba59 Mon Sep 17 00:00:00 2001 From: Dean Schmigelski Date: Wed, 10 Sep 2025 19:44:23 -0400 Subject: [PATCH 06/31] split jobs --- .github/workflows/LAMBDA_LAYERS.md | 100 +++++++++++++++++++++ .github/workflows/publish-lambda-layer.yml | 57 ++++++++---- 2 files changed, 140 insertions(+), 17 deletions(-) create mode 100644 .github/workflows/LAMBDA_LAYERS.md diff --git a/.github/workflows/LAMBDA_LAYERS.md b/.github/workflows/LAMBDA_LAYERS.md new file mode 100644 index 000000000..1fcddae18 --- /dev/null +++ b/.github/workflows/LAMBDA_LAYERS.md @@ -0,0 +1,100 @@ +# Lambda Layers Standard Operating Procedures (SOP) + +## Overview + +This document defines the standard operating procedures for managing Strands Agents Lambda layers across all AWS regions, Python versions, and architectures. + +## Core Principles + +### Version Synchronization +- **All variants must have the same layer version number** for each PyPI package version +- This includes all combinations of: + - Python versions (3.10, 3.11, 3.12, 3.13) + - Architectures (x86_64, aarch64) + - AWS regions (all non opt-in regions) +- **Total: 136 individual Lambda layers** (17 regions × 2 architectures × 4 Python versions) +- Each layer is published separately but must maintain version synchronization + +### Documentation Consistency +- Only **one row per PyPI version** appears in documentation +- The layer version number represents all variants for that PyPI package version + +## Deployment Process + +### 1. Initial Deployment +1. Run workflow with ALL options selected (default) +2. Specify PyPI package version +3. Type "Create Lambda Layer" to confirm +4. All 136 individual layers deploy in parallel (4 Python × 2 arch × 17 regions) +5. Each layer gets its own unique name: `strands-agents-py{VERSION}-{ARCH}` +6. Documentation automatically updates with new row + +### 2. Version Buffering for New Variants +When adding new variants (new Python version, architecture, or region): + +1. **Determine target layer version**: Check existing variants to find the highest layer version +2. **Buffer deployment**: Deploy new variants multiple times until layer version matches existing variants +3. **Example**: If existing variants are at layer version 5, deploy new variant 5 times to reach version 5 + +### 3. Handling Transient Failures +When some regions fail during deployment: + +1. **Identify failed regions**: Check which combinations didn't complete successfully +2. **Targeted redeployment**: Use specific region/arch/Python inputs to redeploy failed combinations +3. **Version alignment**: Continue deploying until all variants reach the same layer version +4. **Verification**: Confirm all combinations have identical layer versions before updating docs + +## Yank Process + +### When to Yank +- Security vulnerabilities discovered in PyPI package +- Critical bugs affecting Lambda functionality +- Compliance requirements + +### Yank Procedure +1. **Remove public permissions**: + ```bash + aws lambda remove-layer-version-permission \ + --layer-name strands-agents-py{VERSION}-{ARCH} \ + --version-number {LAYER_VERSION} \ + --statement-id public \ + --region {REGION} + ``` + +2. **Update documentation**: Remove or mark the row as yanked in lambda-layers.md + +3. **Coordinate across all variants**: Repeat for all 136 combinations + +4. **Communication**: Notify users through appropriate channels + +## Workflow Usage + +### Full Deployment (Default) +- Python Version: ALL +- Architecture: ALL +- Region: ALL +- Result: 136 parallel deployments + +### Targeted Deployment +- Select specific values for failed/new variants +- Used for version synchronization and failure recovery + +### Validation Steps +1. Verify all combinations completed successfully +2. Check layer versions are synchronized across all variants +3. Confirm documentation reflects single version per PyPI package +4. Test layer functionality in representative regions/architectures + +## Troubleshooting + +### Common Issues +- **Partial failures**: Use targeted deployment to retry failed combinations +- **Version drift**: Deploy additional times to align layer versions +- **Permission errors**: Verify IAM role has necessary permissions across all regions +- **S3 bucket issues**: Ensure buckets exist in all target regions + +### Recovery Actions +1. Identify scope of issue (specific regions, architectures, Python versions) +2. Use targeted deployment to address specific failures +3. Continue until version synchronization is achieved +4. Update documentation only after full synchronization \ No newline at end of file diff --git a/.github/workflows/publish-lambda-layer.yml b/.github/workflows/publish-lambda-layer.yml index 6868e6191..64f3d0412 100644 --- a/.github/workflows/publish-lambda-layer.yml +++ b/.github/workflows/publish-lambda-layer.yml @@ -1,4 +1,4 @@ -name: Publish Lambda Layer +name: Publish PyPI Package to Lambda Layer on: workflow_dispatch: @@ -35,16 +35,13 @@ env: IS_FULL_DEPLOY: ${{ inputs.python_version == 'ALL' && inputs.architecture == 'ALL' && inputs.region == 'ALL' }} jobs: - publish-layer: + 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('["{}"', inputs.python_version, ']')) }} architecture: ${{ inputs.architecture == 'ALL' && fromJson('["x86_64", "aarch64"]') || fromJson(format('["{}"', 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('["{}"', inputs.region, ']')) }} - outputs: - layer-version: ${{ env.LAYER_VERSION }} permissions: id-token: write contents: read @@ -76,7 +73,7 @@ jobs: uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: ${{ secrets.STRANDS_LAMBDA_LAYER_PUBLISHER_ROLE }} - aws-region: ${{ matrix.region }} + aws-region: us-east-1 - name: Create layer directory structure run: | @@ -94,27 +91,53 @@ jobs: run: | cd layer zip -r ../lambda-layer.zip . - - - name: Upload layer to S3 and publish + + - name: Upload to S3 run: | PYTHON_VERSION="${{ matrix.python-version }}" ARCH="${{ matrix.architecture }}" - REGION="${{ matrix.region }}" LAYER_NAME="strands-agents-py${PYTHON_VERSION//./_}-${ARCH}" - BUCKET_NAME="strands-agents-lambda-layers-$(aws sts get-caller-identity --query Account --output text)-${REGION}" + BUCKET_NAME="strands-agents-lambda-layers-$(aws sts get-caller-identity --query Account --output text)" LAYER_KEY="$LAYER_NAME/v${{ inputs.package_version }}/lambda-layer.zip" - if ! aws s3api head-bucket --bucket "$BUCKET_NAME" 2>/dev/null; then - if [ "$REGION" = "us-east-1" ]; then - aws s3api create-bucket --bucket "$BUCKET_NAME" --region "$REGION" - else - aws s3api create-bucket --bucket "$BUCKET_NAME" --region "$REGION" --create-bucket-configuration LocationConstraint="$REGION" - fi + if ! aws s3api head-bucket --bucket "$BUCKET_NAME" --region us-east-1 2>/dev/null; then + aws s3api create-bucket --bucket "$BUCKET_NAME" --region us-east-1 fi - aws s3 cp lambda-layer.zip "s3://$BUCKET_NAME/$LAYER_KEY" --region "$REGION" + aws s3 cp lambda-layer.zip "s3://$BUCKET_NAME/$LAYER_KEY" --region us-east-1 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('["{}"', inputs.python_version, ']')) }} + architecture: ${{ inputs.architecture == 'ALL' && fromJson('["x86_64", "aarch64"]') || fromJson(format('["{}"', 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('["{}"', inputs.region, ']')) }} + + outputs: + layer-version: ${{ env.LAYER_VERSION }} + permissions: + id-token: write + contents: read + + steps: + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v4 + 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}" + BUCKET_NAME="strands-agents-lambda-layers-$(aws sts get-caller-identity --query Account --output text)" + LAYER_KEY="$LAYER_NAME/v${{ inputs.package_version }}/lambda-layer.zip" + DESCRIPTION="PyPI package: strands-agents v${{ inputs.package_version }} (Python $PYTHON_VERSION, $ARCH)" LAYER_OUTPUT=$(aws lambda publish-layer-version \ From 0dac0c7f0111a91af3f93011470439d296770138 Mon Sep 17 00:00:00 2001 From: Dean Schmigelski Date: Wed, 10 Sep 2025 20:03:10 -0400 Subject: [PATCH 07/31] move create outside --- .github/workflows/publish-lambda-layer.yml | 31 +++++++++++++++++----- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/.github/workflows/publish-lambda-layer.yml b/.github/workflows/publish-lambda-layer.yml index 64f3d0412..0bd43a546 100644 --- a/.github/workflows/publish-lambda-layer.yml +++ b/.github/workflows/publish-lambda-layer.yml @@ -35,7 +35,30 @@ env: IS_FULL_DEPLOY: ${{ inputs.python_version == 'ALL' && inputs.architecture == 'ALL' && inputs.region == 'ALL' }} jobs: + setup: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: read + steps: + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: ${{ secrets.STRANDS_LAMBDA_LAYER_PUBLISHER_ROLE }} + aws-region: us-east-1 + + - name: Create S3 bucket + run: | + BUCKET_NAME="strands-agents-lambda-layers-032316178046" + if ! aws s3api head-bucket --bucket "$BUCKET_NAME" --region us-east-1 2>/dev/null; then + aws s3api create-bucket --bucket "$BUCKET_NAME" --region us-east-1 + echo "Created S3 bucket: $BUCKET_NAME" + else + echo "S3 bucket already exists: $BUCKET_NAME" + fi + package-and-upload: + needs: setup runs-on: ubuntu-latest strategy: matrix: @@ -97,13 +120,9 @@ jobs: PYTHON_VERSION="${{ matrix.python-version }}" ARCH="${{ matrix.architecture }}" LAYER_NAME="strands-agents-py${PYTHON_VERSION//./_}-${ARCH}" - BUCKET_NAME="strands-agents-lambda-layers-$(aws sts get-caller-identity --query Account --output text)" + BUCKET_NAME="strands-agents-lambda-layers-032316178046" LAYER_KEY="$LAYER_NAME/v${{ inputs.package_version }}/lambda-layer.zip" - if ! aws s3api head-bucket --bucket "$BUCKET_NAME" --region us-east-1 2>/dev/null; then - aws s3api create-bucket --bucket "$BUCKET_NAME" --region us-east-1 - fi - aws s3 cp lambda-layer.zip "s3://$BUCKET_NAME/$LAYER_KEY" --region us-east-1 echo "Uploaded layer to s3://$BUCKET_NAME/$LAYER_KEY" @@ -135,7 +154,7 @@ jobs: ARCH="${{ matrix.architecture }}" REGION="${{ matrix.region }}" LAYER_NAME="strands-agents-py${PYTHON_VERSION//./_}-${ARCH}" - BUCKET_NAME="strands-agents-lambda-layers-$(aws sts get-caller-identity --query Account --output text)" + BUCKET_NAME="strands-agents-lambda-layers-032316178046" LAYER_KEY="$LAYER_NAME/v${{ inputs.package_version }}/lambda-layer.zip" DESCRIPTION="PyPI package: strands-agents v${{ inputs.package_version }} (Python $PYTHON_VERSION, $ARCH)" From 4d380ec22971d65874440ba8bfeb069a3821b8a6 Mon Sep 17 00:00:00 2001 From: Dean Schmigelski Date: Wed, 10 Sep 2025 20:16:32 -0400 Subject: [PATCH 08/31] move create outside --- .github/workflows/LAMBDA_LAYERS.md | 5 +++++ .github/workflows/publish-lambda-layer.yml | 15 ++++++++++----- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/.github/workflows/LAMBDA_LAYERS.md b/.github/workflows/LAMBDA_LAYERS.md index 1fcddae18..de07e8a79 100644 --- a/.github/workflows/LAMBDA_LAYERS.md +++ b/.github/workflows/LAMBDA_LAYERS.md @@ -21,6 +21,11 @@ This document defines the standard operating procedures for managing Strands Age ## Deployment Process +### Staging Region +- **us-east-1** serves as the staging region for all layer packages +- S3 bucket and layer zip files are created in us-east-1 +- All other regions reference the same S3 objects from us-east-1 + ### 1. Initial Deployment 1. Run workflow with ALL options selected (default) 2. Specify PyPI package version diff --git a/.github/workflows/publish-lambda-layer.yml b/.github/workflows/publish-lambda-layer.yml index 0bd43a546..0a8f37ce3 100644 --- a/.github/workflows/publish-lambda-layer.yml +++ b/.github/workflows/publish-lambda-layer.yml @@ -33,6 +33,7 @@ on: env: IS_FULL_DEPLOY: ${{ inputs.python_version == 'ALL' && inputs.architecture == 'ALL' && inputs.region == 'ALL' }} + BUCKET_NAME: strands-agents-lambda-layer-032316178046 jobs: setup: @@ -47,12 +48,16 @@ jobs: role-to-assume: ${{ secrets.STRANDS_LAMBDA_LAYER_PUBLISHER_ROLE }} aws-region: us-east-1 - - name: Create S3 bucket + - name: Create S3 bucket with versioning run: | - BUCKET_NAME="strands-agents-lambda-layers-032316178046" + BUCKET_NAME="${{ env.BUCKET_NAME }}" if ! aws s3api head-bucket --bucket "$BUCKET_NAME" --region us-east-1 2>/dev/null; then aws s3api create-bucket --bucket "$BUCKET_NAME" --region us-east-1 - echo "Created S3 bucket: $BUCKET_NAME" + + # Enable versioning (required for CRR) + aws s3api put-bucket-versioning --bucket "$BUCKET_NAME" --versioning-configuration Status=Enabled --region us-east-1 + + echo "Created S3 bucket with versioning: $BUCKET_NAME" else echo "S3 bucket already exists: $BUCKET_NAME" fi @@ -120,7 +125,7 @@ jobs: PYTHON_VERSION="${{ matrix.python-version }}" ARCH="${{ matrix.architecture }}" LAYER_NAME="strands-agents-py${PYTHON_VERSION//./_}-${ARCH}" - BUCKET_NAME="strands-agents-lambda-layers-032316178046" + BUCKET_NAME="${{ env.BUCKET_NAME }}" LAYER_KEY="$LAYER_NAME/v${{ inputs.package_version }}/lambda-layer.zip" aws s3 cp lambda-layer.zip "s3://$BUCKET_NAME/$LAYER_KEY" --region us-east-1 @@ -154,7 +159,7 @@ jobs: ARCH="${{ matrix.architecture }}" REGION="${{ matrix.region }}" LAYER_NAME="strands-agents-py${PYTHON_VERSION//./_}-${ARCH}" - BUCKET_NAME="strands-agents-lambda-layers-032316178046" + BUCKET_NAME="${{ env.BUCKET_NAME }}" LAYER_KEY="$LAYER_NAME/v${{ inputs.package_version }}/lambda-layer.zip" DESCRIPTION="PyPI package: strands-agents v${{ inputs.package_version }} (Python $PYTHON_VERSION, $ARCH)" From c4f558c044f2c73f39e15e6f896782a24dfd8638 Mon Sep 17 00:00:00 2001 From: Dean Schmigelski Date: Wed, 10 Sep 2025 20:29:25 -0400 Subject: [PATCH 09/31] create n s3 buckets --- .github/workflows/publish-lambda-layer.yml | 49 +++++++++++++++------- 1 file changed, 35 insertions(+), 14 deletions(-) diff --git a/.github/workflows/publish-lambda-layer.yml b/.github/workflows/publish-lambda-layer.yml index 0a8f37ce3..0ced8feca 100644 --- a/.github/workflows/publish-lambda-layer.yml +++ b/.github/workflows/publish-lambda-layer.yml @@ -34,10 +34,14 @@ on: env: IS_FULL_DEPLOY: ${{ inputs.python_version == 'ALL' && inputs.architecture == 'ALL' && inputs.region == 'ALL' }} BUCKET_NAME: strands-agents-lambda-layer-032316178046 + REGIONS: '["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"]' jobs: setup: runs-on: ubuntu-latest + strategy: + matrix: + region: ${{ inputs.region == 'ALL' && fromJson(env.REGIONS) || fromJson(format('["{}"', inputs.region, ']')) }} permissions: id-token: write contents: read @@ -46,20 +50,33 @@ jobs: uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: ${{ secrets.STRANDS_LAMBDA_LAYER_PUBLISHER_ROLE }} - aws-region: us-east-1 + aws-region: ${{ matrix.region }} - - name: Create S3 bucket with versioning + - name: Create S3 buckets run: | - BUCKET_NAME="${{ env.BUCKET_NAME }}" - if ! aws s3api head-bucket --bucket "$BUCKET_NAME" --region us-east-1 2>/dev/null; then - aws s3api create-bucket --bucket "$BUCKET_NAME" --region us-east-1 - - # Enable versioning (required for CRR) - aws s3api put-bucket-versioning --bucket "$BUCKET_NAME" --versioning-configuration Status=Enabled --region us-east-1 - - echo "Created S3 bucket with versioning: $BUCKET_NAME" + REGION="${{ matrix.region }}" + SOURCE_BUCKET="${{ env.BUCKET_NAME }}" + REGION_BUCKET="${{ env.BUCKET_NAME }}-${REGION}" + + # Create source bucket (us-east-1 only) + if [ "$REGION" = "us-east-1" ]; then + if ! aws s3api head-bucket --bucket "$SOURCE_BUCKET" --region us-east-1 2>/dev/null; then + aws s3api create-bucket --bucket "$SOURCE_BUCKET" --region us-east-1 + aws s3api put-bucket-versioning --bucket "$SOURCE_BUCKET" --versioning-configuration Status=Enabled --region us-east-1 + echo "Created source S3 bucket with versioning: $SOURCE_BUCKET" + fi + fi + + # Create regional bucket + if ! aws s3api head-bucket --bucket "$REGION_BUCKET" --region "$REGION" 2>/dev/null; then + if [ "$REGION" = "us-east-1" ]; then + aws s3api create-bucket --bucket "$REGION_BUCKET" --region "$REGION" + else + aws s3api create-bucket --bucket "$REGION_BUCKET" --region "$REGION" --create-bucket-configuration LocationConstraint="$REGION" + fi + echo "Created regional S3 bucket: $REGION_BUCKET" else - echo "S3 bucket already exists: $BUCKET_NAME" + echo "Regional S3 bucket already exists: $REGION_BUCKET" fi package-and-upload: @@ -138,7 +155,7 @@ jobs: matrix: python-version: ${{ inputs.python_version == 'ALL' && fromJson('["3.10", "3.11", "3.12", "3.13"]') || fromJson(format('["{}"', inputs.python_version, ']')) }} architecture: ${{ inputs.architecture == 'ALL' && fromJson('["x86_64", "aarch64"]') || fromJson(format('["{}"', 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('["{}"', inputs.region, ']')) }} + region: ${{ inputs.region == 'ALL' && fromJson(env.REGIONS) || fromJson(format('["{}"', inputs.region, ']')) }} outputs: layer-version: ${{ env.LAYER_VERSION }} @@ -159,15 +176,19 @@ jobs: ARCH="${{ matrix.architecture }}" REGION="${{ matrix.region }}" LAYER_NAME="strands-agents-py${PYTHON_VERSION//./_}-${ARCH}" - BUCKET_NAME="${{ env.BUCKET_NAME }}" + SOURCE_BUCKET="${{ env.BUCKET_NAME }}" + REGION_BUCKET="${{ env.BUCKET_NAME }}-${REGION}" LAYER_KEY="$LAYER_NAME/v${{ inputs.package_version }}/lambda-layer.zip" + # Copy layer zip from source bucket to region bucket + aws s3 cp "s3://$SOURCE_BUCKET/$LAYER_KEY" "s3://$REGION_BUCKET/$LAYER_KEY" --source-region us-east-1 --region "$REGION" + DESCRIPTION="PyPI package: strands-agents v${{ inputs.package_version }} (Python $PYTHON_VERSION, $ARCH)" LAYER_OUTPUT=$(aws lambda publish-layer-version \ --layer-name $LAYER_NAME \ --description "$DESCRIPTION" \ - --content S3Bucket=$BUCKET_NAME,S3Key=$LAYER_KEY \ + --content S3Bucket=$REGION_BUCKET,S3Key=$LAYER_KEY \ --compatible-runtimes python${{ matrix.python-version }} \ --region "$REGION" \ --license-info Apache-2.0 \ From eb3466f13eedc5da84c9d3ac6c436a5c9932b814 Mon Sep 17 00:00:00 2001 From: Dean Schmigelski Date: Wed, 10 Sep 2025 20:38:05 -0400 Subject: [PATCH 10/31] try anchors --- .github/workflows/publish-lambda-layer.yml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/workflows/publish-lambda-layer.yml b/.github/workflows/publish-lambda-layer.yml index 0ced8feca..08f49d72d 100644 --- a/.github/workflows/publish-lambda-layer.yml +++ b/.github/workflows/publish-lambda-layer.yml @@ -31,17 +31,21 @@ on: required: true type: string +x-regions: ®ions + ['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'] + env: IS_FULL_DEPLOY: ${{ inputs.python_version == 'ALL' && inputs.architecture == 'ALL' && inputs.region == 'ALL' }} BUCKET_NAME: strands-agents-lambda-layer-032316178046 - REGIONS: '["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"]' jobs: setup: runs-on: ubuntu-latest strategy: matrix: - region: ${{ inputs.region == 'ALL' && fromJson(env.REGIONS) || fromJson(format('["{}"', inputs.region, ']')) }} + region: ${{ inputs.region == 'ALL' && *regions || fromJson(format('["{}"', inputs.region, ']')) }} permissions: id-token: write contents: read @@ -155,7 +159,7 @@ jobs: matrix: python-version: ${{ inputs.python_version == 'ALL' && fromJson('["3.10", "3.11", "3.12", "3.13"]') || fromJson(format('["{}"', inputs.python_version, ']')) }} architecture: ${{ inputs.architecture == 'ALL' && fromJson('["x86_64", "aarch64"]') || fromJson(format('["{}"', inputs.architecture, ']')) }} - region: ${{ inputs.region == 'ALL' && fromJson(env.REGIONS) || fromJson(format('["{}"', inputs.region, ']')) }} + region: ${{ inputs.region == 'ALL' && *regions || fromJson(format('["{}"', inputs.region, ']')) }} outputs: layer-version: ${{ env.LAYER_VERSION }} From 65ed3925859c76a5da2c9a8e3db4f009f1b3a6c3 Mon Sep 17 00:00:00 2001 From: Dean Schmigelski Date: Wed, 10 Sep 2025 20:41:06 -0400 Subject: [PATCH 11/31] remove anchors --- .github/workflows/publish-lambda-layer.yml | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/.github/workflows/publish-lambda-layer.yml b/.github/workflows/publish-lambda-layer.yml index 08f49d72d..2bef3a5ff 100644 --- a/.github/workflows/publish-lambda-layer.yml +++ b/.github/workflows/publish-lambda-layer.yml @@ -31,11 +31,6 @@ on: required: true type: string -x-regions: ®ions - ['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'] - env: IS_FULL_DEPLOY: ${{ inputs.python_version == 'ALL' && inputs.architecture == 'ALL' && inputs.region == 'ALL' }} BUCKET_NAME: strands-agents-lambda-layer-032316178046 @@ -45,7 +40,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - region: ${{ inputs.region == 'ALL' && *regions || fromJson(format('["{}"', inputs.region, ']')) }} + 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('["{}"', inputs.region, ']')) }} permissions: id-token: write contents: read @@ -159,7 +154,7 @@ jobs: matrix: python-version: ${{ inputs.python_version == 'ALL' && fromJson('["3.10", "3.11", "3.12", "3.13"]') || fromJson(format('["{}"', inputs.python_version, ']')) }} architecture: ${{ inputs.architecture == 'ALL' && fromJson('["x86_64", "aarch64"]') || fromJson(format('["{}"', inputs.architecture, ']')) }} - region: ${{ inputs.region == 'ALL' && *regions || fromJson(format('["{}"', inputs.region, ']')) }} + 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('["{}"', inputs.region, ']')) }} outputs: layer-version: ${{ env.LAYER_VERSION }} From a84b51dac5a6ad173d49452d5f2084a470acebaf Mon Sep 17 00:00:00 2001 From: Dean Schmigelski Date: Wed, 10 Sep 2025 20:47:04 -0400 Subject: [PATCH 12/31] more --- .github/workflows/publish-lambda-layer.yml | 37 +++++++--------------- 1 file changed, 12 insertions(+), 25 deletions(-) diff --git a/.github/workflows/publish-lambda-layer.yml b/.github/workflows/publish-lambda-layer.yml index 2bef3a5ff..3ef7921ea 100644 --- a/.github/workflows/publish-lambda-layer.yml +++ b/.github/workflows/publish-lambda-layer.yml @@ -51,31 +51,16 @@ jobs: role-to-assume: ${{ secrets.STRANDS_LAMBDA_LAYER_PUBLISHER_ROLE }} aws-region: ${{ matrix.region }} - - name: Create S3 buckets + - name: Create S3 bucket run: | REGION="${{ matrix.region }}" - SOURCE_BUCKET="${{ env.BUCKET_NAME }}" - REGION_BUCKET="${{ env.BUCKET_NAME }}-${REGION}" - - # Create source bucket (us-east-1 only) - if [ "$REGION" = "us-east-1" ]; then - if ! aws s3api head-bucket --bucket "$SOURCE_BUCKET" --region us-east-1 2>/dev/null; then - aws s3api create-bucket --bucket "$SOURCE_BUCKET" --region us-east-1 - aws s3api put-bucket-versioning --bucket "$SOURCE_BUCKET" --versioning-configuration Status=Enabled --region us-east-1 - echo "Created source S3 bucket with versioning: $SOURCE_BUCKET" - fi - fi + BUCKET_NAME="${{ env.BUCKET_NAME }}-${REGION}" - # Create regional bucket - if ! aws s3api head-bucket --bucket "$REGION_BUCKET" --region "$REGION" 2>/dev/null; then - if [ "$REGION" = "us-east-1" ]; then - aws s3api create-bucket --bucket "$REGION_BUCKET" --region "$REGION" - else - aws s3api create-bucket --bucket "$REGION_BUCKET" --region "$REGION" --create-bucket-configuration LocationConstraint="$REGION" - fi - echo "Created regional S3 bucket: $REGION_BUCKET" + if ! aws s3api head-bucket --bucket "$BUCKET_NAME" 2>/dev/null; then + aws s3api create-bucket --bucket "$BUCKET_NAME" + echo "Created S3 bucket: $BUCKET_NAME" else - echo "Regional S3 bucket already exists: $REGION_BUCKET" + echo "S3 bucket already exists: $BUCKET_NAME" fi package-and-upload: @@ -141,7 +126,7 @@ jobs: PYTHON_VERSION="${{ matrix.python-version }}" ARCH="${{ matrix.architecture }}" LAYER_NAME="strands-agents-py${PYTHON_VERSION//./_}-${ARCH}" - BUCKET_NAME="${{ env.BUCKET_NAME }}" + BUCKET_NAME="${{ env.BUCKET_NAME }}-us-east-1" LAYER_KEY="$LAYER_NAME/v${{ inputs.package_version }}/lambda-layer.zip" aws s3 cp lambda-layer.zip "s3://$BUCKET_NAME/$LAYER_KEY" --region us-east-1 @@ -175,12 +160,14 @@ jobs: ARCH="${{ matrix.architecture }}" REGION="${{ matrix.region }}" LAYER_NAME="strands-agents-py${PYTHON_VERSION//./_}-${ARCH}" - SOURCE_BUCKET="${{ env.BUCKET_NAME }}" REGION_BUCKET="${{ env.BUCKET_NAME }}-${REGION}" LAYER_KEY="$LAYER_NAME/v${{ inputs.package_version }}/lambda-layer.zip" - # Copy layer zip from source bucket to region bucket - aws s3 cp "s3://$SOURCE_BUCKET/$LAYER_KEY" "s3://$REGION_BUCKET/$LAYER_KEY" --source-region us-east-1 --region "$REGION" + # Copy layer zip from us-east-1 bucket to region bucket + if [ "$REGION" != "us-east-1" ]; then + SOURCE_BUCKET="${{ env.BUCKET_NAME }}-us-east-1" + aws s3 cp "s3://$SOURCE_BUCKET/$LAYER_KEY" "s3://$REGION_BUCKET/$LAYER_KEY" --source-region us-east-1 --region "$REGION" + fi DESCRIPTION="PyPI package: strands-agents v${{ inputs.package_version }} (Python $PYTHON_VERSION, $ARCH)" From 9b0142bcb879d5f71b2294f5e32285e465ed67df Mon Sep 17 00:00:00 2001 From: Dean Schmigelski Date: Wed, 10 Sep 2025 20:50:07 -0400 Subject: [PATCH 13/31] location constraint --- .github/workflows/publish-lambda-layer.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/publish-lambda-layer.yml b/.github/workflows/publish-lambda-layer.yml index 3ef7921ea..345c55794 100644 --- a/.github/workflows/publish-lambda-layer.yml +++ b/.github/workflows/publish-lambda-layer.yml @@ -57,7 +57,11 @@ jobs: BUCKET_NAME="${{ env.BUCKET_NAME }}-${REGION}" if ! aws s3api head-bucket --bucket "$BUCKET_NAME" 2>/dev/null; then - aws s3api create-bucket --bucket "$BUCKET_NAME" + if [ "$REGION" = "us-east-1" ]; then + aws s3api create-bucket --bucket "$BUCKET_NAME" --region "$REGION" + else + aws s3api create-bucket --bucket "$BUCKET_NAME" --region "$REGION" --create-bucket-configuration LocationConstraint="$REGION" + fi echo "Created S3 bucket: $BUCKET_NAME" else echo "S3 bucket already exists: $BUCKET_NAME" From 3d36e48e8c1f4c41cfbe959bfdbaf44f227d1cff Mon Sep 17 00:00:00 2001 From: Dean Schmigelski Date: Wed, 10 Sep 2025 20:55:13 -0400 Subject: [PATCH 14/31] regionalize --- .github/workflows/publish-lambda-layer.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/publish-lambda-layer.yml b/.github/workflows/publish-lambda-layer.yml index 345c55794..858ef5cc1 100644 --- a/.github/workflows/publish-lambda-layer.yml +++ b/.github/workflows/publish-lambda-layer.yml @@ -54,17 +54,17 @@ jobs: - name: Create S3 bucket run: | REGION="${{ matrix.region }}" - BUCKET_NAME="${{ env.BUCKET_NAME }}-${REGION}" + REGIONAL_BUCKET="${{ env.BUCKET_NAME }}-${REGION}" - if ! aws s3api head-bucket --bucket "$BUCKET_NAME" 2>/dev/null; then + if ! aws s3api head-bucket --bucket "$REGIONAL_BUCKET" 2>/dev/null; then if [ "$REGION" = "us-east-1" ]; then - aws s3api create-bucket --bucket "$BUCKET_NAME" --region "$REGION" + aws s3api create-bucket --bucket "$REGIONAL_BUCKET" --region "$REGION" 2>/dev/null || echo "Bucket $REGIONAL_BUCKET already exists" else - aws s3api create-bucket --bucket "$BUCKET_NAME" --region "$REGION" --create-bucket-configuration LocationConstraint="$REGION" + aws s3api create-bucket --bucket "$REGIONAL_BUCKET" --region "$REGION" --create-bucket-configuration LocationConstraint="$REGION" 2>/dev/null || echo "Bucket $REGIONAL_BUCKET already exists" fi - echo "Created S3 bucket: $BUCKET_NAME" + echo "S3 bucket ready: $REGIONAL_BUCKET" else - echo "S3 bucket already exists: $BUCKET_NAME" + echo "S3 bucket already exists: $REGIONAL_BUCKET" fi package-and-upload: From 822863e58ff263f3e35e3d2409bb5ab73db4ee2e Mon Sep 17 00:00:00 2001 From: Dean Schmigelski Date: Wed, 10 Sep 2025 21:00:35 -0400 Subject: [PATCH 15/31] no copy --- .github/workflows/publish-lambda-layer.yml | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/.github/workflows/publish-lambda-layer.yml b/.github/workflows/publish-lambda-layer.yml index 858ef5cc1..3741ab172 100644 --- a/.github/workflows/publish-lambda-layer.yml +++ b/.github/workflows/publish-lambda-layer.yml @@ -74,6 +74,7 @@ jobs: matrix: python-version: ${{ inputs.python_version == 'ALL' && fromJson('["3.10", "3.11", "3.12", "3.13"]') || fromJson(format('["{}"', inputs.python_version, ']')) }} architecture: ${{ inputs.architecture == 'ALL' && fromJson('["x86_64", "aarch64"]') || fromJson(format('["{}"', 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('["{}"', inputs.region, ']')) }} permissions: id-token: write @@ -106,7 +107,7 @@ jobs: uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: ${{ secrets.STRANDS_LAMBDA_LAYER_PUBLISHER_ROLE }} - aws-region: us-east-1 + aws-region: ${{ matrix.region }} - name: Create layer directory structure run: | @@ -129,11 +130,12 @@ jobs: run: | PYTHON_VERSION="${{ matrix.python-version }}" ARCH="${{ matrix.architecture }}" + REGION="${{ matrix.region }}" LAYER_NAME="strands-agents-py${PYTHON_VERSION//./_}-${ARCH}" - BUCKET_NAME="${{ env.BUCKET_NAME }}-us-east-1" + BUCKET_NAME="${{ env.BUCKET_NAME }}-${REGION}" LAYER_KEY="$LAYER_NAME/v${{ inputs.package_version }}/lambda-layer.zip" - aws s3 cp lambda-layer.zip "s3://$BUCKET_NAME/$LAYER_KEY" --region us-east-1 + aws s3 cp lambda-layer.zip "s3://$BUCKET_NAME/$LAYER_KEY" --region "$REGION" echo "Uploaded layer to s3://$BUCKET_NAME/$LAYER_KEY" publish-layer: @@ -167,12 +169,6 @@ jobs: REGION_BUCKET="${{ env.BUCKET_NAME }}-${REGION}" LAYER_KEY="$LAYER_NAME/v${{ inputs.package_version }}/lambda-layer.zip" - # Copy layer zip from us-east-1 bucket to region bucket - if [ "$REGION" != "us-east-1" ]; then - SOURCE_BUCKET="${{ env.BUCKET_NAME }}-us-east-1" - aws s3 cp "s3://$SOURCE_BUCKET/$LAYER_KEY" "s3://$REGION_BUCKET/$LAYER_KEY" --source-region us-east-1 --region "$REGION" - fi - DESCRIPTION="PyPI package: strands-agents v${{ inputs.package_version }} (Python $PYTHON_VERSION, $ARCH)" LAYER_OUTPUT=$(aws lambda publish-layer-version \ @@ -240,5 +236,3 @@ jobs: --body "Automated update to add new lambda layer version ${{ inputs.package_version }}" \ --head "$BRANCH" \ --base main - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file From 3e4aa871ebf32c1a9a9e3689aff9b6eff6e33595 Mon Sep 17 00:00:00 2001 From: Dean Schmigelski Date: Wed, 10 Sep 2025 21:29:57 -0400 Subject: [PATCH 16/31] remove publish docs --- .github/workflows/publish-lambda-layer.yml | 40 +--------------------- 1 file changed, 1 insertion(+), 39 deletions(-) diff --git a/.github/workflows/publish-lambda-layer.yml b/.github/workflows/publish-lambda-layer.yml index 3741ab172..080f5c96f 100644 --- a/.github/workflows/publish-lambda-layer.yml +++ b/.github/workflows/publish-lambda-layer.yml @@ -36,7 +36,7 @@ env: BUCKET_NAME: strands-agents-lambda-layer-032316178046 jobs: - setup: + create-buckets: runs-on: ubuntu-latest strategy: matrix: @@ -198,41 +198,3 @@ jobs: if [ "${{ env.IS_FULL_DEPLOY }}" = "true" ] && [ "$REGION" = "us-east-1" ] && [ "$PYTHON_VERSION" = "3.10" ] && [ "$ARCH" = "x86_64" ]; then echo "LAYER_VERSION=$LAYER_VERSION" >> $GITHUB_ENV fi - - update-docs: - if: ${{ inputs.python_version == 'ALL' && inputs.architecture == 'ALL' && inputs.region == 'ALL' }} - needs: publish-layer - runs-on: ubuntu-latest - steps: - - name: Checkout docs repository - uses: actions/checkout@v4 - with: - repository: ${{ github.repository_owner }}/docs - token: ${{ secrets.GITHUB_TOKEN }} - path: docs - - - name: Update lambda layers documentation - run: | - cd docs - LAYER_VERSION="${{ needs.publish-layer.outputs.layer-version }}" - NEW_ROW="| $LAYER_VERSION | [${{ inputs.package_version }}](https://pypi.org/project/strands-agents/${{ inputs.package_version }}) | \`arn:aws:lambda:{REGION}:856699698935:layer:strands-agents-{VERSION}-{ARCHITECTURE}:$LAYER_VERSION\` |" - - sed -i "//a\$NEW_ROW" docs/user-guide/deploy/lambda-layers.md - - - name: Create Pull Request - run: | - cd docs - git config user.name "github-actions[bot]" - git config user.email "github-actions[bot]@users.noreply.github.com" - - BRANCH="update-lambda-layers-${{ inputs.package_version }}" - git checkout -b "$BRANCH" - git add docs/user-guide/deploy/lambda-layers.md - git commit -m "Update lambda layers with version ${{ inputs.package_version }}" - git push origin "$BRANCH" - - gh pr create \ - --title "Update lambda layers documentation for v${{ inputs.package_version }}" \ - --body "Automated update to add new lambda layer version ${{ inputs.package_version }}" \ - --head "$BRANCH" \ - --base main From 0b4248e288df749f81c2f6cb58b1967f3b3c5a2a Mon Sep 17 00:00:00 2001 From: Dean Schmigelski Date: Wed, 10 Sep 2025 21:33:44 -0400 Subject: [PATCH 17/31] fix --- .github/workflows/publish-lambda-layer.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish-lambda-layer.yml b/.github/workflows/publish-lambda-layer.yml index 080f5c96f..b3d44e653 100644 --- a/.github/workflows/publish-lambda-layer.yml +++ b/.github/workflows/publish-lambda-layer.yml @@ -68,7 +68,7 @@ jobs: fi package-and-upload: - needs: setup + needs: create-buckets runs-on: ubuntu-latest strategy: matrix: From 4bd64fb113e0ddec208c14f491ea4a19b4a2013c Mon Sep 17 00:00:00 2001 From: Dean Schmigelski Date: Wed, 10 Sep 2025 21:37:55 -0400 Subject: [PATCH 18/31] fix --- .github/workflows/publish-lambda-layer.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/publish-lambda-layer.yml b/.github/workflows/publish-lambda-layer.yml index b3d44e653..11920ed20 100644 --- a/.github/workflows/publish-lambda-layer.yml +++ b/.github/workflows/publish-lambda-layer.yml @@ -40,7 +40,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - 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('["{}"', inputs.region, ']')) }} + 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 contents: read @@ -72,9 +72,9 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ${{ inputs.python_version == 'ALL' && fromJson('["3.10", "3.11", "3.12", "3.13"]') || fromJson(format('["{}"', inputs.python_version, ']')) }} - architecture: ${{ inputs.architecture == 'ALL' && fromJson('["x86_64", "aarch64"]') || fromJson(format('["{}"', 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('["{}"', inputs.region, ']')) }} + 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 @@ -143,9 +143,9 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ${{ inputs.python_version == 'ALL' && fromJson('["3.10", "3.11", "3.12", "3.13"]') || fromJson(format('["{}"', inputs.python_version, ']')) }} - architecture: ${{ inputs.architecture == 'ALL' && fromJson('["x86_64", "aarch64"]') || fromJson(format('["{}"', 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('["{}"', inputs.region, ']')) }} + 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)) }} outputs: layer-version: ${{ env.LAYER_VERSION }} From 6551d44dc49cb651815bd4ffd5e9ac7bdbaa28ac Mon Sep 17 00:00:00 2001 From: Dean Schmigelski Date: Mon, 15 Sep 2025 10:33:40 -0400 Subject: [PATCH 19/31] add yank --- .github/workflows/LAMBDA_LAYERS.md | 105 --------------------- .github/workflows/LAMBDA_LAYERS_SOP.md | 42 +++++++++ .github/workflows/publish-lambda-layer.yml | 17 ++-- .github/workflows/yank-lambda-layer.yml | 80 ++++++++++++++++ 4 files changed, 128 insertions(+), 116 deletions(-) delete mode 100644 .github/workflows/LAMBDA_LAYERS.md create mode 100644 .github/workflows/LAMBDA_LAYERS_SOP.md create mode 100644 .github/workflows/yank-lambda-layer.yml diff --git a/.github/workflows/LAMBDA_LAYERS.md b/.github/workflows/LAMBDA_LAYERS.md deleted file mode 100644 index de07e8a79..000000000 --- a/.github/workflows/LAMBDA_LAYERS.md +++ /dev/null @@ -1,105 +0,0 @@ -# Lambda Layers Standard Operating Procedures (SOP) - -## Overview - -This document defines the standard operating procedures for managing Strands Agents Lambda layers across all AWS regions, Python versions, and architectures. - -## Core Principles - -### Version Synchronization -- **All variants must have the same layer version number** for each PyPI package version -- This includes all combinations of: - - Python versions (3.10, 3.11, 3.12, 3.13) - - Architectures (x86_64, aarch64) - - AWS regions (all non opt-in regions) -- **Total: 136 individual Lambda layers** (17 regions × 2 architectures × 4 Python versions) -- Each layer is published separately but must maintain version synchronization - -### Documentation Consistency -- Only **one row per PyPI version** appears in documentation -- The layer version number represents all variants for that PyPI package version - -## Deployment Process - -### Staging Region -- **us-east-1** serves as the staging region for all layer packages -- S3 bucket and layer zip files are created in us-east-1 -- All other regions reference the same S3 objects from us-east-1 - -### 1. Initial Deployment -1. Run workflow with ALL options selected (default) -2. Specify PyPI package version -3. Type "Create Lambda Layer" to confirm -4. All 136 individual layers deploy in parallel (4 Python × 2 arch × 17 regions) -5. Each layer gets its own unique name: `strands-agents-py{VERSION}-{ARCH}` -6. Documentation automatically updates with new row - -### 2. Version Buffering for New Variants -When adding new variants (new Python version, architecture, or region): - -1. **Determine target layer version**: Check existing variants to find the highest layer version -2. **Buffer deployment**: Deploy new variants multiple times until layer version matches existing variants -3. **Example**: If existing variants are at layer version 5, deploy new variant 5 times to reach version 5 - -### 3. Handling Transient Failures -When some regions fail during deployment: - -1. **Identify failed regions**: Check which combinations didn't complete successfully -2. **Targeted redeployment**: Use specific region/arch/Python inputs to redeploy failed combinations -3. **Version alignment**: Continue deploying until all variants reach the same layer version -4. **Verification**: Confirm all combinations have identical layer versions before updating docs - -## Yank Process - -### When to Yank -- Security vulnerabilities discovered in PyPI package -- Critical bugs affecting Lambda functionality -- Compliance requirements - -### Yank Procedure -1. **Remove public permissions**: - ```bash - aws lambda remove-layer-version-permission \ - --layer-name strands-agents-py{VERSION}-{ARCH} \ - --version-number {LAYER_VERSION} \ - --statement-id public \ - --region {REGION} - ``` - -2. **Update documentation**: Remove or mark the row as yanked in lambda-layers.md - -3. **Coordinate across all variants**: Repeat for all 136 combinations - -4. **Communication**: Notify users through appropriate channels - -## Workflow Usage - -### Full Deployment (Default) -- Python Version: ALL -- Architecture: ALL -- Region: ALL -- Result: 136 parallel deployments - -### Targeted Deployment -- Select specific values for failed/new variants -- Used for version synchronization and failure recovery - -### Validation Steps -1. Verify all combinations completed successfully -2. Check layer versions are synchronized across all variants -3. Confirm documentation reflects single version per PyPI package -4. Test layer functionality in representative regions/architectures - -## Troubleshooting - -### Common Issues -- **Partial failures**: Use targeted deployment to retry failed combinations -- **Version drift**: Deploy additional times to align layer versions -- **Permission errors**: Verify IAM role has necessary permissions across all regions -- **S3 bucket issues**: Ensure buckets exist in all target regions - -### Recovery Actions -1. Identify scope of issue (specific regions, architectures, Python versions) -2. Use targeted deployment to address specific failures -3. Continue until version synchronization is achieved -4. Update documentation only after full synchronization \ No newline at end of file diff --git a/.github/workflows/LAMBDA_LAYERS_SOP.md b/.github/workflows/LAMBDA_LAYERS_SOP.md new file mode 100644 index 000000000..6ad391d49 --- /dev/null +++ b/.github/workflows/LAMBDA_LAYERS_SOP.md @@ -0,0 +1,42 @@ +# Lambda Layers Standard Operating Procedures (SOP) + +## Overview + +This document defines the standard operating procedures for managing Strands Agents Lambda layers across all AWS regions, Python versions, and architectures. + +**Total: 136 individual Lambda layers** (17 regions × 2 architectures × 4 Python versions). All variants must maintain the same layer version number for each PyPI package version, with only one row per PyPI version appearing in documentation. + +## Deployment Process + +### 1. Initial Deployment +1. Run workflow with ALL options selected (default) +2. Specify PyPI package version +3. Type "Create Lambda Layer {package_version}" to confirm +4. All 136 individual layers deploy in parallel (4 Python × 2 arch × 17 regions) +5. Each layer gets its own unique name: `strands-agents-py{PYTHON_VERSION}-{ARCH}-all` + +### 2. Version Buffering for New Variants +When adding new variants (new Python version, architecture, or region): + +1. **Determine target layer version**: Check existing variants to find the highest layer version +2. **Buffer deployment**: Deploy new variants multiple times until layer version matches existing variants +3. **Example**: If existing variants are at layer version 5, deploy new variant 5 times to reach version 5 + +### 3. Handling Transient Failures +When some regions fail during deployment: + +1. **Identify failed regions**: Check which combinations didn't complete successfully +2. **Targeted redeployment**: Use specific region/arch/Python inputs to redeploy failed combinations +3. **Version alignment**: Continue deploying until all variants reach the same layer version +4. **Verification**: Confirm all combinations have identical layer versions before updating docs + +## Yank Process + +### Yank Procedure +1. Use the `yank_lambda_layer` GitHub action workflow +2. **Full yank**: Run with ALL options selected (default) to yank all 136 variants +3. **Partial yank**: Specify Python versions, architectures, and regions for targeted yanking +4. **Update documentation**: Remove or mark the row as yanked in lambda-layers.md +5. **Communication**: Notify users through appropriate channels + +**Note**: Yanking removes public permissions making layers private but does not delete them. Use `delete-layer-version` to actually delete layer versions. \ No newline at end of file diff --git a/.github/workflows/publish-lambda-layer.yml b/.github/workflows/publish-lambda-layer.yml index 11920ed20..6079e946c 100644 --- a/.github/workflows/publish-lambda-layer.yml +++ b/.github/workflows/publish-lambda-layer.yml @@ -43,7 +43,6 @@ jobs: 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 - contents: read steps: - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v4 @@ -84,13 +83,9 @@ jobs: - name: Validate confirmation run: | CONFIRM="${{ inputs.confirm }}" - if [ "$CONFIRM" != "Create Lambda Layer" ]; then - if [[ "$CONFIRM" =~ ^(x86_64|aarch64|3\.[0-9]+|[a-z]+-[a-z]+-[0-9]+)$ ]]; then - echo "Error: You entered '$CONFIRM' which looks like an architecture, Python version, or region." - echo "Please type exactly 'Create Lambda Layer' to confirm." - else - echo "Confirmation failed. You must type exactly 'Create Lambda Layer' to proceed." - fi + EXPECTED="Create Lambda Layer ${{ inputs.package_version }}" + if [ "$CONFIRM" != "$EXPECTED" ]; then + echo "Confirmation failed. You must type exactly '$EXPECTED' to proceed." exit 1 fi echo "Confirmation validated" @@ -115,7 +110,7 @@ jobs: - name: Download and install package run: | - pip install strands-agents==${{ inputs.package_version }} \ + pip install strands-agents==${{ inputs.package_version }}[all] \ --python-version ${{ matrix.python-version }} \ --platform manylinux2014_${{ matrix.architecture }} \ -t layer/python/ \ @@ -131,7 +126,7 @@ jobs: PYTHON_VERSION="${{ matrix.python-version }}" ARCH="${{ matrix.architecture }}" REGION="${{ matrix.region }}" - LAYER_NAME="strands-agents-py${PYTHON_VERSION//./_}-${ARCH}" + LAYER_NAME="strands-agents-py${PYTHON_VERSION//./_}-${ARCH}-all" BUCKET_NAME="${{ env.BUCKET_NAME }}-${REGION}" LAYER_KEY="$LAYER_NAME/v${{ inputs.package_version }}/lambda-layer.zip" @@ -165,7 +160,7 @@ jobs: PYTHON_VERSION="${{ matrix.python-version }}" ARCH="${{ matrix.architecture }}" REGION="${{ matrix.region }}" - LAYER_NAME="strands-agents-py${PYTHON_VERSION//./_}-${ARCH}" + LAYER_NAME="strands-agents-py${PYTHON_VERSION//./_}-${ARCH}-all" REGION_BUCKET="${{ env.BUCKET_NAME }}-${REGION}" LAYER_KEY="$LAYER_NAME/v${{ inputs.package_version }}/lambda-layer.zip" diff --git a/.github/workflows/yank-lambda-layer.yml b/.github/workflows/yank-lambda-layer.yml new file mode 100644 index 000000000..e0114b6a8 --- /dev/null +++ b/.github/workflows/yank-lambda-layer.yml @@ -0,0 +1,80 @@ +name: Yank Lambda Layer + +on: + workflow_dispatch: + inputs: + layer_version: + description: 'Layer version to yank' + 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 "Yank Lambda Layer" to confirm yanking the layer' + required: true + type: string + +jobs: + yank-layer: + 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: Validate confirmation + run: | + CONFIRM="${{ inputs.confirm }}" + if [ "$CONFIRM" != "Yank Lambda Layer" ]; then + echo "Confirmation failed. You must type exactly 'Yank Lambda Layer' to proceed." + exit 1 + fi + echo "Confirmation validated" + + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: ${{ secrets.STRANDS_LAMBDA_LAYER_PUBLISHER_ROLE }} + aws-region: ${{ matrix.region }} + + - name: Yank layer + run: | + PYTHON_VERSION="${{ matrix.python-version }}" + ARCH="${{ matrix.architecture }}" + REGION="${{ matrix.region }}" + LAYER_NAME="strands-agents-py${PYTHON_VERSION//./_}-${ARCH}-all" + LAYER_VERSION="${{ inputs.layer_version }}" + + echo "Attempting to yank layer $LAYER_NAME version $LAYER_VERSION in region $REGION" + + # Remove public permissions (ignore errors if version doesn't exist) + # Note: This makes the layer private but does not delete it - use delete-layer-version to actually delete + aws lambda remove-layer-version-permission \ + --layer-name $LAYER_NAME \ + --version-number $LAYER_VERSION \ + --statement-id public \ + --region "$REGION" 2>/dev/null || echo "Layer version $LAYER_VERSION not found or already yanked for $LAYER_NAME in $REGION" + + echo "Completed yank attempt for layer $LAYER_NAME version $LAYER_VERSION in region $REGION" \ No newline at end of file From ea3957c9de6fce871c4cf6825f72639bc78ac069 Mon Sep 17 00:00:00 2001 From: Dean Schmigelski Date: Mon, 15 Sep 2025 10:37:09 -0400 Subject: [PATCH 20/31] cleaning --- .github/workflows/publish-lambda-layer.yml | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/.github/workflows/publish-lambda-layer.yml b/.github/workflows/publish-lambda-layer.yml index 6079e946c..97e47385d 100644 --- a/.github/workflows/publish-lambda-layer.yml +++ b/.github/workflows/publish-lambda-layer.yml @@ -32,8 +32,7 @@ on: type: string env: - IS_FULL_DEPLOY: ${{ inputs.python_version == 'ALL' && inputs.architecture == 'ALL' && inputs.region == 'ALL' }} - BUCKET_NAME: strands-agents-lambda-layer-032316178046 + BUCKET_NAME: strands-agents-lambda-layer jobs: create-buckets: @@ -53,7 +52,8 @@ jobs: - name: Create S3 bucket run: | REGION="${{ matrix.region }}" - REGIONAL_BUCKET="${{ env.BUCKET_NAME }}-${REGION}" + ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text) + REGIONAL_BUCKET="${{ env.BUCKET_NAME }}-${ACCOUNT_ID}-${REGION}" if ! aws s3api head-bucket --bucket "$REGIONAL_BUCKET" 2>/dev/null; then if [ "$REGION" = "us-east-1" ]; then @@ -127,7 +127,8 @@ jobs: ARCH="${{ matrix.architecture }}" REGION="${{ matrix.region }}" LAYER_NAME="strands-agents-py${PYTHON_VERSION//./_}-${ARCH}-all" - BUCKET_NAME="${{ env.BUCKET_NAME }}-${REGION}" + ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text) + BUCKET_NAME="${{ env.BUCKET_NAME }}-${ACCOUNT_ID}-${REGION}" LAYER_KEY="$LAYER_NAME/v${{ inputs.package_version }}/lambda-layer.zip" aws s3 cp lambda-layer.zip "s3://$BUCKET_NAME/$LAYER_KEY" --region "$REGION" @@ -142,8 +143,6 @@ jobs: 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)) }} - outputs: - layer-version: ${{ env.LAYER_VERSION }} permissions: id-token: write contents: read @@ -161,7 +160,8 @@ jobs: ARCH="${{ matrix.architecture }}" REGION="${{ matrix.region }}" LAYER_NAME="strands-agents-py${PYTHON_VERSION//./_}-${ARCH}-all" - REGION_BUCKET="${{ env.BUCKET_NAME }}-${REGION}" + ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text) + REGION_BUCKET="${{ env.BUCKET_NAME }}-${ACCOUNT_ID}-${REGION}" LAYER_KEY="$LAYER_NAME/v${{ inputs.package_version }}/lambda-layer.zip" DESCRIPTION="PyPI package: strands-agents v${{ inputs.package_version }} (Python $PYTHON_VERSION, $ARCH)" @@ -189,7 +189,3 @@ jobs: --region "$REGION" echo "Successfully published layer version $LAYER_VERSION in region $REGION" - - if [ "${{ env.IS_FULL_DEPLOY }}" = "true" ] && [ "$REGION" = "us-east-1" ] && [ "$PYTHON_VERSION" = "3.10" ] && [ "$ARCH" = "x86_64" ]; then - echo "LAYER_VERSION=$LAYER_VERSION" >> $GITHUB_ENV - fi From 23a103079fb81204db49aee3f26029dfbac150d8 Mon Sep 17 00:00:00 2001 From: Dean Schmigelski Date: Mon, 15 Sep 2025 10:41:48 -0400 Subject: [PATCH 21/31] edit --- .github/workflows/publish-lambda-layer.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish-lambda-layer.yml b/.github/workflows/publish-lambda-layer.yml index 97e47385d..1152add0b 100644 --- a/.github/workflows/publish-lambda-layer.yml +++ b/.github/workflows/publish-lambda-layer.yml @@ -27,7 +27,7 @@ on: # 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" to confirm publishing the layer' + description: 'Type "Create Lambda Layer {PyPI version}" to confirm publishing the layer' required: true type: string From 495d9164b3cfa885c1a556bbe6969a2fa326de0a Mon Sep 17 00:00:00 2001 From: Dean Schmigelski Date: Mon, 15 Sep 2025 10:44:38 -0400 Subject: [PATCH 22/31] validation --- .github/workflows/publish-lambda-layer.yml | 29 +++++++++++----------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/.github/workflows/publish-lambda-layer.yml b/.github/workflows/publish-lambda-layer.yml index 1152add0b..f372cd519 100644 --- a/.github/workflows/publish-lambda-layer.yml +++ b/.github/workflows/publish-lambda-layer.yml @@ -35,7 +35,21 @@ env: BUCKET_NAME: strands-agents-lambda-layer jobs: + validate: + runs-on: ubuntu-latest + steps: + - name: Validate confirmation + run: | + CONFIRM="${{ inputs.confirm }}" + EXPECTED="Create Lambda Layer ${{ inputs.package_version }}" + if [ "$CONFIRM" != "$EXPECTED" ]; then + echo "Confirmation failed. You must type exactly '$EXPECTED' to proceed." + exit 1 + fi + echo "Confirmation validated" + create-buckets: + needs: validate runs-on: ubuntu-latest strategy: matrix: @@ -77,22 +91,8 @@ jobs: permissions: id-token: write - contents: read steps: - - name: Validate confirmation - run: | - CONFIRM="${{ inputs.confirm }}" - EXPECTED="Create Lambda Layer ${{ inputs.package_version }}" - if [ "$CONFIRM" != "$EXPECTED" ]; then - echo "Confirmation failed. You must type exactly '$EXPECTED' to proceed." - exit 1 - fi - echo "Confirmation validated" - - - name: Checkout current repository - uses: actions/checkout@v4 - - name: Set up Python uses: actions/setup-python@v4 with: @@ -145,7 +145,6 @@ jobs: permissions: id-token: write - contents: read steps: - name: Configure AWS credentials From 334a9edd691221f6f588db53f063cf989999c464 Mon Sep 17 00:00:00 2001 From: Dean Schmigelski Date: Mon, 15 Sep 2025 10:47:17 -0400 Subject: [PATCH 23/31] close --- .github/workflows/publish-lambda-layer.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish-lambda-layer.yml b/.github/workflows/publish-lambda-layer.yml index f372cd519..61a0a4c47 100644 --- a/.github/workflows/publish-lambda-layer.yml +++ b/.github/workflows/publish-lambda-layer.yml @@ -110,7 +110,7 @@ jobs: - name: Download and install package run: | - pip install strands-agents==${{ inputs.package_version }}[all] \ + pip install 'strands-agents==${{ inputs.package_version }}[all]' \ --python-version ${{ matrix.python-version }} \ --platform manylinux2014_${{ matrix.architecture }} \ -t layer/python/ \ From e406ec85a1ab9f4a8bacbca1af6f2ee19880d435 Mon Sep 17 00:00:00 2001 From: Dean Schmigelski Date: Mon, 15 Sep 2025 10:53:36 -0400 Subject: [PATCH 24/31] brackets --- .github/workflows/publish-lambda-layer.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish-lambda-layer.yml b/.github/workflows/publish-lambda-layer.yml index 61a0a4c47..d1d1c4739 100644 --- a/.github/workflows/publish-lambda-layer.yml +++ b/.github/workflows/publish-lambda-layer.yml @@ -110,7 +110,7 @@ jobs: - name: Download and install package run: | - pip install 'strands-agents==${{ inputs.package_version }}[all]' \ + pip install "strands-agents==${{ inputs.package_version }}[all]" \ --python-version ${{ matrix.python-version }} \ --platform manylinux2014_${{ matrix.architecture }} \ -t layer/python/ \ From 7cd48b31f346c91fd2ad11eff2d178b9f32cd999 Mon Sep 17 00:00:00 2001 From: Dean Schmigelski Date: Mon, 15 Sep 2025 11:00:16 -0400 Subject: [PATCH 25/31] optioanl deps --- .github/workflows/publish-lambda-layer.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/publish-lambda-layer.yml b/.github/workflows/publish-lambda-layer.yml index d1d1c4739..53e40ceed 100644 --- a/.github/workflows/publish-lambda-layer.yml +++ b/.github/workflows/publish-lambda-layer.yml @@ -110,11 +110,12 @@ jobs: - name: Download and install package run: | - pip install "strands-agents==${{ inputs.package_version }}[all]" \ + pip install strands-agents==${{ inputs.package_version }} \ --python-version ${{ matrix.python-version }} \ --platform manylinux2014_${{ matrix.architecture }} \ -t layer/python/ \ --only-binary=:all: + --extras "all" - name: Create layer zip run: | From 6a202bf656c64f9e9415f52a177a5d7dacecedc8 Mon Sep 17 00:00:00 2001 From: Dean Schmigelski Date: Mon, 15 Sep 2025 11:13:31 -0400 Subject: [PATCH 26/31] trying again --- .github/workflows/publish-lambda-layer.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/publish-lambda-layer.yml b/.github/workflows/publish-lambda-layer.yml index 53e40ceed..5d9e67fd0 100644 --- a/.github/workflows/publish-lambda-layer.yml +++ b/.github/workflows/publish-lambda-layer.yml @@ -110,12 +110,11 @@ jobs: - name: Download and install package run: | - pip install strands-agents==${{ inputs.package_version }} \ + pip install strands-agents[all]==${{ inputs.package_version }} \ --python-version ${{ matrix.python-version }} \ --platform manylinux2014_${{ matrix.architecture }} \ -t layer/python/ \ --only-binary=:all: - --extras "all" - name: Create layer zip run: | From 92477559e02577d52a098b14544598262f30e1fe Mon Sep 17 00:00:00 2001 From: Dean Schmigelski Date: Mon, 15 Sep 2025 11:55:25 -0400 Subject: [PATCH 27/31] filter grpc --- .github/workflows/publish-lambda-layer.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/publish-lambda-layer.yml b/.github/workflows/publish-lambda-layer.yml index 5d9e67fd0..c3f551005 100644 --- a/.github/workflows/publish-lambda-layer.yml +++ b/.github/workflows/publish-lambda-layer.yml @@ -115,6 +115,10 @@ jobs: --platform manylinux2014_${{ matrix.architecture }} \ -t layer/python/ \ --only-binary=:all: + - name: Remove grpc files to reduce size + run: | + find layer/python -name "*grpc*" -type f -delete + find layer/python -name "*grpc*" -type d -exec rm -rf {} + 2>/dev/null || true - name: Create layer zip run: | From d993008be157574c04132edee4c27f797cd92f43 Mon Sep 17 00:00:00 2001 From: Dean Schmigelski Date: Mon, 15 Sep 2025 12:24:33 -0400 Subject: [PATCH 28/31] just standard --- .github/workflows/LAMBDA_LAYERS_SOP.md | 2 +- .github/workflows/publish-lambda-layer.yml | 10 +++------- .github/workflows/yank-lambda-layer.yml | 2 +- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/.github/workflows/LAMBDA_LAYERS_SOP.md b/.github/workflows/LAMBDA_LAYERS_SOP.md index 6ad391d49..17a34b00d 100644 --- a/.github/workflows/LAMBDA_LAYERS_SOP.md +++ b/.github/workflows/LAMBDA_LAYERS_SOP.md @@ -13,7 +13,7 @@ This document defines the standard operating procedures for managing Strands Age 2. Specify PyPI package version 3. Type "Create Lambda Layer {package_version}" to confirm 4. All 136 individual layers deploy in parallel (4 Python × 2 arch × 17 regions) -5. Each layer gets its own unique name: `strands-agents-py{PYTHON_VERSION}-{ARCH}-all` +5. Each layer gets its own unique name: `strands-agents-py{PYTHON_VERSION}-{ARCH}` ### 2. Version Buffering for New Variants When adding new variants (new Python version, architecture, or region): diff --git a/.github/workflows/publish-lambda-layer.yml b/.github/workflows/publish-lambda-layer.yml index c3f551005..8391337d2 100644 --- a/.github/workflows/publish-lambda-layer.yml +++ b/.github/workflows/publish-lambda-layer.yml @@ -110,15 +110,11 @@ jobs: - name: Download and install package run: | - pip install strands-agents[all]==${{ inputs.package_version }} \ + pip install strands-agents==${{ inputs.package_version }} \ --python-version ${{ matrix.python-version }} \ --platform manylinux2014_${{ matrix.architecture }} \ -t layer/python/ \ --only-binary=:all: - - name: Remove grpc files to reduce size - run: | - find layer/python -name "*grpc*" -type f -delete - find layer/python -name "*grpc*" -type d -exec rm -rf {} + 2>/dev/null || true - name: Create layer zip run: | @@ -130,7 +126,7 @@ jobs: PYTHON_VERSION="${{ matrix.python-version }}" ARCH="${{ matrix.architecture }}" REGION="${{ matrix.region }}" - LAYER_NAME="strands-agents-py${PYTHON_VERSION//./_}-${ARCH}-all" + LAYER_NAME="strands-agents-py${PYTHON_VERSION//./_}-${ARCH}" ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text) BUCKET_NAME="${{ env.BUCKET_NAME }}-${ACCOUNT_ID}-${REGION}" LAYER_KEY="$LAYER_NAME/v${{ inputs.package_version }}/lambda-layer.zip" @@ -162,7 +158,7 @@ jobs: PYTHON_VERSION="${{ matrix.python-version }}" ARCH="${{ matrix.architecture }}" REGION="${{ matrix.region }}" - LAYER_NAME="strands-agents-py${PYTHON_VERSION//./_}-${ARCH}-all" + LAYER_NAME="strands-agents-py${PYTHON_VERSION//./_}-${ARCH}" ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text) REGION_BUCKET="${{ env.BUCKET_NAME }}-${ACCOUNT_ID}-${REGION}" LAYER_KEY="$LAYER_NAME/v${{ inputs.package_version }}/lambda-layer.zip" diff --git a/.github/workflows/yank-lambda-layer.yml b/.github/workflows/yank-lambda-layer.yml index e0114b6a8..3a6ff14cd 100644 --- a/.github/workflows/yank-lambda-layer.yml +++ b/.github/workflows/yank-lambda-layer.yml @@ -64,7 +64,7 @@ jobs: PYTHON_VERSION="${{ matrix.python-version }}" ARCH="${{ matrix.architecture }}" REGION="${{ matrix.region }}" - LAYER_NAME="strands-agents-py${PYTHON_VERSION//./_}-${ARCH}-all" + LAYER_NAME="strands-agents-py${PYTHON_VERSION//./_}-${ARCH}" LAYER_VERSION="${{ inputs.layer_version }}" echo "Attempting to yank layer $LAYER_NAME version $LAYER_VERSION in region $REGION" From 075c154fbe1cd88d5da66a5e5a61f99e2c4a2e25 Mon Sep 17 00:00:00 2001 From: Dean Schmigelski Date: Mon, 15 Sep 2025 12:42:10 -0400 Subject: [PATCH 29/31] yank --- .github/workflows/LAMBDA_LAYERS_SOP.md | 14 ++++++++------ .github/workflows/publish-lambda-layer.yml | 8 ++++++++ .github/workflows/yank-lambda-layer.yml | 17 +++++++++-------- 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/.github/workflows/LAMBDA_LAYERS_SOP.md b/.github/workflows/LAMBDA_LAYERS_SOP.md index 17a34b00d..f8a10b930 100644 --- a/.github/workflows/LAMBDA_LAYERS_SOP.md +++ b/.github/workflows/LAMBDA_LAYERS_SOP.md @@ -34,9 +34,11 @@ When some regions fail during deployment: ### Yank Procedure 1. Use the `yank_lambda_layer` GitHub action workflow -2. **Full yank**: Run with ALL options selected (default) to yank all 136 variants -3. **Partial yank**: Specify Python versions, architectures, and regions for targeted yanking -4. **Update documentation**: Remove or mark the row as yanked in lambda-layers.md -5. **Communication**: Notify users through appropriate channels - -**Note**: Yanking removes public permissions making layers private but does not delete them. Use `delete-layer-version` to actually delete layer versions. \ No newline at end of file +2. Specify the layer version to yank +3. Type "Yank Lambda Layer {layer_version}" to confirm +4. **Full yank**: Run with ALL options selected (default) to yank all 136 variants +5. **Partial yank**: Specify Python versions, architectures, and regions for targeted yanking +6. **Update documentation**: Remove or mark the row as yanked in lambda-layers.md +7. **Communication**: Notify users through appropriate channels + +**Note**: Yanking deletes layer versions completely. Existing Lambda functions using the layer continue to work, but new functions cannot use the yanked version. \ No newline at end of file diff --git a/.github/workflows/publish-lambda-layer.yml b/.github/workflows/publish-lambda-layer.yml index 8391337d2..b4bceca83 100644 --- a/.github/workflows/publish-lambda-layer.yml +++ b/.github/workflows/publish-lambda-layer.yml @@ -165,11 +165,19 @@ jobs: 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) diff --git a/.github/workflows/yank-lambda-layer.yml b/.github/workflows/yank-lambda-layer.yml index 3a6ff14cd..27927a862 100644 --- a/.github/workflows/yank-lambda-layer.yml +++ b/.github/workflows/yank-lambda-layer.yml @@ -27,14 +27,16 @@ on: # 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 "Yank Lambda Layer" to confirm yanking the layer' + description: 'Type "Yank Lambda Layer {layer version}" to confirm yanking the layer' required: true type: string jobs: yank-layer: runs-on: ubuntu-latest + continue-on-error: true strategy: + fail-fast: false 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)) }} @@ -47,8 +49,9 @@ jobs: - name: Validate confirmation run: | CONFIRM="${{ inputs.confirm }}" - if [ "$CONFIRM" != "Yank Lambda Layer" ]; then - echo "Confirmation failed. You must type exactly 'Yank Lambda Layer' to proceed." + EXPECTED="Yank Lambda Layer ${{ inputs.layer_version }}" + if [ "$CONFIRM" != "$EXPECTED" ]; then + echo "Confirmation failed. You must type exactly '$EXPECTED' to proceed." exit 1 fi echo "Confirmation validated" @@ -69,12 +72,10 @@ jobs: echo "Attempting to yank layer $LAYER_NAME version $LAYER_VERSION in region $REGION" - # Remove public permissions (ignore errors if version doesn't exist) - # Note: This makes the layer private but does not delete it - use delete-layer-version to actually delete - aws lambda remove-layer-version-permission \ + # Delete the layer version completely + aws lambda delete-layer-version \ --layer-name $LAYER_NAME \ --version-number $LAYER_VERSION \ - --statement-id public \ - --region "$REGION" 2>/dev/null || echo "Layer version $LAYER_VERSION not found or already yanked for $LAYER_NAME in $REGION" + --region "$REGION" echo "Completed yank attempt for layer $LAYER_NAME version $LAYER_VERSION in region $REGION" \ No newline at end of file From 6e2e752c571e6cdf3ee1a4fc8eebace8f9ca9d96 Mon Sep 17 00:00:00 2001 From: Dean Schmigelski Date: Thu, 23 Oct 2025 16:17:52 -0400 Subject: [PATCH 30/31] Update STYLE_GUIDE.md --- STYLE_GUIDE.md | 1 + 1 file changed, 1 insertion(+) diff --git a/STYLE_GUIDE.md b/STYLE_GUIDE.md index 51dc0a73a..2f7113713 100644 --- a/STYLE_GUIDE.md +++ b/STYLE_GUIDE.md @@ -6,6 +6,7 @@ The Strands Agents style guide aims to establish consistent formatting, naming c Where possible, we will codify these style guidelines into our linting rules and pre-commit hooks to automate enforcement and reduce the manual review burden. + ## Log Formatting The format for Strands Agents logs is as follows: From dd5fd58828512819540d7085e8ef5d9ebdba6666 Mon Sep 17 00:00:00 2001 From: Dean Schmigelski Date: Thu, 23 Oct 2025 16:43:38 -0400 Subject: [PATCH 31/31] Update STYLE_GUIDE.md --- STYLE_GUIDE.md | 1 - 1 file changed, 1 deletion(-) diff --git a/STYLE_GUIDE.md b/STYLE_GUIDE.md index 2f7113713..51dc0a73a 100644 --- a/STYLE_GUIDE.md +++ b/STYLE_GUIDE.md @@ -6,7 +6,6 @@ The Strands Agents style guide aims to establish consistent formatting, naming c Where possible, we will codify these style guidelines into our linting rules and pre-commit hooks to automate enforcement and reduce the manual review burden. - ## Log Formatting The format for Strands Agents logs is as follows: