Skip to content

Commit 93c5f65

Browse files
author
Ran Isenberg
committed
feature: added github actions
1 parent f3506d2 commit 93c5f65

File tree

8 files changed

+258
-15
lines changed

8 files changed

+258
-15
lines changed

.coveragerc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[run]
2+
omit = ["tests/*", "cdk/*"]

.github/workflows/python-app.yml

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# This workflow will install Python dependencies, run tests and lint with a single version of Python
2+
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
3+
4+
name: Python application
5+
6+
on:
7+
push:
8+
branches: [main]
9+
pull_request:
10+
branches: [main]
11+
12+
jobs:
13+
build:
14+
runs-on: ubuntu-latest
15+
16+
steps:
17+
- run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event."
18+
- run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub!"
19+
- run: echo "🔎 The name of your branch is ${{ github.ref }} and your repository is ${{ github.repository }}."
20+
- name: Check out repository code
21+
uses: actions/checkout@v2
22+
- run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner."
23+
- uses: actions/checkout@v2
24+
- name: Set up Python 3.8
25+
uses: actions/setup-python@v2
26+
with:
27+
python-version: "3.8"
28+
- name: Install dependencies
29+
run: |
30+
python -m pip install --upgrade pip
31+
pip install -r dev_requirements.txt
32+
pip install -r lambda_requirements.txt
33+
- name: pre commit
34+
run: |
35+
make pre-commit
36+
- name: Lint with flake8
37+
run: |
38+
make lint
39+
- name: file format
40+
run: |
41+
yapf -d -vv --style=./.style --exclude=.venv --exclude=.build --exclude=cdk.out --exclude=.git -r .
42+
- name: Complexity scan
43+
run: |
44+
make complex
45+
- run: echo "🖥️ The workflow is now ready to test your code on the runner."
46+
- name: Unit tests
47+
run: |
48+
make unit
49+
- run: echo "🍏 This job's status is ${{ job.status }}."

Makefile

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
.PHONY: dev lint complex coverage pre-commit yapf sort deploy destroy
1+
.PHONY: dev lint complex coverage pre-commit yapf sort deploy destroy deps unit e2e
22

33

44

@@ -9,9 +9,6 @@ lint:
99
@echo "Running flake8"
1010
flake8 service/* tests/*
1111

12-
coverage:
13-
pytest --cov
14-
1512
complex:
1613
@echo "Running Radon"
1714
radon cc -e 'tests/*,cdk.out/*' .
@@ -24,7 +21,17 @@ sort:
2421
pre-commit:
2522
pre-commit run -a
2623

27-
pr: yapf sort pre-commit complex lint coverage
24+
deps:
25+
pipenv lock -r -d > dev_requirements.txt
26+
pipenv lock -r > lambda_requirements.txt
27+
28+
unit:
29+
pytest tests/unit --cov-config=.coveragerc --cov=service
30+
31+
e2e:
32+
pytest tests/e2e --cov-config=.coveragerc --cov=service
33+
34+
pr: deps yapf sort pre-commit complex lint unit e2e
2835

2936
yapf:
3037
yapf -i -vv --style=./.style --exclude=.venv --exclude=.build --exclude=cdk.out --exclude=.git -r .

README.md

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# AWS Lambda Cookbook - Elevate your handler's code
2+
![PythonSupport](https://img.shields.io/static/v1?label=python&message=3.8&color=blue?style=flat-square&logo=python)
23

34
What makes an AWS Lambda handler resilient, traceable and easy to maintain? How do you write such a code?
45

@@ -74,13 +75,7 @@ make destroy
7475
Unit tests can be found under the `tests` folder.
7576
You can run the tests by using the following command:
7677
```shell script
77-
pytest -v
78-
```
79-
80-
81-
To calculate test code coverage us the command:
82-
```shell script
83-
pytest --cov
78+
make unit
8479
```
8580

8681
## E2E Tests
@@ -89,5 +84,8 @@ These tests send a 'GET' message to the deployed API GW and trigger the actual L
8984

9085
The tests are run automatically by:
9186
```shell script
92-
pytest --cov
87+
make e2e
9388
```
89+
90+
## License
91+
This library is licensed under the MIT License. See the LICENSE file.

dev_requirements.txt

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
-i https://pypi.org/simple
2+
-e ./cdk
3+
attrs==21.4.0
4+
aws-cdk.assets==1.145.0
5+
aws-cdk.aws-acmpca==1.145.0
6+
aws-cdk.aws-apigateway==1.145.0
7+
aws-cdk.aws-applicationautoscaling==1.145.0
8+
aws-cdk.aws-autoscaling-common==1.145.0
9+
aws-cdk.aws-certificatemanager==1.145.0
10+
aws-cdk.aws-cloudformation==1.145.0
11+
aws-cdk.aws-cloudwatch==1.145.0
12+
aws-cdk.aws-codeguruprofiler==1.145.0
13+
aws-cdk.aws-codestarnotifications==1.145.0
14+
aws-cdk.aws-cognito==1.145.0
15+
aws-cdk.aws-ec2==1.145.0
16+
aws-cdk.aws-ecr-assets==1.145.0
17+
aws-cdk.aws-ecr==1.145.0
18+
aws-cdk.aws-efs==1.145.0
19+
aws-cdk.aws-elasticloadbalancingv2==1.145.0
20+
aws-cdk.aws-events==1.145.0
21+
aws-cdk.aws-iam==1.145.0
22+
aws-cdk.aws-kms==1.145.0
23+
aws-cdk.aws-lambda-python==1.145.0
24+
aws-cdk.aws-lambda==1.145.0
25+
aws-cdk.aws-logs==1.145.0
26+
aws-cdk.aws-route53==1.145.0
27+
aws-cdk.aws-s3-assets==1.145.0
28+
aws-cdk.aws-s3==1.145.0
29+
aws-cdk.aws-sam==1.145.0
30+
aws-cdk.aws-signer==1.145.0
31+
aws-cdk.aws-sns==1.145.0
32+
aws-cdk.aws-sqs==1.145.0
33+
aws-cdk.aws-ssm==1.145.0
34+
aws-cdk.aws-stepfunctions==1.145.0
35+
aws-cdk.cloud-assembly-schema==1.145.0
36+
aws-cdk.core==1.145.0
37+
aws-cdk.custom-resources==1.145.0
38+
aws-cdk.cx-api==1.145.0
39+
aws-cdk.region-info==1.145.0
40+
boto3==1.21.6
41+
botocore==1.24.6
42+
cattrs==1.10.0 ; python_version >= '3.7'
43+
certifi==2021.10.8
44+
cfgv==3.3.1
45+
charset-normalizer==2.0.12 ; python_version >= '3'
46+
colorama==0.4.4 ; python_version > '3.4'
47+
constructs==3.3.226
48+
coverage[toml]==6.3.2
49+
distlib==0.3.4
50+
filelock==3.6.0
51+
flake8==4.0.1
52+
future==0.18.2
53+
gitdb==4.0.9
54+
gitpython==3.1.27
55+
identify==2.4.11
56+
idna==3.3
57+
iniconfig==1.1.1
58+
isort==5.10.1
59+
jmespath==0.10.0
60+
jsii==1.54.0
61+
mando==0.6.4
62+
mccabe==0.6.1
63+
nodeenv==1.6.0
64+
packaging==21.3
65+
platformdirs==2.5.1
66+
pluggy==1.0.0
67+
pre-commit==2.17.0
68+
publication==0.0.3
69+
py==1.11.0
70+
pycodestyle==2.8.0
71+
pyflakes==2.4.0
72+
pyparsing==3.0.7
73+
pytest-cov==3.0.0
74+
pytest-html==3.1.1
75+
pytest-metadata==1.11.0
76+
pytest-mock==3.7.0
77+
pytest==7.0.1
78+
python-dateutil==2.8.2
79+
python-dotenv==0.19.2
80+
pyyaml==6.0
81+
radon==5.1.0
82+
requests==2.27.1
83+
s3transfer==0.5.1
84+
six==1.16.0
85+
smmap==5.0.0
86+
toml==0.10.2
87+
tomli==2.0.1
88+
typing-extensions==4.1.1
89+
urllib3==1.26.8
90+
virtualenv==20.13.2
91+
xenon==0.9.0
92+
yapf==0.32.0

lambda_requirements.txt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
-i https://pypi.org/simple
2+
aws-lambda-powertools==1.25.1
3+
aws-xray-sdk==2.9.0
4+
boto3==1.21.6
5+
botocore==1.24.6
6+
dnspython==2.2.0
7+
email-validator==1.1.3
8+
fastjsonschema==2.15.3
9+
future==0.18.2
10+
idna==3.3
11+
jmespath==0.10.0
12+
pydantic[email]==1.9.0
13+
python-dateutil==2.8.2
14+
s3transfer==0.5.1
15+
six==1.16.0
16+
typing-extensions==4.1.1
17+
urllib3==1.26.8
18+
wrapt==1.13.3

tests/unit/test_my_handler.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
from http import HTTPStatus
33

44
from service.handlers.my_handler import my_handler
5-
from tests.utils import generate_context
5+
from tests.utils import generate_api_gw_event, generate_context
66

77

88
def test_handler_200_ok():
9-
response = my_handler({}, generate_context())
9+
response = my_handler(generate_api_gw_event(), generate_context())
1010
assert response['statusCode'] == HTTPStatus.OK
1111
body_dict = json.loads(response['body'])
1212
assert body_dict['message'] == 'success'

tests/utils.py

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from typing import Any, Dict
2+
13
import boto3
24
from aws_lambda_powertools.utilities.typing import LambdaContext
35

@@ -10,6 +12,81 @@ def generate_context() -> LambdaContext:
1012
return context
1113

1214

15+
# example taken from AWS Lambda Powertools test files
16+
# https://github.com/awslabs/aws-lambda-powertools-python/blob/develop/tests/events/apiGatewayProxyEvent.json
17+
def generate_api_gw_event() -> Dict[str, Any]:
18+
return {
19+
'version': '1.0',
20+
'resource': '/my/path',
21+
'path': '/my/path',
22+
'httpMethod': 'GET',
23+
'headers': {
24+
'Header1': 'value1',
25+
'Header2': 'value2'
26+
},
27+
'multiValueHeaders': {
28+
'Header1': ['value1'],
29+
'Header2': ['value1', 'value2']
30+
},
31+
'queryStringParameters': {
32+
'parameter1': 'value1',
33+
'parameter2': 'value'
34+
},
35+
'multiValueQueryStringParameters': {
36+
'parameter1': ['value1', 'value2'],
37+
'parameter2': ['value']
38+
},
39+
'requestContext': {
40+
'accountId': '123456789012',
41+
'apiId': 'id',
42+
'authorizer': {
43+
'claims': None,
44+
'scopes': None
45+
},
46+
'domainName': 'id.execute-api.us-east-1.amazonaws.com',
47+
'domainPrefix': 'id',
48+
'extendedRequestId': 'request-id',
49+
'httpMethod': 'GET',
50+
'identity': {
51+
'accessKey': None,
52+
'accountId': None,
53+
'caller': None,
54+
'cognitoAuthenticationProvider': None,
55+
'cognitoAuthenticationType': None,
56+
'cognitoIdentityId': None,
57+
'cognitoIdentityPoolId': None,
58+
'principalOrgId': None,
59+
'sourceIp': '192.168.0.1/32',
60+
'user': None,
61+
'userAgent': 'user-agent',
62+
'userArn': None,
63+
'clientCert': {
64+
'clientCertPem': 'CERT_CONTENT',
65+
'subjectDN': 'www.example.com',
66+
'issuerDN': 'Example issuer',
67+
'serialNumber': 'a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1',
68+
'validity': {
69+
'notBefore': 'May 28 12:30:02 2019 GMT',
70+
'notAfter': 'Aug 5 09:36:04 2021 GMT'
71+
}
72+
}
73+
},
74+
'path': '/my/path',
75+
'protocol': 'HTTP/1.1',
76+
'requestId': 'id=',
77+
'requestTime': '04/Mar/2020:19:15:17 +0000',
78+
'requestTimeEpoch': 1583349317135,
79+
'resourceId': None,
80+
'resourcePath': '/my/path',
81+
'stage': '$default'
82+
},
83+
'pathParameters': None,
84+
'stageVariables': None,
85+
'body': 'Hello from Lambda!',
86+
'isBase64Encoded': True
87+
}
88+
89+
1390
def get_stack_output(output_key: str) -> str:
1491
client = boto3.client('cloudformation')
1592
response = client.describe_stacks(StackName=get_stack_name())

0 commit comments

Comments
 (0)