Add your description here
Project description
pulse-aws
AWS deployment utilities for Pulse applications on ECS Fargate.
Folder Structure
src/pulse_aws/
├── __init__.py # Public exports
├── config.py # TaskConfig, HealthCheckConfig, ReaperConfig, DockerBuild
├── deployment.py # Core deployment orchestration, deploy()
├── plugin.py # AWSECSPlugin for Pulse integration
├── baseline.py # VPC, ALB, ECS cluster setup
├── certificate.py # ACM certificate management
├── teardown.py # Infrastructure cleanup
├── reporting.py # Deployment status reporting
├── reaper_lambda.py # Lambda for graceful task draining
│
├── cdk/ # AWS CDK infrastructure
│ ├── app.py # CDK app entrypoint
│ ├── baseline.py # Baseline stack definition
│ └── helpers.py # CDK utilities
│
scripts/
├── deploy.py # Deployment script
├── teardown.py # Teardown script
└── verify.py # Verification script
Features
- Zero-downtime deployments with deployment-affinity routing for HTTP and websockets
- Automatic ACM certificate management with DNS validation
- DNS configuration detection - automatically detects and guides you through DNS setup
- Baseline infrastructure as code using AWS CDK
- Multi-version support - run multiple deployments simultaneously
Quick Start
# Install
uv add pulse-aws
# Requires a working `cdk` executable on PATH.
# If you use a wrapper, pass it via --cdk-bin.
# Deploy
uv run pulse-aws deploy \
--deployment-name prod \
--domain app.example.com \
--app-file src/app/main.py \
--web-root web \
--dockerfile Dockerfile \
--context .
Architecture
See ARCHITECTURE.md for a detailed overview of:
- Infrastructure resources and how they relate
- Traffic routing with deployment affinity
- Zero-downtime deployment workflow
- Security architecture
Deployment Workflow
The deployment script orchestrates the full workflow:
1. ACM Certificate
from pulse_aws import ensure_acm_certificate
cert = await ensure_acm_certificate("api.example.com")
- Creates or retrieves an ACM certificate
- Provides DNS validation records if needed
- Waits for certificate to be ISSUED
2. Baseline Infrastructure
from pulse_aws import ensure_baseline_stack
outputs = await ensure_baseline_stack(
"prod",
certificate_arn=cert.arn,
)
Creates shared infrastructure:
- VPC with public/private subnets
- Application Load Balancer with HTTPS listener
- ECS Fargate cluster
- ECR repository
- CloudWatch log group
- Security groups
3. DNS Configuration Check
from pulse_aws import check_domain_dns
dns_config = check_domain_dns(domain, alb_dns_name)
if dns_config:
print(dns_config.format_for_display())
Automatically checks if your domain resolves to the ALB:
- ✅ Already configured: Silent success
- ✅ Proxied through Cloudflare: Treated as configured once records point to Cloudflare
- ⚠️ Not configured: Shows exact DNS record to add
Example output:
⚠️ Domain DNS Configuration Required
============================================================
🔗 Configure DNS for test.stoneware.rocks
Add the following records to your DNS provider:
• Type: CNAME
Name: test.stoneware.rocks
Value: test-alb-514905529.us-east-2.elb.amazonaws.com
(Route traffic to Application Load Balancer)
Once the records are added, your domain will be live within a few minutes.
4. Deploy Application
from pulse_aws import (
generate_deployment_id,
build_and_push_image,
register_task_definition,
create_service_and_target_group,
install_listener_rules_and_switch_traffic,
)
deployment_id = generate_deployment_id("prod")
image_uri = await build_and_push_image(...)
task_def_arn = await register_task_definition(...)
service_arn, tg_arn = await create_service_and_target_group(...)
await install_listener_rules_and_switch_traffic(...) # Waits for health checks
- Builds and pushes Docker image to ECR (with correct x86_64 architecture)
- Registers ECS task definition with IAM roles
- Creates target group and attaches to ALB listener
- Creates ECS service with 2 Fargate tasks
- Waits for targets to pass health checks (zero-downtime)
- Switches default traffic to new deployment
Zero-Downtime Deployments
Each deployment gets a unique ID (e.g., prod-20251027-122112Z):
- New deployment starts - New tasks spin up alongside old tasks
- Affinity routing - ALB creates rules for
?pulse_deployment=<deployment-id>→ target group, then uses ALBlb_cookiestickiness to keep that browser on the same ECS task inside that target group. - Default action switches - New users get new version
- Old sessions continue - Existing users stay pinned to the same deployment via prerender and Socket.IO query directives
Opening a new tab does not inherit that session affinity query, so a new tab (or any fresh session) follows the default listener action and reaches the latest deployment. 5. Drain old deployment - When ready, call drain endpoint to shut down gracefully
# Drain an old deployment
curl -X POST \
-H "Authorization: Bearer <drain-secret>" \
https://api.example.com/drain
AWSECSPlugin also exposes /_pulse/meta, which returns deployment metadata for affinity verification.
Configuration
Environment Variables
AWS_PROFILE- AWS profile to useAWS_REGION- AWS region (or set in~/.aws/config)PULSE_AWS_CDK_BIN- optional CDK executable or wrapper pathPULSE_AWS_CDK_WORKDIR- optional custom CDK app directory
Deployment Settings
result = await deploy(
domain="api.example.com",
deployment_name="prod",
docker=DockerBuild(
dockerfile_path=Path("Dockerfile"),
context_path=Path("."),
),
cdk_bin="cdk",
cdk_workdir=None,
)
- By default,
pulse-awsuses the packaged CDK app that ships insidepulse_aws/cdk. - Use
cdk_binor--cdk-binwhen you want to supply a wrapper script or alternate executable. - Use
cdk_workdiror--cdk-workdironly when you want to point deploy at a custom CDK app directory. - Host paths like
--dockerfile,--context, and--cdk-workdirresolve from the directory where you invokepulse-aws. --app-fileand--web-rootstay relative to the Docker build context.
Security
Defense in depth:
- ALB in public subnets (internet-facing)
- ECS tasks in private subnets (no direct internet access)
- NAT gateway for task outbound internet
- ALB security group: Only 80/443 from internet
- Service security group: Only 8000 from ALB
- IAM roles with least privilege
Development
# Run tests
uv run pytest packages/pulse-aws/tests/
# Deploy test environment
AWS_PROFILE=your-profile uv run packages/pulse-aws/scripts/deploy.py
Troubleshooting
Certificate validation stuck
If certificate stays in PENDING_VALIDATION:
- Check DNS validation records are added correctly
- Wait 5-10 minutes for DNS propagation
- Use
digto verify:dig _xxx.yourdomain.com CNAME
Domain not accessible after deployment
- Check DNS record points to ALB:
dig yourdomain.com - Wait for DNS propagation (can take 5-60 minutes)
- Verify ALB is healthy: Visit ALB DNS directly
Tasks failing health checks
- Check logs:
aws logs tail /aws/pulse/{env}/app --follow - Verify tasks are listening on port 8000
- Check
/_pulse/healthendpoint returns 200
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pulse_aws-0.1.10.tar.gz.
File metadata
- Download URL: pulse_aws-0.1.10.tar.gz
- Upload date:
- Size: 44.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.2 {"installer":{"name":"uv","version":"0.11.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dd2cf2f1e1d87f3dbe31d4978e58a940cccb4ca91f36830a525755e996eb67d4
|
|
| MD5 |
3fd60710701cdc70ad24555c4a1a2d29
|
|
| BLAKE2b-256 |
9a5191c9a828784d4c8c3e4eb9d2d87a05175ec26d62c4e58f35d637d9dbb7b4
|
File details
Details for the file pulse_aws-0.1.10-py3-none-any.whl.
File metadata
- Download URL: pulse_aws-0.1.10-py3-none-any.whl
- Upload date:
- Size: 52.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.2 {"installer":{"name":"uv","version":"0.11.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
511af9de86ffa8e79f13123bad5c103dddbfe1af9319d7db82cb485fee0246de
|
|
| MD5 |
58e511451b599c18930e34ec4b9da30d
|
|
| BLAKE2b-256 |
8debd29d96ad8db54a2e5df16261e506200007816c2d904c77c8eb4e0ad7806d
|