utilities/pipelines/publish/helper/Get-ModulesToPublish.ps1 (172 lines of code) (raw):

#region Helper functions <# .SYNOPSIS Get modified files between previous and current commit depending on if you are running on main/master or a custom branch. .EXAMPLE Get-ModifiedFileList Directory: .utilities\pipelines\publish Mode LastWriteTime Length Name ---- ------------- ------ ---- la--- 08.12.2021 15:50 7133 Script.ps1 Get modified files between previous and current commit depending on if you are running on main/master or a custom branch. #> function Get-ModifiedFileList { if ((Get-GitBranchName) -eq 'main') { Write-Verbose 'Gathering modified files from the previous head' -Verbose $Diff = git diff --name-only --diff-filter=AM HEAD^ HEAD } $ModifiedFiles = $Diff ? ($Diff | Get-Item -Force) : @() return $ModifiedFiles } <# .SYNOPSIS Get the name of the current checked out branch. .DESCRIPTION Get the name of the current checked out branch. If git cannot find it, best effort based on environment variables is used. .EXAMPLE Get-CurrentBranch Get the name of the current checked out branch. #> function Get-GitBranchName { [CmdletBinding()] param () # Get branch name from Git $BranchName = git branch --show-current # If git could not get name, try GitHub variable if ([string]::IsNullOrEmpty($BranchName) -and (Test-Path env:GITHUB_REF_NAME)) { $BranchName = $env:GITHUB_REF_NAME } return $BranchName } <# .SYNOPSIS Find the closest main.json file to the changed files in the module folder structure. .DESCRIPTION Find the closest main.json file to the changed files in the module folder structure. .PARAMETER ModuleFolderPath Mandatory. Path to the main/parent module folder. .PARAMETER PathsToInclude Mandatory. Paths to include in the search for the closest main.json file. .PARAMETER SkipNotVersionedModules Optional. Specify if filtering the list by returning only versioned modified modules. .EXAMPLE Get-TemplateFileToPublish -ModuleFolderPath ".\avm\storage\storage-account\" .\avm\storage\storage-account\table-service\table\main.json Gets the closest main.json file to the changed files in the module folder structure. Assuming there is a changed file in 'storage\storage-account\table-service\table' and that a version.json file exists in the same folder, the function would return the main.json file in the same folder. #> function Get-TemplateFileToPublish { [CmdletBinding()] param ( [Parameter(Mandatory)] [string] $ModuleFolderPath, [Parameter(Mandatory)] [string[]] $PathsToInclude = @(), [Parameter(Mandatory = $false)] [switch] $SkipNotVersionedModules ) $ModuleRelativeFolderPath = (($ModuleFolderPath -split '[\/|\\](avm)[\/|\\](res|ptn|utl)[\/|\\]')[-3..-1] -join '/') -replace '\\', '/' $ModifiedFiles = Get-ModifiedFileList -Verbose Write-Verbose "Looking for modified files under: [$ModuleRelativeFolderPath]" -Verbose $modifiedModuleFiles = $ModifiedFiles.FullName | Where-Object { $_ -like "*$ModuleFolderPath*" } $relevantPaths = @() $PathsToInclude += './version.json' # Add the file itself to be considered too foreach ($modifiedFile in $modifiedModuleFiles) { foreach ($path in $PathsToInclude) { if ($modifiedFile -eq (Resolve-Path (Join-Path (Split-Path $modifiedFile) $path) -ErrorAction 'SilentlyContinue')) { $relevantPaths += $modifiedFile } } } $TemplateFilesToPublish = $relevantPaths | ForEach-Object { Find-TemplateFile -Path $_ -Verbose } | Sort-Object -Culture 'en-US' -Unique -Descending if ($TemplateFilesToPublish.Count -eq 0) { Write-Verbose 'No template file found in the modified module.' -Verbose } Write-Verbose ('Modified modules found: [{0}]' -f $TemplateFilesToPublish.count) -Verbose $TemplateFilesToPublish | ForEach-Object { $RelPath = (($_ -split '[\/|\\](avm)[\/|\\](res|ptn|utl)[\/|\\]')[-3..-1] -join '/') -replace '\\', '/' $RelPath = $RelPath.Split('/main.')[0] Write-Verbose " - [$RelPath]" -Verbose } if ($SkipNotVersionedModules) { Write-Verbose 'Skipping modules that are not versioned.' -Verbose $TemplateFilesToPublish = $TemplateFilesToPublish | Where-Object { Test-Path (Join-Path (Split-Path $_) 'version.json') } } Write-Verbose ('Versioned modules to publish: [{0}]' -f $TemplateFilesToPublish.count) -Verbose $TemplateFilesToPublish | ForEach-Object { $RelPath = (($_ -split '[\/|\\](avm)[\/|\\](res|ptn|utl)[\/|\\]')[-3..-1] -join '/') -replace '\\', '/' $RelPath = $RelPath.Split('/main.')[0] Write-Verbose " - [$RelPath]" -Verbose } return $TemplateFilesToPublish } <# .SYNOPSIS Find the closest main.json file to the current directory/file. .DESCRIPTION This function will search the current directory and all parent directories for a main.json file. This can be relevant if, for example, only a version.json file was changed, but what we need to find then is the corresponding main.json file. .PARAMETER Path Mandatory. Path to the folder/file that should be searched .EXAMPLE Find-TemplateFile -Path ".\avm\storage\storage-account\table-service\table\.bicep\nested_roleAssignments.bicep" Directory: .\avm\storage\storage-account\table-service\table Mode LastWriteTime Length Name ---- ------------- ------ ---- la--- 05.12.2021 22:45 1230 main.json Gets the closest main.json file to the current directory. #> function Find-TemplateFile { [CmdletBinding()] param ( [Parameter(Mandatory)] [string] $Path ) $FolderPath = Split-Path $Path -Parent $FolderName = Split-Path $Path -Leaf if ($FolderName -eq 'modules') { return $null } $TemplateFilePath = Join-Path $FolderPath 'main.json' if (-not (Test-Path $TemplateFilePath)) { return Find-TemplateFile -Path $FolderPath } return ($TemplateFilePath | Get-Item).FullName } #endregion <# .SYNOPSIS Get any template (main.json) files in the given folder path that would qualify for publishing. .DESCRIPTION Get any template (main.json) files in the given folder path that would qualify for publishing. Uses Head^-1 to check for changed files and filters them by the module path & path filter of the version.json .PARAMETER ModuleFolderPath Mandatory. The path to the module to check for changed files in. .PARAMETER SkipNotVersionedModules Optional. Specify if filtering the list by returning only versioned modified modules. .EXAMPLE Get-ModulesToPublish -ModuleFolderPath "C:\avm\storage\storage-account" Could return paths like - C:\avm\storage\storage-account\main.json - C:\avm\storage\storage-account\blob-service\main.json #> function Get-ModulesToPublish { [CmdletBinding()] param ( [Parameter(Mandatory)] [string] $ModuleFolderPath, [Parameter(Mandatory = $false)] [switch] $SkipNotVersionedModules ) $versionFile = (Get-Content (Join-Path $ModuleFolderPath 'version.json') -Raw) | ConvertFrom-Json $PathsToInclude = $versionFile.PathFilters # Check as per a `diff` with head^-1 if there was a change in any file that would justify a publish $TemplateFilesToPublish = Get-TemplateFileToPublish -ModuleFolderPath $ModuleFolderPath -PathsToInclude $PathsToInclude -SkipNotVersionedModules # Return the remaining template file(s) return $TemplateFilesToPublish }