Skip to content

chore(layers): add release pipeline in GitHub Actions #1278

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 25 commits into from
Jul 7, 2022
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
49ed47a
chore: add layer project
Jul 4, 2022
fee2d9a
reduce to 1 region for dev
Jul 4, 2022
cfe92fc
Merge branch 'awslabs:develop' into chore/layer-release
am29d Jul 4, 2022
9f1042e
chore: shorter name for the workflow
Jul 4, 2022
d07e0b6
fix ignore markdown lint for now
Jul 4, 2022
3431528
fix: more f strings
Jul 4, 2022
3d49b5a
Merge branch 'awslabs:develop' into chore/layer-release
am29d Jul 4, 2022
e3af831
ignore mdlint
Jul 4, 2022
3918cbd
Merge branch 'chore/layer-release' of github.com:am29d/aws-lambda-pow…
Jul 4, 2022
94e3ab7
add reusable workflow for both beta and prod
Jul 5, 2022
bfc4980
Update layer/layer/canary/app.py
am29d Jul 5, 2022
43f6df9
Update layer/layer/canary/app.py
am29d Jul 5, 2022
ace2df6
readme review
Jul 5, 2022
b1b5408
Merge branch 'chore/layer-release' of github.com:am29d/aws-lambda-pow…
Jul 5, 2022
b21e6f6
rephrase canary stack ssm parameter usage
Jul 5, 2022
5696954
add default RELEASE_TAG_VERSION assignment based on the input (releas…
Jul 5, 2022
c08ca46
add reference to layer docs
Jul 5, 2022
4045d70
wording
Jul 5, 2022
9df6443
move version trackign arn to canary stack
Jul 5, 2022
2a2a8d7
remove outdated npm caching, add release tag resolution for manual wo…
Jul 5, 2022
28d986a
review: fix layer name and remove dependencies from reusable workflow
Jul 6, 2022
b89c53e
remove debug statement, add default working dir
Jul 6, 2022
c4a5699
pin versions and hashes for requirements with pip-compile
Jul 6, 2022
5dd6b76
rename reusable workflow
Jul 7, 2022
b60d57b
pass artefact name to the reusable workflow to prevent potential futu…
Jul 7, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
207 changes: 207 additions & 0 deletions .github/workflows/publish_layer.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
name: Deploy layer to all regions

permissions:
id-token: write
contents: read

on:
# TODO: remove after setup is finished
workflow_dispatch: { }
workflow_run:
workflows: [ "Publish to PyPi" ]
types:
- completed


jobs:
build-layer:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v2
with:
ref: ${{ github.event.pull_request.head.ref }}
repository: ${{ github.event.pull_request.head.repo.full_name }}
- name: Setup Node.js
uses: actions/setup-node@v2
with:
node-version: '16.12'
- name: Setup python
uses: actions/setup-python@v4
- name: Cache dependencies
uses: actions/cache@v2
with:
path: ~/.npm
key: npm-${{ hashFiles('package-lock.json') }}
restore-keys: npm-
- name: Set release notes tag
run: |
RELEASE_TAG_VERSION=${{ github.event.release.tag_name }}
echo "RELEASE_TAG_VERSION=${RELEASE_TAG_VERSION:1}" >> $GITHUB_ENV
- name: install cdk and deps
run: |
npm install -g [email protected]
cdk --version
- name: install deps
run: |
cd layer
pip install -r requirements.txt
- name: CDK build
run: cdk synth --context version=$RELEASE_TAG_VERSION -o cdk.out
- name: zip output
run: zip -r cdk.out.zip cdk.out
- name: Archive CDK artifacts
uses: actions/upload-artifact@v3
with:
name: cdk.out
path: cdk.out.zip

deploy-beta:
runs-on: ubuntu-latest
needs:
- build-layer
strategy:
fail-fast: false
matrix:
region: [
"af-south-1",
# "eu-central-1",
# "us-east-1",
# "us-east-2",
# "us-west-1",
# "us-west-2",
# "ap-east-1",
# "ap-south-1",
# "ap-northeast-1",
# "ap-northeast-2",
# "ap-southeast-1",
# "ap-southeast-2",
# "ca-central-1",
# "eu-west-1",
# "eu-west-2",
# "eu-west-3",
# "eu-south-1",
# "eu-north-1",
# "sa-east-1",
# "ap-southeast-3",
# "ap-northeast-3",
# "me-south-1"
]
steps:
- name: checkout
uses: actions/checkout@v2
with:
ref: ${{ github.event.pull_request.head.ref }}
repository: ${{ github.event.pull_request.head.repo.full_name }}
- name: aws credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-region: ${{ matrix.region }}
role-to-assume: arn:aws:iam::${{ secrets.LAYERS_BETA_ACCOUNT }}:role/${{ secrets.AWS_GITHUB_OIDC_ROLE }}
- name: Print assumed role
run: aws sts get-caller-identity
- name: Setup Node.js
uses: actions/setup-node@v2
with:
node-version: '16.12'
- name: Setup python
uses: actions/setup-python@v4
- name: Cache dependencies
uses: actions/cache@v2
with:
path: ~/.npm
key: npm-${{ hashFiles('package-lock.json') }}
restore-keys: npm-
- name: install cdk and deps
run: |
npm install -g [email protected]
cdk --version
- name: install deps
run: |
cd layer
pip install -r requirements.txt
- name: Download a single artifact
uses: actions/download-artifact@v3
with:
name: cdk.out
- name: unzip cdk.out.zip
run: unzip cdk.out.zip
- name: CDK Deploy Layer
run: cdk deploy --app cdk.out --context region=${{ matrix.region }} 'PowertoolsLayerStack' --require-approval never --verbose
- name: CDK Deploy Canary
run: cdk deploy --app cdk.out --context region=${{ matrix.region}} --parameters DeployStage="BETA" 'CanaryStack' --require-approval never --verbose

deploy-prod:
runs-on: ubuntu-latest
needs:
- deploy-beta
strategy:
fail-fast: false
matrix:
region: [
"af-south-1",
# "eu-central-1",
# "us-east-1",
# "us-east-2",
# "us-west-1",
# "us-west-2",
# "ap-east-1",
# "ap-south-1",
# "ap-northeast-1",
# "ap-northeast-2",
# "ap-southeast-1",
# "ap-southeast-2",
# "ca-central-1",
# "eu-west-1",
# "eu-west-2",
# "eu-west-3",
# "eu-south-1",
# "eu-north-1",
# "sa-east-1",
# "ap-southeast-3",
# "ap-northeast-3",
# "me-south-1"
]
steps:
- name: checkout
uses: actions/checkout@v2
with:
ref: ${{ github.event.pull_request.head.ref }}
repository: ${{ github.event.pull_request.head.repo.full_name }}
- name: aws credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-region: ${{ matrix.region }}
role-to-assume: arn:aws:iam::${{ secrets.LAYERS_PROD_ACCOUNT }}:role/${{ secrets.AWS_GITHUB_OIDC_ROLE }}
- name: Print assumed role
run: aws sts get-caller-identity
- name: Setup Node.js
uses: actions/setup-node@v2
with:
node-version: '16.12'
- name: Setup python
uses: actions/setup-python@v4
- name: Cache dependencies
uses: actions/cache@v2
with:
path: ~/.npm
key: npm-${{ hashFiles('package-lock.json') }}
restore-keys: npm-
- name: install cdk and deps
run: |
npm install -g [email protected]
cdk --version
- name: install deps
run: |
cd layer
pip install -r requirements.txt
- name: Download a single artifact
uses: actions/download-artifact@v3
with:
name: cdk.out
- name: unzip cdk.out.zip
run: unzip cdk.out.zip
- name: CDK Deploy Layer
run: cdk deploy --app cdk.out --context region=${{ matrix.region }} 'PowertoolsLayerStack' --require-approval never --verbose
- name: CDK Deploy Canary
run: cdk deploy --app cdk.out --context region=${{ matrix.region}} --parameters DeployStage="PROD" 'CanaryStack' --require-approval never --verbose
10 changes: 10 additions & 0 deletions layer/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
*.swp
package-lock.json
__pycache__
.pytest_cache
.venv
*.egg-info

# CDK asset staging directory
.cdk.staging
cdk.out
26 changes: 26 additions & 0 deletions layer/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<!-- markdownlint-disable MD041 MD043-->
# CDK Powertools layer

This is a CDK project to build and deploy AWS Lambda Powertools layer to multiple commercial regions.

## Build the layer

To build the layer construct you need to provide the powertools version.
You can pass it as a context variable when running `synth` or `deploy`,

```shell
cdk synth --context version=1.25.1
```

## Canary stack

We use a canary stack to verify that the deployment is successful and we can use the layer by adding it to a newly created Lambda function.
The canary is deployed after the layer construct. Because the layer ARN is created during the deploy we need to pass this information async via SSM parameter.
To achieve that, we establish a naming convention for the SSM key. The layer construct knows where to write the layer ARN after the deployment and the Canary stacks know where to read this information.

## Version tracking

AWS Lambda versions the layers by incrementing a number at the end of the arn.
This means it's hard to tell which powertools version is inside the layer.
For better tracking of the ARNs and the corresponding version we need to keep track which powertools version was deployed to which layer.
To achieve that we created two components. First, we created a version tracking app which receives evnets via Event Bridge. Second, after a successful canary deployment we send the layer ARN, powertools version, and the region to this Event Bridge.
31 changes: 31 additions & 0 deletions layer/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#!/usr/bin/env python3

import aws_cdk as cdk

from layer.canary_stack import CanaryStack
from layer.layer_stack import LayerStack

app = cdk.App()

POWERTOOLS_VERSION: str = app.node.try_get_context("version")
SSM_PARAM_LAYER_ARN: str = "/layers/powertools-layer-arn"

VERSION_TRACKING_EVENT_BUS_ARN: str = "arn:aws:events:eu-central-1:027876851704:event-bus/VersionTrackingEventBus"

if not POWERTOOLS_VERSION:
raise ValueError(
"Please set the version for Powertools by passing the '--context=version:<version>' parameter to the CDK "
"synth step."
)

LayerStack(app, "LayerStack", powertools_version=POWERTOOLS_VERSION, ssm_paramter_layer_arn=SSM_PARAM_LAYER_ARN)

CanaryStack(
app,
"CanaryStack",
powertools_version=POWERTOOLS_VERSION,
ssm_paramter_layer_arn=SSM_PARAM_LAYER_ARN,
version_tracking_event_bus_arn=VERSION_TRACKING_EVENT_BUS_ARN,
)

app.synth()
35 changes: 35 additions & 0 deletions layer/cdk.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"app": "python3 app.py",
"watch": {
"include": [
"**"
],
"exclude": [
"README.md",
"cdk*.json",
"requirements*.txt",
"source.bat",
"**/__init__.py",
"python/__pycache__",
"tests"
]
},
"context": {
"@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": true,
"@aws-cdk/core:stackRelativeExports": true,
"@aws-cdk/aws-rds:lowercaseDbIdentifier": true,
"@aws-cdk/aws-lambda:recognizeVersionProps": true,
"@aws-cdk/aws-lambda:recognizeLayerVersion": true,
"@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": true,
"@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": true,
"@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": true,
"@aws-cdk/core:checkSecretUsage": true,
"@aws-cdk/aws-iam:minimizePolicies": true,
"@aws-cdk/core:validateSnapshotRemovalPolicy": true,
"@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": true,
"@aws-cdk/core:target-partitions": [
"aws",
"aws-cn"
]
}
}
Empty file added layer/layer/__init__.py
Empty file.
Loading