Avm.Authoring
0.1.7
Minimum PowerShell version
7.4
Installation Options
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
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
- Avm.Authoring.nuspec
- Avm.Authoring.psd1
- Private\Assets\Resolve-AvmPolicyBundle.ps1
- Private\Output\ConvertTo-AvmResultLine.ps1
- Engines\Terraform\README.md
- Avm.Authoring.psm1
- Private\Assets\Resolve-AvmPinnedAsset.ps1
- Private\Output\Write-AvmLog.ps1
- Resources\tflint\avm.tflint_module.hcl
- README.md
- Private\Layout\Test-AvmModuleLayout.ps1
- Private\Output\Assert-AvmCommandSuccess.ps1
- Resources\tflint\avm.tflint.hcl
- Resources\avm.pins.jsonc
- Private\Tools\Expand-AvmToolArchive.ps1
- Private\Output\Write-AvmResult.ps1
- Resources\tflint\avm.tflint_example.hcl
- Resources\PSScriptAnalyzerSettings.psd1
- Private\Tools\Resolve-AvmMirrorUrl.ps1
- Private\Output\Get-AvmFailureDetail.ps1
- Resources\Rules\030-gitignore-essentials.psd1
- Public\Invoke-AvmCheckConvention.ps1
- Private\Tools\Install-AvmToolFromPins.ps1
- Engines\ManagedFiles\Merge-AvmFileLine.ps1
- Resources\Rules\010-outputs-tf-not-output-tf.psd1
- Public\Invoke-AvmDocs.ps1
- Private\Tools\Read-AvmPins.ps1
- Engines\ManagedFiles\Sync-AvmManagedFile.ps1
- Resources\Rules\023-tests-dir-must-exist.psd1
- Public\Invoke-AvmPreCommit.ps1
- Private\Tools\Invoke-AvmHttp.ps1
- Engines\Bicep\Invoke-AvmBicepDocs.ps1
- Resources\Rules\020-terraform-tf-must-exist.psd1
- Public\Invoke-AvmCheckPolicy.ps1
- Private\Tools\Test-AvmAutoInstallDisabled.ps1
- Engines\Bicep\Invoke-AvmBicepTransform.ps1
- Resources\Rules\011-variables-tf-not-variable-tf.psd1
- Public\Invoke-AvmPrCheck.ps1
- Private\Tools\Find-AvmToolOnPath.ps1
- Engines\Bicep\Invoke-AvmBicepCheckConvention.ps1
- Resources\Rules\021-header-md-must-exist.psd1
- Public\Get-AvmAuthoringPlaceholder.ps1
- Private\Tools\Resolve-AvmTool.ps1
- Engines\Bicep\Invoke-AvmBicepTest.ps1
- Resources\Rules\022-examples-dir-must-exist.psd1
- Public\Invoke-Avm.ps1
- Private\Tools\Test-AvmPins.ps1
- Engines\Bicep\Invoke-AvmBicepLint.ps1
- Resources\CustomRules\AvmAvoidStringThrow.psm1
- Public\Get-AvmVersion.ps1
- Private\Tools\Lock-AvmToolCache.ps1
- Engines\Bicep\Format-AvmBicepModule.ps1
- Private\Rules\Primitives\Test-AvmRuleFileMustNotExist.ps1
- Public\Invoke-AvmDoctor.ps1
- Private\Tools\Get-AvmToolPlatform.ps1
- Engines\Bicep\Invoke-AvmBicepCheckPolicy.ps1
- Private\Rules\Primitives\Test-AvmRuleGitignoreMustContain.ps1
- Public\Install-AvmTool.ps1
- Private\Folders\Get-AvmFolder.ps1
- Engines\Bicep\README.md
- Private\Rules\Primitives\Test-AvmRuleFileMustExist.ps1
- Public\Get-AvmModuleContext.ps1
- Private\Folders\Get-AvmFileSnapshot.ps1
- Engines\Terraform\Format-AvmTerraformModule.ps1
- Private\Rules\Primitives\Test-AvmRuleDirectoryMustExist.ps1
- Public\Invoke-AvmTestUnit.ps1
- Private\Process\Invoke-AvmProcess.ps1
- Engines\Terraform\Invoke-AvmTerraformTestE2e.ps1
- Resources\mapotf\pre-commit\required_provider_versions.mptf.hcl
- Public\Invoke-AvmTestIntegration.ps1
- Private\Process\ConvertFrom-AvmDotEnv.ps1
- Engines\Terraform\Invoke-AvmTerraformCheckPolicy.ps1
- Resources\mapotf\pre-commit\order_resource_meta.mptf.hcl
- Public\Invoke-AvmFormat.ps1
- Private\Process\New-AvmToolPathEnvironment.ps1
- Engines\Terraform\Invoke-AvmTerraformCheckConvention.ps1
- Resources\mapotf\pre-commit\move_misplaced_blocks.mptf.hcl
- Public\Get-AvmTool.ps1
- Private\Dispatch\Get-AvmVerbRegistry.ps1
- Engines\Terraform\Get-AvmTerraformE2eExample.ps1
- Resources\mapotf\pre-commit\avm_headers_for_azapi.mptf.hcl
- Public\Invoke-AvmSync.ps1
- Private\Dispatch\Test-AvmDisableSentinel.ps1
- Engines\Terraform\Invoke-AvmTerraformTransform.ps1
- Resources\mapotf\pre-commit\sort_outputs.mptf.hcl
- Public\Invoke-AvmTransform.ps1
- Private\Rules\AvmRule.ps1
- Engines\Terraform\Invoke-AvmTerraformLint.ps1
- Resources\mapotf\pre-commit\order_module_attrs.mptf.hcl
- Public\Invoke-AvmTestE2e.ps1
- Private\Rules\Read-AvmRuleSet.ps1
- Engines\Terraform\Invoke-AvmTerraformTestSuite.ps1
- Resources\mapotf\pre-commit\main_telemetry_tf.mptf.hcl
- Public\Invoke-AvmLint.ps1
- Private\Exceptions\AvmExceptions.ps1
- Engines\Terraform\Invoke-AvmTerraformTest.ps1
- Resources\mapotf\pre-commit\sort_variables.mptf.hcl
- Public\Invoke-AvmTest.ps1
- Private\Context\Read-AvmContextOverride.ps1
- Engines\Terraform\Invoke-AvmTerraformDocs.ps1
- Resources\mapotf\pre-commit\order_resource_attrs.mptf.hcl
- Private\Context\Get-AvmModuleContextInternal.ps1