Skip to content
Closed
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
63 changes: 63 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Docker Compose environment configuration
# Copy this file to .env and fill in your values
# See config/README.md for detailed documentation

# =============================================================================
# Server Configuration
# =============================================================================

# Port to expose the API (default: 8080)
PORT=8080

# Flask debug mode (0=production, 1=development)
FLASK_DEBUG=0

# =============================================================================
# Authentication (Optional)
# =============================================================================

# Enable Auth0 authentication (default: false)
AUTH__ENABLED=false

# Auth0 domain (without https:// or trailing slash)
AUTH0_ADDRESS_NO_DOMAIN=

# Auth0 API audience
AUTH0_AUDIENCE_NO_DOMAIN=

# Auth0 test token (for CI testing)
AUTH0_TEST_TOKEN_NO_DOMAIN=

# =============================================================================
# Analytics (Optional)
# =============================================================================

# Enable user analytics collection (default: false)
ANALYTICS__ENABLED=false

# For local MySQL (when using docker compose --profile analytics)
MYSQL_ROOT_PASSWORD=rootpass
MYSQL_USER=analytics
MYSQL_PASSWORD=analytics_pass

# For Google Cloud SQL (production)
# USER_ANALYTICS_DB_CONNECTION_NAME=
# USER_ANALYTICS_DB_USERNAME=
# USER_ANALYTICS_DB_PASSWORD=

# =============================================================================
# AI Features (Optional)
# =============================================================================

# Enable AI-powered features (default: false)
AI__ENABLED=false

# Anthropic API key for AI features
ANTHROPIC_API_KEY=

# =============================================================================
# Configuration File (Optional)
# =============================================================================

# Custom configuration file path (mounted into container)
# CONFIG_FILE=./config/local.yaml
21 changes: 15 additions & 6 deletions Dockerfile.build
Original file line number Diff line number Diff line change
@@ -1,17 +1,26 @@
# Development Dockerfile for PolicyEngine Household API
# Use docker-compose.yml for easier development setup
FROM python:3.12
ENV VIRTUAL_ENV=/env
ENV PATH=/env/bin:$PATH

# Install system dependencies
RUN apt-get update && apt-get install -y build-essential checkinstall redis-server
RUN apt-get update && apt-get install -y \
build-essential \
checkinstall \
curl \
&& rm -rf /var/lib/apt/lists/*

RUN python3.12 -m pip install --upgrade pip

# Copy and install the application
WORKDIR /app
COPY . /app
RUN pip install -e .
RUN pip install -e .[dev]

# Set default environment
ENV FLASK_APP=policyengine_household_api.api
ENV FLASK_DEBUG=1

# Start Redis
RUN service redis-server start
# Expose Flask default port
EXPOSE 5000

CMD ["bash"]
25 changes: 25 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,31 @@ debug-test:
format:
black . -l 79

# Docker Compose commands
docker-build:
docker compose build

docker-up:
docker compose up

docker-up-detached:
docker compose up -d

docker-down:
docker compose down

docker-dev:
docker compose --profile dev up api-dev

docker-test:
docker compose --profile test run --rm test

docker-test-auth:
docker compose --profile test-auth run --rm test-with-auth

docker-logs:
docker compose logs -f

deploy:
python gcp/export.py
gcloud config set app/cloud_build_timeout 1800
Expand Down
56 changes: 53 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,58 @@
# PolicyEngine Household API
# PolicyEngine Household API

A version of the PolicyEngine API that runs the `calculate` endpoint over household object. To debug locally, run `make debug`.
A version of the PolicyEngine API that runs the `calculate` endpoint over household object.

## Development rules
## Quick Start

### Local Development (without Docker)

```bash
make install
make debug
```

### Docker Compose

```bash
# Copy environment template
cp .env.example .env

# Start the API
make docker-up

# Or run in development mode with hot-reload
make docker-dev
```

### Running Tests

```bash
# Without Docker
make test

# With Docker Compose
make docker-test
```

## Docker Compose Services

| Command | Description |
|---------|-------------|
| `make docker-up` | Start the API service |
| `make docker-up-detached` | Start in background |
| `make docker-dev` | Start with hot-reload |
| `make docker-test` | Run unit tests |
| `make docker-test-auth` | Run auth integration tests |
| `make docker-down` | Stop all services |
| `make docker-logs` | View logs |

See `docker-compose.yml` for available services and profiles.

## Configuration

See [config/README.md](config/README.md) for detailed configuration options.

## Development Rules

1. Every endpoint should return a JSON object with at least a "status" and "message" field.

Expand Down
6 changes: 6 additions & 0 deletions changelog_entry.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
- bump: minor
changes:
added:
- Docker Compose structure for local development and CI
- .env.example with documented environment variables
- Make targets for common Docker operations (docker-up, docker-dev, docker-test)
124 changes: 124 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
# Docker Compose configuration for PolicyEngine Household API
# Use this for local development and CI testing
#
# Usage:
# Development: docker compose up
# Testing: docker compose --profile test up
# With analytics: docker compose --profile analytics up
#
# See config/README.md for configuration options

services:
# Main API service
api:
build:
context: .
dockerfile: gcp/policyengine_household_api/Dockerfile.production
ports:
- "${PORT:-8080}:8080"
environment:
- PORT=8080
- FLASK_DEBUG=${FLASK_DEBUG:-0}
# Optional features - disabled by default for local development
- AUTH__ENABLED=${AUTH__ENABLED:-false}
- AUTH0_ADDRESS_NO_DOMAIN=${AUTH0_ADDRESS_NO_DOMAIN:-}
- AUTH0_AUDIENCE_NO_DOMAIN=${AUTH0_AUDIENCE_NO_DOMAIN:-}
- ANALYTICS__ENABLED=${ANALYTICS__ENABLED:-false}
- AI__ENABLED=${AI__ENABLED:-false}
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:-}
volumes:
# Mount custom config if provided
- ${CONFIG_FILE:-./config/default.yaml}:/app/config/custom.yaml:ro
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
restart: unless-stopped

# Development service with hot-reload support
api-dev:
build:
context: .
dockerfile: Dockerfile.build
ports:
- "${PORT:-8080}:5000"
environment:
- FLASK_APP=policyengine_household_api.api
- FLASK_DEBUG=1
- AUTH__ENABLED=${AUTH__ENABLED:-false}
- AUTH0_ADDRESS_NO_DOMAIN=${AUTH0_ADDRESS_NO_DOMAIN:-}
- AUTH0_AUDIENCE_NO_DOMAIN=${AUTH0_AUDIENCE_NO_DOMAIN:-}
- ANALYTICS__ENABLED=${ANALYTICS__ENABLED:-false}
- AI__ENABLED=${AI__ENABLED:-false}
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:-}
volumes:
# Mount source code for hot-reload
- ./policyengine_household_api:/app/policyengine_household_api:ro
- ./config:/app/config:ro
command: ["flask", "run", "--host=0.0.0.0", "--without-threads"]
profiles:
- dev

# Test runner service
test:
build:
context: .
dockerfile: Dockerfile.build
environment:
- FLASK_DEBUG=1
- AUTH__ENABLED=${AUTH__ENABLED:-false}
- AUTH0_ADDRESS_NO_DOMAIN=${AUTH0_ADDRESS_NO_DOMAIN:-}
- AUTH0_AUDIENCE_NO_DOMAIN=${AUTH0_AUDIENCE_NO_DOMAIN:-}
- AUTH0_TEST_TOKEN_NO_DOMAIN=${AUTH0_TEST_TOKEN_NO_DOMAIN:-}
- CONFIG_FILE=${CONFIG_FILE:-}
volumes:
- ./tests:/app/tests:ro
- ./policyengine_household_api:/app/policyengine_household_api:ro
- ./config:/app/config:ro
command: ["pytest", "-vv", "--timeout=150", "-rP", "tests/to_refactor", "tests/unit"]
profiles:
- test

# Test with auth service
test-with-auth:
build:
context: .
dockerfile: Dockerfile.build
environment:
- AUTH__ENABLED=true
- AUTH0_ADDRESS_NO_DOMAIN=${AUTH0_ADDRESS_NO_DOMAIN}
- AUTH0_AUDIENCE_NO_DOMAIN=${AUTH0_AUDIENCE_NO_DOMAIN}
- AUTH0_TEST_TOKEN_NO_DOMAIN=${AUTH0_TEST_TOKEN_NO_DOMAIN}
- CONFIG_FILE=/app/config/test_with_auth.yaml
volumes:
- ./tests:/app/tests:ro
- ./policyengine_household_api:/app/policyengine_household_api:ro
- ./config:/app/config:ro
command: ["pytest", "-vv", "--timeout=150", "-rP", "tests/integration_with_auth"]
profiles:
- test-auth

# MySQL database for analytics (optional)
mysql:
image: mysql:8.0
environment:
- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:-rootpass}
- MYSQL_DATABASE=user_analytics
- MYSQL_USER=${MYSQL_USER:-analytics}
- MYSQL_PASSWORD=${MYSQL_PASSWORD:-analytics_pass}
volumes:
- mysql_data:/var/lib/mysql
ports:
- "3306:3306"
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 5
profiles:
- analytics

volumes:
mysql_data:
Empty file added tests/data/__init__.py
Empty file.
Empty file added tests/fixtures/__init__.py
Empty file.
Empty file added tests/fixtures/data/__init__.py
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file added tests/to_refactor/__init__.py
Empty file.
Empty file.
Empty file added tests/unit/__init__.py
Empty file.
Empty file added tests/unit/data/__init__.py
Empty file.
Empty file.
Empty file.
Empty file added tests/unit/utils/__init__.py
Empty file.
Loading