2727on :
2828 workflow_dispatch :
2929 inputs :
30- environment :
31- description : Deployment environment
32- type : choice
33- options :
34- - Gamma
35- - Prod
36- required : true
37- version :
38- description : Layer version to duplicate
39- type : string
40- required : true
4130 partition :
4231 description : Partition to deploy to
4332 type : choice
4433 options :
4534 - China
4635 - GovCloud
47- workflow_call :
48- inputs :
49- environment :
50- description : Deployment environment
51- type : string
52- required : true
53- version :
54- description : Layer version to duplicate
55- type : string
56- required : true
5736
5837name : Layer Deployment (Partitions)
59- run-name : Layer Deployment (${{ inputs.partition }}) - ${{ inputs.environment }} / Version - ${{ inputs.version }}
38+ run-name : Layer Deployment (${{ inputs.partition }})
6039
6140permissions :
6241 contents : read
9877 role-to-assume : ${{ secrets.AWS_IAM_ROLE }}
9978 aws-region : us-east-1
10079 mask-aws-account-id : true
80+ - name : Get Latest Layer Version
81+ id : get_latest_layer_version
82+ run : |
83+ set -euo pipefail
84+ LAYER_VERSION=$(aws lambda list-layer-versions --layer-name AWSLambdaPowertoolsTypeScriptV2 --query 'LayerVersions[0].Version' --output text)
85+ echo "LAYER_VERSION=$LAYER_VERSION" >> $GITHUB_OUTPUT
10186 - name : Grab Zip
10287 env :
103- VERSION : ${{ inputs.version }}
88+ VERSION : ${{ steps.get_latest_layer_version.outputs.LAYER_VERSION }}
10489 run : |
10590 set -euo pipefail
10691 aws --region us-east-1 lambda get-layer-version-by-arn --arn "arn:aws:lambda:us-east-1:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:${VERSION}" --query 'Content.Location' | xargs curl -L -o AWSLambdaPowertoolsTypeScriptV2.zip
@@ -119,96 +104,25 @@ jobs:
119104 path : AWSLambdaPowertoolsTypeScriptV2.json
120105 retention-days : 1
121106 if-no-files-found : error
122- # 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.
123- copy :
124- name : Copy
125- needs :
126- - setup
127- - download
128- runs-on : ubuntu-latest
129- permissions :
130- id-token : write
131- contents : read
132- # Environment should interperlate as "GovCloud Prod" or "China Beta"
133- environment : ${{ inputs.partition }} ${{ inputs.environment }}
134- strategy :
135- matrix :
136- region : ${{ fromJson(needs.setup.outputs.regions) }}
137- steps :
138- - name : Download Zip
139- uses : actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
140- with :
141- name : AWSLambdaPowertoolsTypeScriptV2.zip
142- - name : Download Metadata
143- uses : actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
144- with :
145- name : AWSLambdaPowertoolsTypeScriptV2.json
146- - name : Verify Layer Signature
147- run : |
148- SHA=$(jq -r '.Content.CodeSha256' 'AWSLambdaPowertoolsTypeScriptV2.json')
149- test "$(openssl dgst -sha256 -binary AWSLambdaPowertoolsTypeScriptV2.zip | openssl enc -base64)" == "$SHA" && echo "SHA OK: ${SHA}" || exit 1
150- - id : transform
151- run : |
152- echo 'CONVERTED_REGION=${{ matrix.region }}' | tr 'a-z\-' 'A-Z_' >> "$GITHUB_OUTPUT"
153- - name : Configure AWS Credentials
154- uses : aws-actions/configure-aws-credentials@61815dcd50bd041e203e49132bacad1fd04d2708 # v5.1.1
155- with :
156- # Dynamic secret access is safe here - secrets are scoped per environment
157- role-to-assume : ${{ secrets[format('IAM_ROLE_{0}', steps.transform.outputs.CONVERTED_REGION)] }}
158- aws-region : ${{ matrix.region}}
159- mask-aws-account-id : true
160- audience : ${{ needs.setup.outputs.aud }}
161- - name : Create Layer
162- id : create-layer
163- run : |
164- set -euo pipefail
165- cat AWSLambdaPowertoolsTypeScriptV2.json | jq '{"LayerName": "AWSLambdaPowertoolsTypeScriptV2", "Description": .Description, "CompatibleRuntimes": .CompatibleRuntimes, "LicenseInfo": .LicenseInfo}' > input.json
166-
167- LAYER_VERSION=$(aws --region "${{ matrix.region }}" lambda publish-layer-version \
168- --zip-file fileb://./AWSLambdaPowertoolsTypeScriptV2.zip \
169- --cli-input-json file://./input.json \
170- --query 'Version' \
171- --output text)
172-
173- echo "LAYER_VERSION=$LAYER_VERSION" >> "$GITHUB_OUTPUT"
174-
175- aws --region "${{ matrix.region }}" lambda add-layer-version-permission \
176- --layer-name 'AWSLambdaPowertoolsTypeScriptV2' \
177- --statement-id 'PublicLayer' \
178- --action lambda:GetLayerVersion \
179- --principal '*' \
180- --version-number "$LAYER_VERSION"
181- # This step retrieves the newly deployed layer metadata and compares it against the original source layer:
182- # 1. SHA256 hash verification - ensures the layer content is identical to the source
183- # 2. Description validation - confirms the version number in the description matches the source
184- # 3. Layer Version number verification - validates that the layer version numbers match between source and target
185- # 4. Tabular comparison output - displays side-by-side comparison of key layer properties
186- - name : Verify Layer
187- env :
188- LAYER_VERSION : ${{ steps.create-layer.outputs.LAYER_VERSION }}
189- ENVIRONMENT : ${{ inputs.environment }}
190- run : |
191- set -euo pipefail
192- export layer_output="AWSLambdaPowertoolsTypeScriptV2-${{ matrix.region }}.json"
193- # Dynamic secret access is safe here - secrets are scoped per environment
194- 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:${LAYER_VERSION}" > "$layer_output"
195- REMOTE_SHA=$(jq -r '.Content.CodeSha256' $layer_output)
196- LOCAL_SHA=$(jq -r '.Content.CodeSha256' AWSLambdaPowertoolsTypeScriptV2.json)
197- test "$REMOTE_SHA" == "$LOCAL_SHA" && echo "SHA OK: ${LOCAL_SHA}" || exit 1
198- REMOTE_DESCRIPTION=$(jq -r '.Description' $layer_output)
199- LOCAL_DESCRIPTION=$(jq -r '.Description' AWSLambdaPowertoolsTypeScriptV2.json)
200- test "$REMOTE_DESCRIPTION" == "$LOCAL_DESCRIPTION" && echo "Version number OK: ${LOCAL_DESCRIPTION}" || exit 1
201- if [ "$ENVIRONMENT" == "Prod" ]; then
202- REMOTE_LAYER_VERSION=$(jq -r '.LayerVersionArn' $layer_output | sed 's/.*://')
203- LOCAL_LAYER_VERSION=$(jq -r '.LayerVersionArn' AWSLambdaPowertoolsTypeScriptV2.json | sed 's/.*://')
204- test "$REMOTE_LAYER_VERSION" == "$LOCAL_LAYER_VERSION" && echo "Layer Version number OK: ${LOCAL_LAYER_VERSION}" || exit 1
205- fi
206- 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'
207-
208- - name : Store Metadata - ${{ matrix.region }}
209- uses : actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
210- with :
211- name : AWSLambdaPowertoolsTypeScriptV2-${{ matrix.region }}.json
212- path : AWSLambdaPowertoolsTypeScriptV2-${{ matrix.region }}.json
213- retention-days : 1
214- if-no-files-found : error
107+ # Copies the Layer to the Gamma Environment in the selected partition
108+ deploy-gamma :
109+ name : Deploy Gamma Layer
110+ needs : [setup, download]
111+ uses : ./.github/workflows/layers_partitions_deploy.yml
112+ with :
113+ environment : Gamma
114+ partition : ${{ inputs.partition }}
115+ regions : ${{ needs.setup.outputs.regions }}
116+ aud : ${{ needs.setup.outputs.aud }}
117+ secrets : inherit
118+ # Copies the Layer to the Gamma Environment in the selected partition
119+ deploy-prod :
120+ name : Deploy Prod Layer
121+ needs : [setup, download, deploy-gamma]
122+ uses : ./.github/workflows/layers_partitions_deploy.yml
123+ with :
124+ environment : Prod
125+ partition : ${{ inputs.partition }}
126+ regions : ${{ needs.setup.outputs.regions }}
127+ aud : ${{ needs.setup.outputs.aud }}
128+ secrets : inherit
0 commit comments