Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
39 changes: 26 additions & 13 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ on:
push:
branches: [ "main" ]

env:
# Opt JS actions into Node 24 runtime now (stops Node20 deprecation warnings)
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true

permissions:
id-token: write
contents: read
Expand All @@ -14,36 +18,45 @@ jobs:

steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v6

- name: Configure AWS credentials via OIDC
uses: aws-actions/configure-aws-credentials@v4
uses: aws-actions/configure-aws-credentials@v6
with:
role-to-assume: arn:aws:iam::637423424745:role/GitHubActionsDeployRole
aws-region: us-east-1
aws-region: us-east-2

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"

- name: Install dependencies
- name: Install dependencies (backend)
working-directory: backend
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
# Optional: if you create this file for moto/pytest/boto3
if [ -f requirements-dev.txt ]; then pip install -r requirements-dev.txt; fi

- name: Clean Python caches
working-directory: backend
run: |
if [ -f src/requirements.txt ]; then
pip install -r src/requirements.txt
else
echo "No requirements file, skipping"
fi
pip install pytest

- name: Run unit tests
find . -type d -name "__pycache__" -prune -exec rm -rf {} +
find . -type f -name "*.pyc" -delete
rm -rf .pytest_cache

- name: Run unit tests (backend)
working-directory: backend
run: pytest -q

- name: Install SAM CLI
run: pip install aws-sam-cli

- name: SAM Build
working-directory: backend
run: sam build --use-container

- name: SAM Deploy
run: sam deploy --no-confirm-changeset --no-fail-on-empty-changeset
working-directory: backend
run: sam deploy --no-confirm-changeset --no-fail-on-empty-changeset
16 changes: 16 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Python bytecode + cache
__pycache__/
*.pyc
.pytest_cache/

# Virtual environment
.venv/

# SAM build artifacts
.aws-sam/

# VSCode settings (optional)
.vscode/

# macOS/Linux junk (optional)
.DS_Store
5 changes: 5 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"python.analysis.extraPaths": [
"./backend/src"
]
}
File renamed without changes.
File renamed without changes.
4 changes: 4 additions & 0 deletions backend/pytest.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#backend/pytest.ini
[pytest]
testpaths = tests
pythonpath = src
3 changes: 3 additions & 0 deletions backend/requirements-dev.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pytest
boto3
moto[boto3]
6 changes: 2 additions & 4 deletions src/requirements.txt → backend/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
boto3

moto>=4.0

pytest
boto3
moto[boto3]
File renamed without changes.
2 changes: 1 addition & 1 deletion src/app.py → backend/src/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
TABLE_NAME = os.getenv("TABLE_NAME", "visitorCount")

def _get_table():
# Construct the resource each time (or memoize after first call)
# Construct the resource each time to ensure it picks up any changes in environment variables (e.g., for testing)
dynamodb = boto3.resource("dynamodb", region_name=os.getenv("AWS_DEFAULT_REGION", "us-east-2"))
return dynamodb.Table(TABLE_NAME)

Expand Down
File renamed without changes.
File renamed without changes.
39 changes: 39 additions & 0 deletions backend/tests/test_app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# tests/test_app.py
import json
import os
import boto3
import moto

# Use a consistent region for moto/boto3
os.environ.setdefault("AWS_DEFAULT_REGION", "us-east-2")

@moto.mock_aws
def test_lambda_handler_increments_count():
# ---- Arrange
# 1) Set env vars your handler expects
os.environ["TABLE_NAME"] = "visitorCount"

# 2) Create the mocked table
dynamodb = boto3.resource("dynamodb", region_name="us-east-2")
table = dynamodb.create_table(
TableName=os.environ["TABLE_NAME"],
KeySchema=[{"AttributeName": "id", "KeyType": "HASH"}],
AttributeDefinitions=[{"AttributeName": "id", "AttributeType": "S"}],
BillingMode="PAY_PER_REQUEST",
)
table.put_item(Item={"id": "count", "count": 0})

# 3) Import AFTER moto + env are in place (important if app.py binds boto3 at import)
from app import lambda_handler

# ---- Act
resp = lambda_handler({"requestContext": {"http": {"method": "GET"}}}, {})
assert resp["statusCode"] == 200

body = json.loads(resp["body"])

# ---- Assert
assert isinstance(body, dict)
assert body["count"] == 1
# (optional) assert content type if your lambda sets it:
# assert resp["headers"]["content-type"] == "application/json"
Binary file removed src/__pycache__/app.cpython-313.pyc
Binary file not shown.
Binary file not shown.
Binary file not shown.
33 changes: 0 additions & 33 deletions tests/test_app.py

This file was deleted.

Loading