Avm.Authoring

0.1.7

Cross-platform PowerShell 7 CLI that consolidates the authoring and CI tooling for Azure Verified Modules (https://aka.ms/avm). A single avm command (alias: avm) works across both ecosystems and ships: environment diagnostics (avm version, avm doctor); a checksum-pinned managed-tool resolver (avm tool list/which/install) that downloads and verifies the exact terraform
Cross-platform PowerShell 7 CLI that consolidates the authoring and CI tooling for Azure Verified Modules (https://aka.ms/avm). A single avm command (alias: avm) works across both ecosystems and ships: environment diagnostics (avm version, avm doctor); a checksum-pinned managed-tool resolver (avm tool list/which/install) that downloads and verifies the exact terraform, terraform-docs, tflint, conftest and mapotf binaries a module needs; and a fully wired Terraform authoring chain - avm pre-commit fixes and checks a module locally (convention checks, HCL transforms via mapotf, terraform fmt and terraform-docs) while avm pr-check adds tflint, APRL/AVMSEC policy checks and terraform validate. No Docker, make or porch required. The Bicep facade is in active development. Requires PowerShell 7.4+ (Core). See https://github.com/Azure/azure-verified-modules-tools for status and docs.
Show more

Minimum PowerShell version

7.4

Installation Options

Copy and Paste the following command to install this package using PowerShellGet More Info

Install-Module -Name Avm.Authoring

Copy and Paste the following command to install this package using Microsoft.PowerShell.PSResourceGet More Info

Install-PSResource -Name Avm.Authoring

You can deploy this package directly to Azure Automation. Note that deploying packages with dependencies will deploy all the dependencies to Azure Automation. Learn More

Manually download the .nupkg file to your system's default download location. Note that the file won't be unpacked, and won't include any dependencies. Learn More

Owners

Copyright

(c) Microsoft Corporation. All rights reserved.

Package Details

Author(s)

  • Azure Verified Modules

Tags

Azure AVM AzureVerifiedModules Bicep Terraform Authoring CLI

Functions

Get-AvmAuthoringPlaceholder Get-AvmModuleContext Get-AvmTool Get-AvmVersion Install-AvmTool Invoke-Avm Invoke-AvmCheckConvention Invoke-AvmCheckPolicy Invoke-AvmDoctor Invoke-AvmDocs Invoke-AvmFormat Invoke-AvmLint Invoke-AvmPrCheck Invoke-AvmPreCommit Invoke-AvmSync Invoke-AvmTest Invoke-AvmTestE2e Invoke-AvmTestIntegration Invoke-AvmTestUnit Invoke-AvmTransform

PSEditions

Core

Dependencies

This module has no dependencies.

Release Notes

Second remediation round from end-to-end testing released `0.1.6` against the
canary repo `Azure/terraform-azurerm-avm-ptn-example-repo` (F23–F48).

Two numbering sequences collided during review, so the `F` tags below are
branch-local. Where a reviewer used the same number for a different defect, the
mapping is:

| Reviewer ID | Tag used here | Defect |
| --- | --- | --- |
| F39 | F41 | Three unanchored `::error::` annotations per failure, worst-first |
| F40 | F42 | `format` and `docs` auto-fix the CI working copy and report `pass` |

Both are fixed in this release. The F39 and F40 tags below refer to the
shell-hook guard and the empty-tier status respectively.

### Breaking

- **`avm pr-check` now fails on formatting and documentation drift.** `format`
 and `docs` previously rewrote your files in the CI working copy and reported
 `pass`, so the fix was thrown away with the runner and the defect merged. Both
 steps now check rather than fix, and report `fail` with one issue per file. A
 repository with unformatted sources or a stale `README.md` that passed on
 `0.1.6` will fail on `0.1.7`. **Action required:** run `avm pre-commit`
 locally and commit the result. `pre-commit` still auto-fixes — only `pr-check`
 gates. (F42)
- **The end-to-end check name has changed.** Fanning e2e out across a per-example
 matrix renames the check from `End-to-end tests` to
 `End-to-end tests (<example>)`, one per example. A branch protection rule that
 requires the old literal name will not error — it will simply never be
 satisfied, and pull requests will wait on a check that no longer reports.
 **Action required:** in Settings → Branches → your protection rule, remove the
 required check `End-to-end tests` and add each `End-to-end tests (<example>)`
 entry that now appears. Do this in the same change that picks up `0.1.7`.
- `avm` no longer writes result objects to the success stream. Anything that
 captured a command's output as an object needs `--passthru` to get it back.
 (F23)
- `avm test e2e --example <name>` treats an unknown name, or one carrying a
 `.e2eignore` marker, as a hard error rather than a silent skip. This is
 deliberate — it is what stops a typo in a CI matrix from quietly passing — but
 a matrix generated by hand rather than by `--list` may now fail.
- The round-robin subscription fan-out reads `TEST_SUBSCRIPTION_IDS`. Repos
 configured with only `ARM_SUBSCRIPTION_ID` still work through the preserved
 fallback path, but every parallel matrix leg then deploys into the same
 subscription and may hit quota where a sequential run did not.
- **`avm pr-check` now runs the unit test tier, and its `test` step is renamed
 to `validate`.** The step called `test` never ran a test: it routes to
 `terraform validate` / `bicep build`, reports `FilesProcessed` and carries no
 run counts, so a module whose tests were broken — or entirely absent — still
 produced an all-green gauntlet in a few seconds. The step is now named for
 what it does, and a real `unit test` step runs after it.

 Two consequences. `pr-check` gets slower by the cost of your unit tier
 (~20s on a typical module). And it can newly fail: if your unit tests were
 never actually running locally, this is the run that tells you. Both are the
 point — `pr-check` documents itself as running *every check that runs in CI*,
 and that claim was not true while the unit tier was absent. Only the unit
 tier is included, because it is the one tier that is credential-free by
 design; `integration` and `e2e` need a live subscription and stay out.
 `avm pre-commit` is unchanged and still offline. (F38)
- **A repo misconfiguration now fails the gauntlet instead of skipping it.**
 `avm pr-check` and `avm pre-commit` mapped every `AvmConfigurationException`
 to `skipped`, which does not flip the overall status. That type is thrown
 both for "this verb does not apply to this ecosystem" and for real
 misconfigurations — an unresolvable tflint or mapotf config bundle, an
 unresolvable managed-files repo id, an invalid `.avm` context override,
 `AVM_OFFLINE=1`, an invalid `AVM_MIRROR`, an unknown or `.e2eignore`d e2e
 example. Any of those inside a gauntlet step rendered as a benign green run.
 Ecosystem gates now throw the new `AvmNotSupportedException` (which derives
 from `AvmConfigurationException`, so nothing else changes), and only that
 type still skips. **Action required:** none, unless one of your repos was
 quietly misconfigured — in which case the gauntlet will now say so. The step
 fails rather than errors, so the chain still runs to the end and reports
 every problem instead of stopping at the first. (F39)
- **A test tier with no test files now reports `skipped`, not `pass`.**
 `avm test unit`, `avm test integration` and `avm test e2e` returned
 `Status: pass` with `FilesProcessed = 0` when the module shipped no
 `tests/<tier>/*.tftest.hcl` (or no runnable `examples/`). Once F38 put the
 unit tier inside `pr-check`, that rendered as `unit test -> pass` for a module
 with no tests at all — indistinguishable from a real pass, and exactly the
 vacuous-green failure mode the F33 run counts exist to prevent, one level up.
 `skipped` does not flip the overall status and the CLI still exits `0`, so a
 module with no tier is reported rather than broken. **Action required:** none,
 unless you parse `Status` from these verbs — an absent tier now yields
 `skipped`. A tier whose files exist but execute no `run` blocks still reports
 `pass`; `RunsTotal = 0` is the signal there. (F40)

### Upgrade notes

- **`tflint --init` needs an authenticated token outside the reusable workflow.**
 TFLint resolves its ruleset plugins through the GitHub releases API, which
 allows 60 unauthenticated requests per hour *per source IP*. Hosted runners
 share an egress IP, so a busy period surfaces as an intermittent, platform-
 correlated lint failure that looks like a flake rather than a rate limit.
 `.github/workflows/terraform-module.yml` and this repo's own CI now both set
 `GITHUB_TOKEN` for the 5,000/hour authenticated budget, and a workflow-contract
 test keeps the two from drifting apart again. If you self-host runners, or call
 `tflint` outside the reusable workflow, set `GITHUB_TOKEN` in that environment
 too.

### Added

- `avm test e2e --example <name>` targets a single example. It accepts either
 the folder leaf (`example-a`) or a repo-relative path (`examples/example-a`)
 and may be repeated. Omitting it keeps the existing behaviour of running every
 runnable example sequentially. A name that does not exist, or that carries a
 `.e2eignore` marker, is a hard error listing the valid names rather than a
 silent pass, so a typo in a CI matrix cannot skip a real test. (F26)
- `avm test e2e --list` emits a compact JSON array of runnable example names and
 nothing else, so a workflow can build a matrix with `fromJson()` and no
 post-processing. A module with no runnable examples emits `[]`. (F27)
- The Terraform reusable workflow fans end-to-end tests out across a per-example
 matrix with `fail-fast: false`, restoring the governance round-robin
 subscription fan-out so parallel legs do not collide on quota. The matrix is
 skipped cleanly when a module has no runnable examples.
- Every step and sub-step now carries `StartTime`, `EndTime` and a duration, both
 on the result objects and in the rendered output. (F29)
- `RUNNER_DEBUG=1` (set when a workflow is re-run with debug logging) turns
 verbose on, and verbose now cascades from the entry point to engines,
 sub-cmdlets and `Invoke-AvmProcess`. `AVM_VERBOSE=1` does the same outside
 GitHub Actions. (F30)
- `avm test unit` and `avm test integration` report `RunsTotal`, `RunsPassed` and
 `RunsFailed` alongside `FilesProcessed`, and render the tally. A file count is a
 poor coverage signal; a run count exposes an empty suite immediately. (F33)

### Changed

- All module output routes through a single writer with levels, which is GitHub
 Actions aware (`::group::`, `::error::`, `::warning::`, `::debug::`) instead of
 mixing `Write-Host`, `Write-Information` and `Write-Verbose`. (F31)
- Subprocess output is quiet by default and replayed in full at the point of
 failure. Verbose or debug streams it live; GitHub Actions wraps it in a
 collapsed `::group::` so the log is present but not noisy. Long-running
 sub-steps emit a periodic elapsed-time heartbeat so a slow deploy is
 distinguishable from a hang. (F28)
- `avm` renders one summary per invocation instead of one per emitted result
 object, and labels per-item rows with the item's own identity, so
 `avm tool list` no longer reads as six conflicting statuses for one command.
 (F25)
- `avm` no longer writes result objects to the success stream by default; pass
 `--passthru` to get them back for scripting. (F23)
- Both test tiers now invoke `terraform test` identically and render a progress
 line per test run with its duration, instead of the unit tier running silently
 and the integration tier dumping raw `-json` NDJSON on the human channel. The
 `terraform init` sub-step follows the same quiet-by-default rule as everything
 else. (F33)
- Caller-rendered progress is no longer collapsed behind a GitHub Actions
 `::group::`. Grouping exists to fold away raw child output, and a sub-step that
 supplies its own line renderer emits no raw output, so the fold hid exactly the
 curated per-run progress it was meant to reveal. (F33)

### Fixed

- The release workflow no longer fails at the point of publishing. The `build`
 task stamps the tag's whole CHANGELOG section into the staged manifest's
 `ReleaseNotes`, and the PowerShell Gallery rejects any package whose
 `ReleaseNotes` exceeds 10600 characters — 0.1.7's section is 23987, so the
 first attempt was rejected with `400 (The package is invalid)` *after* the tag
 and the GitHub Release already existed. `Get-AvmReleaseNotes.ps1` gained
 `-MaxLength`, which truncates on a line boundary from the bottom (a section
 leads with `### Breaking`, so the tail is the safe end to lose) and appends a
 link to the full notes on the GitHub Release, which has no such limit. Newlines

---

These notes are truncated to fit the PowerShell Gallery's 10600-character limit. Full notes: https://github.com/Azure/azure-verified-modules-tools/releases/tag/v0.1.7

FileList

Version History

Version Downloads Last updated
0.1.7 (current version) 16 7/31/2026
0.1.6 13 7/31/2026
0.1.5 9 7/31/2026
0.1.4 16 7/30/2026
0.1.3 3 7/30/2026
0.1.0 44 6/23/2026
Show more