Layer Deployment (China) - Gamma / Version - 34 #80
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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 |