Skip to content

Commit 0464f46

Browse files
feat(layer): publish SAR v2 via Github actions (#1585)
Co-authored-by: Heitor Lessa <[email protected]>
1 parent f63d437 commit 0464f46

File tree

7 files changed

+243
-46
lines changed

7 files changed

+243
-46
lines changed

.github/workflows/publish_v2_layer.yml

+26-4
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ on:
88
workflow_dispatch:
99
inputs:
1010
latest_published_version:
11-
description: "Latest PyPi published version to rebuild latest docs for, e.g. v1.22.0"
12-
default: "v2.0.0"
11+
description: "Latest PyPi published version to rebuild latest docs for, e.g. v2.0.0"
1312
required: true
1413
# workflow_run:
1514
# workflows: ["Publish to PyPi"]
@@ -23,6 +22,8 @@ jobs:
2322
defaults:
2423
run:
2524
working-directory: ./layer
25+
outputs:
26+
release-tag-version: ${{ steps.release-notes-tag.outputs.RELEASE_TAG_VERSION }}
2627
steps:
2728
- name: checkout
2829
uses: actions/checkout@v3
@@ -46,11 +47,12 @@ jobs:
4647
poetry export --format requirements.txt --output requirements.txt
4748
pip install -r requirements.txt
4849
- name: Set release notes tag
50+
id: release-notes-tag
4951
run: |
5052
RELEASE_INPUT=${{ inputs.latest_published_version }}
5153
LATEST_TAG=$(git describe --tag --abbrev=0)
5254
RELEASE_TAG_VERSION=${RELEASE_INPUT:-$LATEST_TAG}
53-
echo RELEASE_TAG_VERSION="${RELEASE_TAG_VERSION:1}" >> "$GITHUB_ENV"
55+
echo RELEASE_TAG_VERSION="${RELEASE_TAG_VERSION:1}" >> "$GITHUB_OUTPUT"
5456
- name: Set up QEMU
5557
uses: docker/setup-qemu-action@8b122486cedac8393e77aa9734c3528886e4a1a8 # v2.0.0
5658
# NOTE: we need QEMU to build Layer against a different architecture (e.g., ARM)
@@ -62,7 +64,7 @@ jobs:
6264
npm install -g [email protected]
6365
cdk --version
6466
- name: CDK build
65-
run: cdk synth --context version="$RELEASE_TAG_VERSION" -o cdk.out
67+
run: cdk synth --context version="${{ steps.release-notes-tag.outputs.RELEASE_TAG_VERSION }}" -o cdk.out
6668
- name: zip output
6769
run: zip -r cdk.out.zip cdk.out
6870
- name: Archive CDK artifacts
@@ -90,3 +92,23 @@ jobs:
9092
# stage: "PROD"
9193
# artefact-name: "cdk-layer-artefact"
9294
# environment: "layer-prod"
95+
96+
deploy-sar-beta:
97+
needs: build-layer
98+
uses: ./.github/workflows/reusable_deploy_v2_sar.yml
99+
secrets: inherit
100+
with:
101+
stage: "BETA"
102+
artefact-name: "cdk-layer-artefact"
103+
environment: "layer-beta"
104+
package-version: ${{ needs.build-layer.outputs.release-tag-version }}
105+
106+
deploy-sar-prod:
107+
needs: deploy-sar-beta
108+
uses: ./.github/workflows/reusable_deploy_v2_sar.yml
109+
secrets: inherit
110+
with:
111+
stage: "PROD"
112+
artefact-name: "cdk-layer-artefact"
113+
environment: "layer-prod"
114+
package-version: ${{ needs.build-layer.outputs.release-tag-version }}

.github/workflows/reusable_deploy_v2_layer_stack.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,6 @@ jobs:
9797
- name: unzip artefact
9898
run: unzip cdk.out.zip
9999
- name: CDK Deploy Layer
100-
run: cdk deploy --app cdk.out --context region=${{ matrix.region }} 'LayerStack' --require-approval never --verbose
100+
run: cdk deploy --app cdk.out --context region=${{ matrix.region }} 'LayerV2Stack' --require-approval never --verbose
101101
- name: CDK Deploy Canary
102-
run: cdk deploy --app cdk.out --context region=${{ matrix.region}} --parameters DeployStage="${{ inputs.stage }}" 'CanaryStack' --require-approval never --verbose
102+
run: cdk deploy --app cdk.out --context region=${{ matrix.region}} --parameters DeployStage="${{ inputs.stage }}" 'CanaryV2Stack' --require-approval never --verbose

.github/workflows/reusable_deploy_v2_sar.yml

+114-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,24 @@
11
name: Deploy V2 SAR
22

3+
# SAR deployment process
4+
#
5+
# 1. This workflow starts after the layer artifact is produced on `publish_v2_layer`
6+
# 2. We use the same layer artifact to ensure the SAR app is consistent with the published Lambda Layer
7+
# 3. We publish the SAR for both x86_64 and arm64 (see `matrix` section)
8+
# 4. We use `sam package` and `sam publish` to publish the SAR app
9+
# 5. We remove the previous Canary stack (if present) and deploy a new one to test the SAR App. We retain the Canary in the account for debugging purposes
10+
# 6. Finally the published SAR app is made public on the PROD environment
11+
12+
permissions:
13+
id-token: write
14+
contents: read
15+
16+
env:
17+
NODE_VERSION: 16.12
18+
AWS_REGION: eu-west-1
19+
SAR_NAME: aws-lambda-powertools-python-layer-v2
20+
TEST_STACK_NAME: serverlessrepo-v2-powertools-layer-test-stack
21+
322
on:
423
workflow_call:
524
inputs:
@@ -21,8 +40,100 @@ on:
2140
type: string
2241

2342
jobs:
24-
dummy:
43+
deploy-sar-app:
2544
runs-on: ubuntu-latest
45+
environment: ${{ inputs.environment }}
46+
strategy:
47+
matrix:
48+
architecture: ["x86_64", "arm64"]
2649
steps:
27-
- name: Hello world
28-
run: echo "hello world"
50+
- name: Checkout
51+
uses: actions/checkout@v3
52+
- name: AWS credentials
53+
uses: aws-actions/configure-aws-credentials@v1
54+
with:
55+
aws-region: ${{ env.AWS_REGION }}
56+
role-to-assume: ${{ secrets.AWS_LAYERS_ROLE_ARN }}
57+
- name: AWS credentials SAR role
58+
uses: aws-actions/configure-aws-credentials@v1
59+
id: aws-credentials-sar-role
60+
with:
61+
aws-access-key-id: ${{ env.AWS_ACCESS_KEY_ID }}
62+
aws-secret-access-key: ${{ env.AWS_SECRET_ACCESS_KEY }}
63+
aws-session-token: ${{ env.AWS_SESSION_TOKEN }}
64+
role-duration-seconds: 1200
65+
aws-region: ${{ env.AWS_REGION }}
66+
role-to-assume: ${{ secrets.AWS_SAR_V2_ROLE_ARN }}
67+
- name: Setup Node.js
68+
uses: actions/setup-node@v3
69+
with:
70+
node-version: ${{ env.NODE_VERSION }}
71+
- name: Download artifact
72+
uses: actions/download-artifact@v3
73+
with:
74+
name: ${{ inputs.artefact-name }}
75+
- name: Unzip artefact
76+
run: unzip cdk.out.zip
77+
- name: Configure SAR name
78+
run: |
79+
if [[ "${{ inputs.stage }}" == "BETA" ]]; then
80+
SAR_NAME="test-${SAR_NAME}"
81+
fi
82+
echo SAR_NAME="${SAR_NAME}" >> "$GITHUB_ENV"
83+
- name: Adds arm64 suffix to SAR name
84+
if: ${{ matrix.architecture == 'arm64' }}
85+
run: echo SAR_NAME="${SAR_NAME}-arm64" >> "$GITHUB_ENV"
86+
- name: Deploy SAR
87+
run: |
88+
# From the generated LayerStack cdk.out artifact, find the layer asset path for the correct architecture.
89+
# We'll use this as the source directory of our SAR. This way we are re-using the same layer asset for our SAR.
90+
asset=$(jq -jc '.Resources[] | select(.Properties.CompatibleArchitectures == ["${{ matrix.architecture }}"]) | .Metadata."aws:asset:path"' cdk.out/LayerV2Stack.template.json)
91+
92+
# fill in the SAR SAM template
93+
sed -e "s|<VERSION>|${{ inputs.package-version }}|g" -e "s/<SAR_APP_NAME>/${{ env.SAR_NAME }}/g" -e "s|<LAYER_CONTENT_PATH>|./cdk.out/$asset|g" layer/sar/template.txt > template.yml
94+
95+
# SAR needs a README and a LICENSE, so just copy the ones from the repo
96+
cp README.md LICENSE "./cdk.out/$asset/"
97+
98+
# Package the SAR to our SAR S3 bucket, and publish it
99+
sam package --template-file template.yml --output-template-file packaged.yml --s3-bucket ${{ secrets.AWS_SAR_S3_BUCKET }}
100+
sam publish --template packaged.yml --region "$AWS_REGION"
101+
- name: Deploy BETA canary
102+
if: ${{ inputs.stage == 'BETA' }}
103+
run: |
104+
if [[ "${{ matrix.architecture }}" == "arm64" ]]; then
105+
TEST_STACK_NAME="${TEST_STACK_NAME}-arm64"
106+
fi
107+
108+
echo "Check if stack does not exist"
109+
stack_exists=$(aws cloudformation list-stacks --query "StackSummaries[?(StackName == '$TEST_STACK_NAME' && StackStatus == 'CREATE_COMPLETE')].{StackId:StackId, StackName:StackName, CreationTime:CreationTime, StackStatus:StackStatus}" --output text)
110+
111+
if [[ -n "$stack_exists" ]] ; then
112+
echo "Found test deployment stack, removing..."
113+
aws cloudformation delete-stack --stack-name "$TEST_STACK_NAME"
114+
aws cloudformation wait stack-delete-complete --stack-name "$TEST_STACK_NAME"
115+
fi
116+
117+
echo "Creating canary stack"
118+
echo "Stack name: $TEST_STACK_NAME"
119+
aws serverlessrepo create-cloud-formation-change-set --application-id arn:aws:serverlessrepo:${{ env.AWS_REGION }}:${{ steps.aws-credentials-sar-role.outputs.aws-account-id }}:applications/${{ env.SAR_NAME }} --stack-name "${TEST_STACK_NAME/serverlessrepo-/}" --capabilities CAPABILITY_NAMED_IAM
120+
CHANGE_SET_ID=$(aws cloudformation list-change-sets --stack-name "$TEST_STACK_NAME" --query 'Summaries[*].ChangeSetId' --output text)
121+
aws cloudformation wait change-set-create-complete --change-set-name "$CHANGE_SET_ID"
122+
aws cloudformation execute-change-set --change-set-name "$CHANGE_SET_ID"
123+
aws cloudformation wait stack-create-complete --stack-name "$TEST_STACK_NAME"
124+
echo "Waiting until stack deployment completes..."
125+
126+
echo "Exit with error if stack is not in CREATE_COMPLETE"
127+
stack_exists=$(aws cloudformation list-stacks --query "StackSummaries[?(StackName == '$TEST_STACK_NAME' && StackStatus == 'CREATE_COMPLETE')].{StackId:StackId, StackName:StackName, CreationTime:CreationTime, StackStatus:StackStatus}")
128+
if [[ -z "$stack_exists" ]] ; then
129+
echo "Could find successful deployment, exit error..."
130+
exit 1
131+
fi
132+
echo "Deployment successful"
133+
- name: Publish SAR
134+
if: ${{ inputs.stage == 'PROD' }}
135+
run: |
136+
# wait until SAR registers the app, otherwise it fails to make it public
137+
sleep 15
138+
echo "Make SAR app public"
139+
aws serverlessrepo put-application-policy --application-id arn:aws:serverlessrepo:${{ env.AWS_REGION }}:${{ steps.aws-credentials-sar-role.outputs.aws-account-id }}:applications/${{ env.SAR_NAME }} --statements Principals='*',Actions=Deploy

layer/app.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,15 @@
1919

2020
LayerStack(
2121
app,
22-
"LayerStack",
22+
"LayerV2Stack",
2323
powertools_version=POWERTOOLS_VERSION,
2424
ssm_paramter_layer_arn=SSM_PARAM_LAYER_ARN,
2525
ssm_parameter_layer_arm64_arn=SSM_PARAM_LAYER_ARM64_ARN,
2626
)
2727

2828
CanaryStack(
2929
app,
30-
"CanaryStack",
30+
"CanaryV2Stack",
3131
powertools_version=POWERTOOLS_VERSION,
3232
ssm_paramter_layer_arn=SSM_PARAM_LAYER_ARN,
3333
ssm_parameter_layer_arm64_arn=SSM_PARAM_LAYER_ARM64_ARN,

0 commit comments

Comments
 (0)