AWS CDK app describing Maple's infrastructure: a shared VPC, an ECS cluster, an
RDS Postgres instance, an HTTP API Gateway, and two Typesense search services
(dev and prod). Everything is deployed by a self-mutating CodePipeline defined
in maple/infra/cicd_stack.py, which triggers on pushes to main.
This project uses uv. Python and every dependency
are pinned in uv.lock.
uv syncThe CDK CLI is an npm package, not a Python one, and is pinned to the version the pipeline uses:
npm install -g aws-cdk@2.1139.0uv run pytest # synth regression tests, no AWS credentials needed
cdk synth # write CloudFormation to cdk.out/
cdk diff # compare against what is deployed (needs credentials)
uv run black app.py maple tests # formatcdk.json points the CLI at uv run --frozen --no-dev python3 app.py, so cdk
picks up the locked environment without a separate activation step.
The CDK CLI refuses to deploy against a bootstrap stack older than what the synthesized app declares. Check both numbers before a deploy:
# what the app needs (currently 6)
grep -o '"requiresBootstrapStackVersion": *[0-9]*' cdk.out/manifest.json
# what the account has (currently 15)
aws ssm get-parameter --name /cdk-bootstrap/hnb659fds/version \
--region us-east-1 --query Parameter.Value --output textIf the deployed number is lower, run cdk bootstrap aws://<account>/<region>.
One-time note for the poetry-to-uv migration: the pipeline is self-mutating,
and its deployed Synth step still runs the old poetry commands. The first
commit that removes poetry.lock therefore fails Synth before SelfMutate can
pick up the new commands, and a revert push fails the same way. That commit
must be deployed once by hand — cdk deploy Maple from a credentialed
workstation — after which pushes to main self-mutate normally again.
Separately, bootstrap versions below 21 are affected by AWS advisory aws-cdk#31885: if the asset bucket alone is ever deleted, a third party can recreate it under the predictable name and receive subsequent asset uploads. Version 21 scopes the file publishing role to same-account buckets. Re-bootstrapping clears it and is independent of any app deploy.
cdk.context.jsonholds the AWS account, region, CodeConnections ARN, and the Typesense image tag. It is committed on purpose.- The
contextblock incdk.jsonis a pinned set of CDK feature flags. Unlisted flags keep their pre-flag defaults; adopting new ones changes synthesized output, so do it deliberately and in its own change. tests/test_synth.pypins the CloudFormation logical IDs of the two Typesense admin key secrets. Those secrets hold live API keys — renaming or re-scoping the constructs that own them would delete and recreate them. Treat a failure there as a stop sign, not a snapshot to update.