Skip to content

Commit 50f22e2

Browse files
committed
automated the layer creation in china and govcloud region
1 parent ddad329 commit 50f22e2

File tree

2 files changed

+143
-116
lines changed

2 files changed

+143
-116
lines changed

.github/workflows/layers_partitions.yml

Lines changed: 30 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -27,36 +27,15 @@
2727
on:
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

5837
name: Layer Deployment (Partitions)
59-
run-name: Layer Deployment (${{ inputs.partition }}) - ${{ inputs.environment }} / Version - ${{ inputs.version }}
38+
run-name: Layer Deployment (${{ inputs.partition }})
6039

6140
permissions:
6241
contents: read
@@ -98,9 +77,15 @@ jobs:
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
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
name: Copy Layer
2+
3+
on:
4+
workflow_call:
5+
inputs:
6+
environment:
7+
required: true
8+
type: string
9+
partition:
10+
required: true
11+
type: string
12+
regions:
13+
required: true
14+
type: string
15+
aud:
16+
required: true
17+
type: string
18+
19+
jobs:
20+
# 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.
21+
deploy:
22+
name: Deploy ${{ inputs.partition }} - ${{ inputs.environment }}
23+
runs-on: ubuntu-latest
24+
permissions:
25+
id-token: write
26+
contents: read
27+
environment: ${{ inputs.partition }} ${{ inputs.environment }}
28+
strategy:
29+
matrix:
30+
region: ${{ fromJson(inputs.regions) }}
31+
steps:
32+
- name: Download Zip
33+
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53
34+
with:
35+
name: AWSLambdaPowertoolsTypeScriptV2.zip
36+
37+
- name: Download Metadata
38+
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53
39+
with:
40+
name: AWSLambdaPowertoolsTypeScriptV2.json
41+
42+
- name: Verify Layer Signature
43+
run: |
44+
SHA=$(jq -r '.Content.CodeSha256' 'AWSLambdaPowertoolsTypeScriptV2.json')
45+
test "$(openssl dgst -sha256 -binary AWSLambdaPowertoolsTypeScriptV2.zip | openssl enc -base64)" == "$SHA" && echo "SHA OK: ${SHA}" || exit 1
46+
47+
- id: transform
48+
run: echo "CONVERTED_REGION=$(echo '${{ matrix.region }}' | tr 'a-z\-' 'A-Z_')" >> "$GITHUB_OUTPUT"
49+
50+
- name: Configure AWS Credentials
51+
uses: aws-actions/configure-aws-credentials@61815dcd50bd041e203e49132bacad1fd04d2708
52+
with:
53+
role-to-assume: ${{ secrets[format('IAM_ROLE_{0}', steps.transform.outputs.CONVERTED_REGION)] }}
54+
aws-region: ${{ matrix.region }}
55+
mask-aws-account-id: true
56+
audience: ${{ inputs.aud }}
57+
58+
- name: Create Layer
59+
id: create-layer
60+
run: |
61+
set -euo pipefail
62+
jq '{"LayerName": "AWSLambdaPowertoolsTypeScriptV2", "Description": .Description, "CompatibleRuntimes": .CompatibleRuntimes, "LicenseInfo": .LicenseInfo}' AWSLambdaPowertoolsTypeScriptV2.json > input.json
63+
64+
LAYER_VERSION=$(aws --region "${{ matrix.region }}" lambda publish-layer-version \
65+
--zip-file fileb://./AWSLambdaPowertoolsTypeScriptV2.zip \
66+
--cli-input-json file://./input.json \
67+
--query 'Version' --output text)
68+
69+
echo "LAYER_VERSION=$LAYER_VERSION" >> "$GITHUB_OUTPUT"
70+
71+
aws --region "${{ matrix.region }}" lambda add-layer-version-permission \
72+
--layer-name 'AWSLambdaPowertoolsTypeScriptV2' \
73+
--statement-id 'PublicLayer' \
74+
--action lambda:GetLayerVersion \
75+
--principal '*' \
76+
--version-number "$LAYER_VERSION"
77+
78+
- name: Verify Layer
79+
env:
80+
LAYER_VERSION: ${{ steps.create-layer.outputs.LAYER_VERSION }}
81+
ENVIRONMENT: ${{ inputs.environment }}
82+
run: |
83+
set -euo pipefail
84+
layer_output="AWSLambdaPowertoolsTypeScriptV2-${{ matrix.region }}.json"
85+
86+
aws --region "${{ matrix.region }}" lambda get-layer-version-by-arn \
87+
--arn "arn:${{ inputs.partition }}:lambda:${{ matrix.region }}:${{ secrets[format('AWS_ACCOUNT_{0}', steps.transform.outputs.CONVERTED_REGION)] }}:layer:AWSLambdaPowertoolsTypeScriptV2:${LAYER_VERSION}" \
88+
> "$layer_output"
89+
90+
REMOTE_SHA=$(jq -r '.Content.CodeSha256' "$layer_output")
91+
LOCAL_SHA=$(jq -r '.Content.CodeSha256' AWSLambdaPowertoolsTypeScriptV2.json)
92+
test "$REMOTE_SHA" == "$LOCAL_SHA" && echo "SHA OK: ${LOCAL_SHA}" || exit 1
93+
94+
REMOTE_DESCRIPTION=$(jq -r '.Description' "$layer_output")
95+
LOCAL_DESCRIPTION=$(jq -r '.Description' AWSLambdaPowertoolsTypeScriptV2.json)
96+
test "$REMOTE_DESCRIPTION" == "$LOCAL_DESCRIPTION" && echo "Version number OK: ${LOCAL_DESCRIPTION}" || exit 1
97+
98+
if [ "$ENVIRONMENT" == "Prod" ]; then
99+
REMOTE_LAYER_VERSION=$(jq -r '.LayerVersionArn' "$layer_output" | sed 's/.*://')
100+
LOCAL_LAYER_VERSION=$(jq -r '.LayerVersionArn' AWSLambdaPowertoolsTypeScriptV2.json | sed 's/.*://')
101+
test "$REMOTE_LAYER_VERSION" == "$LOCAL_LAYER_VERSION" && echo "Layer Version number OK: ${LOCAL_LAYER_VERSION}" || exit 1
102+
fi
103+
104+
jq -s -r '["Layer Arn", "Runtimes", "Version", "Description", "SHA256"], ([.[0], .[1]] | .[] | [.LayerArn, (.CompatibleRuntimes | join("/")), .Version, .Description, .Content.CodeSha256]) |@tsv' \
105+
AWSLambdaPowertoolsTypeScriptV2.json "$layer_output" | column -t -s $'\t'
106+
107+
- name: Store Metadata
108+
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4
109+
with:
110+
name: AWSLambdaPowertoolsTypeScriptV2-${{ inputs.environment }}-${{ matrix.region }}.json
111+
path: AWSLambdaPowertoolsTypeScriptV2-${{ matrix.region }}.json
112+
retention-days: 1
113+
if-no-files-found: error

0 commit comments

Comments
 (0)