Power Platform Terraform Development Workflow
Development Workflow
Follow these steps when implementing changes to a Power Platform Terraform module:
0. Initialize from Template
- Choose a module classification based on scope:
res-*— Resource module (wraps a single resource type)ptn-*— Pattern module (composes multiple resources)utl-*— Utility module (data lookups and helpers)
- Replace the placeholder comments in
main.tfwith actual resource definitions. - Update
terraform.tfwith the correctmicrosoft/power-platformprovider version constraint. - Write
_header.mddescribing the module's purpose (used by terraform-docs to generateREADME.md). - Update
_footer.mdwith any additional notes, if needed. - Set the registry source in every
examples/**/main.tf— stripterraform-powerplatform-from the repo name to get{module-name}, then setsource = "rpothin/{module-name}/powerplatform". Noversionargument. SeeAGENTS.mdfor the canonical rule and examples. - Run
terraform init -backend=falseto initialize the working directory.
1. Branch
git checkout -b feat/<short-description>
Use conventional prefixes: feat/, fix/, docs/, ci/, refactor/, test/.
2. Implement
- Add resources in
main.tf - Add input variables in
variables.tfwith descriptions and validation blocks - Add outputs in
outputs.tfwith descriptions - Add local computations in
locals.tf - Update provider constraints in
terraform.tfif needed
Examples Structure
Every module MUST provide two examples:
| Directory | Purpose | Contents |
|---|---|---|
examples/basic/ |
Minimum viable configuration | Required inputs only; simplest working configuration with sensible defaults |
examples/complete/ |
Full-featured configuration | All optional features exercised; realistic end-to-end scenario |
Each example MUST:
- Have its own
_header.mddescribing the scenario - Have
README.mdauto-generated by terraform-docs - Be referenced in
tests/unit/ortests/integration/viamodule { source = "./examples/basic" } - Use the registry
source(derived from the repo name — seeAGENTS.md), with noversionargument, so consumers always resolve to the latest published version
Example test referencing the basic example:
mock_provider "powerplatform" {}
run "basic_example_plan" {
command = plan
module {
source = "./examples/basic"
}
assert {
condition = true
error_message = "Basic example must plan successfully."
}
}
Correct example source format:
module "this" {
source = "rpothin/res-environment/powerplatform"
# ... module inputs
}
3. Format & Validate
terraform fmt -recursive
terraform validate
Optional: If tflint is installed, run
tflint --recursivefor additional linting beyondterraform validate. Add a.tflint.hclat the module root to enable the terraform plugin:plugin "terraform" { enabled = true preset = "recommended" }Run
tflint --initonce after creating this file.
4. Test
# Run unit tests (no credentials needed)
terraform test -test-directory=tests/unit
# Run integration tests (requires OIDC credentials)
terraform test -test-directory=tests/integration
5. Generate Documentation
terraform-docs .
Verify that README.md is updated. Never edit README.md manually — it is auto-generated.
6. Security Scan
trivy config .
Trivy uses .trivy.yaml at the repo root for configuration. The template ships a minimal config scoped to the template itself (no real resources). When building a real module from this template, review and adjust .trivy.yaml — see Security Guidance for the full process.
Resolve any HIGH or CRITICAL findings before committing. If a finding is a confirmed false positive for Power Platform resources, suppress it by rule ID in .trivy.yaml with an explanatory comment. Uncommented suppressions will be rejected in code review.
7. Commit & Push
git add .
git commit -m "feat: <concise description>"
git push origin feat/<short-description>
Code Quality Rules
Variables
- Every variable must have a
description - Every variable must have a
type - Use
validationblocks for input constraints - Sensitive values must be marked
sensitive = true - Use
nullable = falsewhen null is not a valid input - Optional inputs SHOULD have a
defaultvalue; defaults MUST represent the most secure, compliant, and governance-aligned configuration for the attribute — prefer the most restrictive, least-privilege value that still makes the module useful out of the box, minimising the number of required inputs while delivering a strong baseline without extra caller configuration - Sensitive inputs MUST NOT have a
defaultvalue (see TFNFR23 in AVM Alignment Guide)
Outputs
- Every output must have a
description - Mark sensitive outputs with
sensitive = true - Output the resource ID and name at minimum
Resources
- Use meaningful resource names that describe purpose
- Always set
lifecycleblocks explicitly when needed - Tag resources using the
tagsvariable pattern - Never hardcode credentials — use OIDC or environment variables
Naming Conventions
- File names: lowercase with hyphens (
main.tf,variables.tf) - Variable names: lowercase with underscores (
environment_id) - Resource names: lowercase with underscores (
powerplatform_environment.this) - Output names: lowercase with underscores (
resource_id)
Provider Conventions
- Pin provider version with pessimistic constraint (
~> 4.0) - Pin Terraform version range:
>= 1.9, < 2.0 - Provider configuration belongs in
terraform.tf
Power Platform–Specific Conventions
- Use OIDC authentication for CI/CD (no client secrets in pipelines)
- Environment IDs are UUIDs — validate format when accepting as input
- DLP policies may restrict connector usage — document any connector dependencies
- Power Platform resources may have propagation delays — use appropriate timeouts
Tools & MCP Integration
Terraform MCP Server
The Terraform MCP Server allows AI agents to look up live provider schemas from the Terraform Registry at runtime. This is especially valuable for the Power Platform provider, which is not as well-represented in LLM training data as major cloud providers.
Configure the MCP server in your AI tool:
{
"mcpServers": {
"terraform": {
"command": "docker",
"args": ["run", "-i", "--rm", "-e", "TFE_TOKEN", "-e", "TFE_ADDRESS", "hashicorp/terraform-mcp-server"],
"env": {
"TFE_TOKEN": "${TFE_TOKEN}",
"TFE_ADDRESS": "${TFE_ADDRESS}"
}
}
}
}
With this configured, agents can query the exact attributes, types, and descriptions for any microsoft/power-platform resource before writing code — preventing hallucinated resource arguments.
Related Skills
For detailed guidance on specific topics, the agent should load the appropriate skill:
- terraform-style — File organization, naming, formatting, version pinning, provider resource reference
- terraform-testing —
.tftest.hclsyntax, mock providers, unit/integration testing patterns - terraform-avm — AVM specification mapping, compliance checklist
- terraform-security — OIDC authentication, credential handling, DLP, Trivy configuration
Source: rpothin/terraform-github-res-repository — distributed by TomeVault.