Polo Legacy — Deploy & Test Strategy
Development
Local Dev Server
python run.py # or: inv run
- Flask app on port 2200 with LiveReload
- Watches
src/*for changes, auto-restarts on crash (5s backoff) - Sets
ENV=dev,USE_LOCAL_DATA=true - Uses
LocalDataService(readslocal_data.jsoninstead of DynamoDB) - Converts Lambda event/context into Flask request objects
Tailwind CSS
inv tailwind # one-shot compile
inv tailwind --watch # watch mode
Output: src/static/dist/main.css
Syncing Local Data
inv sync # all resources, all profiles
inv sync -r instances # single resource type
inv sync -p prod,staging # specific AWS profiles
Requires AWS CLI profile "polo" configured. Writes per-type JSON files, then
combine() merges into local_data.json for the dev server.
Build
Lambda Package
inv zip # creates lambda_deployment.zip with deps
inv build # SAM build
inv build -p polo # with specific AWS profile
SAM Template (template.yaml)
- Runtime: Python 3.12
- Memory: 256 MB
- Timeout: 30 seconds
- Layers: AWS Lambda Powertools v2
- Functions:
PoloFunction→lambda_function.lambda_handler(API routes)StaticFunction→lambda_static.lambda_handler(/static files)
- API Events:
/{proxy+}ANY → PoloFunction/ANY → PoloFunction
Deploy
CDK Deployment
inv bootstrap -p polo # CDK bootstrap (first time)
inv deploy -p polo -e prod # deploy to production
inv deploy -p polo -e prod -s PoloStack # specific stack
inv deploy -p polo -e prod --exclusively # only named stack
inv destroy -p polo -e prod # tear down
inv destroy -p polo -e prod --force # skip confirmation
CDK apps defined in:
infra/app.py— main application stackinfra/ci.py— CI/CD pipelineinfra/destination.py— cross-account destination
Environment Variables (Production Lambda)
Required:
| Variable | Value |
|---|---|
ENV | prod |
AWS_REGION | us-east-1 |
DYNAMODB_TABLE_NAME | prod-ResourceTable |
DYNAMODB_REPORT_TABLE_NAME | prod-ReportTable |
POWERTOOLS_SERVICE_NAME | polo |
POWERTOOLS_METRICS_NAMESPACE | Polo |
LOGOUT_URL | /auth/logout |
Optional:
| Variable | Purpose |
|---|---|
USE_LOCAL_DATA | true for dev mode |
SLACK_WEBHOOK_URL | Cloud Cop Slack notifications |
DATA_BUCKET_NAME | S3 bucket for sync data |
CORE_ACCOUNT_ID | Cross-account cost data |
CORE_ROLE_ARN | Cross-account role assumption |
Testing
Configuration
pytest.ini / conftest.py:
- Auto-mocks
os.environ(function scope) with:LOGOUT_URL=/auth/logoutDATA_BUCKET_NAME=test-dataUSE_LOCAL_DATA=1
Test Commands
inv test # all tests
inv test --local # local tests only (no AWS)
inv test --integration # integration tests (requires AWS)
inv test --watch # watch mode (pytest-watch)
inv test --coverage # with coverage report
inv test --report # HTML coverage report
inv test --fail-under 80 # minimum coverage threshold
Test Stack
| Tool | Purpose |
|---|---|
| pytest | Test runner |
| moto | AWS service mocking (DynamoDB, S3, EC2, etc.) |
| freezegun | Time freezing for date-dependent tests |
| pytest-coverage | Coverage measurement |
| pytest-watch | File-watching test re-runner |
Test Files
src/lambda_function_test.py — API handler tests
src/lambda_cop_test.py — Cloud Cop tests
src/routes/common_test.py — Route utility tests
src/services/dynamo_data_service_test.py — DynamoDB service tests
src/services/local_data_service_test.py — Local data service tests
src/services/cost_breakdown_service_test.py — Cost calculation tests
src/services/models/instance_test.py — Instance model tests
src/services/models/marqoindex_test.py — Index model tests
src/services/models/all_test.py — Everything object tests
src/services/reports/*_test.py — Reporter tests
Test Strategy
- Unit tests: Models, services, utilities — fast, no external deps
- Mocked AWS tests: Using
mototo simulate DynamoDB, S3, EC2 APIs - Time-dependent tests: Using
freezegunfor report generation, TTL logic - No E2E browser tests: Frontend is server-rendered, no Playwright/Selenium
- No snapshot tests: HTML output not snapshot-tested
CI/CD
CDK-managed pipeline (infra/ci.py). Build steps:
- Tailwind CSS compilation
- Lambda zip creation
- SAM build
- CDK synth
- CDK deploy
Dependencies
Production (src/requirements.txt)
arrow — datetime utilities
boto3 — AWS SDK
htmxido — HTML generation DSL
humanize — human-readable numbers
pytz — timezone handling
requests — HTTP client
Development (requirements.dev.txt)
# Infrastructure
aws-cdk-lib, aws_cdk.aws_lambda_python_alpha, constructs
# AWS
aws_lambda_powertools[tracer], boto3-stubs[*]
# Testing
pytest, pytest-coverage, pytest-watch, pytest-freezegun, moto
# Code quality
ruff, mypy, mypy-extensions
# Dev server
flask, livereload, python-dotenv, invoke
# Utilities
coverage, freezegun, ujson, setuptools