Skip to content

Commit d170ae2

Browse files
authored
create github CI workflow (#1)
1 parent 34a35dd commit d170ae2

File tree

5 files changed

+127
-11
lines changed

5 files changed

+127
-11
lines changed
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
name: Run Integration Tests
2+
3+
on:
4+
push:
5+
paths-ignore:
6+
- 'README.md'
7+
branches:
8+
- main
9+
pull_request:
10+
branches:
11+
- main
12+
13+
jobs:
14+
run-it-tests-job:
15+
runs-on: ubuntu-latest
16+
steps:
17+
- name: Checkout
18+
uses: actions/checkout@v2
19+
20+
- name: Set up Python 3.9
21+
id: setup-python
22+
uses: actions/setup-python@v2
23+
with:
24+
python-version: 3.9
25+
26+
- name: Set up Project
27+
run: |
28+
pip install -r requirements-dev.txt
29+
30+
- name: Start LocalStack
31+
env:
32+
LOCALSTACK_API_KEY: ${{ secrets.LOCALSTACK_API_KEY }}
33+
DNS_ADDRESS: 0
34+
EDGE_PORT: 4566
35+
run: |
36+
pip install localstack awscli-local[ver1]
37+
docker pull localstack/localstack
38+
# Start LocalStack in the background
39+
localstack start -d
40+
# Wait 30 seconds for the LocalStack container to become ready before timing out
41+
echo "Waiting for LocalStack startup..."
42+
localstack wait -t 30
43+
echo "Startup complete"
44+
45+
- name: Deploy infrastructure
46+
run: |
47+
bin/deploy.sh
48+
49+
- name: Run Tests
50+
env:
51+
AWS_DEFAULT_REGION: us-east-1
52+
AWS_REGION: us-east-1
53+
AWS_ACCESS_KEY_ID: test
54+
AWS_SECRET_ACCESS_KEY: test
55+
run: |
56+
pytest tests
57+
58+
- name: Show localstack logs
59+
if: always()
60+
run: |
61+
localstack logs

bin/deploy.sh

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#!/bin/bash
2+
3+
awslocal s3 mb s3://localstack-thumbnails-app-images
4+
awslocal s3 mb s3://localstack-thumbnails-app-resized
5+
6+
awslocal ssm put-parameter --name /localstack-thumbnail-app/buckets/images --value "localstack-thumbnails-app-images"
7+
awslocal ssm put-parameter --name /localstack-thumbnail-app/buckets/resized --value "localstack-thumbnails-app-resized"
8+
9+
awslocal sns create-topic --name failed-resize-topic
10+
awslocal sns subscribe \
11+
--topic-arn arn:aws:sns:us-east-1:000000000000:failed-resize-topic \
12+
--protocol email \
13+
--notification-endpoint my-email@example.com
14+
15+
(cd lambdas/presign; rm -f lambda.zip; zip lambda.zip handler.py)
16+
awslocal lambda create-function \
17+
--function-name presign \
18+
--runtime python3.9 \
19+
--timeout 10 \
20+
--zip-file fileb://lambdas/presign/lambda.zip \
21+
--handler handler.handler \
22+
--role arn:aws:iam::000000000000:role/lambda-role
23+
24+
awslocal lambda create-function-url-config \
25+
--function-name presign \
26+
--auth-type NONE
27+
28+
(
29+
cd lambdas/resize
30+
rm -rf package lambda.zip
31+
mkdir package
32+
pip install -r requirements.txt -t package
33+
zip lambda.zip handler.py
34+
cd package
35+
zip -r ../lambda.zip *;
36+
)
37+
awslocal lambda create-function \
38+
--function-name resize \
39+
--runtime python3.9 \
40+
--timeout 10 \
41+
--zip-file fileb://lambdas/resize/lambda.zip \
42+
--handler handler.handler \
43+
--dead-letter-config TargetArn=arn:aws:sns:us-east-1:000000000000:failed-resize-topic \
44+
--role arn:aws:iam::000000000000:role/lambda-role
45+
46+
awslocal s3api put-bucket-notification-configuration \
47+
--bucket localstack-thumbnails-app-images \
48+
--notification-configuration "{\"LambdaFunctionConfigurations\": [{\"LambdaFunctionArn\": \"$(awslocal lambda get-function --function-name resize | jq -r .Configuration.FunctionArn)\", \"Events\": [\"s3:ObjectCreated:*\"]}]}"
49+
50+
awslocal s3 mb s3://webapp
51+
awslocal s3 sync --delete ./website s3://webapp
52+
awslocal s3 website s3://webapp --index-document index.html

lambdas/resize/handler.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ def handler(event, context):
3838
target_bucket = get_bucket_name()
3939

4040
for record in event["Records"]:
41-
source_bucket = record['s3']['bucket']['name']
41+
source_bucket = record["s3"]["bucket"]["name"]
4242
key = unquote_plus(record["s3"]["object"]["key"])
4343
print(source_bucket, key)
4444

tests/test_integration.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020

2121
def test_s3_resize_integration():
22-
file = "nyan-cat.png"
22+
file = os.path.join(os.path.dirname(__file__), "nyan-cat.png")
2323
key = os.path.basename(file)
2424

2525
parameter = ssm.get_parameter(Name="/localstack-thumbnail-app/buckets/images")
@@ -44,16 +44,14 @@ def test_s3_resize_integration():
4444
Bucket=target_bucket, Key=key, Filename="/tmp/nyan-cat-resized.png"
4545
)
4646

47-
assert (
48-
os.stat("/tmp/nyan-cat-resized.png").st_size < os.stat(key).st_size
49-
)
47+
assert os.stat("/tmp/nyan-cat-resized.png").st_size < os.stat(file).st_size
5048

5149
s3.delete_object(Bucket=source_bucket, Key=key)
5250
s3.delete_object(Bucket=target_bucket, Key=key)
5351

5452

5553
def test_failure_sns_to_ses_integration():
56-
file = "some-file.txt"
54+
file = os.path.join(os.path.dirname(__file__), "some-file.txt")
5755
key = f"{uuid.uuid4()}-{os.path.basename(file)}"
5856

5957
parameter = ssm.get_parameter(Name="/localstack-thumbnail-app/buckets/images")
@@ -63,8 +61,8 @@ def test_failure_sns_to_ses_integration():
6361

6462
def _check_message():
6563
response = requests.get("http://localhost:4566/_localstack/ses")
66-
messages = response.json()['messages']
67-
assert key in messages[-1]['Body']['text_part']
64+
messages = response.json()["messages"]
65+
assert key in messages[-1]["Body"]["text_part"]
6866

6967
# retry to check for the message
7068
for i in range(9):

website/app.js

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,18 +32,23 @@
3232
$("#" + key).val(fields[key]);
3333
}
3434

35+
let formData = new FormData($("#uploadForm")[0]);
36+
console.log("sending form data", formData);
37+
3538
$.ajax({
36-
type: 'POST',
39+
type: "POST",
3740
url: data['url'],
38-
data: new FormData($("#uploadForm")[0]),
41+
data: formData,
3942
processData: false,
4043
contentType: false,
4144
success: function () {
4245
alert("success!");
4346
},
47+
error: function() {
48+
alert("error! check the logs");
49+
},
4450
complete: function (event) {
4551
console.log("done", event);
46-
alert("error uploading. check the logs!")
4752
$("#uploadForm button").removeClass('disabled');
4853
}
4954
});

0 commit comments

Comments
 (0)