beps/DEPLOYMENT.md
Complete guide for deploying BAML Enhancement Proposals (BEPs) documentation to AWS with subdomain-based previews using AWS CDK.
https://beps.boundaryml.com (from canary branch)https://{branch-name}.beps.boundaryml.com (from PRs)# If using AWS SSO, login first
aws sso login --profile boundaryml-dev
export AWS_PROFILE=boundaryml-dev
# Deploy infrastructure
cd beps/infrastructure
npm install
./deploy.sh
See infrastructure/README.md for detailed documentation.
S3 Bucket - Hosts all static files
/{branch-name}/CloudFront Distribution - CDN with subdomain routing
beps.boundaryml.com*.beps.boundaryml.comACM Certificate - SSL for HTTPS
beps.boundaryml.com and *.beps.boundaryml.comIAM Role - GitHub Actions deployment
Located in .github/workflows/:
deploy-beps.yml - Main deployment
canary or PRcleanup-beps-preview.yml - Immediate cleanup
cleanup-stale-previews.yml - Scheduled cleanup
Add these to your repository (Settings → Secrets → Actions):
AWS_ROLE_ARN=arn:aws:iam::123456789012:role/GitHubActions-BEPs-Deploy
S3_BUCKET_BEPS=baml-beps-123456789012
CLOUDFRONT_DISTRIBUTION_ID_BEPS=E1234567890ABC
BEPS_DOMAIN=beps.boundaryml.com
The deployment outputs these exact values.
Add CNAME records to your domain registrar:
| Type | Name | Value |
|---|---|---|
| CNAME | beps.boundaryml.com | d1234567890abc.cloudfront.net |
| CNAME | *.beps.boundaryml.com | d1234567890abc.cloudfront.net |
Get the CloudFront domain from the deployment output.
If a new ACM certificate was created, validate it via DNS:
aws acm describe-certificate \
--certificate-arn <arn-from-output> \
--region us-east-1
Add the CNAME records shown in the output.
Push a change to the canary branch or create a PR to test the deployment:
git checkout -b test-deployment
# Make a change to beps/docs/
git commit -am "Test deployment"
git push origin test-deployment
# Open PR on GitHub
You should see:
https://test-deployment.beps.boundaryml.comcd beps
uv run --with mkdocs-material --with mkdocs-awesome-pages-plugin mkdocs serve
Or use mise:
mise run bep:serve
mise run bep:new
mise run bep:update BEP-001
mise run bep:readme
┌─────────────────────────────────────────────────────────────┐
│ GitHub Actions │
│ (Triggered by push to canary or PR) │
└───────────────────────────┬─────────────────────────────────┘
│
│ OIDC Auth (no keys!)
│
▼
┌───────────────────────┐
│ IAM Role (Deploy) │
└───────────┬───────────┘
│
┌───────────┴───────────┐
│ │
▼ ▼
┌───────────────┐ ┌──────────────┐
│ S3 Bucket │ │ CloudFront │
│ │◄─────┤ │
│ /index.html │ │ Distribution│
│ /branch-1/ │ └──────┬───────┘
│ /branch-2/ │ │
└───────────────┘ │
│
▼
┌────────────────────────┐
│ CloudFront Function │
│ (Subdomain Router) │
└────────────────────────┘
│
┌─────────────────────┴──────────────────────┐
│ │
▼ ▼
beps.boundaryml.com branch.beps.boundaryml.com
→ /index.html → /branch/index.html
The CloudFront Function examines the Host header:
Main domain (beps.boundaryml.com)
/docs/setup/s3://bucket/docs/setup/index.htmlSubdomain (my-branch.beps.boundaryml.com)
/docs/setup/my-branchs3://bucket/my-branch/docs/setup/index.htmlThis allows infinite preview environments without changing infrastructure!
# Clean up a specific branch
BRANCH="my-feature"
aws s3 rm s3://baml-beps-123456789012/$BRANCH/ --recursive
aws cloudfront create-invalidation \
--distribution-id E1234567890ABC \
--paths "/$BRANCH/*"
Based on moderate usage (100 GB/month):
| Service | Monthly Cost |
|---|---|
| S3 Storage (10 GB) | $0.23 |
| S3 Requests (100K) | $0.04 |
| CloudFront (100 GB) | $8.50 |
| ACM Certificate | Free |
| Total | ~$9-10 |
aws s3 ls s3://bucket/branch-name/curl https://cloudfront-domain/branch-name/index.htmldig validation-domain.example.com CNAMEid-token: write permission in workflowcd beps/infrastructure
# Edit lib/beps-stack.ts
npm run diff # Preview changes
npm run deploy # Apply changes
cd beps
# Update mkdocs.yml
# Or update Python dependencies
CloudFront automatically scales. For very high traffic:
For issues: