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'
}
}
}