Local Testing — Azure (floci-az)
Show the whole prompt
Read https://intentius.io/chant/local-testing/azure/.
In `examples/local-cloud-trio`, run `npm install` and then `npx chant run azure --no-record`. The run boots floci-az and applies the ARM template with `azApply`. It checks the storage account and then removes the container, and it needs Docker.
Keep the `endpoint` override on the local floci-az port, and show me what the run prints.
Never deploy to a real cloud account or shared environment (with `chant run`, `chant components` or a platform's own CLI), approve (a pull request review, `chant approve` or `chant run approve`), override a policy denial (`chant approve policy-override`), or merge; never cut or publish a release (`chant release cut --yes` or `chant release publish`), push or delete a `ci/*` tag (`chant ci tick` pushes them), or change the value of an existing flag; never touch `.chant/allowed_signers` or `chant/lifecycle`.Optional: hand this page to your coding agent
Read https://intentius.io/chant/local-testing/azure/.In `examples/local-cloud-trio`, run `npm install` and then `npx chant run azure --no-record`. The run boots floci-az and applies the ARM template with `azApply`. It checks the storage account and then removes the container, and it needs Docker.Keep the `endpoint` override on the local floci-az port, and show me what the run prints.Never deploy to a real cloud account or shared environment (with `chant run`, `chant components` or a platform's own CLI), approve (a pull request review, `chant approve` or `chant run approve`), override a policy denial (`chant approve policy-override`), or merge; never cut or publish a release (`chant release cut --yes` or `chant release publish`), push or delete a `ci/*` tag (`chant ci tick` pushes them), or change the value of an existing flag; never touch `.chant/allowed_signers` or `chant/lifecycle`.floci-az emulates Azure’s resource CRUD but not the Microsoft.Resources/deployments provider, so az deployment has nothing to talk to. azApply works around that: it reads the ARM template chant synthesizes and PUTs each resource straight to floci-az’s ARM resource endpoints, in dependency order, resolving ARM expressions from live responses as it goes.
The resource
Section titled “The resource”A storage account, described as data. It synthesizes to an ARM template:
// src/azure/infra.ts — StorageAccountSecure is a composite (secure defaults)export const { storageAccount } = StorageAccountSecure({ name: "triostore", location: "eastus", sku: "Standard_LRS", tags: { project: "cross-cloud-demo" },});The op
Section titled “The op”chant run azure boots floci-az, builds the ARM template, applies it with azApply, verifies the account over the ARM endpoint, and removes the container.
export default Op({ name: "azure", taskQueue: "trio-azure", phases: [ phase("Emulator", [flociAzUp()]), phase("Build", [build(".", { script: "build:azure" })]), phase("Apply", [azApply("dist/azure.json", { resourceGroup: "trio-rg", location: "eastus", endpoint: "http://localhost:4577" })]), phase("Verify", [httpCheck("http://localhost:4577/subscriptions/.../providers/Microsoft.Storage/storageAccounts/triostore?api-version=2025-06-01")]), phase("Teardown", [flociAzDown()]), ],});How azApply works
Section titled “How azApply works”az deployment submits a whole template to the deployments provider and lets Azure order and resolve it. floci-az has no such provider, so azApply does that work itself:
- Reads the ARM template chant emitted and ensures the resource group exists.
- Orders resources by their
resourceId/referencereferences — a referenced resource applies before the one that references it — and detects cycles. - Evaluates ARM expressions as it applies:
resourceGroup(),subscription(),concat,uniqueString,resourceId(...), plus the runtime-state functionsreference('name')andlistKeys(id, apiVersion), resolved from the live PUT responses of resources applied earlier in the run. - PUTs each resource to
{endpoint}{resourceId}?api-version=...and captures the response so later resources can reference it.
This is the same evaluation a real ARM deployment performs; azApply just runs it client-side against the emulator’s resource CRUD.
Run it
Section titled “Run it”Requires Docker and curl on PATH.
cd examples/local-cloud-trionpm installchant run azureDeleting and pruning
Section titled “Deleting and pruning”azDelete is the inverse of azApply: it reads the same template and deletes the resources it declares, in reverse dependency order (a referrer goes before what it references), idempotently.
azApply also takes prune: true for an owned-only prune — after applying, it deletes chant-managed resources of a templated type whose name is no longer in the template. chant stamps a managed-by: chant tag on everything it applies and only ever prunes tagged resources, so a foreign resource sharing the group is never touched.
From local to real cloud
Section titled “From local to real cloud”Drop the endpoint override and azApply targets real Azure ARM. The template, the ordering, and the expression evaluation are unchanged — only the resource-manager host differs.