| title | Use a local Dialect |
|---|---|
| description | Try a Dialect against a real plan, test its evidence, then record it in the project selection. |
A Dialect interprets provider instances. Keep its source beside the project while authoring, pass --dialect for one run, and add it to rootform.lock only after reviewing the resulting facts. This example uses random_pet to keep the plan small; the same sequence applies to a provider-specific Dialect with architectural Contexts and Relations.
Prerequisites: Rootform, Terraform, and a project directory you control. OpenTofu users run the Terraform commands with tofu. Run commands below from that directory. The plan JSON and saved plan can carry cleartext secrets in a real project; keep them out of Git. Plan inputs gives the complete export and protection procedure.
Use this small project and Dialect source to observe one interpretation:
.
├── main.tf
└── dialects/
└── network-review/
└── dialect.rf.hcl
terraform {
required_providers {
random = {
source = "hashicorp/random"
version = "= 3.9.1"
}
}
}
resource "random_pet" "service" {
length = 2
}dialect "network-review" {
version = "0.1.0"
provider "hashicorp/random" {
version = "= 3.9.1"
}
}
concept "generated-identifier" {
description = "An identifier generated for a service."
}
rule "service-name" {
match {
kind = "resource"
type = "random_pet"
}
as = concept.generated-identifier
}
The manifest binds the provider and the Rule identifies eligible instances. as gives an interpreted instance a Concept; this example emits no Context or Relation. Write a Dialect explains Rules, endpoint identity, null handling, and evidence tests.
Produce a saved plan and its JSON export. Rootform reads the completed export; it never runs Terraform or contacts the provider:
terraform init
terraform plan -out=plan.tfplan
terraform show -json plan.tfplan > plan.jsonTry the source for this run without changing the project selection:
rootform run plan.json --plan-file plan.tfplan --require-enrichment \
--dialect ./dialects/network-review --no-serve -o analysis.jsonPlan analyzed
Enrichment Saved plan paired with this plan JSON (1 module)
Architecture
Instances 1
Interpreted 1
Facts none determined
The instance is interpreted, while no facts are determined because the Rule only classifies it. Inspect the Form or rootform explain instance random_pet.service --input analysis.json when the result differs. --dialect compiles current source each run and never writes the lock.
Check the Dialect source and show the Rule before recording a golden:
rootform validate dialects ./dialects/network-review
rootform show network-review.rule.service-name \
--dialect ./dialects/network-reviewnetwork-review.rule.service-name
Matches resource "random_pet"
Produces network-review.concept.generated-identifier
Defined dialect.rf.hcl:13
validate compiles the source; show confirms the selected Rule's match and output. Neither proves what a particular plan instance did. Keep a fixture for that proof:
fixtures/network/
├── plan.json
├── plan.tfplan
└── analysis.golden
Copy the plan pair to the fixture. Record a reviewed golden once with rootform test ./fixtures --dialect ./dialects/network-review --update; then run the ordinary test after each Rule change:
rootform test ./fixtures --dialect ./dialects/network-reviewTests passed
1 case
The test analyzes plan.json, verifies the adjacent saved plan, and compares the resulting Form with analysis.golden. A mismatch is a review signal: inspect changed interpretations, facts, closures, and diagnostics before updating the golden. Test and validate covers fixture behavior.
Once its result is right, select it for this project:
rootform add dialects ./dialects/network-reviewrootform.lock updated
add Dialect network-review 0.1.0 (dialects/network-review)
The lock records the owner, version, digest, and project-relative local path. Commit it with Dialect source and reviewed fixture. Future runs use the selection through --project without the override; --locked checks that it has not drifted. If the source changes later, try it with --dialect, then run rootform update dialect network-review to record the new digest. init never adopts source drift. If your owner collides with an embedded Dialect, add requires an explicit --replace; review the loss of that embedded owner's Rules first.
After selection, a source edit changes the compiled content digest. A normal locked run refuses it instead of silently adopting new meaning. Continue testing the edited source with --dialect; when its fixture and analysis are right, run rootform update dialect network-review from the project root and review the lock diff. Commit the updated source, golden, and lock together.
From the project root, copy the selected Dialect into the project so another checkout can use it without the original source directory:
rootform vendor dialects --offline
git add rootform.lock .rootform/dialects/network-reviewThe vendored copy lives at .rootform/dialects/network-review/. In a clone
that contains the lock and this directory, prepare and analyze offline:
rootform init . --locked --offline --no-input
rootform run plan.json --plan-file plan.tfplan --locked --no-serveSee the rootform vendor dialects reference
for selection requirements and other destinations, and
external content storage for what to commit. For
several repositories, package and publish the Dialect,
then select its reviewed OCI reference in each project.
If the project no longer needs this interpretation, remove its selection:
rootform remove dialects network-reviewrootform.lock updated
remove Dialect network-review 0.1.0 (dialects/network-review)
The source directory remains. A later analysis can still show the base Representation for random_pet.service, but no Rule interprets it. Reproduce an analysis offline shows how to prove another environment loaded a reviewed selection.