Skip to content

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.

Typed resources → chant build → spec-native artifact → native applier (awsApply / azApply / gcpApply) speaking each cloud's own API → endpoint override → Floci emulator or real cloud Typed resources → chant build → spec-native artifact → native applier (awsApply / azApply / gcpApply) speaking each cloud's own API → endpoint override → Floci emulator or real cloud
The same pipeline, local or real — the applier speaks each cloud's native protocol, and only the endpoint changes

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.

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.

CloudResource shapeSynthesizes toApplied byEmulatorPort
AWSS3, IAM, Lambda, …CloudFormationawsApplyfloci4566
AzureStorage, KeyVault, …ARM templateazApplyfloci-az4577
GCPGCS, PubSub, Secrets, …Config ConnectorgcpApplyfloci-gcp4588

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.

There is no shared apply verb off-cluster. Each cloud’s local story forced a different path:

  • AWSawsApply calls 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/deployments provider, so az deployment can’t run locally. azApply reads the ARM template and PUTs each resource directly to floci-az’s ARM resource CRUD, in dependency order, resolving reference()/listKeys() from live responses.
  • GCP — GCP has no native deployment service. gcpApply maps 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.

Each page walks the full loop for one cloud: boot the emulator, build the stack, apply it, verify the resource, tear down.

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.

Terminal window
cd examples/local-cloud-trio
npm install
chant run aws # S3 bucket → Floci
chant run azure # storage account → floci-az
chant run gcp # GCS bucket → floci-gcp

Each 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;

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.