Local Testing
chant synthesizes each cloud’s native format — CloudFormation for AWS, ARM for Azure, Config Connector for GCP — and can apply that output to a local emulator instead of a real account. You get a fast, free, offline run of the exact deployer code that stands things up in production, against a real cloud-shaped API.
This is not a mock. The applier issues the same calls it would against AWS, Azure, or GCP; only the endpoint changes. When a local run succeeds, you’ve exercised synthesis, serialization, and apply end-to-end.
The path deliberately has no CLI shell-out on it. chant build is a pure function — typed TypeScript in, a validated spec-native artifact out. The applier then speaks the cloud’s own protocol directly: awsApply calls the CloudFormation API, azApply PUTs ARM resources, gcpApply calls the GCS/PubSub/IAM REST APIs. It doesn’t wrap aws, az, or gcloud. That’s what makes a green local run meaningful — the thing under test is the real deployer, not a script around a CLI.
What runs locally
Section titled “What runs locally”Each cloud keeps its native format and its own local target. The emulators are the Floci suite — LocalStack-compatible, Quarkus/GraalVM native, one per cloud.
| Cloud | Resource shape | Synthesizes to | Applied by | Emulator | Port |
|---|---|---|---|---|---|
| AWS | S3, IAM, Lambda, … | CloudFormation | awsApply | floci | 4566 |
| Azure | Storage, KeyVault, … | ARM template | azApply | floci-az | 4577 |
| GCP | GCS, PubSub, Secrets, … | Config Connector | gcpApply | floci-gcp | 4588 |
The resource description is identical in shape across clouds. What differs is how each cloud’s apply reaches the emulator — because each cloud’s control plane is different.
Why three different appliers
Section titled “Why three different appliers”There is no shared apply verb off-cluster. Each cloud’s local story forced a different path:
- AWS —
awsApplycalls the CloudFormation API directly (create-or-update the stack, then poll it to a settled state) against Floci’s emulated CloudFormation control plane. The stack is the deploy boundary. - Azure — floci-az has no
Microsoft.Resources/deploymentsprovider, soaz deploymentcan’t run locally.azApplyreads the ARM template and PUTs each resource directly to floci-az’s ARM resource CRUD, in dependency order, resolvingreference()/listKeys()from live responses. - GCP — GCP has no native deployment service.
gcpApplymaps each Config Connector resource to its underlying REST call and drives create/update/delete itself, including long-running operations and orphan pruning.
In every case the deployer code is the thing under test, run against a real cloud-shaped API.
Pick your path
Section titled “Pick your path”Each page walks the full loop for one cloud: boot the emulator, build the stack, apply it, verify the resource, tear down.
The tri-cloud example
Section titled “The tri-cloud example”examples/local-cloud-trio is the reference for all three paths in one project. The same infrastructure — an object store — is described once per cloud and deployed to each cloud’s emulator.
cd examples/local-cloud-trionpm install
chant run aws # S3 bucket → Flocichant run azure # storage account → floci-azchant run gcp # GCS bucket → floci-gcpEach op boots that cloud’s emulator, builds the stack, applies it, verifies the resource exists, and tears the emulator down. The project needs Docker plus aws and curl on PATH — no cloud account.
The chant.config.ts loads all three cloud lexicons so chant run resolves each cloud’s applier activity:
export default { lexicons: ["aws", "azure", "gcp", "temporal"] } satisfies ChantConfig;From local to real cloud
Section titled “From local to real cloud”The emulator is only an endpoint. The same stacks and ops target a real account by dropping the endpoint override — and, for AWS, unsetting AWS_ENDPOINT_URL. Nothing about the resources or the apply logic changes, which is what makes a green local run meaningful.