Skip to content

Tags: Azure/ALZ-PowerShell-Module

Tags

v7.1.4

Toggle v7.1.4's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
fix: bump hcl2json parser to v0.6.9 for namespaced provider functions (

…#535)

## Summary

Bumps the pinned `hcl2json` (HCLToJSON) parser version from `v0.6.0` to
**`v0.6.9`** in `Deploy-Accelerator.ps1`, so the accelerator can parse
Terraform **provider-defined (namespaced) functions**.

## Root cause

When running `Deploy-Accelerator`, the ALZ module downloads the
`tmccombs/hcl2json` binary and uses it to convert the accelerator's
`variables.*.tf` template files into JSON to build the input config
schema.

A template in the `alz-terraform-accelerator` repo
(`templates/platform_landing_zone/variables.connectivity.virtual.wan.tf`)
now uses a provider-defined function:

```hcl
|| can(provider::azapi::parse_resource_id("Microsoft.Network/virtualWans", var.virtual_wan_settings.virtual_wan.id).name)
```

The pinned `hcl2json` `v0.6.0` vendors `github.com/hashicorp/hcl/v2
v2.17.0`, which predates support for the namespaced
`provider::<ns>::<func>()` call syntax (added to `hashicorp/hcl/v2` in
**v2.20.0**, "Support for namespaced functions"). So `v0.6.0` parses
`provider` as a normal identifier, hits the first `::`, and fails:

```
Failed to convert file: parse config: [...variables.connectivity.virtual.wan.tf:1043,22-23: Missing argument separator; A comma is required to separate each function argument from the next.]
```

(col 22–23 is exactly the first `::`.)

## Fix

Bump to `hcl2json` **`v0.6.9`** (latest release), which vendors
`hashicorp/hcl/v2 v2.24.0` and fully supports the namespaced function
syntax. This unblocks parsing of `provider::azapi::parse_resource_id` in
the platform landing zone variables.

## Notes

- `Private/Tools/Get-HCLParserTool.ps1` needs **no changes** — it builds
the asset filename as `hcl2json_<os>_<arch>` (plus `.exe` on Windows)
and downloads from
`https://github.com/tmccombs/hcl2json/releases/download/<toolVersion>/<asset>`.
The `v0.6.9` release assets keep the same naming scheme, so the
downloader is compatible.
- `v0.6.0` was the only hard-coded reference to the parser version in
the repo; the `.gitignore` entry for the binary is version-agnostic and
the unit tests mock `Get-HCLParserTool`.
- Module versioning is handled by release automation (release-drafter),
so the `.psd1` ModuleVersion is intentionally left untouched, matching
repo precedent.

## Validation

`Invoke-Build -File .\src\ALZ.build.ps1 -Task TestLocal` → **Build
succeeded. 7 tasks, 0 errors, 0 warnings.**
- PSScriptAnalyzer (Module + Tests): clean
- Pester: **47 passed, 0 failed, 0 skipped**

## Files changed

- `src/ALZ/Public/Deploy-Accelerator.ps1` — `toolVersion` `v0.6.0` →
`v0.6.9`

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

v7.1.3

Toggle v7.1.3's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
fix: stage release downloads outside target folder so failures don't …

…leave empty dirs (#534)

v7.1.2

Toggle v7.1.2's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
fix: handle expired gh CLI tokens and macOS restricted file access (#533

)

## Summary

Fixes two classes of user-reported failures:

1. **GitHub API 403s when the `gh` CLI token is expired.** The module
attaches the token from `gh auth token` to API requests; when that token
is expired or has insufficient scopes, `api.github.com` returns 403 and
the deployment fails with a misleading downstream error (`The release v
does not exist...`).
2. **macOS file access errors** on protected paths when reading files
without `-Force`.

## Changes

### GitHub auth resiliency

- `Invoke-GitHubApiRequest`: when the attached `gh` token causes a
401/403, automatically retry once without auth (anonymous, subject to
rate limits) and warn the user to run `gh auth login`. Applies to all
three code paths (file download, `SkipHttpErrorCheck`, standard API
call). Factored repeated logic into `Disable-AuthAndWarn` and
`Get-StatusCodeFromError` helpers.
- `Get-GithubReleaseTag`: on 401/403, throw an actionable error naming
the likely cause (expired gh token or rate limiting) and the fix (`gh
auth login`) instead of the generic "check your internet connection"
message.
- `Test-NetworkConnectivity`: inspect the status code from the
`api.github.com` probe and record 401/403 as a Failure with the same
guidance, so connectivity checks surface this issue up front.

### macOS file access

- Added `-Force` to every `Get-Item`, `Get-ChildItem`, and `Get-Content`
call across the module so reads succeed on macOS paths where
hidden/protected attributes would otherwise block access. (`Test-Path` /
`Resolve-Path` intentionally untouched — they do not support `-Force`.)

### UX

- `Get-AzureContext`: clarified that "Querying Azure for management
groups, subscriptions, and regions..." can take up to 30 seconds.

## Testing

- `Invoke-Build -File .\src\ALZ.build.ps1` — passes locally.
- Existing `Test-NetworkConnectivity.Tests.ps1` still covers the mocked
success/failure paths.

v7.1.1

Toggle v7.1.1's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
feat: add SMB scenarios 10 and 11, load scenarios from JSON config (#532

)

## Summary

Adds missing SMB scenarios 10 and 11 to the accelerator folder structure
creation, and refactors scenario management to use the existing
`TerraformScenarios.json` config file as the single source of truth.

Closes Azure/Azure-Landing-Zones#4105

## Changes

### TerraformScenarios.json
- Added `path` property to each scenario entry, mapping scenario numbers
to their tfvars file paths
- Scenarios 10 and 11 were already present (labels only) — now they also
have paths:
  - **10**: `smb-single-region/hub-and-spoke-vnet.tfvars`
  - **11**: `smb-single-region/virtual-wan.tfvars`

### New-AcceleratorFolderStructure.ps1
- Replaced hardcoded `` hashtable with dynamic loading from
`TerraformScenarios.json`
- Fixed `int64`/`int32` type mismatch when looking up scenario paths
(JSON parser returns `int64`, parameter is `[int]`/`int32` — without the
cast, hashtable lookup returns `` and `Copy-Item` creates a directory
instead of copying the file)

v7.1.0

Toggle v7.1.0's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
refactor: extract Terraform scenarios to JSON config and add SMB scen…

…arios (#531)

## Summary

Azure/Azure-Landing-Zones#4095

Extract the hardcoded Terraform scenario options from
`Request-AcceleratorConfigurationInput.ps1` into a dedicated
`TerraformScenarios.json` config file, making it easier to add, remove,
or update scenarios without modifying PowerShell code.

## Changes

- **New file**: `TerraformScenarios.json` - JSON array of scenario
objects with `label` and `value` properties
- **Modified**: `Request-AcceleratorConfigurationInput.ps1` - loads
scenarios from the JSON file via `ConvertFrom-Json` instead of inline
array
- **Added scenarios 10-11**: SMB Single-Region Hub and Spoke VNet /
Virtual WAN (per Azure/alz-terraform-accelerator#305)

v7.0.5

Toggle v7.0.5's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Add verbose logging to Invoke-HttpRequestWithRetry (#530)

Adds Write-Verbose logging to Invoke-HttpRequestWithRetry so HTTP
request details and errors are visible when running with -Verbose.

## Changes
- Log request method, URI, retry config, timeout, and download path on
entry
- Log each attempt number
- Log transient status codes before retrying
- Log final status code on success with SkipHttpErrorCheck
- Log download completion with file path
- Log status code and exception message on errors

v7.0.4

Toggle v7.0.4's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Refactor HTTP requests to use centralized Invoke-HttpRequestWithRetry (

…#529)

## Summary

Introduces a new `Invoke-HttpRequestWithRetry` cmdlet that centralizes
HTTP retry logic for transient errors (408, 429, 500, 502, 503, 504) and
refactors existing callers to use it.

## Changes

- **New cmdlet**: `Invoke-HttpRequestWithRetry` in `Private/Shared` —
wraps `Invoke-WebRequest` with configurable retry count, interval, and
transient status code handling
- **Refactored** `Invoke-GitHubApiRequest` to delegate retry logic to
the new shared cmdlet instead of implementing its own retry loop
- **Updated** `Test-NetworkConnectivity` to use
`Invoke-HttpRequestWithRetry` instead of calling `Invoke-WebRequest`
directly
- **Updated** `Get-TerraformTool` to use `Invoke-HttpRequestWithRetry`
for HashiCorp API calls and file downloads
- **Updated** unit tests to mock `Invoke-HttpRequestWithRetry` instead
of `Invoke-WebRequest`

## Benefits

- Single place to maintain retry logic, reducing duplication
- Consistent retry behavior across all HTTP calls in the module
- Easier to test and extend retry behavior in the future

v7.0.3

Toggle v7.0.3's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
feat: centralize GitHub API requests with auth and retry logic (#528)

## Summary

Introduces a centralized `Invoke-GitHubApiRequest` function that
consolidates all GitHub API calls with:

- **Automatic authentication** via GitHub CLI (`gh auth token`) when
available, increasing API rate limits
- **Configurable retry logic** for transient HTTP errors (408, 429, 500,
502, 503, 504)
- **Consistent error handling** across all GitHub API interactions

## Changes

### New Function
- **`Invoke-GitHubApiRequest`** — Central function for all GitHub HTTP
requests with auth header injection and retry support

### Updated Functions
- **`Get-GithubRelease`** — Uses `Invoke-GitHubApiRequest` instead of
`Invoke-WebRequest` for downloading release artifacts
- **`Get-GithubReleaseTag`** — Uses `Invoke-GitHubApiRequest` instead of
`Invoke-RestMethod` with inline retry logic removed
- **`Get-HCLParserTool`** — Uses `Invoke-GitHubApiRequest` for
downloading HCL parser binaries
- **`Test-NetworkConnectivity`** — Routes `api.github.com` connectivity
check through `Invoke-GitHubApiRequest`
- **`New-ModuleSetup`** — Propagates `maxRetryCount` parameter; fixes
`isFirstRun` → `firstRun` variable references
- **`New-FolderStructure`** — Accepts and passes through `maxRetryCount`
parameter
- **`Deploy-Accelerator`** — Adds `github_max_retry_count` parameter
(alias: `gmrc`, `githubMaxRetryCount`)

### Tests
- Updated `Test-NetworkConnectivity.Tests.ps1` to mock
`Invoke-GitHubApiRequest` for the GitHub API endpoint

v7.0.2

Toggle v7.0.2's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
feat: Add NetworkConnectivity pre-flight check to Test-AcceleratorReq…

…uirement (#527)

- [x] Understand current state of checks in `Deploy-Accelerator.ps1` and
`Test-NetworkConnectivity.ps1`
- [x] Add `https://www.powershellgallery.com` endpoint to
`Test-NetworkConnectivity.ps1`
- [x] Add `NetworkConnectivity` to the checks in
`Deploy-Accelerator.ps1` (guarded by `skip_internet_checks`)
- [x] Update `Test-NetworkConnectivity.Tests.ps1` endpoint count
assertions: 5 → 6
- [x] All 47 unit tests pass

<!-- START COPILOT ORIGINAL PROMPT -->



<details>

<summary>Original prompt</summary>


## Summary

Add a new `NetworkConnectivity` check to `Test-AcceleratorRequirement`
(and the underlying `Test-Tooling` plumbing) that probes the external
URLs the module must reach during a Bicep deployment, before any
download or API call is attempted.

## Background

Currently the module has no pre-flight network reachability check. It
assumes connectivity is present and only surfaces failures at the point
of use (e.g. inside `Invoke-WebRequest`/`Invoke-RestMethod`). This makes
it hard for users in restricted environments to diagnose connectivity
issues early.

## Changes Required

### 1. New file:
`src/ALZ/Private/Tools/Checks/Test-NetworkConnectivity.ps1`

Create a new check function following the same pattern as the existing
checks (e.g. `Test-GitInstallation.ps1`). It should:

- Probe each of the external endpoints the module calls during a Bicep
deployment using `Invoke-WebRequest` with `-Method Head` (or a
lightweight GET where HEAD is not supported), with a short timeout (e.g.
10 seconds) and `-SkipHttpErrorCheck` / `-ErrorAction SilentlyContinue`
so it doesn't throw.
- Return a `Results` array and a `HasFailure` bool in the same shape as
all other checks.
- Treat any endpoint that **cannot be reached** (connection error /
timeout) as a **Failure**, and any reachable endpoint (even a non-200
status, which may just be auth) as a **Success** — the goal is
reachability, not authentication.
- The endpoints to check are:

| Endpoint | Purpose |
|---|---|
| `https://api.github.com` | GitHub API (release tag lookups) |
| `https://github.com` | Bootstrap & starter module downloads |
| `https://api.releases.hashicorp.com` | Terraform version resolution |
| `https://releases.hashicorp.com` | Terraform binary download |
| `https://management.azure.com` | Azure Management API |

Example skeleton (follow the pattern of `Test-GitInstallation.ps1`):

```powershell
function Test-NetworkConnectivity {
    [CmdletBinding()]
    param()

    $results = @()
    $hasFailure = $false

    $endpoints = @(
        @{ Uri = "https://api.github.com";                   Description = "GitHub API (release lookups)" },
        @{ Uri = "https://github.com";                       Description = "GitHub (module downloads)" },
        @{ Uri = "https://api.releases.hashicorp.com";       Description = "HashiCorp Releases API (Terraform version)" },
        @{ Uri = "https://releases.hashicorp.com";           Description = "HashiCorp Releases (Terraform binary download)" },
        @{ Uri = "https://management.azure.com";             Description = "Azure Management API" }
    )

    foreach ($endpoint in $endpoints) {
        Write-Verbose "Testing network connectivity to $($endpoint.Uri)"
        try {
            $response = Invoke-WebRequest -Uri $endpoint.Uri -Method Head -TimeoutSec 10 -SkipHttpErrorCheck -ErrorAction Stop -UseBasicParsing
            $results += @{
                message = "Network connectivity to $($endpoint.Description) ($($endpoint.Uri)) is available."
                result  = "Success"
            }
        } catch {
            $results += @{
                message = "Cannot reach $($endpoint.Description) ($($endpoint.Uri)). Check network/firewall settings. Error: $($_.Exception.Message)"
                result  = "Failure"
            }
            $hasFailure = $true
        }
    }

    return @{
        Results    = $results
        HasFailure = $hasFailure
    }
}
```

### 2. Update `src/ALZ/Private/Tools/Test-Tooling.ps1`

- Add `"NetworkConnectivity"` to the `[ValidateSet(...)]` on the
`$Checks` parameter.
- Add a new `if ($Checks -contains "NetworkConnectivity")` block that
calls `Test-NetworkConnectivity` and accumulates results, following the
same pattern as the other checks.

### 3. Update `src/ALZ/Public/Test-AcceleratorRequirement.ps1`

- Add `"NetworkConnectivity"` to the `[ValidateSet(...)]` on the
`$Checks` parameter.
- Add `"NetworkConnectivity"` to the **default** value of `$Checks` so
it runs automatically when `Test-AcceleratorRequirement` is called with
no arguments.
- Update the `.SYNOPSIS`/`.DESCRIPTION` doc comment to mention the
network connectivity check.

### 4. Add unit tests:
`src/Tests/Unit/Private/Test-NetworkConnectivity.Tests.ps1`

Add Pester unit tests for `Test-NetworkConnectivity` following the
pattern used by other tests in `src/Tests/Unit/`. Cover at minimum:
- All endpoints reachable → no failure, all Success results.
- One or more endpoints unreachable (mock `Invoke-WebRequest` to throw)
→ `HasFailure = $true`, correct Failure messages.

## Notes

- **Do not** add `NetworkConnectivity` to the default checks inside
`Deploy-Accelerator.ps1` — it already has its own
`$skip_internet_checks` bypass path and calling a network check there
would be redundant. The check belongs in `Test-AcceleratorRequirement`
only.
- Keep the check **non-blocking** in the sense that it should check all
endpoints and report all failures, not stop at the first unreachable
one.
- Follow t...

</details>



<!-- START COPILOT CODING AGENT SUFFIX -->

*This pull request was created from Copilot chat.*
>

<!-- START COPILOT CODING AGENT TIPS -->
---

✨ Let Copilot coding agent [set things up for
you](https://github.com/Azure/ALZ-PowerShell-Module/issues/new?title=✨+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%20coding%20agent%20in%20your%20repository%5D%28https://gh.io/copilot-coding-agent-tips%29%2E%0A%0A%3COnboard%20this%20repo%3E&assignees=copilot)
— coding agent works faster and does higher quality work when set up for
your repo.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: jtracey93 <41163455+jtracey93@users.noreply.github.com>

v7.0.1

Toggle v7.0.1's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
feat: improve yaml serialisation (#526)