From eba940968758c565f0f51b2b2ee3b9857607e1dc Mon Sep 17 00:00:00 2001 From: Jack Tracey <41163455+jtracey93@users.noreply.github.com> Date: Wed, 8 Jan 2025 12:11:35 +0000 Subject: [PATCH] feat: Add child module support to `publishModuleIndex.json` generation (#4130) ## Description Add child module support to `publishModuleIndex.json` generation Also refactored the adding to the object that gets converted to json into another function for DRY purposes and easier reuse ## Pipeline Reference | Pipeline | | -------- | | N/A - As none to test against as no child modules exist | Image below shows functioning as expected ![image](https://github.com/user-attachments/assets/e09d88d2-4c76-4794-a569-38584f4705df) ## Type of Change - [x] Update to CI Environment or utilities (Non-module affecting changes) - [ ] Azure Verified Module updates: - [ ] Bugfix containing backwards-compatible bug fixes, and I have NOT bumped the MAJOR or MINOR version in `version.json`: - [ ] Someone has opened a bug report issue, and I have included "Closes #{bug_report_issue_number}" in the PR description. - [ ] The bug was found by the module author, and no one has opened an issue to report it yet. - [ ] Feature update backwards compatible feature updates, and I have bumped the MINOR version in `version.json`. - [ ] Breaking changes and I have bumped the MAJOR version in `version.json`. - [ ] Update to documentation ## Checklist - [x] I'm sure there are no other open Pull Requests for the same update/change - [ ] I have run `Set-AVMModule` locally to generate the supporting module files. - [x] My corresponding pipelines / checks run clean and green without any errors or warnings --- .../Invoke-AvmJsonModuleIndexGeneration.ps1 | 147 ++++++++++++------ 1 file changed, 97 insertions(+), 50 deletions(-) diff --git a/utilities/pipelines/platform/Invoke-AvmJsonModuleIndexGeneration.ps1 b/utilities/pipelines/platform/Invoke-AvmJsonModuleIndexGeneration.ps1 index 0c0a5a2f07..b90939545a 100644 --- a/utilities/pipelines/platform/Invoke-AvmJsonModuleIndexGeneration.ps1 +++ b/utilities/pipelines/platform/Invoke-AvmJsonModuleIndexGeneration.ps1 @@ -71,8 +71,8 @@ function Invoke-AvmJsonModuleIndexGeneration { Write-Verbose "Generating the current generated moduleIndex.json file and saving to: $currentGeneratedModuleIndexJsonFilePath ..." -Verbose - $anyErrorsOccurred = $false - $moduleIndexData = @() + $global:anyErrorsOccurred = $false + $global:moduleIndexData = @() foreach ($avmModuleRoot in @('avm/res', 'avm/ptn', 'avm/utl')) { $avmModuleGroups = (Get-ChildItem -Path $avmModuleRoot -Directory).Name @@ -86,55 +86,37 @@ function Invoke-AvmJsonModuleIndexGeneration { $mainJsonPath = "$modulePath/main.json" $tagListUrl = "https://mcr.microsoft.com/v2/bicep/$modulePath/tags/list" - try { - Write-Verbose "Processing AVM Module '$modulePath'..." -Verbose - Write-Verbose " Getting available tags at '$tagListUrl'..." -Verbose - - try { - $tagListResponse = Invoke-RestMethod -Uri $tagListUrl - } catch { - $anyErrorsOccurred = $true - Write-Error "Error occurred while accessing URL: $tagListUrl" - Write-Error "Error message: $($_.Exception.Message)" - continue - } - $tags = $tagListResponse.tags | Sort-Object -Culture 'en-US' - - # Sort tags by order of semantic versioning with the latest version last - $tags = $tags | Sort-Object -Property { [semver] $_ } - - $properties = [ordered]@{} - foreach ($tag in $tags) { - $gitTag = "$modulePath/$tag" - $documentationUri = "https://github.com/Azure/bicep-registry-modules/tree/$gitTag/$modulePath/README.md" - - try { - $moduleMainJsonUri = "https://raw.githubusercontent.com/Azure/bicep-registry-modules/$gitTag/$mainJsonPath" - Write-Verbose " Getting available description for tag $tag via '$moduleMainJsonUri'..." -Verbose - $moduleMainJsonUriResponse = Invoke-RestMethod -Uri $moduleMainJsonUri - $description = $moduleMainJsonUriResponse.metadata.description - } catch { - $anyErrorsOccurred = $true - Write-Error "Error occurred while accessing description for tag $tag via '$moduleMainJsonUri'" - Write-Error "Error message: $($_.Exception.Message)" - continue - } + Add-ModuleToAvmJsonModuleIndex -modulePath $modulePath -mainJsonPath $mainJsonPath -tagListUrl $tagListUrl + + ## Find child modules that contain a main.bicep, main.json, README.md and version.json file + $verifiedChildModules = @() + $possibleChildModules = (Get-ChildItem -Path $modulePath -Directory -Exclude 'tests').Name + Write-Verbose ' Checking for possible child modules...' -Verbose + if ($possibleChildModules.Count -ne 0) { + Write-Verbose " Possible child modules: $possibleChildModules" -Verbose + foreach ($possibleChildModule in $possibleChildModules) { + Write-Verbose " Processing possible child module: $possibleChildModule" -Verbose + + $checkChildModuleContainsRequiredFilesForPublishing = (Test-Path -Path "$modulePath/$possibleChildModule/main.bicep") -and (Test-Path -Path "$modulePath/$possibleChildModule/main.json") -and (Test-Path -Path "$modulePath/$possibleChildModule/README.md") -and (Test-Path -Path "$modulePath/$possibleChildModule/version.json") + Write-Verbose " Child module contains required files for publishing?: $checkChildModuleContainsRequiredFilesForPublishing" -Verbose - $properties[$tag] = [ordered]@{ - description = $description - documentationUri = $documentationUri + if ($checkChildModuleContainsRequiredFilesForPublishing) { + Write-Verbose ' Add child module to array for inclusion in index JSON generation...' -Verbose + $verifiedChildModules += $possibleChildModule } } + } else { + Write-Verbose ' No possible child modules found for this module.' -Verbose + } - $moduleIndexData += [ordered]@{ - moduleName = $modulePath - tags = @($tags) - properties = $properties - } - } catch { - $anyErrorsOccurred = $true - Write-Error "Error message: $($_.Exception.Message)" + foreach ($verifiedChildModule in $verifiedChildModules) { + $childModulePath = "$modulePath/$verifiedChildModule" + $childModuleMainJsonPath = "$childModulePath/main.json" + $childModuleTagListUrl = "https://mcr.microsoft.com/v2/bicep/$childModulePath$mod/tags/list" + + Add-ModuleToAvmJsonModuleIndex -modulePath $childModulePath -mainJsonPath $childModuleMainJsonPath -tagListUrl $childModuleTagListUrl } + } $numberOfModuleGroupsProcessed++ @@ -142,10 +124,10 @@ function Invoke-AvmJsonModuleIndexGeneration { } Write-Verbose "Processed $numberOfModuleGroupsProcessed modules groups." -Verbose - Write-Verbose "Processed $($moduleIndexData.Count) total modules." -Verbose + Write-Verbose "Processed $($global:moduleIndexData.Count) total modules." -Verbose Write-Verbose "Convert moduleIndexData variable to JSON and save as 'generated-moduleIndex.json'" -Verbose - $moduleIndexData | ConvertTo-Json -Depth 10 | Out-File -FilePath $currentGeneratedModuleIndexJsonFilePath + $global:moduleIndexData | ConvertTo-Json -Depth 10 | Out-File -FilePath $currentGeneratedModuleIndexJsonFilePath ## Download the current published moduleIndex.json from the storage account if the $doNotMergeWithLastModuleIndexJsonFileVersion is set to $false if (-not $doNotMergeWithLastModuleIndexJsonFileVersion) { @@ -215,9 +197,74 @@ function Invoke-AvmJsonModuleIndexGeneration { } if ($doNotMergeWithLastModuleIndexJsonFileVersion -eq $true) { Write-Verbose "Convert currentGeneratedModuleIndexData variable to JSON and save as 'moduleIndex.json to overwrite it as `doNotMergeWithLastModuleIndexJsonFileVersion` was specified'" -Verbose - $moduleIndexData | ConvertTo-Json -Depth 10 | Out-File -FilePath $moduleIndexJsonFilePath -Force + $global:moduleIndexData | ConvertTo-Json -Depth 10 | Out-File -FilePath $moduleIndexJsonFilePath -Force } - return ($anyErrorsOccurred ? $false : $true) + return ($global:anyErrorsOccurred ? $false : $true) + +} + +function Add-ModuleToAvmJsonModuleIndex { + param ( + [Parameter(Mandatory = $true)] + [string] $modulePath, + + [Parameter(Mandatory = $false)] + [string] $mainJsonPath = "$modulePath/main.json", + + [Parameter(Mandatory = $false)] + [string] $tagListUrl = "https://mcr.microsoft.com/v2/bicep/$modulePath/tags/list" + ) + + try { + Write-Verbose "Processing AVM Module '$modulePath'..." -Verbose + Write-Verbose " Getting available tags at '$tagListUrl'..." -Verbose + + try { + $tagListResponse = Invoke-RestMethod -Uri $tagListUrl + } catch { + $global:anyErrorsOccurred = $true + Write-Error "Error occurred while accessing URL: $tagListUrl" + Write-Error "Error message: $($_.Exception.Message)" + continue + } + $tags = $tagListResponse.tags | Sort-Object -Culture 'en-US' + + # Sort tags by order of semantic versioning with the latest version last + $tags = $tags | Sort-Object -Property { [semver] $_ } + + $properties = [ordered]@{} + foreach ($tag in $tags) { + $gitTag = "$modulePath/$tag" + $documentationUri = "https://github.com/Azure/bicep-registry-modules/tree/$gitTag/$modulePath/README.md" + + try { + $moduleMainJsonUri = "https://raw.githubusercontent.com/Azure/bicep-registry-modules/$gitTag/$mainJsonPath" + Write-Verbose " Getting available description for tag $tag via '$moduleMainJsonUri'..." -Verbose + $moduleMainJsonUriResponse = Invoke-RestMethod -Uri $moduleMainJsonUri + $description = $moduleMainJsonUriResponse.metadata.description + } catch { + $global:anyErrorsOccurred = $true + Write-Error "Error occurred while accessing description for tag $tag via '$moduleMainJsonUri'" + Write-Error "Error message: $($_.Exception.Message)" + continue + } + + $properties[$tag] = [ordered]@{ + description = $description + documentationUri = $documentationUri + } + } + + $global:moduleIndexData += [ordered]@{ + moduleName = $modulePath + tags = @($tags) + properties = $properties + } + } catch { + $global:anyErrorsOccurred = $true + Write-Error "Error message: $($_.Exception.Message)" + } + return ($global:anyErrorsOccurred ? $false : $true) }