Skip to content

Layer Deployment (China) - Gamma / Version - 34 #80

Layer Deployment (China) - Gamma / Version - 34

Layer Deployment (China) - Gamma / Version - 34 #80

# Partitioned Layer Publish
# ---
# This workflow publishes a specific layer version in an AWS account based on the environment input.
#
# We pull each the version of the layer and store them as artifacts, the we upload them to each of the Partitioned AWS accounts.
#
# A number of safety checks are performed to ensure safety.
#
# === Automated activities ===
# 1. [Setup] configure partition-specific regions, partition names, and STS audience based on target partition (China/GovCloud)
# 2. [Download] retrieve the specified layer version from the main AWS partition (us-east-1) and store as artifacts
# 3. [Copy & Verify] deploy the layer to all regions in the target partition and validate layer deployment by comparing SHA256, description, and version numbers
#
# === Manual activities ===
# 1. After the `make-release` workflow finishes and the PR for the documentation update gets created, trigger this workflow manually via `workflow_dispatch` with environment, version, and partition inputs for each Gamma and Prod environment in the China and GovCloud partitions
# 2. Monitor deployment progress and verify successful layer publication across all target regions
# 3. Once this workflow is completed, the PR for the documentation update can me merged
on:
workflow_dispatch:
inputs:
environment:
description: Deployment environment
type: choice
options:
- Gamma
- Prod
required: true
version:
description: Layer version to duplicate
type: string
required: true
partition:
description: Partition to deploy to
type: choice
options:
- China
- GovCloud
workflow_call:
inputs:
environment:
description: Deployment environment
type: string
required: true
version:
description: Layer version to duplicate
type: string
required: true
name: Layer Deployment (Partitions)
run-name: Layer Deployment (${{ inputs.partition }}) - ${{ inputs.environment }} / Version - ${{ inputs.version }}
permissions:
contents: read
jobs:
# This job configures partition-specific settings including regions, partition names, and STS audience based on the target partition (China or GovCloud) selected in the workflow inputs.
setup:
runs-on: ubuntu-latest
outputs:
regions: ${{ format('{0}{1}', steps.regions_china.outputs.regions, steps.regions_govcloud.outputs.regions) }}
partition: ${{ format('{0}{1}', steps.regions_china.outputs.partition, steps.regions_govcloud.outputs.partition) }}
aud: ${{ format('{0}{1}', steps.regions_china.outputs.aud, steps.regions_govcloud.outputs.aud) }}
steps:
- id: regions_china
name: Partition (China)
if: ${{ inputs.partition == 'China' }}
run: |
echo regions='["cn-north-1"]'>> "$GITHUB_OUTPUT"
echo partition='aws-cn'>> "$GITHUB_OUTPUT"
echo aud='sts.amazonaws.com.cn'>> "$GITHUB_OUTPUT"
- id: regions_govcloud
name: Partition (GovCloud)
if: ${{ inputs.partition == 'GovCloud' }}
run: |
echo regions='["us-gov-east-1", "us-gov-west-1"]'>> "$GITHUB_OUTPUT"
echo partition='aws-us-gov'>> "$GITHUB_OUTPUT"
echo aud='sts.amazonaws.com'>> "$GITHUB_OUTPUT"
# This job downloads the specified layer version from the main AWS partition (us-east-1) and stores both the layer zip file and metadata as GitHub Actions artifacts for use in deployment.
download:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
environment: Prod (Readonly)
steps:
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@7474bc4690e29a8392af63c5b98e7449536d5c3a # v4.3.1
with:
role-to-assume: ${{ secrets.AWS_IAM_ROLE }}
aws-region: us-east-1
mask-aws-account-id: true
- name: Grab Zip
run: |
aws --region us-east-1 lambda get-layer-version-by-arn --arn arn:aws:lambda:us-east-1:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:${{ inputs.version }} --query 'Content.Location' | xargs curl -L -o AWSLambdaPowertoolsTypeScriptV2.zip
aws --region us-east-1 lambda get-layer-version-by-arn --arn arn:aws:lambda:us-east-1:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:${{ inputs.version }} > AWSLambdaPowertoolsTypeScriptV2.json
- name: Store Zip
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: AWSLambdaPowertoolsTypeScriptV2.zip
path: AWSLambdaPowertoolsTypeScriptV2.zip
retention-days: 1
if-no-files-found: error
- name: Store Metadata
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: AWSLambdaPowertoolsTypeScriptV2.json
path: AWSLambdaPowertoolsTypeScriptV2.json
retention-days: 1
if-no-files-found: error
# This job deploys the layer to all regions in the target partition using a matrix strategy. It performs integrity checks, publishes the layer, sets public permissions, and validates deployment.
copy:
name: Copy
needs:
- setup
- download
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
# Environment should interperlate as "GovCloud Prod" or "China Beta"
environment: ${{ inputs.partition }} ${{ inputs.environment }}
strategy:
matrix:
region: ${{ fromJson(needs.setup.outputs.regions) }}
steps:
- name: Download Zip
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
with:
name: AWSLambdaPowertoolsTypeScriptV2.zip
- name: Download Metadata
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
with:
name: AWSLambdaPowertoolsTypeScriptV2.json
- name: Verify Layer Signature
run: |
SHA=$(jq -r '.Content.CodeSha256' 'AWSLambdaPowertoolsTypeScriptV2.json')
test "$(openssl dgst -sha256 -binary AWSLambdaPowertoolsTypeScriptV2.zip | openssl enc -base64)" == "$SHA" && echo "SHA OK: ${SHA}" || exit 1
- id: transform
run: |
echo 'CONVERTED_REGION=${{ matrix.region }}' | tr 'a-z\-' 'A-Z_' >> "$GITHUB_OUTPUT"
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@7474bc4690e29a8392af63c5b98e7449536d5c3a # v4.3.1
with:
role-to-assume: ${{ secrets[format('IAM_ROLE_{0}', steps.transform.outputs.CONVERTED_REGION)] }}
aws-region: ${{ matrix.region}}
mask-aws-account-id: true
audience: ${{ needs.setup.outputs.aud }}
- name: Create Layer
id: create-layer
run: |
cat AWSLambdaPowertoolsTypeScriptV2.json | jq '{"LayerName": "AWSLambdaPowertoolsTypeScriptV2", "Description": .Description, "CompatibleRuntimes": .CompatibleRuntimes, "LicenseInfo": .LicenseInfo}' > input.json
LAYER_VERSION=$(aws --region ${{ matrix.region}} lambda publish-layer-version \
--zip-file fileb://./AWSLambdaPowertoolsTypeScriptV2.zip \
--cli-input-json file://./input.json \
--query 'Version' \
--output text)
echo "LAYER_VERSION=$LAYER_VERSION" >> "$GITHUB_OUTPUT"
aws --region ${{ matrix.region}} lambda add-layer-version-permission \
--layer-name 'AWSLambdaPowertoolsTypeScriptV2' \
--statement-id 'PublicLayer' \
--action lambda:GetLayerVersion \
--principal '*' \
--version-number "$LAYER_VERSION"
# This step retrieves the newly deployed layer metadata and compares it against the original source layer:
# 1. SHA256 hash verification - ensures the layer content is identical to the source
# 2. Description validation - confirms the version number in the description matches the source
# 3. Layer Version number verification - validates that the layer version numbers match between source and target
# 4. Tabular comparison output - displays side-by-side comparison of key layer properties
- name: Verify Layer
env:
LAYER_VERSION: ${{ steps.create-layer.outputs.LAYER_VERSION }}
run: |
export layer_output='AWSLambdaPowertoolsTypeScriptV2-${{matrix.region}}.json'
aws --region ${{ matrix.region}} lambda get-layer-version-by-arn --arn 'arn:${{ needs.setup.outputs.partition }}:lambda:${{ matrix.region}}:${{ secrets[format('AWS_ACCOUNT_{0}', steps.transform.outputs.CONVERTED_REGION)] }}:layer:AWSLambdaPowertoolsTypeScriptV2:${{ env.LAYER_VERSION }}' > $layer_output
REMOTE_SHA=$(jq -r '.Content.CodeSha256' $layer_output)
LOCAL_SHA=$(jq -r '.Content.CodeSha256' AWSLambdaPowertoolsTypeScriptV2.json)
test "$REMOTE_SHA" == "$LOCAL_SHA" && echo "SHA OK: ${LOCAL_SHA}" || exit 1
REMOTE_DESCRIPTION=$(jq -r '.Description' $layer_output)
LOCAL_DESCRIPTION=$(jq -r '.Description' AWSLambdaPowertoolsTypeScriptV2.json)
test "$REMOTE_DESCRIPTION" == "$LOCAL_DESCRIPTION" && echo "Version number OK: ${LOCAL_DESCRIPTION}" || exit 1
if [ "${{ inputs.environment }}" == "Prod" ]; then
REMOTE_LAYER_VERSION=$(jq -r '.LayerVersionArn' $layer_output | sed 's/.*://')
LOCAL_LAYER_VERSION=$(jq -r '.LayerVersionArn' AWSLambdaPowertoolsTypeScriptV2.json | sed 's/.*://')
test "$REMOTE_LAYER_VERSION" == "$LOCAL_LAYER_VERSION" && echo "Layer Version number OK: ${LOCAL_LAYER_VERSION}" || exit 1
fi
jq -s -r '["Layer Arn", "Runtimes", "Version", "Description", "SHA256"], ([.[0], .[1]] | .[] | [.LayerArn, (.CompatibleRuntimes | join("/")), .Version, .Description, .Content.CodeSha256]) |@tsv' AWSLambdaPowertoolsTypeScriptV2.json $layer_output | column -t -s $'\t'
- name: Store Metadata - ${{ matrix.region }}
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: AWSLambdaPowertoolsTypeScriptV2-${{ matrix.region }}.json
path: AWSLambdaPowertoolsTypeScriptV2-${{ matrix.region }}.json
retention-days: 1
if-no-files-found: error