utilities/tools/Set-Module.ps1 (131 lines of code) (raw):

#requires -version 7.3 <# .SYNOPSIS Create/update all content of an AVM module that can be generated for the user .DESCRIPTION Create/update all content of an AVM module that can be generated for the user This includes - The `main.json` template(s) - The `README.md` file(s) .PARAMETER ModuleFolderPath Mandatory. The path to the module folder to generate the content for. .PARAMETER Recurse Optional. Set this parameter if you not only want to generate the content for one module, but also any nested module in the same path. .PARAMETER Depth Optional. Recursion depth for the module search. .PARAMETER SkipBuild Optional. Set this parameter if you don't want to build/compile the JSON template(s) for the contained `main.bicep` file(s). .PARAMETER SkipReadMe Optional. Set this parameter if you don't want to generate the ReadMe file(s) for the module(s). .PARAMETER SkipFileAndFolderSetup Optional. Set this parameter if you don't want to setup the file & folder structure for the module(s). .PARAMETER ThrottleLimit Optional. The number of parallel threads to use for the generation. Defaults to 5. .EXAMPLE Set-Module -ModuleFolderPath 'C:\avm\res\key-vault\vault' For the [key-vault\vault] module, build the Bicep module template & generate its ReadMe. .EXAMPLE Set-Module -ModuleFolderPath 'C:\avm\res\key-vault\vault' -Recurse For the [key-vault\vault] module or any of its children, build the Bicep module template & generate the ReadMe. .EXAMPLE Set-Module -ModuleFolderPath 'C:\avm\res\key-vault\vault' -Recurse -SkipReadMe For the [key-vault\vault] module or any of its children, build only the Bicep module template. .EXAMPLE Set-Module -ModuleFolderPath 'C:\avm\res' -Recurse For all modules in path [C:\avm\res], build the Bicep module template & generate the ReadMe. #> function Set-Module { [CmdletBinding(SupportsShouldProcess = $true)] param ( [Parameter(Mandatory = $true)] [string] $ModuleFolderPath, [Parameter(Mandatory = $false)] [switch] $Recurse, [Parameter(Mandatory = $false)] [switch] $SkipBuild, [Parameter(Mandatory = $false)] [switch] $SkipReadMe, [Parameter(Mandatory = $false)] [switch] $SkipFileAndFolderSetup, [Parameter(Mandatory = $false)] [int] $ThrottleLimit = 5, [Parameter(Mandatory = $false)] [int] $Depth ) # # Load helper scripts # . (Join-Path $PSScriptRoot 'helper' 'Set-ModuleFileAndFolderSetup.ps1') $resolvedPath = (Resolve-Path $ModuleFolderPath).Path # Build up module file & folder structure if not yet existing. Should only run if an actual module path was provided (and not any of their parent paths) # if (-not $SkipFileAndFolderSetup -and ((($resolvedPath -split '\bavm\b')[1].Trim('\,/') -split '[\/|\\]').Count -gt 2)) { # if ($PSCmdlet.ShouldProcess("File & folder structure for path [$resolvedPath]", "Setup")) { # Set-ModuleFileAndFolderSetup -FullModuleFolderPath $resolvedPath # } # } if ($Recurse) { $childInput = @{ Path = $resolvedPath Recurse = $Recurse File = $true Filter = 'main.bicep' } if ($Depth) { $childInput.Depth = $Depth } $relevantTemplatePaths = (Get-ChildItem @childInput).FullName } else { $relevantTemplatePaths = Join-Path $resolvedPath 'main.bicep' } # Load recurring information we'll need for the modules if (-not $SkipReadMe) { . (Join-Path $PSScriptRoot 'Get-CrossReferencedModuleList.ps1') # load cross-references $crossReferencedModuleList = Get-CrossReferencedModuleList # create reference as it must be loaded in the thread to work $ReadMeScriptFilePath = (Join-Path (Get-Item $PSScriptRoot).Parent.FullName 'pipelines' 'sharedScripts' 'Set-ModuleReadMe.ps1') } else { # Instatiate values to enable safe $using usage $crossReferencedModuleList = $null $ReadMeScriptFilePath = $null } # Using threading to speed up the process if ($PSCmdlet.ShouldProcess(('Building & generation of [{0}] modules in path [{1}]' -f $relevantTemplatePaths.Count, $resolvedPath), 'Execute')) { try { $job = $relevantTemplatePaths | ForEach-Object -ThrottleLimit $ThrottleLimit -AsJob -Parallel { $resourceTypeIdentifier = ((Split-Path $_) -split '[\/|\\]{1}modules[\/|\\]{1}')[1] # avm/res/<provider>/<resourceType> ############### ## Build ## ############### if (-not $using:SkipBuild) { Write-Output "Building [$resourceTypeIdentifier]" bicep build $_ } ################ ## ReadMe ## ################ if (-not $using:SkipReadMe) { Write-Output "Generating readme for [$resourceTypeIdentifier]" # If the template was just build, we can pass the JSON into the readme script to be more efficient $readmeTemplateFilePath = (-not $using:SkipBuild) ? (Join-Path (Split-Path $_ -Parent) 'main.json') : $_ . $using:ReadMeScriptFilePath Set-ModuleReadMe -TemplateFilePath $readmeTemplateFilePath -CrossReferencedModuleList $using:crossReferencedModuleList } } do { # Sleep a bit to allow the threads to run - adjust as desired. Start-Sleep -Seconds 0.5 # Determine how many jobs have completed so far. $completedJobsCount = ($job.ChildJobs | Where-Object { $_.State -notin @('NotStarted', 'Running') }).Count # Relay any pending output from the child jobs. $job | Receive-Job # Update the progress display. [int] $percent = ($completedJobsCount / $job.ChildJobs.Count) * 100 Write-Progress -Activity ("Processed [$completedJobsCount/{0}] files" -f $relevantTemplatePaths.Count) -Status "$percent% complete" -PercentComplete $percent } while ($completedJobsCount -lt $job.ChildJobs.Count) # Clean up the job. $job | Remove-Job } finally { # In case the user cancelled the process, we need to make sure to stop all running jobs $job | Remove-Job -Force -ErrorAction 'SilentlyContinue' } } }