utilities/pipelines/platform/Sync-AvmModulesList.ps1 (174 lines of code) (raw):

<# .SYNOPSIS If module list is not in sync with CSV file, an issue is created .DESCRIPTION CSV data for moules and pattern is loaded and compared with the list in the issue template. If they are not in sync, an issue with the necessary changes is created .PARAMETER Repo Mandatory. The name of the respository to scan. Needs to have the structure "<owner>/<repositioryName>", like 'Azure/bicep-registry-modules/' .PARAMETER RepoRoot Optional. Path to the root of the repository. .EXAMPLE Sync-AvmModulesList -Repo 'Azure/bicep-registry-modules' .NOTES Will be triggered by the workflow platform.sync-avm-modules-list.yml #> function Sync-AvmModulesList { param ( [Parameter(Mandatory = $true)] [string] $Repo, [Parameter(Mandatory = $false)] [string] $RepoRoot = (Get-Item -Path $PSScriptRoot).parent.parent.parent.FullName ) # Loading helper functions . (Join-Path $RepoRoot 'utilities' 'pipelines' 'platform' 'helper' 'Get-AvmCsvData.ps1') . (Join-Path $RepoRoot 'utilities' 'pipelines' 'platform' 'helper' 'Add-GitHubIssueToProject.ps1') # get CSV data $targetModules = Get-AvmCsvData -ModuleIndex 'Bicep-Resource' | Where-Object { ($_.ModuleStatus -eq 'Available :green_circle:') -or ($_.ModuleStatus -eq 'Orphaned :eyes:') } | Select-Object -ExpandProperty 'ModuleName' | Sort-Object $targetPatterns = Get-AvmCsvData -ModuleIndex 'Bicep-Pattern' | Where-Object { ($_.ModuleStatus -eq 'Available :green_circle:') -or ($_.ModuleStatus -eq 'Orphaned :eyes:') } | Select-Object -ExpandProperty 'ModuleName' | Sort-Object $targetUtilities = Get-AvmCsvData -ModuleIndex 'Bicep-Utility' | Where-Object { ($_.ModuleStatus -eq 'Available :green_circle:') -or ($_.ModuleStatus -eq 'Orphaned :eyes:') } | Select-Object -ExpandProperty 'ModuleName' | Sort-Object $issueTemplatePath = Join-Path $RepoRoot '.github' 'ISSUE_TEMPLATE' 'avm_module_issue.yml' $issueTemplateContent = Get-Content $issueTemplatePath # Identify listed modules $startIndex = 0 while ($issueTemplateContent[$startIndex] -notmatch '^\s*#?\s*\-\s+\"avm\/.+\"' -and $startIndex -ne $issueTemplateContent.Length) { $startIndex++ } $endIndex = $startIndex while ($issueTemplateContent[$endIndex] -match '.*- "avm\/.*' -and $endIndex -ne $issueTemplateContent.Length) { $endIndex++ } $endIndex-- # Go one back to last module line $listedModules = $issueTemplateContent[$startIndex..$endIndex] | Where-Object { -not $_.Contains('#') } | ForEach-Object { $_ -replace '.*- "(avm\/.*)".*', '$1' } | Where-Object { $_ -match 'avm\/res\/.*' } $listedPatterns = $issueTemplateContent[$startIndex..$endIndex] | Where-Object { -not $_.Contains('#') } | ForEach-Object { $_ -replace '.*- "(avm\/.*)".*', '$1' } | Where-Object { $_ -match 'avm\/ptn\/.*' } $listedUtilities = $issueTemplateContent[$startIndex..$endIndex] | Where-Object { -not $_.Contains('#') } | ForEach-Object { $_ -replace '.*- "(avm\/.*)".*', '$1' } | Where-Object { $_ -match 'avm\/utl\/.*' } $body = '' $missingModules = $targetModules | Where-Object { $listedModules -NotContains $_ } $unexpectedModules = $listedModules | Where-Object { $targetModules -NotContains $_ } $missingPatterns = $targetPatterns | Where-Object { $listedPatterns -NotContains $_ } $unexpectedPatterns = $listedPatterns | Where-Object { $targetPatterns -NotContains $_ } $missingUtilities = $targetUtilities | Where-Object { $listedUtilities -NotContains $_ } $unexpectedUtilities = $listedUtilities | Where-Object { $targetUtilities -NotContains $_ } # Resource modules # ---------------- if ($missingModules.Count -gt 0) { $body += @" **Missing resource modules:** $($missingModules -join ([Environment]::NewLine)) $([Environment]::NewLine) "@ } if ($unexpectedModules.Count -gt 0) { $body += @" **Unexpected resource modules:** $($unexpectedModules -join ([Environment]::NewLine)) $([Environment]::NewLine) "@ } # Patterns # -------- if ($missingPatterns.Count -gt 0) { $body += @" **Missing pattern modules:** $($missingPatterns -join ([Environment]::NewLine)) $([Environment]::NewLine) "@ } if ($unexpectedPatterns.Count -gt 0) { $body += @" **Unexpected pattern modules:** $($unexpectedPatterns -join ([Environment]::NewLine)) $([Environment]::NewLine) "@ } # Utilities # --------- if ($missingUtilities.Count -gt 0) { $body += @" **Missing utility modules:** $($missingUtilities -join ([Environment]::NewLine)) $([Environment]::NewLine) "@ } if ($unexpectedUtilities.Count -gt 0) { $body += @" **Unexpected utility modules:** $($unexpectedUtilities -join ([Environment]::NewLine)) $([Environment]::NewLine) "@ } # Resource modules # ---------------- # Should be at correct location $incorrectModuleLines = @() foreach ($finding in (Compare-Object $listedModules ($listedModules | Sort-Object) -SyncWindow 0)) { if ($finding.SideIndicator -eq '<=') { $incorrectModuleLines += $finding.InputObject } } $incorrectModuleLines = $incorrectModuleLines | Sort-Object -Unique if ($incorrectModuleLines.Count -gt 0) { $body += @" **Resource modules that are not correctly sorted:** $($incorrectModuleLines -join ([Environment]::NewLine)) $([Environment]::NewLine) "@ } # Patterns # -------- $incorrectPatternLines = @() foreach ($finding in (Compare-Object $listedPatterns ($listedPatterns | Sort-Object) -SyncWindow 0)) { if ($finding.SideIndicator -eq '<=') { $incorrectPatternLines += $finding.InputObject } } $incorrectPatternLines = $incorrectPatternLines | Sort-Object -Unique if ($incorrectPatternLines.Count -gt 0) { $body += @" **Pattern modules that are not correctly sorted:** $($incorrectPatternLines -join ([Environment]::NewLine)) $([Environment]::NewLine) "@ } # Utilities # --------- $incorrectUtilityLines = @() foreach ($finding in (Compare-Object $listedUtilities ($listedUtilities | Sort-Object) -SyncWindow 0)) { if ($finding.SideIndicator -eq '<=') { $incorrectUtilityLines += $finding.InputObject } } $incorrectUtilityLines = $incorrectUtilityLines | Sort-Object -Unique if ($incorrectUtilityLines.Count -gt 0) { $body += @" **Utility modules that are not correctly sorted:** $($incorrectUtilityLines -join ([Environment]::NewLine)) $([Environment]::NewLine) "@ } $issuesFound = $body -ne '' $title = '[AVM core] AVM Module Issue template is not in sync with published resource modules and pattern modules list' $label = 'Type: AVM :a: :v: :m:,Type: Hygiene :broom:' $issues = gh issue list --state open --limit 500 --label $label --json 'title,url' --repo $Repo | ConvertFrom-Json -Depth 100 $body = @" > [!IMPORTANT] > The file [avm_module_issue.yml](https://github.com/Azure/bicep-registry-modules/blob/main/.github/ISSUE_TEMPLATE/avm_module_issue.yml?plain=1) which lists all modules when creating a new issue, is not in sync with the CSV files, that can be found under [resource modules](https://aka.ms/avm/index/bicep/res/csv), [pattern modules](https://aka.ms/avm/index/bicep/ptn/csv) and [utility modules](https://aka.ms/avm/index/bicep/utl/csv). These CSV files are the single source of truth regarding published modules. Please update the ``avm_module_issue.yml`` accordingly. Please see the following differences that were found. $([Environment]::NewLine) "@ + $body if ($issues.title -notcontains $title) { if ($issuesFound) { # create issue $issueUrl = gh issue create --title $title --body $body --label $label --repo $Repo # add issue to project $ProjectNumber = 538 # AVM - Issue Triage Add-GitHubIssueToProject -Repo $Repo -ProjectNumber $ProjectNumber -IssueUrl $issueUrl } } else { if ($issuesFound) { # update body gh issue edit $issues[0].url --body $body --repo $Repo } else { # close issue gh issue close $issues[0].url --repo $Repo } } }