Public/Get-AvmLatestVersion.ps1
|
function Get-AvmLatestVersion { <# .SYNOPSIS Fetches all available versions and the latest stable version for a single AVM module. .DESCRIPTION Queries the appropriate registry (MCR for Bicep, Terraform Registry for Terraform) to retrieve all published versions of a module and determine the highest stable (non-preview, non-pre-release) semantic version. Caches responses in-memory for the duration of the run. On failure, returns an object with status='lookup-failed' without throwing. .PARAMETER RegistryPath The registry path of the module. For Bicep: 'bicep/avm/res/<group>/<module>'. For Terraform: 'Azure/<avmModuleName>/azurerm'. .PARAMETER Ecosystem The IaC ecosystem — 'bicep' or 'terraform'. .PARAMETER Config Configuration hashtable (loaded from avmupdater.config.json). Used for timeout/retry. .OUTPUTS PSCustomObject with: registryPath, ecosystem, latestStable, allVersions[], status. .EXAMPLE Get-AvmLatestVersion -RegistryPath 'bicep/avm/res/storage/storage-account' -Ecosystem 'bicep' .EXAMPLE Get-AvmLatestVersion -RegistryPath 'Azure/avm-res-storage-storageaccount/azurerm' -Ecosystem 'terraform' #> [CmdletBinding()] [OutputType([PSCustomObject])] param( [Parameter(Mandatory)] [string]$RegistryPath, [Parameter(Mandatory)] [ValidateSet('bicep', 'terraform')] [string]$Ecosystem, [Parameter()] [hashtable]$Config = @{} ) # In-memory cache keyed by registryPath+ecosystem (module-level variable, initialized in psm1) $cacheKey = "$Ecosystem|$RegistryPath" if ($script:_AvmVersionCache.ContainsKey($cacheKey)) { Write-Verbose "Cache hit: $cacheKey" return $script:_AvmVersionCache[$cacheKey] } $cfg = if ($Config.Count) { $Config } else { Get-AvmConfig } $timeout = $cfg.registry.httpTimeoutSeconds $retries = $cfg.registry.maxRetries $delay = $cfg.registry.retryDelaySeconds $result = [PSCustomObject]@{ registryPath = $RegistryPath ecosystem = $Ecosystem latestStable = $null allVersions = @() status = 'ok' } try { $rawVersions = Invoke-WithRetry -MaxRetries $retries -DelaySeconds $delay -OperationName "version-lookup:$RegistryPath" -ScriptBlock { if ($Ecosystem -eq 'bicep') { $url = "https://mcr.microsoft.com/v2/$RegistryPath/tags/list" $response = Invoke-RestMethod -Uri $url -TimeoutSec $timeout -ErrorAction Stop return $response.tags } else { $url = "https://registry.terraform.io/v1/modules/$RegistryPath/versions" $response = Invoke-RestMethod -Uri $url -TimeoutSec $timeout -ErrorAction Stop return $response.modules[0].versions | ForEach-Object { $_.version } } } # Filter: keep only valid semver, drop 'latest' and pre-release (beta/rc/alpha/...) versions $stable = $rawVersions | Where-Object { $_ -and $_ -ne 'latest' } | ForEach-Object { $parsed = ConvertTo-SemVer -Version $_ if ($parsed -and -not $parsed.PreReleaseLabel) { [PSCustomObject]@{ Original = $_; Parsed = $parsed } } } | Sort-Object -Property Parsed -Descending | ForEach-Object { $_.Original } $result.allVersions = @($stable) $result.latestStable = $stable | Select-Object -First 1 } catch { Write-Warning "Version lookup failed for ${RegistryPath}: $_" $result.status = 'lookup-failed' } $script:_AvmVersionCache[$cacheKey] = $result return $result } |