From 6f493711e91aaeacacbde74a24ed803d23448a66 Mon Sep 17 00:00:00 2001 From: Callidus2000 <73584079+Callidus2000@users.noreply.github.com> Date: Wed, 16 Feb 2022 10:43:39 +0100 Subject: [PATCH 1/8] Seperated Template-Output-Creation from writing to disk --- .../templating/Invoke-PSMDTemplate.ps1 | 154 +++++++++++++++--- 1 file changed, 131 insertions(+), 23 deletions(-) diff --git a/PSModuleDevelopment/functions/templating/Invoke-PSMDTemplate.ps1 b/PSModuleDevelopment/functions/templating/Invoke-PSMDTemplate.ps1 index 4652ffe..62448bc 100644 --- a/PSModuleDevelopment/functions/templating/Invoke-PSMDTemplate.ps1 +++ b/PSModuleDevelopment/functions/templating/Invoke-PSMDTemplate.ps1 @@ -1,5 +1,5 @@ function Invoke-PSMDTemplate { -<# + <# .SYNOPSIS Creates a project/file from a template. @@ -49,6 +49,10 @@ By default, all parameters will be replaced during invocation. In Raw mode, this is skipped, reproducing mostly the original template input (dynamic scriptblocks will now be named scriptblocks)). + .PARAMETER GenerateObjects + By default, Invoke-PSMDTemplate generates files. + In GenerateObjects mode, no file but objects are created. + .PARAMETER Force If the target path the template should be written to (filename or folder name within $OutPath), then overwrite it. By default, this function will fail if an overwrite is required. @@ -78,7 +82,7 @@ #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSPossibleIncorrectUsageOfAssignmentOperator", "")] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', '')] - [Alias('imt')] + [Alias('imt')] [CmdletBinding(SupportsShouldProcess = $true)] param ( [Parameter(Mandatory = $true, Position = 0, ParameterSetName = 'NameStore')] @@ -119,6 +123,9 @@ [switch] $Raw, + [switch] + $GenerateObjects, + [switch] $Force, @@ -175,6 +182,9 @@ [bool] $Raw, + [switch] + $GenerateObjects, + [bool] $Silent ) @@ -215,10 +225,12 @@ switch ($templateData.Type.ToString()) { #region File - "File" - { + "File" { foreach ($child in $templateData.Children) { - Write-TemplateItem -Item $child -Path $OutPath -Encoding $Encoding -ParameterFlat $Parameters -ParameterScript $scriptParameters -Raw $Raw + $createdTemplateItems = New-TemplateItem -Item $child -Path $OutPath -Encoding $Encoding -ParameterFlat $Parameters -ParameterScript $scriptParameters -Raw $Raw + Write-PSFMessage "`$createdTemplateItems=$($createdTemplateItems|convertto-json)" + #Todo: Parameter umstellen + Write-TemplateResults -TemplateResult $createdTemplateItems -Encoding $Encoding } if ($Raw -and $templateData.Scripts.Values) { $templateData.Scripts.Values | Export-Clixml -Path (Join-Path $OutPath "_PSMD_ParameterScripts.xml") @@ -227,8 +239,7 @@ #endregion File #region Project - "Project" - { + "Project" { #region Resolve output folder if (-not $NoFolder) { if ($Parameters["Name"]) { @@ -247,7 +258,10 @@ #endregion Resolve output folder foreach ($child in $templateData.Children) { - Write-TemplateItem -Item $child -Path $newFolder.FullName -Encoding $Encoding -ParameterFlat $Parameters -ParameterScript $scriptParameters -Raw $Raw + $createdTemplateItems = New-TemplateItem -Item $child -Path $newFolder.FullName -Encoding $Encoding -ParameterFlat $Parameters -ParameterScript $scriptParameters -Raw $Raw + Write-PSFMessage "`$createdTemplateItems=$($createdTemplateItems|convertto-json)" + #Todo: Parameter umstellen + Write-TemplateResults -TemplateResult $createdTemplateItems -Encoding $Encoding } #region Write Config File (Raw) @@ -287,7 +301,7 @@ } } - function Write-TemplateItem { + function New-TemplateItem { [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")] [CmdletBinding()] param ( @@ -309,8 +323,7 @@ [bool] $Raw ) - - Write-PSFMessage -Level Verbose -Message "Creating file: $($Item.Name) ($($Item.RelativePath))" -FunctionName Invoke-PSMDTemplate -ModuleName PSModuleDevelopment -Tag 'create', 'template' + Write-PSFMessage -Level Verbose -Message "Creating Template-Item: $($Item.Name) ($($Item.RelativePath))" -FunctionName Invoke-PSMDTemplate -ModuleName PSModuleDevelopment -Tag 'create', 'template' $identifier = $Item.Identifier $isFile = $Item.GetType().Name -eq 'TemplateItemFile' @@ -320,7 +333,7 @@ $fileName = $Item.Name if (-not $Raw) { foreach ($param in $Item.FileSystemParameterFlat) { - $fileName = [PSModuleDevelopment.Utility.UtilityHost]::Replace($fileName,"$($identifier)$($param)$($identifier)", $ParameterFlat[$param], $false) + $fileName = [PSModuleDevelopment.Utility.UtilityHost]::Replace($fileName, "$($identifier)$($param)$($identifier)", $ParameterFlat[$param], $false) } foreach ($param in $Item.FileSystemParameterScript) { $fileName = [PSModuleDevelopment.Utility.UtilityHost]::Replace($fileName, "$($identifier)$($param)$($identifier)", $ParameterScript[$param], $false) @@ -338,11 +351,22 @@ $text = [PSModuleDevelopment.Utility.UtilityHost]::Replace($text, "$($identifier)!$($param)!$($identifier)", $ParameterScript[$param], $false) } } - [System.IO.File]::WriteAllText($destPath, $text, $Encoding) + return [TemplateResult]@{ + Filename = $fileName + Path = $Path + FullPath = $destPath + Content = $text + } } else { $bytes = [System.Convert]::FromBase64String($Item.Value) - [System.IO.File]::WriteAllBytes($destPath, $bytes) + return [TemplateResult]@{ + Filename = $fileName + Path = $Path + FullPath = $destPath + Content = $bytes + IsText = $false + } } } #endregion File @@ -358,26 +382,110 @@ $folderName = $folderName -replace "$($identifier)!$([regex]::Escape($param))!$($identifier)", $ParameterScript[$param] } } - $folder = New-Item -Path $Path -Name $folderName -ItemType Directory - + $folder = Join-Path -Path (get-item $Path).FullName -ChildPath $folderName + # $folder = New-Item -Path $Path -Name $folderName -ItemType Directory + $createdTemplateItems = @() foreach ($child in $Item.Children) { - Write-TemplateItem -Item $child -Path $folder.FullName -Encoding $Encoding -ParameterFlat $ParameterFlat -ParameterScript $ParameterScript -Raw $Raw + $createdTemplateItems += New-TemplateItem -Item $child -Path $folder -Encoding $Encoding -ParameterFlat $ParameterFlat -ParameterScript $ParameterScript -Raw $Raw } + return $createdTemplateItems } #endregion Folder } + function Write-TemplateResults { + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")] + [CmdletBinding()] + param ( + [TemplateResult[]] + $TemplateResult, + + [PSFEncoding] + $Encoding + ) + foreach ($item in $TemplateResult) { + Write-PSFMessage -Level Verbose -Message "Creating file: $($Item.FullPath)" -FunctionName Invoke-PSMDTemplate -ModuleName PSModuleDevelopment -Tag 'create', 'template' + Write-PSFMessage -Level Verbose -Message "Creating file: $($Item |convertto-json)" -FunctionName Invoke-PSMDTemplate -ModuleName PSModuleDevelopment -Tag 'create', 'template' + if (-not (Test-Path $Item.Path)) { + Write-PSFMessage -Level Verbose -Message "Creating Folder $($Item.Path)" + New-Item -Path $Item.Path -ItemType Directory + } + if ($Item.IsText) { + Write-PSFMessage -Level Verbose -Message "Creating as a Text-File" + [System.IO.File]::WriteAllText($Item.FullPath, $Item.Content, $Encoding) + } + else { + Write-PSFMessage -Level Verbose -Message "Creating as a Binary-File" + [System.IO.File]::WriteAllBytes($Item.FullPath, $Item.Content) + } + } + + # $identifier = $Item.Identifier + # $isFile = $Item.GetType().Name -eq 'TemplateItemFile' + + # #region File + # if ($isFile) { + # $fileName = $Item.Name + # if (-not $Raw) { + # foreach ($param in $Item.FileSystemParameterFlat) { + # $fileName = [PSModuleDevelopment.Utility.UtilityHost]::Replace($fileName, "$($identifier)$($param)$($identifier)", $ParameterFlat[$param], $false) + # } + # foreach ($param in $Item.FileSystemParameterScript) { + # $fileName = [PSModuleDevelopment.Utility.UtilityHost]::Replace($fileName, "$($identifier)$($param)$($identifier)", $ParameterScript[$param], $false) + # } + # } + # $destPath = Join-Path $Path $fileName + + # if ($Item.PlainText) { + # $text = $Item.Value + # if (-not $Raw) { + # foreach ($param in $Item.ContentParameterFlat) { + # $text = [PSModuleDevelopment.Utility.UtilityHost]::Replace($text, "$($identifier)$($param)$($identifier)", $ParameterFlat[$param], $false) + # } + # foreach ($param in $Item.ContentParameterScript) { + # $text = [PSModuleDevelopment.Utility.UtilityHost]::Replace($text, "$($identifier)!$($param)!$($identifier)", $ParameterScript[$param], $false) + # } + # } + # [System.IO.File]::WriteAllText($destPath, $text, $Encoding) + # } + # else { + # $bytes = [System.Convert]::FromBase64String($Item.Value) + # [System.IO.File]::WriteAllBytes($destPath, $bytes) + # } + # } + # #endregion File + + # #region Folder + # else { + # $folderName = $Item.Name + # if (-not $Raw) { + # foreach ($param in $Item.FileSystemParameterFlat) { + # $folderName = $folderName -replace "$($identifier)$([regex]::Escape($param))$($identifier)", $ParameterFlat[$param] + # } + # foreach ($param in $Item.FileSystemParameterScript) { + # $folderName = $folderName -replace "$($identifier)!$([regex]::Escape($param))!$($identifier)", $ParameterScript[$param] + # } + # } + # $folder = New-Item -Path $Path -Name $folderName -ItemType Directory + + # foreach ($child in $Item.Children) { + # Write-TemplateResults -Item $child -Path $folder.FullName -Encoding $Encoding -ParameterFlat $ParameterFlat -ParameterScript $ParameterScript -Raw $Raw + # } + # } + # #endregion Folder + } #endregion Helper function } process { if (Test-PSFFunctionInterrupt) { return } $invokeParam = @{ - Parameters = $Parameters.Clone() - OutPath = Resolve-PSFPath -Path $OutPath - NoFolder = $NoFolder - Encoding = $Encoding - Raw = $Raw - Silent = $Silent + Parameters = $Parameters.Clone() + OutPath = Resolve-PSFPath -Path $OutPath + NoFolder = $NoFolder + Encoding = $Encoding + Raw = $Raw + Silent = $Silent + GenerateObjects = $GenerateObjects } foreach ($item in $Template) { From f07d63cb180f43912e2f426c223460bbb0efa295 Mon Sep 17 00:00:00 2001 From: Callidus2000 <73584079+Callidus2000@users.noreply.github.com> Date: Wed, 16 Feb 2022 12:50:38 +0100 Subject: [PATCH 2/8] Added Class TemplateResult --- PSModuleDevelopment/internal/classes/TemplateResult.ps1 | 7 +++++++ PSModuleDevelopment/internal/scripts/preimport.ps1 | 8 +++++++- 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 PSModuleDevelopment/internal/classes/TemplateResult.ps1 diff --git a/PSModuleDevelopment/internal/classes/TemplateResult.ps1 b/PSModuleDevelopment/internal/classes/TemplateResult.ps1 new file mode 100644 index 0000000..2ca7c27 --- /dev/null +++ b/PSModuleDevelopment/internal/classes/TemplateResult.ps1 @@ -0,0 +1,7 @@ +class TemplateResult { + [string]$Filename + [string]$Path + [string]$FullPath + $Content + [bool]$IsText=$true +} \ No newline at end of file diff --git a/PSModuleDevelopment/internal/scripts/preimport.ps1 b/PSModuleDevelopment/internal/scripts/preimport.ps1 index 6d065ae..c0197f4 100644 --- a/PSModuleDevelopment/internal/scripts/preimport.ps1 +++ b/PSModuleDevelopment/internal/scripts/preimport.ps1 @@ -17,4 +17,10 @@ foreach ($file in (Get-ChildItem "$($script:ModuleRoot)\internal\configurations\ } # Load additional resources needed during import -. Import-ModuleFile -Path "$($script:ModuleRoot)\internal\scripts\initialize.ps1" \ No newline at end of file +. Import-ModuleFile -Path "$($script:ModuleRoot)\internal\scripts\initialize.ps1" + +# Load all classes +foreach ($file in (Get-ChildItem "$($script:ModuleRoot)\internal\classes\*.ps1" -ErrorAction Ignore)) +{ + . Import-ModuleFile -Path $file.FullName +} \ No newline at end of file From d5facb0342690422c46cdf6df8defefa08a4c888 Mon Sep 17 00:00:00 2001 From: Callidus2000 <73584079+Callidus2000@users.noreply.github.com> Date: Wed, 16 Feb 2022 12:51:15 +0100 Subject: [PATCH 3/8] Seperated the templating from writing to the filesystem --- .../templating/Invoke-PSMDTemplate.ps1 | 93 +++++-------------- 1 file changed, 22 insertions(+), 71 deletions(-) diff --git a/PSModuleDevelopment/functions/templating/Invoke-PSMDTemplate.ps1 b/PSModuleDevelopment/functions/templating/Invoke-PSMDTemplate.ps1 index 62448bc..77c9bdf 100644 --- a/PSModuleDevelopment/functions/templating/Invoke-PSMDTemplate.ps1 +++ b/PSModuleDevelopment/functions/templating/Invoke-PSMDTemplate.ps1 @@ -222,15 +222,14 @@ } } #endregion Scripts - + $createdTemplateItems=@() switch ($templateData.Type.ToString()) { #region File "File" { foreach ($child in $templateData.Children) { - $createdTemplateItems = New-TemplateItem -Item $child -Path $OutPath -Encoding $Encoding -ParameterFlat $Parameters -ParameterScript $scriptParameters -Raw $Raw - Write-PSFMessage "`$createdTemplateItems=$($createdTemplateItems|convertto-json)" - #Todo: Parameter umstellen - Write-TemplateResults -TemplateResult $createdTemplateItems -Encoding $Encoding + $createdTemplateItems += New-TemplateItem -Item $child -Path $OutPath -ParameterFlat $Parameters -ParameterScript $scriptParameters -Raw $Raw + # Write-PSFMessage "`$createdTemplateItems=$($createdTemplateItems|convertto-json)" + # Write-TemplateResults -TemplateResult $createdTemplateItems -Encoding $Encoding } if ($Raw -and $templateData.Scripts.Values) { $templateData.Scripts.Values | Export-Clixml -Path (Join-Path $OutPath "_PSMD_ParameterScripts.xml") @@ -258,10 +257,9 @@ #endregion Resolve output folder foreach ($child in $templateData.Children) { - $createdTemplateItems = New-TemplateItem -Item $child -Path $newFolder.FullName -Encoding $Encoding -ParameterFlat $Parameters -ParameterScript $scriptParameters -Raw $Raw - Write-PSFMessage "`$createdTemplateItems=$($createdTemplateItems|convertto-json)" - #Todo: Parameter umstellen - Write-TemplateResults -TemplateResult $createdTemplateItems -Encoding $Encoding + $createdTemplateItems += New-TemplateItem -Item $child -Path $newFolder.FullName -ParameterFlat $Parameters -ParameterScript $scriptParameters -Raw $Raw + # Write-PSFMessage "`$createdTemplateItems=$($createdTemplateItems|convertto-json)" + # Write-TemplateResults -TemplateResult $createdTemplateItems -Encoding $Encoding } #region Write Config File (Raw) @@ -293,12 +291,22 @@ } $configFile = Join-Path $newFolder.FullName "PSMDTemplate.ps1" - Set-Content -Path $configFile -Value $optionsTemplate -Encoding ([PSFEncoding]'utf-8').Encoding + $createdTemplateItems += [TemplateResult]@{ + Filename = "PSMDTemplate.ps1" + Path = $newFolder.FullName + FullPath = (Join-Path $newFolder.FullName "PSMDTemplate.ps1") + Content = $optionsTemplate + } + # Set-Content -Path $configFile -Value $optionsTemplate -Encoding ([PSFEncoding]'utf-8').Encoding } #endregion Write Config File (Raw) } #endregion Project } + If($GenerateObjects){ + return $createdTemplateItems + } + Write-TemplateResults -TemplateResult $createdTemplateItems -Encoding $Encoding } function New-TemplateItem { @@ -311,9 +319,6 @@ [string] $Path, - [PSFEncoding] - $Encoding, - [hashtable] $ParameterFlat, @@ -382,11 +387,11 @@ $folderName = $folderName -replace "$($identifier)!$([regex]::Escape($param))!$($identifier)", $ParameterScript[$param] } } - $folder = Join-Path -Path (get-item $Path).FullName -ChildPath $folderName + $folder = Join-Path -Path $Path -ChildPath $folderName # $folder = New-Item -Path $Path -Name $folderName -ItemType Directory $createdTemplateItems = @() foreach ($child in $Item.Children) { - $createdTemplateItems += New-TemplateItem -Item $child -Path $folder -Encoding $Encoding -ParameterFlat $ParameterFlat -ParameterScript $ParameterScript -Raw $Raw + $createdTemplateItems += New-TemplateItem -Item $child -Path $folder -ParameterFlat $ParameterFlat -ParameterScript $ParameterScript -Raw $Raw } return $createdTemplateItems } @@ -404,10 +409,10 @@ ) foreach ($item in $TemplateResult) { Write-PSFMessage -Level Verbose -Message "Creating file: $($Item.FullPath)" -FunctionName Invoke-PSMDTemplate -ModuleName PSModuleDevelopment -Tag 'create', 'template' - Write-PSFMessage -Level Verbose -Message "Creating file: $($Item |convertto-json)" -FunctionName Invoke-PSMDTemplate -ModuleName PSModuleDevelopment -Tag 'create', 'template' + # Write-PSFMessage -Level Verbose -Message "Creating file: $($Item |convertto-json)" -FunctionName Invoke-PSMDTemplate -ModuleName PSModuleDevelopment -Tag 'create', 'template' if (-not (Test-Path $Item.Path)) { Write-PSFMessage -Level Verbose -Message "Creating Folder $($Item.Path)" - New-Item -Path $Item.Path -ItemType Directory + $folder=New-Item -Path $Item.Path -ItemType Directory } if ($Item.IsText) { Write-PSFMessage -Level Verbose -Message "Creating as a Text-File" @@ -418,60 +423,6 @@ [System.IO.File]::WriteAllBytes($Item.FullPath, $Item.Content) } } - - # $identifier = $Item.Identifier - # $isFile = $Item.GetType().Name -eq 'TemplateItemFile' - - # #region File - # if ($isFile) { - # $fileName = $Item.Name - # if (-not $Raw) { - # foreach ($param in $Item.FileSystemParameterFlat) { - # $fileName = [PSModuleDevelopment.Utility.UtilityHost]::Replace($fileName, "$($identifier)$($param)$($identifier)", $ParameterFlat[$param], $false) - # } - # foreach ($param in $Item.FileSystemParameterScript) { - # $fileName = [PSModuleDevelopment.Utility.UtilityHost]::Replace($fileName, "$($identifier)$($param)$($identifier)", $ParameterScript[$param], $false) - # } - # } - # $destPath = Join-Path $Path $fileName - - # if ($Item.PlainText) { - # $text = $Item.Value - # if (-not $Raw) { - # foreach ($param in $Item.ContentParameterFlat) { - # $text = [PSModuleDevelopment.Utility.UtilityHost]::Replace($text, "$($identifier)$($param)$($identifier)", $ParameterFlat[$param], $false) - # } - # foreach ($param in $Item.ContentParameterScript) { - # $text = [PSModuleDevelopment.Utility.UtilityHost]::Replace($text, "$($identifier)!$($param)!$($identifier)", $ParameterScript[$param], $false) - # } - # } - # [System.IO.File]::WriteAllText($destPath, $text, $Encoding) - # } - # else { - # $bytes = [System.Convert]::FromBase64String($Item.Value) - # [System.IO.File]::WriteAllBytes($destPath, $bytes) - # } - # } - # #endregion File - - # #region Folder - # else { - # $folderName = $Item.Name - # if (-not $Raw) { - # foreach ($param in $Item.FileSystemParameterFlat) { - # $folderName = $folderName -replace "$($identifier)$([regex]::Escape($param))$($identifier)", $ParameterFlat[$param] - # } - # foreach ($param in $Item.FileSystemParameterScript) { - # $folderName = $folderName -replace "$($identifier)!$([regex]::Escape($param))!$($identifier)", $ParameterScript[$param] - # } - # } - # $folder = New-Item -Path $Path -Name $folderName -ItemType Directory - - # foreach ($child in $Item.Children) { - # Write-TemplateResults -Item $child -Path $folder.FullName -Encoding $Encoding -ParameterFlat $ParameterFlat -ParameterScript $ParameterScript -Raw $Raw - # } - # } - # #endregion Folder } #endregion Helper function } From ba0a0d4d5a22718382b535b8cf1ba731a999285c Mon Sep 17 00:00:00 2001 From: Callidus2000 <73584079+Callidus2000@users.noreply.github.com> Date: Wed, 16 Feb 2022 13:44:23 +0100 Subject: [PATCH 4/8] Pester Test Fixes --- .../functions/templating/Invoke-PSMDTemplate.ps1 | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/PSModuleDevelopment/functions/templating/Invoke-PSMDTemplate.ps1 b/PSModuleDevelopment/functions/templating/Invoke-PSMDTemplate.ps1 index 77c9bdf..48fad3c 100644 --- a/PSModuleDevelopment/functions/templating/Invoke-PSMDTemplate.ps1 +++ b/PSModuleDevelopment/functions/templating/Invoke-PSMDTemplate.ps1 @@ -229,7 +229,7 @@ foreach ($child in $templateData.Children) { $createdTemplateItems += New-TemplateItem -Item $child -Path $OutPath -ParameterFlat $Parameters -ParameterScript $scriptParameters -Raw $Raw # Write-PSFMessage "`$createdTemplateItems=$($createdTemplateItems|convertto-json)" - # Write-TemplateResults -TemplateResult $createdTemplateItems -Encoding $Encoding + # Write-TemplateResults -TemplateResult $createdTemplateItems -Encoding $Encoding } if ($Raw -and $templateData.Scripts.Values) { $templateData.Scripts.Values | Export-Clixml -Path (Join-Path $OutPath "_PSMD_ParameterScripts.xml") @@ -290,7 +290,6 @@ $optionsTemplate = $optionsTemplate -replace "þþþPLACEHOLDER-$($guid)þþþ", "" } - $configFile = Join-Path $newFolder.FullName "PSMDTemplate.ps1" $createdTemplateItems += [TemplateResult]@{ Filename = "PSMDTemplate.ps1" Path = $newFolder.FullName @@ -306,7 +305,7 @@ If($GenerateObjects){ return $createdTemplateItems } - Write-TemplateResults -TemplateResult $createdTemplateItems -Encoding $Encoding + Write-TemplateResults -TemplateResult $createdTemplateItems -Encoding $Encoding } function New-TemplateItem { @@ -412,7 +411,7 @@ # Write-PSFMessage -Level Verbose -Message "Creating file: $($Item |convertto-json)" -FunctionName Invoke-PSMDTemplate -ModuleName PSModuleDevelopment -Tag 'create', 'template' if (-not (Test-Path $Item.Path)) { Write-PSFMessage -Level Verbose -Message "Creating Folder $($Item.Path)" - $folder=New-Item -Path $Item.Path -ItemType Directory + New-Item -Path $Item.Path -ItemType Directory | Out-Null } if ($Item.IsText) { Write-PSFMessage -Level Verbose -Message "Creating as a Text-File" From c5a7b465421ed77ce4b001fb662569a56639f65a Mon Sep 17 00:00:00 2001 From: Friedrich Weinmann Date: Tue, 19 Apr 2022 10:08:59 +0200 Subject: [PATCH 5/8] Fixed command name No plural nouns, otherwise PSSA is unhappy --- .../functions/templating/Invoke-PSMDTemplate.ps1 | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/PSModuleDevelopment/functions/templating/Invoke-PSMDTemplate.ps1 b/PSModuleDevelopment/functions/templating/Invoke-PSMDTemplate.ps1 index 48fad3c..ec72d48 100644 --- a/PSModuleDevelopment/functions/templating/Invoke-PSMDTemplate.ps1 +++ b/PSModuleDevelopment/functions/templating/Invoke-PSMDTemplate.ps1 @@ -229,7 +229,7 @@ foreach ($child in $templateData.Children) { $createdTemplateItems += New-TemplateItem -Item $child -Path $OutPath -ParameterFlat $Parameters -ParameterScript $scriptParameters -Raw $Raw # Write-PSFMessage "`$createdTemplateItems=$($createdTemplateItems|convertto-json)" - # Write-TemplateResults -TemplateResult $createdTemplateItems -Encoding $Encoding + # Write-TemplateResult -TemplateResult $createdTemplateItems -Encoding $Encoding } if ($Raw -and $templateData.Scripts.Values) { $templateData.Scripts.Values | Export-Clixml -Path (Join-Path $OutPath "_PSMD_ParameterScripts.xml") @@ -259,7 +259,7 @@ foreach ($child in $templateData.Children) { $createdTemplateItems += New-TemplateItem -Item $child -Path $newFolder.FullName -ParameterFlat $Parameters -ParameterScript $scriptParameters -Raw $Raw # Write-PSFMessage "`$createdTemplateItems=$($createdTemplateItems|convertto-json)" - # Write-TemplateResults -TemplateResult $createdTemplateItems -Encoding $Encoding + # Write-TemplateResult -TemplateResult $createdTemplateItems -Encoding $Encoding } #region Write Config File (Raw) @@ -305,7 +305,7 @@ If($GenerateObjects){ return $createdTemplateItems } - Write-TemplateResults -TemplateResult $createdTemplateItems -Encoding $Encoding + Write-TemplateResult -TemplateResult $createdTemplateItems -Encoding $Encoding } function New-TemplateItem { @@ -396,7 +396,7 @@ } #endregion Folder } - function Write-TemplateResults { + function Write-TemplateResult { [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")] [CmdletBinding()] param ( @@ -449,4 +449,4 @@ } -EnableException $EnableException -PSCmdlet $PSCmdlet -Continue } } -} \ No newline at end of file +} From 1cee6bfa9d6b755ad8ba74343560549a97ee93a9 Mon Sep 17 00:00:00 2001 From: Friedrich Weinmann Date: Tue, 19 Apr 2022 13:15:35 +0200 Subject: [PATCH 6/8] templating system updates --- .../bin/PSModuleDevelopment.dll | Bin 22528 -> 22528 bytes .../bin/PSModuleDevelopment.pdb | Bin 79360 -> 83456 bytes .../bin/PSModuleDevelopment.xml | 37 +++++++++ PSModuleDevelopment/changelog.md | 4 + .../templating/Invoke-PSMDTemplate.ps1 | 73 ++++++++++-------- .../internal/classes/TemplateResult.ps1 | 7 -- .../internal/scripts/preimport.ps1 | 8 +- .../xml/PSModuleDevelopment.Format.ps1xml | 35 +++++++++ .../PSModuleDevelopment.csproj | 4 +- .../Template/TemplateResult.cs | 35 +++++++++ 10 files changed, 156 insertions(+), 47 deletions(-) delete mode 100644 PSModuleDevelopment/internal/classes/TemplateResult.ps1 create mode 100644 library/PSModuleDevelopment/PSModuleDevelopment/Template/TemplateResult.cs diff --git a/PSModuleDevelopment/bin/PSModuleDevelopment.dll b/PSModuleDevelopment/bin/PSModuleDevelopment.dll index 3a051c111a17a741893a50e965e73275a88afec7..57ef0fa6c4959cae6e6bc81cfce0350b2f2135e5 100644 GIT binary patch delta 5792 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 BAuIp@ diff --git a/PSModuleDevelopment/bin/PSModuleDevelopment.pdb b/PSModuleDevelopment/bin/PSModuleDevelopment.pdb index 49f6b651683d93e7debe16db88d43709a6ccedbc..c0a219a5d048a77f499d57e62204f3277f574fc6 100644 GIT binary patch delta 9600 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 F{{zycQRx5x delta 9164 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 diff --git a/PSModuleDevelopment/bin/PSModuleDevelopment.xml b/PSModuleDevelopment/bin/PSModuleDevelopment.xml index 40be847..8fb47fb 100644 --- a/PSModuleDevelopment/bin/PSModuleDevelopment.xml +++ b/PSModuleDevelopment/bin/PSModuleDevelopment.xml @@ -682,6 +682,43 @@ Items under the current item. + +

+ The result object of a template invokation item. + A project template will generate one such object per file/folder + + + + + Name of the file or folder + + + + + Path the file or folder should be written to + + + + + The full, resolved path of the item + + + + + Any content to write (only viable for files) + + + + + Whether the item to create is a folder or a file + + + + + Whether the file is a text-file. + If false, it will be written as a binary file instead. + + Is the template a single file or a project? diff --git a/PSModuleDevelopment/changelog.md b/PSModuleDevelopment/changelog.md index 4aa9fb1..670f81d 100644 --- a/PSModuleDevelopment/changelog.md +++ b/PSModuleDevelopment/changelog.md @@ -1,5 +1,9 @@ # Changelog +## ??? + ++ Upd: Invoke-PSMDTemplate - added parameter `-GenerateObjects` to return objects representing what would have been created as file, rather than actually creating files / folders. + ## 2.2.10.134 (2022-03-17) + New: Test-PSMDClmCompatibility - Tests, whether the targeted file would have trouble executing under Constrained Language Mode. diff --git a/PSModuleDevelopment/functions/templating/Invoke-PSMDTemplate.ps1 b/PSModuleDevelopment/functions/templating/Invoke-PSMDTemplate.ps1 index ec72d48..911986d 100644 --- a/PSModuleDevelopment/functions/templating/Invoke-PSMDTemplate.ps1 +++ b/PSModuleDevelopment/functions/templating/Invoke-PSMDTemplate.ps1 @@ -222,14 +222,11 @@ } } #endregion Scripts - $createdTemplateItems=@() - switch ($templateData.Type.ToString()) { + $createdTemplateItems = switch ($templateData.Type.ToString()) { #region File "File" { foreach ($child in $templateData.Children) { - $createdTemplateItems += New-TemplateItem -Item $child -Path $OutPath -ParameterFlat $Parameters -ParameterScript $scriptParameters -Raw $Raw - # Write-PSFMessage "`$createdTemplateItems=$($createdTemplateItems|convertto-json)" - # Write-TemplateResult -TemplateResult $createdTemplateItems -Encoding $Encoding + New-TemplateItem -Item $child -Path $OutPath -ParameterFlat $Parameters -ParameterScript $scriptParameters -Raw $Raw } if ($Raw -and $templateData.Scripts.Values) { $templateData.Scripts.Values | Export-Clixml -Path (Join-Path $OutPath "_PSMD_ParameterScripts.xml") @@ -257,9 +254,7 @@ #endregion Resolve output folder foreach ($child in $templateData.Children) { - $createdTemplateItems += New-TemplateItem -Item $child -Path $newFolder.FullName -ParameterFlat $Parameters -ParameterScript $scriptParameters -Raw $Raw - # Write-PSFMessage "`$createdTemplateItems=$($createdTemplateItems|convertto-json)" - # Write-TemplateResult -TemplateResult $createdTemplateItems -Encoding $Encoding + New-TemplateItem -Item $child -Path $newFolder.FullName -ParameterFlat $Parameters -ParameterScript $scriptParameters -Raw $Raw } #region Write Config File (Raw) @@ -290,19 +285,18 @@ $optionsTemplate = $optionsTemplate -replace "þþþPLACEHOLDER-$($guid)þþþ", "" } - $createdTemplateItems += [TemplateResult]@{ - Filename = "PSMDTemplate.ps1" + [PSModuleDevelopment.Template.TemplateResult]@{ + Name = "PSMDTemplate.ps1" Path = $newFolder.FullName FullPath = (Join-Path $newFolder.FullName "PSMDTemplate.ps1") Content = $optionsTemplate } - # Set-Content -Path $configFile -Value $optionsTemplate -Encoding ([PSFEncoding]'utf-8').Encoding } #endregion Write Config File (Raw) } #endregion Project } - If($GenerateObjects){ + If ($GenerateObjects) { return $createdTemplateItems } Write-TemplateResult -TemplateResult $createdTemplateItems -Encoding $Encoding @@ -355,8 +349,8 @@ $text = [PSModuleDevelopment.Utility.UtilityHost]::Replace($text, "$($identifier)!$($param)!$($identifier)", $ParameterScript[$param], $false) } } - return [TemplateResult]@{ - Filename = $fileName + return [PSModuleDevelopment.Template.TemplateResult]@{ + Name = $fileName Path = $Path FullPath = $destPath Content = $text @@ -364,8 +358,8 @@ } else { $bytes = [System.Convert]::FromBase64String($Item.Value) - return [TemplateResult]@{ - Filename = $fileName + return [PSModuleDevelopment.Template.TemplateResult]@{ + Name = $fileName Path = $Path FullPath = $destPath Content = $bytes @@ -387,39 +381,54 @@ } } $folder = Join-Path -Path $Path -ChildPath $folderName - # $folder = New-Item -Path $Path -Name $folderName -ItemType Directory - $createdTemplateItems = @() + + # Return a folder object to make sure empty folders are not excluded + [PSModuleDevelopment.Template.TemplateResult]@{ + Name = $folderName + Path = $Path + FullPath = $folder + IsFolder = $true + IsText = $false + } + foreach ($child in $Item.Children) { - $createdTemplateItems += New-TemplateItem -Item $child -Path $folder -ParameterFlat $ParameterFlat -ParameterScript $ParameterScript -Raw $Raw + New-TemplateItem -Item $child -Path $folder -ParameterFlat $ParameterFlat -ParameterScript $ParameterScript -Raw $Raw } - return $createdTemplateItems } #endregion Folder } + function Write-TemplateResult { [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")] [CmdletBinding()] param ( - [TemplateResult[]] + [PSModuleDevelopment.Template.TemplateResult[]] $TemplateResult, [PSFEncoding] $Encoding ) - foreach ($item in $TemplateResult) { - Write-PSFMessage -Level Verbose -Message "Creating file: $($Item.FullPath)" -FunctionName Invoke-PSMDTemplate -ModuleName PSModuleDevelopment -Tag 'create', 'template' - # Write-PSFMessage -Level Verbose -Message "Creating file: $($Item |convertto-json)" -FunctionName Invoke-PSMDTemplate -ModuleName PSModuleDevelopment -Tag 'create', 'template' - if (-not (Test-Path $Item.Path)) { - Write-PSFMessage -Level Verbose -Message "Creating Folder $($Item.Path)" - New-Item -Path $Item.Path -ItemType Directory | Out-Null + $msgParam = @{ Level = 'Verbose'; FunctionName = 'Invoke-PSMDTemplate' } + foreach ($item in $TemplateResult | Sort-Object { $_.FullPath.Length }) { + Write-PSFMessage @msgParam -Message "Creating file: $($item.FullPath)" -FunctionName Invoke-PSMDTemplate -ModuleName PSModuleDevelopment -Tag 'create', 'template' + if (-not (Test-Path $item.Path)) { + Write-PSFMessage -Level Verbose -Message "Creating Folder $($item.Path)" + $null = New-Item -Path $item.Path -ItemType Directory + } + if ($item.IsFolder) { + if (-not (Test-Path $item.FullPath)) { + Write-PSFMessage @msgParam -Message "Creating Folder $($item.FullPath)" + $null = New-Item -Path $item.FullPath -ItemType Directory + } + continue } - if ($Item.IsText) { - Write-PSFMessage -Level Verbose -Message "Creating as a Text-File" - [System.IO.File]::WriteAllText($Item.FullPath, $Item.Content, $Encoding) + if ($item.IsText) { + Write-PSFMessage @msgParam -Message "Creating as a Text-File" + [System.IO.File]::WriteAllText($item.FullPath, $item.Content, $Encoding) } else { - Write-PSFMessage -Level Verbose -Message "Creating as a Binary-File" - [System.IO.File]::WriteAllBytes($Item.FullPath, $Item.Content) + Write-PSFMessage @msgParam -Message "Creating as a Binary-File" + [System.IO.File]::WriteAllBytes($item.FullPath, $item.Content) } } } diff --git a/PSModuleDevelopment/internal/classes/TemplateResult.ps1 b/PSModuleDevelopment/internal/classes/TemplateResult.ps1 deleted file mode 100644 index 2ca7c27..0000000 --- a/PSModuleDevelopment/internal/classes/TemplateResult.ps1 +++ /dev/null @@ -1,7 +0,0 @@ -class TemplateResult { - [string]$Filename - [string]$Path - [string]$FullPath - $Content - [bool]$IsText=$true -} \ No newline at end of file diff --git a/PSModuleDevelopment/internal/scripts/preimport.ps1 b/PSModuleDevelopment/internal/scripts/preimport.ps1 index c0197f4..6d065ae 100644 --- a/PSModuleDevelopment/internal/scripts/preimport.ps1 +++ b/PSModuleDevelopment/internal/scripts/preimport.ps1 @@ -17,10 +17,4 @@ foreach ($file in (Get-ChildItem "$($script:ModuleRoot)\internal\configurations\ } # Load additional resources needed during import -. Import-ModuleFile -Path "$($script:ModuleRoot)\internal\scripts\initialize.ps1" - -# Load all classes -foreach ($file in (Get-ChildItem "$($script:ModuleRoot)\internal\classes\*.ps1" -ErrorAction Ignore)) -{ - . Import-ModuleFile -Path $file.FullName -} \ No newline at end of file +. Import-ModuleFile -Path "$($script:ModuleRoot)\internal\scripts\initialize.ps1" \ No newline at end of file diff --git a/PSModuleDevelopment/xml/PSModuleDevelopment.Format.ps1xml b/PSModuleDevelopment/xml/PSModuleDevelopment.Format.ps1xml index 9eaac5a..caff642 100644 --- a/PSModuleDevelopment/xml/PSModuleDevelopment.Format.ps1xml +++ b/PSModuleDevelopment/xml/PSModuleDevelopment.Format.ps1xml @@ -315,6 +315,41 @@ + + + PSModuleDevelopment.Template.TemplateResult + + PSModuleDevelopment.Template.TemplateResult + + + + + + + + + + + + + + IsFolder + + + Path + + + Name + + + IsText + + + + + + + PSModuleDevelopment.Utility.LinesOfCode diff --git a/library/PSModuleDevelopment/PSModuleDevelopment/PSModuleDevelopment.csproj b/library/PSModuleDevelopment/PSModuleDevelopment/PSModuleDevelopment.csproj index 2673b30..b1fa450 100644 --- a/library/PSModuleDevelopment/PSModuleDevelopment/PSModuleDevelopment.csproj +++ b/library/PSModuleDevelopment/PSModuleDevelopment/PSModuleDevelopment.csproj @@ -9,8 +9,9 @@ Properties PSModuleDevelopment PSModuleDevelopment - v4.5.2 + v4.8 512 + true @@ -69,6 +70,7 @@ + diff --git a/library/PSModuleDevelopment/PSModuleDevelopment/Template/TemplateResult.cs b/library/PSModuleDevelopment/PSModuleDevelopment/Template/TemplateResult.cs new file mode 100644 index 0000000..27583aa --- /dev/null +++ b/library/PSModuleDevelopment/PSModuleDevelopment/Template/TemplateResult.cs @@ -0,0 +1,35 @@ +namespace PSModuleDevelopment.Template +{ + /// + /// The result object of a template invokation item. + /// A project template will generate one such object per file/folder + /// + public class TemplateResult + { + /// + /// Name of the file or folder + /// + public string Name; + /// + /// Path the file or folder should be written to + /// + public string Path; + /// + /// The full, resolved path of the item + /// + public string FullPath; + /// + /// Any content to write (only viable for files) + /// + public object Content; + /// + /// Whether the item to create is a folder or a file + /// + public bool IsFolder; + /// + /// Whether the file is a text-file. + /// If false, it will be written as a binary file instead. + /// + public bool IsText = true; + } +} From 0f631c0103c8e8409f90b061bc3927ea2b4f9c9d Mon Sep 17 00:00:00 2001 From: Friedrich Weinmann Date: Tue, 19 Apr 2022 19:28:20 +0200 Subject: [PATCH 7/8] updates --- PSModuleDevelopment/PSModuleDevelopment.psd1 | 2 +- PSModuleDevelopment/changelog.md | 322 ++++++++++-------- .../functions/utility/Restart-PSMDShell.ps1 | 55 +-- templates/AzureFunction/function/profile.ps1 | 113 +----- .../AzureFunction/function/requirements.psd1 | 9 +- templates/MiniModule/.github/FUNDING.yml | 13 + .../MiniModule/.github/workflows/build.yml | 23 ++ .../MiniModule/.github/workflows/validate.yml | 15 + templates/MiniModule/LICENSE | 21 ++ templates/MiniModule/PSMDInvoke.ps1 | 4 + templates/MiniModule/PSMDTemplate.ps1 | 17 + templates/MiniModule/build/vsts-build.ps1 | 98 ++++++ .../MiniModule/build/vsts-prerequisites.ps1 | 25 ++ templates/MiniModule/build/vsts-validate.ps1 | 2 + templates/MiniModule/readme.md | 3 + .../MiniModule/tests/functions/readme.md | 7 + .../general/FileIntegrity.Exceptions.ps1 | 31 ++ .../tests/general/FileIntegrity.Tests.ps1 | 95 ++++++ .../tests/general/Help.Exceptions.ps1 | 26 ++ .../MiniModule/tests/general/Help.Tests.ps1 | 152 +++++++++ .../tests/general/Manifest.Tests.ps1 | 62 ++++ .../tests/general/PSScriptAnalyzer.Tests.ps1 | 40 +++ templates/MiniModule/tests/pester.ps1 | 113 ++++++ templates/MiniModule/tests/readme.md | 31 ++ .../MiniModule/\303\276name\303\276/LICENSE" | 21 ++ .../\303\276name\303\276/functions/readme.md" | 3 + .../internal/functions/readme.md" | 3 + .../internal/scripts/readme.md" | 3 + .../\303\276name\303\276.psd1" | 126 +++++++ .../\303\276name\303\276.psm1" | 11 + 30 files changed, 1160 insertions(+), 286 deletions(-) create mode 100644 templates/MiniModule/.github/FUNDING.yml create mode 100644 templates/MiniModule/.github/workflows/build.yml create mode 100644 templates/MiniModule/.github/workflows/validate.yml create mode 100644 templates/MiniModule/LICENSE create mode 100644 templates/MiniModule/PSMDInvoke.ps1 create mode 100644 templates/MiniModule/PSMDTemplate.ps1 create mode 100644 templates/MiniModule/build/vsts-build.ps1 create mode 100644 templates/MiniModule/build/vsts-prerequisites.ps1 create mode 100644 templates/MiniModule/build/vsts-validate.ps1 create mode 100644 templates/MiniModule/readme.md create mode 100644 templates/MiniModule/tests/functions/readme.md create mode 100644 templates/MiniModule/tests/general/FileIntegrity.Exceptions.ps1 create mode 100644 templates/MiniModule/tests/general/FileIntegrity.Tests.ps1 create mode 100644 templates/MiniModule/tests/general/Help.Exceptions.ps1 create mode 100644 templates/MiniModule/tests/general/Help.Tests.ps1 create mode 100644 templates/MiniModule/tests/general/Manifest.Tests.ps1 create mode 100644 templates/MiniModule/tests/general/PSScriptAnalyzer.Tests.ps1 create mode 100644 templates/MiniModule/tests/pester.ps1 create mode 100644 templates/MiniModule/tests/readme.md create mode 100644 "templates/MiniModule/\303\276name\303\276/LICENSE" create mode 100644 "templates/MiniModule/\303\276name\303\276/functions/readme.md" create mode 100644 "templates/MiniModule/\303\276name\303\276/internal/functions/readme.md" create mode 100644 "templates/MiniModule/\303\276name\303\276/internal/scripts/readme.md" create mode 100644 "templates/MiniModule/\303\276name\303\276/\303\276name\303\276.psd1" create mode 100644 "templates/MiniModule/\303\276name\303\276/\303\276name\303\276.psm1" diff --git a/PSModuleDevelopment/PSModuleDevelopment.psd1 b/PSModuleDevelopment/PSModuleDevelopment.psd1 index f78ff2a..695be49 100644 --- a/PSModuleDevelopment/PSModuleDevelopment.psd1 +++ b/PSModuleDevelopment/PSModuleDevelopment.psd1 @@ -4,7 +4,7 @@ RootModule = 'PSModuleDevelopment.psm1' # Version number of this module. - ModuleVersion = '2.2.10.134' + ModuleVersion = '2.2.11.138' # ID used to uniquely identify this module GUID = '37dd5fce-e7b5-4d57-ac37-832055ce49d6' diff --git a/PSModuleDevelopment/changelog.md b/PSModuleDevelopment/changelog.md index 670f81d..b17262c 100644 --- a/PSModuleDevelopment/changelog.md +++ b/PSModuleDevelopment/changelog.md @@ -1,8 +1,11 @@ # Changelog -## ??? +## 2.2.11.138 (2022-04-19) -+ Upd: Invoke-PSMDTemplate - added parameter `-GenerateObjects` to return objects representing what would have been created as file, rather than actually creating files / folders. ++ New: Template MiniModule - a scaffold for a minimal dependencies module ++ Upd: Invoke-PSMDTemplate - added parameter `-GenerateObjects` to return objects representing what would have been created as file, rather than actually creating files / folders. (@Callidus2000; #167) ++ Upd: Restart-PSMDShell (rss) - added support for Windows Terminal ++ Upd: Template AzureFunction - added Azure.Function.Tools as a dependency, dropped the automatic Az dependency (still available though) ## 2.2.10.134 (2022-03-17) @@ -23,214 +26,239 @@ ## 2.2.10.123 (2021-07-21) -- Fix: Template PSFProject - fixed string test modulename -- Fix: Template PSFModule - fixed string test modulename -- Fix: Template PSFTest - fixed string test modulename ++ Fix: Template PSFProject+ Fixed string test modulename ++ Fix: Template PSFModule+ Fixed string test modulename ++ Fix: Template PSFTest+ Fixed string test modulename ## 2.2.10.120 (2021-07-20) -- New: Build Component - define build workflows based on pre-defined & extensible action code -- Upd: Template AzureFunction - new layout with better build automation -- Upd: Template AzureFunctionRest - new layout to integrate into new AzureFunction template -- Upd: Template PSFProject - added Github Actions integration -- Upd: Aliases - removed "AllScope" option -- Fix: Template PSFTest - fixed PSScriptAnalyzer test path detection -- Fix: Template PSFTest - fixed string LegalSurplus exception being ignored -- Fix: Template PSFModule - fixed PSScriptAnalyzer test path detection -- Fix: Template PSFModule - fixed string LegalSurplus exception being ignored -- Fix: Template PSFProject - fixed PSScriptAnalyzer test path detection -- Fix: Template PSFProject - fixed string LegalSurplus exception being ignored -- Fix: TemplateStore - default path iss invalid on MAC (#136) -- Fix: Invoke-PSMDTemplate - unreliable string replacement through -replace operator (#113) -- Fix: Publish-PSMDScriptFile - insufficient exclude paths (#138; @Callidus2000) ++ New: Build Component - define build workflows based on pre-defined & extensible action code ++ Upd: Template AzureFunction+ New layout with better build automation ++ Upd: Template AzureFunctionRest+ New layout to integrate into new AzureFunction template ++ Upd: Template PSFProject - added Github Actions integration ++ Upd: Aliases - removed "AllScope" option ++ Fix: Template PSFTest+ Fixed PSScriptAnalyzer test path detection ++ Fix: Template PSFTest+ Fixed string LegalSurplus exception being ignored ++ Fix: Template PSFModule+ Fixed PSScriptAnalyzer test path detection ++ Fix: Template PSFModule+ Fixed string LegalSurplus exception being ignored ++ Fix: Template PSFProject+ Fixed PSScriptAnalyzer test path detection ++ Fix: Template PSFProject+ Fixed string LegalSurplus exception being ignored ++ Fix: TemplateStore - default path iss invalid on MAC (#136) ++ Fix: Invoke-PSMDTemplate - unreliable string replacement through -replace operator (#113) ++ Fix: Publish-PSMDScriptFile - insufficient exclude paths (#138; @Callidus2000) ## 2.2.9.106 (September 10th, 2020) -- New: Convert-PSMDMessage - Converts a file's use of PSFramework messages to strings. -- Upd: Export-PSMDString - Adding support for Test-PSFShouldProcess. -- Fix: Export-PSMDString - Failed with splatting detection ++ New: Convert-PSMDMessage - Converts a file's use of PSFramework messages to strings. ++ Upd: Export-PSMDString - Adding support for Test-PSFShouldProcess. ++ Fix: Export-PSMDString - Failed with splatting detection ## 2.2.8.104 (July 26th, 2020) -- Fix: Various bugs in the new functions ++ Fix: Various bugs in the new functions ## 2.2.8.103 (July 24th, 2020) -- New: Publish-PSMDScriptFile - Packages a script with all dependencies and "publishes" it as a zip package. -- New: Get-PSMDFileCommand - Parses a scriptfile and returns the contained/used commands. -- New: Set-PSMDStagingRepository - Define the repository to use for deploying modules along with scripts. -- New: Publish-PSMDStagedModule - Publish a module to your staging repository. -- Fix: Export-PSMDString - Random failure to execute (thanks @AndiBellstedt !) ++ New: Publish-PSMDScriptFile - Packages a script with all dependencies and "publishes" it as a zip package. ++ New: Get-PSMDFileCommand - Parses a scriptfile and returns the contained/used commands. ++ New: Set-PSMDStagingRepository - Define the repository to use for deploying modules along with scripts. ++ New: Publish-PSMDStagedModule - Publish a module to your staging repository. ++ Fix: Export-PSMDString - Random failure to execute (thanks @AndiBellstedt !) ## 2.2.7.98 (May 30th, 2020) -- Upd: Template PSFTest - Pester v5 compatibility -- Upd: Template PSFModule - Pester v5 compatibility -- Upd: Template PSFProject - Pester v5 compatibility -- Upd: Template PSFProject - Simplified module import workflow -- Upd: Template PSFProject - Improved build process cross-agent convenience -- Upd: Template PSFProject - Prerequisites task automatically detects module dependencies -- Upd: Template PSFProject - Prerequisites task can be configured to work with any registered repository -- Upd: Export-PSMDString - Now also detects splatted localization strings (thanks @StevePlp ; #117) ++ Upd: Template PSFTest - Pester v5 compatibility ++ Upd: Template PSFModule - Pester v5 compatibility ++ Upd: Template PSFProject - Pester v5 compatibility ++ Upd: Template PSFProject - Simplified module import workflow ++ Upd: Template PSFProject - Improved build process cross-agent convenience ++ Upd: Template PSFProject - Prerequisites task automatically detects module dependencies ++ Upd: Template PSFProject - Prerequisites task can be configured to work with any registered repository ++ Upd: Export-PSMDString - Now also detects splatted localization strings (thanks @StevePlp ; #117) ## 2.2.7.90 (September 1st, 2019) - - New: Export-PSMDString - Parses strings from modules using the PSFramework localization feature. - - Upd: Measure-PSMDCommand - Renamed from Measure-PSMDCommandEx, performance upgrades, adding option for comparing multiple test sets. - - Upd: Refactored and updated the ModuleDebug component - - Upd: Renamed Get-PSMDHelpEx to Get-PSMDHelp - - Upd: Template PSFProject - Adding `-IncludAZ` switch parameter to `vsts-packageFunction.ps1`, making the template include the AZ module as managed dependency. - - Upd: Template PSFProject - yaml file for AzDev PR validation pipeline - - Upd: Refactored module structure to comply with current Fred Reference Architecture - - Upd: Template PSFTests - Added localization string tests - - Upd: Remove-PSMDTemplate - Refactored and updated messaging / ShouldProcess implementation - - Upd: Find-PSMDFileContent - Updated extension filtering to be configurable and include .cs files by default. - - Upd: Get-PSMDArgumentCompleter - Refactoring and minor performance improvement - - Upd: Restart-PSMDShell - Will restart same application as current process, enabling it to restart on core versions - - Fix: Template PSFProject - Publish Folder created during build is created using `-Force` - - Fix: Template PSFProject - Cleaning up Azure Function conversion - - Fix: Template PSFTests - Encoding test no longer fails on core (#104) - - Fix: Template PSFTests - Referenced DLLs from GAC will fail as path cannot be found (#100) - - Fix: Template Module - RootModule | 3-element version | Module Import from UNC path - - Fix: Template-System - Bad default template store path on linux or mac. (#106) + ++ New: Export-PSMDString - Parses strings from modules using the PSFramework localization feature. ++ Upd: Measure-PSMDCommand - Renamed from Measure-PSMDCommandEx, performance upgrades, adding option for comparing multiple test sets. ++ Upd: Refactored and updated the ModuleDebug component ++ Upd: Renamed Get-PSMDHelpEx to Get-PSMDHelp ++ Upd: Template PSFProject - Adding `-IncludAZ` switch parameter to `vsts-packageFunction.ps1`, making the template include the AZ module as managed dependency. ++ Upd: Template PSFProject - yaml file for AzDev PR validation pipeline ++ Upd: Refactored module structure to comply with current Fred Reference Architecture ++ Upd: Template PSFTests - Added localization string tests ++ Upd: Remove-PSMDTemplate - Refactored and updated messaging / ShouldProcess implementation ++ Upd: Find-PSMDFileContent+ Updated extension filtering to be configurable and include .cs files by default. ++ Upd: Get-PSMDArgumentCompleter - Refactoring and minor performance improvement ++ Upd: Restart-PSMDShell - Will restart same application as current process, enabling it to restart on core versions ++ Fix: Template PSFProject - Publish Folder created during build is created using `-Force` ++ Fix: Template PSFProject - Cleaning up Azure Function conversion ++ Fix: Template PSFTests - Encoding test no longer fails on core (#104) ++ Fix: Template PSFTests - Referenced DLLs from GAC will fail as path cannot be found (#100) ++ Fix: Template Module - RootModule | 3-element version | Module Import from UNC path ++ Fix: Template-System - Bad default template store path on linux or mac. (#106) ## 2.2.6.72 (May 27th, 2019) - - New: Template AzureFunction - Creates a basic azure function scaffold - - New: Template AzureFunctionTimer - Creates a timer triggered Azure Function - - Upd: Template AzureFunctionRest - Redesigned to only spawn a function rest endpoint to insert into the base AzureFunction template. - - Upd: Template PSFProject - Improved Azure Functions creation experience, added client module support. + ++ New: Template AzureFunction - Creates a basic azure function scaffold ++ New: Template AzureFunctionTimer - Creates a timer triggered Azure Function ++ Upd: Template AzureFunctionRest - Redesigned to only spawn a function rest endpoint to insert into the base AzureFunction template. ++ Upd: Template PSFProject - Improved Azure Functions creation experience, added client module support. ## 2.2.6.68 (May 3rd, 2019) - - Upd: Template PSFProject - Improved Azure Functions creation experience + ++ Upd: Template PSFProject - Improved Azure Functions creation experience ## 2.2.6.67 (May 2nd, 2019) - - Upd: Invoke-PSMDTemplate adding tab completion - - Fix: Invoke-PSMDTemplate fails to create templates + ++ Upd: Invoke-PSMDTemplate adding tab completion ++ Fix: Invoke-PSMDTemplate fails to create templates ## 2.2.6.65 (May 2nd, 2019) - - New: Template: AzureFunctionRest - creates an azure function designed for rest API trigger. - - Upd: Template: PSFProject added Azure Functions Project CI/CD integration. - - Upd: Invoke-PSMDTemplate supports `-Encoding` parameter, defaulting to utf8 with BOM. + ++ New: Template: AzureFunctionRest - creates an azure function designed for rest API trigger. ++ Upd: Template: PSFProject added Azure Functions Project CI/CD integration. ++ Upd: Invoke-PSMDTemplate supports `-Encoding` parameter, defaulting to utf8 with BOM. ## 2.2.6.62 (April 30th, 2019) - - New: Get-PSMDArgumentCompleter - Lists registered argument completers on PS5+ - - New: Template: PSFLoggingProvider - Creates a custom logfile logging provider for module specific logging. - - Upd: Template: PSFTest - Adding test against module tags with whitespace - - Upd: Get-PSMDConstructor - Added `-NonPublic` parameter to show hidden constructors. - - Upd: Template: PSFModule - Improved import speed. - - Upd: Template: PSFProject - Add parameter `-LocalRepo` - - Upd: Template: PSFProject - Add parameter `-AutoVersion` - - Fix: New-PSMDModuleNugetPackage - Resolving input path. - - Fix: New-PSMDModuleNugetPackage - Reregistering temp export repository if accidentally not cleaned up. - - Fix: Template: PSFModule - Fixed format xml closing tag - - Fix: Template: PSFModule - Fixed import from network share. - + ++ New: Get-PSMDArgumentCompleter - Lists registered argument completers on PS5+ ++ New: Template: PSFLoggingProvider - Creates a custom logfile logging provider for module specific logging. ++ Upd: Template: PSFTest - Adding test against module tags with whitespace ++ Upd: Get-PSMDConstructor - Added `-NonPublic` parameter to show hidden constructors. ++ Upd: Template: PSFModule - Improved import speed. ++ Upd: Template: PSFProject - Add parameter `-LocalRepo` ++ Upd: Template: PSFProject - Add parameter `-AutoVersion` ++ Fix: New-PSMDModuleNugetPackage - Resolving input path. ++ Fix: New-PSMDModuleNugetPackage - Reregistering temp export repository if accidentally not cleaned up. ++ Fix: Template: PSFModule+ Fixed format xml closing tag ++ Fix: Template: PSFModule+ Fixed import from network share. + ## 2.2.6.51 (January 29th, 2019) - - New: Format-PSMDParameter - updates legacy parameter notation - - New: Measure-PSMDLinesOfCode - Measures the lines of code in a scriptfile. - - New: Search-PSMDPropertyValue - search objects for values in properties - - Upd: Template PSFTest - adding WMI commands to list of forbidden commands - - Upd: Template PSFModule - adding changelog - - Upd: Template PSFModule - adding strings for localization - - Upd: Template PSFModule - adding scriptblocks - - Upd: Template PSFProject - updated build txt files to include new module content - - Fix: Template PSMTest - replacing all -Filter calls on Get-ChildItem - - Fix: New-PSMDTemplate records binary files as text files + ++ New: Format-PSMDParameter+ Updates legacy parameter notation ++ New: Measure-PSMDLinesOfCode - Measures the lines of code in a scriptfile. ++ New: Search-PSMDPropertyValue - search objects for values in properties ++ Upd: Template PSFTest - adding WMI commands to list of forbidden commands ++ Upd: Template PSFModule - adding changelog ++ Upd: Template PSFModule - adding strings for localization ++ Upd: Template PSFModule - adding scriptblocks ++ Upd: Template PSFProject+ Updated build txt files to include new module content ++ Fix: Template PSMTest - replacing all -Filter calls on Get-ChildItem ++ Fix: New-PSMDTemplate records binary files as text files ## 2.2.5.41 (December 18th, 2018) - - Fix: Get-PSMDMember - dropping the unintentional bool return + ++ Fix: Get-PSMDMember - dropping the unintentional bool return ## 2.2.5.40 (December 17th, 2018) - - New: Command Show-PSMDSyntax, used to show the parameter syntax with proper highlighting - - New: Command Get-PSMDMember, used to show the members in a more organic and useful way - - Fix: Template PSFProject build step was broken + ++ New: Command Show-PSMDSyntax, used to show the parameter syntax with proper highlighting ++ New: Command Get-PSMDMember, used to show the members in a more organic and useful way ++ Fix: Template PSFProject build step was broken ## 2.2.5.37 ( October 20th, 2018) - - Upd: Set-PSMDModulePath - add `-Module` parameter to persist the setting - - Upd: Set-PSMDModulePath - add `-Register` parameter for integrated persistence - - Upd: Set-PSMDEncoding - use `PSFEncoding` parameter class & tabcompletion - - Upd: Template PSFProject - build directly into psm1 - - Upd: Template PSFProject, PSFModule - automatically read version in psm1 from psd1, rather than requiring explicit maintenance. - - Fix: Template PSFTest - use category exclusions + ++ Upd: Set-PSMDModulePath - add `-Module` parameter to persist the setting ++ Upd: Set-PSMDModulePath - add `-Register` parameter for integrated persistence ++ Upd: Set-PSMDEncoding - use `PSFEncoding` parameter class & tabcompletion ++ Upd: Template PSFProject - build directly into psm1 ++ Upd: Template PSFProject, PSFModule - automatically read version in psm1 from psd1, rather than requiring explicit maintenance. ++ Fix: Template PSFTest - use category exclusions ## 2.2.5.31 (September 29th, 2018) - - Fix: Template PSFProject dependencies installed correctly - + ++ Fix: Template PSFProject dependencies installed correctly + ## 2.2.5.30 (September 12th, 2018) - - Upd: Template integrated NUnit Test Reporting - - Upd: Template support for compiled module files + ++ Upd: Template integrated NUnit Test Reporting ++ Upd: Template support for compiled module files ## 2.2.5.28 (September 08th, 2018) - - Fix: Template CommandTest would throw an exception due to missing quotes on a string index + ++ Fix: Template CommandTest would throw an exception due to missing quotes on a string index ## 2.2.5.27 (September 08th, 2018) - - Fix: Fixes in the build task + ++ Fix: Fixes in the build task ## 2.2.5.26 (September 08th, 2018) - - New: Command Read-PSMDScript (Alias: parse) - - New: Command Set-PSMDEncoding - - New: Template PSFTests - Default module tests - - New: Template CommandTest - A tempalte that generate a test from an already existing command. - - Upd: Template PSFModule - some fixes - - Upd: Template PSFProject - some fixes and improvements to the installer - - Fix: Template function - encoding error - - Fix: New-PSMDTemplate - now properly selects scriptblocks across multiple lines + ++ New: Command Read-PSMDScript (Alias: parse) ++ New: Command Set-PSMDEncoding ++ New: Template PSFTests - Default module tests ++ New: Template CommandTest - A tempalte that generate a test from an already existing command. ++ Upd: Template PSFModule - some fixes ++ Upd: Template PSFProject - some fixes and improvements to the installer ++ Fix: Template function - encoding error ++ Fix: New-PSMDTemplate - now properly selects scriptblocks across multiple lines ## 2.2.4.18 (May 04rd, 2018) - - Upd: New-PSMDFormatTableDefinition - Update to add parameters `-IncludePropertyAttribute` and `-ExcludePropertyAttribute` - + ++ Upd: New-PSMDFormatTableDefinition+ Update to add parameters `-IncludePropertyAttribute` and `-ExcludePropertyAttribute` + ## 2.2.3.17 (May 04rd, 2018) - - Upd: New-PSMDFormatTableDefinition - Major redesign, extensive additional functionality (#29) - - Upd: Find-PSMDType - add `-Attribute` parameter to filter by class attributes (#27) - - Fix: Find-PSMDType - suppress error that gets thrown on empty assemblies. - - Fix: New-PSMDFormatTableDefinition - Broken closing `` tag (#28) + ++ Upd: New-PSMDFormatTableDefinition - Major redesign, extensive additional functionality (#29) ++ Upd: Find-PSMDType - add `-Attribute` parameter to filter by class attributes (#27) ++ Fix: Find-PSMDType - suppress error that gets thrown on empty assemblies. ++ Fix: New-PSMDFormatTableDefinition - Broken closing `` tag (#28) ## 2.2.1.12 (March 08th, 2018) - - Added out-of-the box templates - - fix: Verious bugfixes around the template system + ++ Added out-of-the box templates ++ Fix: Verious bugfixes around the template system ## 2.2.1.11 (March 06th, 2018) - - new: Alias imt --> Invoke-PSMDTemplate - - Upd: Added TabCompletion to *-PSMDTemplate commands + ++ New: Alias imt --> Invoke-PSMDTemplate ++ Upd: Added TabCompletion to *-PSMDTemplate commands ## 2.2.0.10 (March 06th, 2018) - - new: Command New-PSMDTemplate - - new: Command Get-PSMDTemplate - - new: Command Invoke-PSMDTemplate - - new: Command Remove-PSMDTemplate + ++ New: Command New-PSMDTemplate ++ New: Command Get-PSMDTemplate ++ New: Command Invoke-PSMDTemplate ++ New: Command Remove-PSMDTemplate ## 2.1.1.3 (February 06th, 2018) - - new: Command New-PSMDModuleNugetPackage - A command that takes a module and writes it to a Nuget package. - - Upd: Increased PSFramework required version to 0.9.9.19 + ++ New: Command New-PSMDModuleNugetPackage - A command that takes a module and writes it to a Nuget package. ++ Upd: Increased PSFramework required version to 0.9.9.19 ## 2.1.0.1 (January 24th, 2018) - - new: Included suite of tests, in order to provide a more reliable user experience. - - new: Command New-PSMDDotNetProject - A wrapper around dotnet.exe + ++ New: Included suite of tests, in order to provide a more reliable user experience. ++ New: Command New-PSMDDotNetProject - A wrapper around dotnet.exe ## 2.0.0.0 (December 18th, 2017) - - Breaking change: Renamed all commands to include the PSMD prefix - - New function: Find-PSMDFileContent (alias: find), to swiftly search in your current project - - New function: New-PSMDHeader, to create headers for documentation - - New function: Set-PSMDModulePath, to define the project currently being worked on - - Suite of new functions that refactor a project: -``` ++ Breaking change: Renamed all commands to include the PSMD prefix ++ New function: Find-PSMDFileContent (alias: find), to swiftly search in your current project ++ New function: New-PSMDHeader, to create headers for documentation ++ New function: Set-PSMDModulePath, to define the project currently being worked on ++ Suite of new functions that refactor a project: + +```text Rename-PSMDParameter: Renames a parameter, then updates the function's internal use, then updates the parameter usage across the entire module. Set-PSMDCmdletBinding: Inserts a CmdletBinding-Attribute into all functions that need one Set-PSMDParameterHelp: Globally updates parameter help for all commands that share a parameter across the project Split-PSMDScriptFile: Exports all functions in a file and creates new files, one per function, named after the function ``` - - New function: New-PSMDFormatTableDefinition, creates format xml for input types that will present it by default as a table - - New function: Expand-PSMDTypeName, returns a list of all type-names an object has (by default, the entire inheritance chain) - - New function: Find-PSMDType, search currently imported assemblies for types - - New function: Get-PSMDAssembly, return the currently imported assemblies - - New function: Get-PSMDConstructor, return the constructor definitions for a type or the type of an input object ++ New function: New-PSMDFormatTableDefinition, creates format xml for input types that will present it by default as a table ++ New function: Expand-PSMDTypeName, returns a list of all type-names an object has (by default, the entire inheritance chain) ++ New function: Find-PSMDType, search currently imported assemblies for types ++ New function: Get-PSMDAssembly, return the currently imported assemblies ++ New function: Get-PSMDConstructor, return the constructor definitions for a type or the type of an input object -## 1.3.0.0 (October 19th, 2016): - - New function: Measure-CommandEx - - Renamed function: Get-ExHelp --> Get-HelpEx - - New Alias: Get-ExHelp --> Get-HelpEx - - New Alias: hex --> Get-HelpEx - -## 1.2.0.0 (August 15th, 2016): - - New function: Get-ExHelp +## 1.3.0.0 (October 19th, 2016) + ++ New function: Measure-CommandEx ++ Renamed function: Get-ExHelp --> Get-HelpEx ++ New Alias: Get-ExHelp --> Get-HelpEx ++ New Alias: hex --> Get-HelpEx + +## 1.2.0.0 (August 15th, 2016) + ++ New function: Get-ExHelp diff --git a/PSModuleDevelopment/functions/utility/Restart-PSMDShell.ps1 b/PSModuleDevelopment/functions/utility/Restart-PSMDShell.ps1 index 67a8a5a..c12e472 100644 --- a/PSModuleDevelopment/functions/utility/Restart-PSMDShell.ps1 +++ b/PSModuleDevelopment/functions/utility/Restart-PSMDShell.ps1 @@ -1,6 +1,5 @@ -function Restart-PSMDShell -{ - <# +function Restart-PSMDShell { + <# .SYNOPSIS A swift way to restart the PowerShell console. @@ -33,13 +32,8 @@ PS C:\> Restart-PSMDShell -Admin -NoExit Creates a new PowerShell process, run with elevation, while keeping the current console around. - - .NOTES - Version 1.0.0.0 - Author: Friedrich Weinmann - Created on: August 6th, 2016 #> - [Alias('rss', 'Restart-Shell')] + [Alias('rss', 'Restart-Shell')] [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Low')] Param ( [Switch] @@ -52,25 +46,36 @@ $NoProfile ) - begin - { - $powershellPath = (Get-Process -id $pid).Path + begin { + $process = Get-Process -Id $pid + $powershellPath = $process.Path + $isWindowsTerminal = $process.Parent.ProcessName -eq 'WindowsTerminal' } - process - { - if ($PSCmdlet.ShouldProcess("Current shell", "Restart")) - { - if ($NoProfile) - { - if ($Admin) { Start-Process $powershellPath -Verb RunAs -ArgumentList '-NoProfile' } - else { Start-Process $powershellPath -ArgumentList '-NoProfile' } + process { + if (-not $PSCmdlet.ShouldProcess("Current shell", "Restart")) { return } + + if ($isWindowsTerminal) { + $psVersionName = 'powershell' + if ($PSVersionTable.PSVersion.Major -gt 5) { $psVersionName = 'pwsh' } + + $param = @{ + FilePath = 'wt' + ArgumentList = @('-w', 0, 'nt','--title', $psVersionName, $powershellPath) } - else - { - if ($Admin) { Start-Process $powershellPath -Verb RunAs } - else { Start-Process $powershellPath } + if ($NoProfile) { $param.ArgumentList = @('-w', 0, 'nt', '--title', $psVersionName, $powershellPath, '-NoProfile') } + if ($Admin) { $param.Verb = 'RunAs' } + Start-Process @param + } + else { + $param = @{ + FilePath = $powershellPath } - if (-not $NoExit) { exit } + if ($NoProfile) { $param.ArgumentList = '-NoProfile' } + if ($Admin) { $param.Verb = 'RunAs' } + Start-Process @param } } + end { + if (-not $NoExit) { exit } + } } \ No newline at end of file diff --git a/templates/AzureFunction/function/profile.ps1 b/templates/AzureFunction/function/profile.ps1 index be04a7d..3d09b77 100644 --- a/templates/AzureFunction/function/profile.ps1 +++ b/templates/AzureFunction/function/profile.ps1 @@ -18,115 +18,4 @@ if ($env:MSI_SECRET -and (Get-Module -ListAvailable Az.Accounts)) # Uncomment the next line to enable legacy AzureRm alias in Azure PowerShell. # Enable-AzureRmAlias -# You can also define functions or aliases that can be referenced in any of your PowerShell functions. - -function Write-FunctionResult { - <# - .SYNOPSIS - Reports back the output / result of the function app. - - .DESCRIPTION - Reports back the output / result of the function app. - - .PARAMETER Status - Whether the function succeeded or not. - - .PARAMETER Body - Any data to include in the response. - - .EXAMPLE - PS C:\> Write-FunctionResult -Status OK -Body $newUser - - Reports success while returning the content of $newUser as output - #> - [CmdletBinding()] - param ( - [Parameter(Mandatory = $true)] - [System.Net.HttpStatusCode] - $Status, - - [AllowNull()] - $Body - ) - - Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = $Status - Body = $Body - }) -} - -function Get-RestParameterValue { - <# - .SYNOPSIS - Extract the exact value of a parameter provided by the user. - - .DESCRIPTION - Extract the exact value of a parameter provided by the user. - Expects either query or body parameters from the rest call to the http trigger. - - .PARAMETER Request - The request object provided as part of the function call. - - .PARAMETER Name - The name of the parameter to provide. - - .EXAMPLE - PS C:\> Get-RestParameterValue -Request $Request -Name Type - - Returns the value of the parameter "Type", as provided by the caller - #> - [CmdletBinding()] - param ( - [Parameter(Mandatory = $true)] - $Request, - - [Parameter(Mandatory = $true)] - [string] - $Name - ) - - if ($Request.Query.$Name) { - return $Request.Query.$Name - } - $Request.Body.$Name -} - -function Get-RestParameter { - <# - .SYNOPSIS - Parses the rest request parameters for all values matching parameters on the specified command. - - .DESCRIPTION - Parses the rest request parameters for all values matching parameters on the specified command. - Returns a hashtable ready for splatting. - Does NOT assert mandatory parameters are specified, so command invocation may fail. - - .PARAMETER Request - The original rest request object, containing the caller's information such as parameters. - - .PARAMETER Command - The command to which to bind input parameters. - - .EXAMPLE - PS C:\> Get-RestParameter -Request $Request -Command Get-AzUser - - Retrieves all parameters on the incoming request that match a parameter on Get-AzUser - #> - [CmdletBinding()] - Param ( - [Parameter(Mandatory = $true)] - $Request, - - [Parameter(Mandatory = $true)] - [string] - $Command - ) - - $commandInfo = Get-Command -Name $Command - $results = @{ } - foreach ($parameter in $commandInfo.Parameters.Keys) { - $value = Get-RestParameterValue -Request $Request -Name $parameter - if ($null -ne $value) { $results[$parameter] = $value } - } - $results -} \ No newline at end of file +# You can also define functions or aliases that can be referenced in any of your PowerShell functions. \ No newline at end of file diff --git a/templates/AzureFunction/function/requirements.psd1 b/templates/AzureFunction/function/requirements.psd1 index bf2c583..83d4313 100644 --- a/templates/AzureFunction/function/requirements.psd1 +++ b/templates/AzureFunction/function/requirements.psd1 @@ -1,3 +1,10 @@ @{ - Az = '1.*' + # Do you really need ALL of the AZ modules? + # Az = '1.*' + + # If you only need Key Vault access, this is your choice + # 'Az.KeyVault' = '4.*' + + # Basic tools used in your function app + 'Azure.Function.Tools' = '1.*' } \ No newline at end of file diff --git a/templates/MiniModule/.github/FUNDING.yml b/templates/MiniModule/.github/FUNDING.yml new file mode 100644 index 0000000..ddf3214 --- /dev/null +++ b/templates/MiniModule/.github/FUNDING.yml @@ -0,0 +1,13 @@ +# These are supported funding model platforms + +github: + FriedrichWeinmann +patreon: # Replace with a single Patreon username +open_collective: # Replace with a single Open Collective username +ko_fi: # Replace with a single Ko-fi username +tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +otechie: # Replace with a single Otechie username +custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] diff --git a/templates/MiniModule/.github/workflows/build.yml b/templates/MiniModule/.github/workflows/build.yml new file mode 100644 index 0000000..80cac05 --- /dev/null +++ b/templates/MiniModule/.github/workflows/build.yml @@ -0,0 +1,23 @@ +on: + push: + branches: + - master + +jobs: + build: + + runs-on: windows-2019 + + steps: + - uses: actions/checkout@v1 + - name: Install Prerequisites + run: .\build\vsts-prerequisites.ps1 + shell: powershell + - name: Validate + run: .\build\vsts-validate.ps1 + shell: powershell + - name: Build + run: .\build\vsts-build.ps1 -ApiKey $env:APIKEY + shell: powershell + env: + APIKEY: ${{ secrets.ApiKey }} \ No newline at end of file diff --git a/templates/MiniModule/.github/workflows/validate.yml b/templates/MiniModule/.github/workflows/validate.yml new file mode 100644 index 0000000..0b516ce --- /dev/null +++ b/templates/MiniModule/.github/workflows/validate.yml @@ -0,0 +1,15 @@ +on: [pull_request] + +jobs: + validate: + + runs-on: windows-2019 + + steps: + - uses: actions/checkout@v1 + - name: Install Prerequisites + run: .\build\vsts-prerequisites.ps1 + shell: powershell + - name: Validate + run: .\build\vsts-validate.ps1 + shell: powershell \ No newline at end of file diff --git a/templates/MiniModule/LICENSE b/templates/MiniModule/LICENSE new file mode 100644 index 0000000..89a8466 --- /dev/null +++ b/templates/MiniModule/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) þ!year!þ þauthorþ + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/templates/MiniModule/PSMDInvoke.ps1 b/templates/MiniModule/PSMDInvoke.ps1 new file mode 100644 index 0000000..20836b6 --- /dev/null +++ b/templates/MiniModule/PSMDInvoke.ps1 @@ -0,0 +1,4 @@ +param ( + $Path +) +New-PSMDTemplate -ReferencePath "$PSScriptRoot" -OutPath $Path \ No newline at end of file diff --git a/templates/MiniModule/PSMDTemplate.ps1 b/templates/MiniModule/PSMDTemplate.ps1 new file mode 100644 index 0000000..812fbcb --- /dev/null +++ b/templates/MiniModule/PSMDTemplate.ps1 @@ -0,0 +1,17 @@ +@{ + TemplateName = 'MiniModule' + Version = "1.0.0.0" + AutoIncrementVersion = $true + Tags = 'module' + Author = 'Friedrich Weinmann' + Description = 'Module scaffold with full CI/CD support and minimal dependencies' + Exclusions = @("PSMDInvoke.ps1") # Contains list of files - relative path to root - to ignore when building the template + Scripts = @{ + guid = { + [System.Guid]::NewGuid().ToString() + } + year = { + Get-Date -Format "yyyy" + } + } +} \ No newline at end of file diff --git a/templates/MiniModule/build/vsts-build.ps1 b/templates/MiniModule/build/vsts-build.ps1 new file mode 100644 index 0000000..218e4bb --- /dev/null +++ b/templates/MiniModule/build/vsts-build.ps1 @@ -0,0 +1,98 @@ +<# +This script publishes the module to the gallery. +It expects as input an ApiKey authorized to publish the module. + +Insert any build steps you may need to take before publishing it here. +#> +param ( + $ApiKey, + + $WorkingDirectory, + + $Repository = 'PSGallery', + + [switch] + $LocalRepo, + + [switch] + $SkipPublish, + + [switch] + $AutoVersion +) + +#region Handle Working Directory Defaults +if (-not $WorkingDirectory) +{ + if ($env:RELEASE_PRIMARYARTIFACTSOURCEALIAS) + { + $WorkingDirectory = Join-Path -Path $env:SYSTEM_DEFAULTWORKINGDIRECTORY -ChildPath $env:RELEASE_PRIMARYARTIFACTSOURCEALIAS + } + else { $WorkingDirectory = $env:SYSTEM_DEFAULTWORKINGDIRECTORY } +} +if (-not $WorkingDirectory) { $WorkingDirectory = Split-Path $PSScriptRoot } +#endregion Handle Working Directory Defaults + +# Prepare publish folder +Write-Host "Creating and populating publishing directory" +$publishDir = New-Item -Path $WorkingDirectory -Name publish -ItemType Directory -Force +Copy-Item -Path "$($WorkingDirectory)\þnameþ" -Destination $publishDir.FullName -Recurse -Force + +#region Gather text data to compile +$text = @() + +# Gather commands +Get-ChildItem -Path "$($publishDir.FullName)\þnameþ\internal\functions\" -Recurse -File -Filter "*.ps1" | ForEach-Object { + $text += [System.IO.File]::ReadAllText($_.FullName) +} +Get-ChildItem -Path "$($publishDir.FullName)\þnameþ\functions\" -Recurse -File -Filter "*.ps1" | ForEach-Object { + $text += [System.IO.File]::ReadAllText($_.FullName) +} + +# Gather scripts +Get-ChildItem -Path "$($publishDir.FullName)\þnameþ\internal\scripts\" -Recurse -File -Filter "*.ps1" | ForEach-Object { + $text += [System.IO.File]::ReadAllText($_.FullName) +} + +#region Update the psm1 file & Cleanup +[System.IO.File]::WriteAllText("$($publishDir.FullName)\þnameþ\þnameþ.psm1", ($text -join "`n`n"), [System.Text.Encoding]::UTF8) +Remove-Item -Path "$($publishDir.FullName)\þnameþ\internal" -Recurse -Force +Remove-Item -Path "$($publishDir.FullName)\þnameþ\functions" -Recurse -Force +#endregion Update the psm1 file & Cleanup + +#region Updating the Module Version +if ($AutoVersion) +{ + Write-Host "Updating module version numbers." + try { [version]$remoteVersion = (Find-Module 'þnameþ' -Repository $Repository -ErrorAction Stop).Version } + catch + { + throw "Failed to access $($Repository) : $_" + } + if (-not $remoteVersion) + { + throw "Couldn't find þnameþ on repository $($Repository) : $_" + } + $newBuildNumber = $remoteVersion.Build + 1 + [version]$localVersion = (Import-PowerShellDataFile -Path "$($publishDir.FullName)\þnameþ\þnameþ.psd1").ModuleVersion + Update-ModuleManifest -Path "$($publishDir.FullName)\þnameþ\þnameþ.psd1" -ModuleVersion "$($localVersion.Major).$($localVersion.Minor).$($newBuildNumber)" +} +#endregion Updating the Module Version + +#region Publish +if ($SkipPublish) { return } +if ($LocalRepo) +{ + # Dependencies must go first + Write-Host "Creating Nuget Package for module: PSFramework" + New-PSMDModuleNugetPackage -ModulePath (Get-Module -Name PSFramework).ModuleBase -PackagePath . + Write-Host "Creating Nuget Package for module: þnameþ" + New-PSMDModuleNugetPackage -ModulePath "$($publishDir.FullName)\þnameþ" -PackagePath . +} +else +{ + # Publish to Gallery + Write-Host "Publishing the þnameþ module to $($Repository)" + Publish-Module -Path "$($publishDir.FullName)\þnameþ" -NuGetApiKey $ApiKey -Force -Repository $Repository +} +#endregion Publish \ No newline at end of file diff --git a/templates/MiniModule/build/vsts-prerequisites.ps1 b/templates/MiniModule/build/vsts-prerequisites.ps1 new file mode 100644 index 0000000..1746aff --- /dev/null +++ b/templates/MiniModule/build/vsts-prerequisites.ps1 @@ -0,0 +1,25 @@ +param ( + [string] + $Repository = 'PSGallery' +) + +$modules = @("Pester", "PSScriptAnalyzer") + +# Automatically add missing dependencies +$data = Import-PowerShellDataFile -Path "$PSScriptRoot\..\þnameþ\þnameþ.psd1" +foreach ($dependency in $data.RequiredModules) { + if ($dependency -is [string]) { + if ($modules -contains $dependency) { continue } + $modules += $dependency + } + else { + if ($modules -contains $dependency.ModuleName) { continue } + $modules += $dependency.ModuleName + } +} + +foreach ($module in $modules) { + Write-Host "Installing $module" -ForegroundColor Cyan + Install-Module $module -Force -SkipPublisherCheck -Repository $Repository + Import-Module $module -Force -PassThru +} \ No newline at end of file diff --git a/templates/MiniModule/build/vsts-validate.ps1 b/templates/MiniModule/build/vsts-validate.ps1 new file mode 100644 index 0000000..1ad4c70 --- /dev/null +++ b/templates/MiniModule/build/vsts-validate.ps1 @@ -0,0 +1,2 @@ +# Run internal pester tests +& "$PSScriptRoot\..\tests\pester.ps1" \ No newline at end of file diff --git a/templates/MiniModule/readme.md b/templates/MiniModule/readme.md new file mode 100644 index 0000000..32e8e0c --- /dev/null +++ b/templates/MiniModule/readme.md @@ -0,0 +1,3 @@ +# þnameþ + +ADD DESCRIPTION HERE diff --git a/templates/MiniModule/tests/functions/readme.md b/templates/MiniModule/tests/functions/readme.md new file mode 100644 index 0000000..f2b2ef0 --- /dev/null +++ b/templates/MiniModule/tests/functions/readme.md @@ -0,0 +1,7 @@ +# Description + +This is where the function tests go. + +Make sure to put them in folders reflecting the actual module structure. + +It is not necessary to differentiate between internal and public functions here. \ No newline at end of file diff --git a/templates/MiniModule/tests/general/FileIntegrity.Exceptions.ps1 b/templates/MiniModule/tests/general/FileIntegrity.Exceptions.ps1 new file mode 100644 index 0000000..0d92e79 --- /dev/null +++ b/templates/MiniModule/tests/general/FileIntegrity.Exceptions.ps1 @@ -0,0 +1,31 @@ +# List of forbidden commands +$global:BannedCommands = @( + 'Write-Output' + + # Use CIM instead where possible + 'Get-WmiObject' + 'Invoke-WmiMethod' + 'Register-WmiEvent' + 'Remove-WmiObject' + 'Set-WmiInstance' + + # Use Get-WinEvent instead + 'Get-EventLog' +) + +<# + Contains list of exceptions for banned cmdlets. + Insert the file names of files that may contain them. + + Example: + "Write-Host" = @('Write-PSFHostColor.ps1','Write-PSFMessage.ps1') +#> +$global:MayContainCommand = @{ + "Write-Host" = @() + "Write-Verbose" = @() + "Write-Warning" = @() + "Write-Error" = @() + "Write-Output" = @() + "Write-Information" = @() + "Write-Debug" = @() +} \ No newline at end of file diff --git a/templates/MiniModule/tests/general/FileIntegrity.Tests.ps1 b/templates/MiniModule/tests/general/FileIntegrity.Tests.ps1 new file mode 100644 index 0000000..8656e65 --- /dev/null +++ b/templates/MiniModule/tests/general/FileIntegrity.Tests.ps1 @@ -0,0 +1,95 @@ +$moduleRoot = (Resolve-Path "$global:testroot\..").Path + +. "$global:testroot\general\FileIntegrity.Exceptions.ps1" + +Describe "Verifying integrity of module files" { + BeforeAll { + function Get-FileEncoding + { + <# + .SYNOPSIS + Tests a file for encoding. + + .DESCRIPTION + Tests a file for encoding. + + .PARAMETER Path + The file to test + #> + [CmdletBinding()] + Param ( + [Parameter(Mandatory = $True, ValueFromPipelineByPropertyName = $True)] + [Alias('FullName')] + [string] + $Path + ) + + if ($PSVersionTable.PSVersion.Major -lt 6) + { + [byte[]]$byte = get-content -Encoding byte -ReadCount 4 -TotalCount 4 -Path $Path + } + else + { + [byte[]]$byte = Get-Content -AsByteStream -ReadCount 4 -TotalCount 4 -Path $Path + } + + if ($byte[0] -eq 0xef -and $byte[1] -eq 0xbb -and $byte[2] -eq 0xbf) { 'UTF8 BOM' } + elseif ($byte[0] -eq 0xfe -and $byte[1] -eq 0xff) { 'Unicode' } + elseif ($byte[0] -eq 0 -and $byte[1] -eq 0 -and $byte[2] -eq 0xfe -and $byte[3] -eq 0xff) { 'UTF32' } + elseif ($byte[0] -eq 0x2b -and $byte[1] -eq 0x2f -and $byte[2] -eq 0x76) { 'UTF7' } + else { 'Unknown' } + } + } + + Context "Validating PS1 Script files" { + $allFiles = Get-ChildItem -Path $moduleRoot -Recurse | Where-Object Name -like "*.ps1" | Where-Object FullName -NotLike "$moduleRoot\tests\*" + + foreach ($file in $allFiles) + { + $name = $file.FullName.Replace("$moduleRoot\", '') + + It "[$name] Should have UTF8 encoding with Byte Order Mark" -TestCases @{ file = $file } { + Get-FileEncoding -Path $file.FullName | Should -Be 'UTF8 BOM' + } + + It "[$name] Should have no trailing space" -TestCases @{ file = $file } { + ($file | Select-String "\s$" | Where-Object { $_.Line.Trim().Length -gt 0}).LineNumber | Should -BeNullOrEmpty + } + + $tokens = $null + $parseErrors = $null + $null = [System.Management.Automation.Language.Parser]::ParseFile($file.FullName, [ref]$tokens, [ref]$parseErrors) + + It "[$name] Should have no syntax errors" -TestCases @{ parseErrors = $parseErrors } { + $parseErrors | Should -BeNullOrEmpty + } + + foreach ($command in $global:BannedCommands) + { + if ($global:MayContainCommand["$command"] -notcontains $file.Name) + { + It "[$name] Should not use $command" -TestCases @{ tokens = $tokens; command = $command } { + $tokens | Where-Object Text -EQ $command | Should -BeNullOrEmpty + } + } + } + } + } + + Context "Validating help.txt help files" { + $allFiles = Get-ChildItem -Path $moduleRoot -Recurse | Where-Object Name -like "*.help.txt" | Where-Object FullName -NotLike "$moduleRoot\tests\*" + + foreach ($file in $allFiles) + { + $name = $file.FullName.Replace("$moduleRoot\", '') + + It "[$name] Should have UTF8 encoding" -TestCases @{ file = $file } { + Get-FileEncoding -Path $file.FullName | Should -Be 'UTF8 BOM' + } + + It "[$name] Should have no trailing space" -TestCases @{ file = $file } { + ($file | Select-String "\s$" | Where-Object { $_.Line.Trim().Length -gt 0 } | Measure-Object).Count | Should -Be 0 + } + } + } +} \ No newline at end of file diff --git a/templates/MiniModule/tests/general/Help.Exceptions.ps1 b/templates/MiniModule/tests/general/Help.Exceptions.ps1 new file mode 100644 index 0000000..f9c9bd7 --- /dev/null +++ b/templates/MiniModule/tests/general/Help.Exceptions.ps1 @@ -0,0 +1,26 @@ +# List of functions that should be ignored +$global:FunctionHelpTestExceptions = @( + +) + +<# + List of arrayed enumerations. These need to be treated differently. Add full name. + Example: + + "Sqlcollaborative.Dbatools.Connection.ManagementConnectionType[]" +#> +$global:HelpTestEnumeratedArrays = @( + +) + +<# + Some types on parameters just fail their validation no matter what. + For those it becomes possible to skip them, by adding them to this hashtable. + Add by following this convention: = @() + Example: + + "Get-DbaCmObject" = @("DoNotUse") +#> +$global:HelpTestSkipParameterType = @{ + +} diff --git a/templates/MiniModule/tests/general/Help.Tests.ps1 b/templates/MiniModule/tests/general/Help.Tests.ps1 new file mode 100644 index 0000000..f1dc4d3 --- /dev/null +++ b/templates/MiniModule/tests/general/Help.Tests.ps1 @@ -0,0 +1,152 @@ +<# + .NOTES + The original test this is based upon was written by June Blender. + After several rounds of modifications it stands now as it is, but the honor remains hers. + + Thank you June, for all you have done! + + .DESCRIPTION + This test evaluates the help for all commands in a module. + + .PARAMETER SkipTest + Disables this test. + + .PARAMETER CommandPath + List of paths under which the script files are stored. + This test assumes that all functions have their own file that is named after themselves. + These paths are used to search for commands that should exist and be tested. + Will search recursively and accepts wildcards, make sure only functions are found + + .PARAMETER ModuleName + Name of the module to be tested. + The module must already be imported + + .PARAMETER ExceptionsFile + File in which exceptions and adjustments are configured. + In it there should be two arrays and a hashtable defined: + $global:FunctionHelpTestExceptions + $global:HelpTestEnumeratedArrays + $global:HelpTestSkipParameterType + These can be used to tweak the tests slightly in cases of need. + See the example file for explanations on each of these usage and effect. +#> +[CmdletBinding()] +Param ( + [switch] + $SkipTest, + + [string[]] + $CommandPath = @("$global:testroot\..\þnameþ\functions", "$global:testroot\..\þnameþ\internal\functions"), + + [string] + $ModuleName = "þnameþ", + + [string] + $ExceptionsFile = "$global:testroot\general\Help.Exceptions.ps1" +) +if ($SkipTest) { return } +. $ExceptionsFile + +$CommandPath = @( + "$global:testroot\..\þnameþ\functions" + "$global:testroot\..\þnameþ\internal\functions" +) + +$includedNames = foreach ($path in $CommandPath) { (Get-ChildItem $path -Recurse -File | Where-Object Name -like "*.ps1").BaseName } +$commandTypes = @('Cmdlet', 'Function') +if ($PSVersionTable.PSEdition -eq 'Desktop' ) { $commandTypes += 'Workflow' } +$commands = Get-Command -Module (Get-Module $ModuleName) -CommandType $commandTypes | Where-Object Name -In $includedNames + +## When testing help, remember that help is cached at the beginning of each session. +## To test, restart session. + + +foreach ($command in $commands) { + $commandName = $command.Name + + # Skip all functions that are on the exclusions list + if ($global:FunctionHelpTestExceptions -contains $commandName) { continue } + + # The module-qualified command fails on Microsoft.PowerShell.Archive cmdlets + $Help = Get-Help $commandName -ErrorAction SilentlyContinue + + Describe "Test help for $commandName" { + + # If help is not found, synopsis in auto-generated help is the syntax diagram + It "should not be auto-generated" -TestCases @{ Help = $Help } { + $Help.Synopsis | Should -Not -BeLike '*`[``]*' + } + + # Should be a description for every function + It "gets description for $commandName" -TestCases @{ Help = $Help } { + $Help.Description | Should -Not -BeNullOrEmpty + } + + # Should be at least one example + It "gets example code from $commandName" -TestCases @{ Help = $Help } { + ($Help.Examples.Example | Select-Object -First 1).Code | Should -Not -BeNullOrEmpty + } + + # Should be at least one example description + It "gets example help from $commandName" -TestCases @{ Help = $Help } { + ($Help.Examples.Example.Remarks | Select-Object -First 1).Text | Should -Not -BeNullOrEmpty + } + + Context "Test parameter help for $commandName" { + + $common = 'Debug', 'ErrorAction', 'ErrorVariable', 'InformationAction', 'InformationVariable', 'OutBuffer', 'OutVariable', 'PipelineVariable', 'Verbose', 'WarningAction', 'WarningVariable' + + $parameters = $command.ParameterSets.Parameters | Sort-Object -Property Name -Unique | Where-Object Name -notin $common + $parameterNames = $parameters.Name + $HelpParameterNames = $Help.Parameters.Parameter.Name | Sort-Object -Unique + foreach ($parameter in $parameters) { + $parameterName = $parameter.Name + $parameterHelp = $Help.parameters.parameter | Where-Object Name -EQ $parameterName + + # Should be a description for every parameter + It "gets help for parameter: $parameterName : in $commandName" -TestCases @{ parameterHelp = $parameterHelp } { + $parameterHelp.Description.Text | Should -Not -BeNullOrEmpty + } + + $codeMandatory = $parameter.IsMandatory.toString() + It "help for $parameterName parameter in $commandName has correct Mandatory value" -TestCases @{ parameterHelp = $parameterHelp; codeMandatory = $codeMandatory } { + $parameterHelp.Required | Should -Be $codeMandatory + } + + if ($HelpTestSkipParameterType[$commandName] -contains $parameterName) { continue } + + $codeType = $parameter.ParameterType.Name + + if ($parameter.ParameterType.IsEnum) { + # Enumerations often have issues with the typename not being reliably available + $names = $parameter.ParameterType::GetNames($parameter.ParameterType) + # Parameter type in Help should match code + It "help for $commandName has correct parameter type for $parameterName" -TestCases @{ parameterHelp = $parameterHelp; names = $names } { + $parameterHelp.parameterValueGroup.parameterValue | Should -be $names + } + } + elseif ($parameter.ParameterType.FullName -in $HelpTestEnumeratedArrays) { + # Enumerations often have issues with the typename not being reliably available + $names = [Enum]::GetNames($parameter.ParameterType.DeclaredMembers[0].ReturnType) + It "help for $commandName has correct parameter type for $parameterName" -TestCases @{ parameterHelp = $parameterHelp; names = $names } { + $parameterHelp.parameterValueGroup.parameterValue | Should -be $names + } + } + else { + # To avoid calling Trim method on a null object. + $helpType = if ($parameterHelp.parameterValue) { $parameterHelp.parameterValue.Trim() } + # Parameter type in Help should match code + It "help for $commandName has correct parameter type for $parameterName" -TestCases @{ helpType = $helpType; codeType = $codeType } { + $helpType | Should -be $codeType + } + } + } + foreach ($helpParm in $HelpParameterNames) { + # Shouldn't find extra parameters in help. + It "finds help parameter in code: $helpParm" -TestCases @{ helpParm = $helpParm; parameterNames = $parameterNames } { + $helpParm -in $parameterNames | Should -Be $true + } + } + } + } +} \ No newline at end of file diff --git a/templates/MiniModule/tests/general/Manifest.Tests.ps1 b/templates/MiniModule/tests/general/Manifest.Tests.ps1 new file mode 100644 index 0000000..215f3b7 --- /dev/null +++ b/templates/MiniModule/tests/general/Manifest.Tests.ps1 @@ -0,0 +1,62 @@ +Describe "Validating the module manifest" { + $moduleRoot = (Resolve-Path "$global:testroot\..\þnameþ").Path + $manifest = ((Get-Content "$moduleRoot\þnameþ.psd1") -join "`n") | Invoke-Expression + Context "Basic resources validation" { + $files = Get-ChildItem "$moduleRoot\functions" -Recurse -File | Where-Object Name -like "*.ps1" + It "Exports all functions in the public folder" -TestCases @{ files = $files; manifest = $manifest } { + + $functions = (Compare-Object -ReferenceObject $files.BaseName -DifferenceObject $manifest.FunctionsToExport | Where-Object SideIndicator -Like '<=').InputObject + $functions | Should -BeNullOrEmpty + } + It "Exports no function that isn't also present in the public folder" -TestCases @{ files = $files; manifest = $manifest } { + $functions = (Compare-Object -ReferenceObject $files.BaseName -DifferenceObject $manifest.FunctionsToExport | Where-Object SideIndicator -Like '=>').InputObject + $functions | Should -BeNullOrEmpty + } + + It "Exports none of its internal functions" -TestCases @{ moduleRoot = $moduleRoot; manifest = $manifest } { + $files = Get-ChildItem "$moduleRoot\internal\functions" -Recurse -File -Filter "*.ps1" + $files | Where-Object BaseName -In $manifest.FunctionsToExport | Should -BeNullOrEmpty + } + } + + Context "Individual file validation" { + It "The root module file exists" -TestCases @{ moduleRoot = $moduleRoot; manifest = $manifest } { + Test-Path "$moduleRoot\$($manifest.RootModule)" | Should -Be $true + } + + foreach ($format in $manifest.FormatsToProcess) + { + It "The file $format should exist" -TestCases @{ moduleRoot = $moduleRoot; format = $format } { + Test-Path "$moduleRoot\$format" | Should -Be $true + } + } + + foreach ($type in $manifest.TypesToProcess) + { + It "The file $type should exist" -TestCases @{ moduleRoot = $moduleRoot; type = $type } { + Test-Path "$moduleRoot\$type" | Should -Be $true + } + } + + foreach ($assembly in $manifest.RequiredAssemblies) + { + if ($assembly -like "*.dll") { + It "The file $assembly should exist" -TestCases @{ moduleRoot = $moduleRoot; assembly = $assembly } { + Test-Path "$moduleRoot\$assembly" | Should -Be $true + } + } + else { + It "The file $assembly should load from the GAC" -TestCases @{ moduleRoot = $moduleRoot; assembly = $assembly } { + { Add-Type -AssemblyName $assembly } | Should -Not -Throw + } + } + } + + foreach ($tag in $manifest.PrivateData.PSData.Tags) + { + It "Tags should have no spaces in name" -TestCases @{ tag = $tag } { + $tag -match " " | Should -Be $false + } + } + } +} \ No newline at end of file diff --git a/templates/MiniModule/tests/general/PSScriptAnalyzer.Tests.ps1 b/templates/MiniModule/tests/general/PSScriptAnalyzer.Tests.ps1 new file mode 100644 index 0000000..1686112 --- /dev/null +++ b/templates/MiniModule/tests/general/PSScriptAnalyzer.Tests.ps1 @@ -0,0 +1,40 @@ +[CmdletBinding()] +Param ( + [switch] + $SkipTest, + + [string[]] + $CommandPath = @("$global:testroot\..\þnameþ\functions", "$global:testroot\..\þnameþ\internal\functions") +) + +if ($SkipTest) { return } + +$global:__pester_data.ScriptAnalyzer = New-Object System.Collections.ArrayList + +Describe 'Invoking PSScriptAnalyzer against commandbase' { + $commandFiles = foreach ($path in $CommandPath) { Get-ChildItem -Path $path -Recurse | Where-Object Name -like "*.ps1" } + $scriptAnalyzerRules = Get-ScriptAnalyzerRule + + foreach ($file in $commandFiles) + { + Context "Analyzing $($file.BaseName)" { + $analysis = Invoke-ScriptAnalyzer -Path $file.FullName -ExcludeRule PSAvoidTrailingWhitespace, PSShouldProcess + + forEach ($rule in $scriptAnalyzerRules) + { + It "Should pass $rule" -TestCases @{ analysis = $analysis; rule = $rule } { + If ($analysis.RuleName -contains $rule) + { + $analysis | Where-Object RuleName -EQ $rule -outvariable failures | ForEach-Object { $null = $global:__pester_data.ScriptAnalyzer.Add($_) } + + 1 | Should -Be 0 + } + else + { + 0 | Should -Be 0 + } + } + } + } + } +} \ No newline at end of file diff --git a/templates/MiniModule/tests/pester.ps1 b/templates/MiniModule/tests/pester.ps1 new file mode 100644 index 0000000..d2785eb --- /dev/null +++ b/templates/MiniModule/tests/pester.ps1 @@ -0,0 +1,113 @@ +param ( + $TestGeneral = $true, + + $TestFunctions = $true, + + [ValidateSet('None', 'Normal', 'Detailed', 'Diagnostic')] + [Alias('Show')] + $Output = "None", + + $Include = "*", + + $Exclude = "" +) + +Write-Host "Starting Tests" + +Write-Host "Importing Module" + +$global:testroot = $PSScriptRoot +$global:__pester_data = @{ } + +Remove-Module þnameþ -ErrorAction Ignore +Import-Module "$PSScriptRoot\..\þnameþ\þnameþ.psd1" +Import-Module "$PSScriptRoot\..\þnameþ\þnameþ.psm1" -Force + +# Need to import explicitly so we can use the configuration class +Import-Module Pester + +Write-Host "Creating test result folder" +$null = New-Item -Path "$PSScriptRoot\.." -Name TestResults -ItemType Directory -Force + +$totalFailed = 0 +$totalRun = 0 + +$testresults = @() +$config = [PesterConfiguration]::Default +$config.TestResult.Enabled = $true + +#region Run General Tests +if ($TestGeneral) +{ + Write-Host "Modules imported, proceeding with general tests" + foreach ($file in (Get-ChildItem "$PSScriptRoot\general" | Where-Object Name -like "*.Tests.ps1")) + { + if ($file.Name -notlike $Include) { continue } + if ($file.Name -like $Exclude) { continue } + + Write-Host " Executing $($file.Name)" + $config.TestResult.OutputPath = Join-Path "$PSScriptRoot\..\TestResults" "TEST-$($file.BaseName).xml" + $config.Run.Path = $file.FullName + $config.Run.PassThru = $true + $config.Output.Verbosity = $Output + $results = Invoke-Pester -Configuration $config + foreach ($result in $results) + { + $totalRun += $result.TotalCount + $totalFailed += $result.FailedCount + $result.Tests | Where-Object Result -ne 'Passed' | ForEach-Object { + $testresults += [pscustomobject]@{ + Block = $_.Block + Name = "It $($_.Name)" + Result = $_.Result + Message = $_.ErrorRecord.DisplayErrorMessage + } + } + } + } +} +#endregion Run General Tests + +$global:__pester_data.ScriptAnalyzer | Out-Host + +#region Test Commands +if ($TestFunctions) +{ + Write-Host "Proceeding with individual tests" + foreach ($file in (Get-ChildItem "$PSScriptRoot\functions" -Recurse -File | Where-Object Name -like "*Tests.ps1")) + { + if ($file.Name -notlike $Include) { continue } + if ($file.Name -like $Exclude) { continue } + + Write-Host " Executing $($file.Name)" + $config.TestResult.OutputPath = Join-Path "$PSScriptRoot\..\TestResults" "TEST-$($file.BaseName).xml" + $config.Run.Path = $file.FullName + $config.Run.PassThru = $true + $config.Output.Verbosity = $Output + $results = Invoke-Pester -Configuration $config + foreach ($result in $results) + { + $totalRun += $result.TotalCount + $totalFailed += $result.FailedCount + $result.Tests | Where-Object Result -ne 'Passed' | ForEach-Object { + $testresults += [pscustomobject]@{ + Block = $_.Block + Name = "It $($_.Name)" + Result = $_.Result + Message = $_.ErrorRecord.DisplayErrorMessage + } + } + } + } +} +#endregion Test Commands + +$testresults | Sort-Object Describe, Context, Name, Result, Message | Format-List + +if ($totalFailed -eq 0) { Write-Host "All $totalRun tests executed without a single failure!" } +else { Write-Host "$totalFailed tests out of $totalRun tests failed!" } + +if ($totalFailed -gt 0) +{ + throw "$totalFailed / $totalRun tests failed!" +} \ No newline at end of file diff --git a/templates/MiniModule/tests/readme.md b/templates/MiniModule/tests/readme.md new file mode 100644 index 0000000..43bb2fa --- /dev/null +++ b/templates/MiniModule/tests/readme.md @@ -0,0 +1,31 @@ +# Description + +This is the folder, where all the tests go. + +Those are subdivided in two categories: + + - General + - Function + +## General Tests + +General tests are function generic and test for general policies. + +These test scan answer questions such as: + + - Is my module following my style guides? + - Does any of my scripts have a syntax error? + - Do my scripts use commands I do not want them to use? + - Do my commands follow best practices? + - Do my commands have proper help? + +Basically, these allow a general module health check. + +These tests are already provided as part of the template. + +## Function Tests + +A healthy module should provide unit and integration tests for the commands & components it ships. +Only then can be guaranteed, that they will actually perform as promised. + +However, as each such test must be specific to the function it tests, there cannot be much in the way of templates. \ No newline at end of file diff --git "a/templates/MiniModule/\303\276name\303\276/LICENSE" "b/templates/MiniModule/\303\276name\303\276/LICENSE" new file mode 100644 index 0000000..89a8466 --- /dev/null +++ "b/templates/MiniModule/\303\276name\303\276/LICENSE" @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) þ!year!þ þauthorþ + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git "a/templates/MiniModule/\303\276name\303\276/functions/readme.md" "b/templates/MiniModule/\303\276name\303\276/functions/readme.md" new file mode 100644 index 0000000..105038b --- /dev/null +++ "b/templates/MiniModule/\303\276name\303\276/functions/readme.md" @@ -0,0 +1,3 @@ +# Functions + +Folder for all the functions the user is supposed to have access to. diff --git "a/templates/MiniModule/\303\276name\303\276/internal/functions/readme.md" "b/templates/MiniModule/\303\276name\303\276/internal/functions/readme.md" new file mode 100644 index 0000000..0643487 --- /dev/null +++ "b/templates/MiniModule/\303\276name\303\276/internal/functions/readme.md" @@ -0,0 +1,3 @@ +# Internal > Functions + +Folder for all the functions you want the user to not see. diff --git "a/templates/MiniModule/\303\276name\303\276/internal/scripts/readme.md" "b/templates/MiniModule/\303\276name\303\276/internal/scripts/readme.md" new file mode 100644 index 0000000..2a21053 --- /dev/null +++ "b/templates/MiniModule/\303\276name\303\276/internal/scripts/readme.md" @@ -0,0 +1,3 @@ +# Internal > Scripts + +Put in all the scripts that should be run once during import diff --git "a/templates/MiniModule/\303\276name\303\276/\303\276name\303\276.psd1" "b/templates/MiniModule/\303\276name\303\276/\303\276name\303\276.psd1" new file mode 100644 index 0000000..4cb69cd --- /dev/null +++ "b/templates/MiniModule/\303\276name\303\276/\303\276name\303\276.psd1" @@ -0,0 +1,126 @@ +@{ + +# Script module or binary module file associated with this manifest. +RootModule = 'þnameþ.psm1' + +# Version number of this module. +ModuleVersion = '1.0.0' + +# Supported PSEditions +# CompatiblePSEditions = @() + +# ID used to uniquely identify this module +GUID = 'þ!guid!þ' + +# Author of this module +Author = 'þauthorþ' + +# Company or vendor of this module +CompanyName = 'þcompanyþ' + +# Copyright statement for this module +Copyright = '(c) þauthorþ. All rights reserved.' + +# Description of the functionality provided by this module +Description = 'þdescriptionþ' + +# Minimum version of the PowerShell engine required by this module +# PowerShellVersion = '' + +# Name of the PowerShell host required by this module +# PowerShellHostName = '' + +# Minimum version of the PowerShell host required by this module +# PowerShellHostVersion = '' + +# Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only. +# DotNetFrameworkVersion = '' + +# Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only. +# ClrVersion = '' + +# Processor architecture (None, X86, Amd64) required by this module +# ProcessorArchitecture = '' + +# Modules that must be imported into the global environment prior to importing this module +# RequiredModules = @() + +# Assemblies that must be loaded prior to importing this module +# RequiredAssemblies = @() + +# Script files (.ps1) that are run in the caller's environment prior to importing this module. +# ScriptsToProcess = @() + +# Type files (.ps1xml) to be loaded when importing this module +# TypesToProcess = @() + +# Format files (.ps1xml) to be loaded when importing this module +# FormatsToProcess = @() + +# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess +# NestedModules = @() + +# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. +FunctionsToExport = @( + +) + +# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. +# CmdletsToExport = '*' + +# Variables to export from this module +# VariablesToExport = '*' + +# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export. +# AliasesToExport = '*' + +# DSC resources to export from this module +# DscResourcesToExport = @() + +# List of all modules packaged with this module +# ModuleList = @() + +# List of all files packaged with this module +# FileList = @() + +# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. +PrivateData = @{ + + PSData = @{ + + # Tags applied to this module. These help with module discovery in online galleries. + # Tags = @() + + # A URL to the license for this module. + # LicenseUri = '' + + # A URL to the main website for this project. + # ProjectUri = '' + + # A URL to an icon representing this module. + # IconUri = '' + + # ReleaseNotes of this module + # ReleaseNotes = '' + + # Prerelease string of this module + # Prerelease = '' + + # Flag to indicate whether the module requires explicit user acceptance for install/update/save + # RequireLicenseAcceptance = $false + + # External dependent modules of this module + # ExternalModuleDependencies = @() + + } # End of PSData hashtable + +} # End of PrivateData hashtable + +# HelpInfo URI of this module +# HelpInfoURI = '' + +# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. +# DefaultCommandPrefix = '' + +} + diff --git "a/templates/MiniModule/\303\276name\303\276/\303\276name\303\276.psm1" "b/templates/MiniModule/\303\276name\303\276/\303\276name\303\276.psm1" new file mode 100644 index 0000000..2681965 --- /dev/null +++ "b/templates/MiniModule/\303\276name\303\276/\303\276name\303\276.psm1" @@ -0,0 +1,11 @@ +foreach ($file in Get-ChildItem -Path "$PSScriptRoot/internal/functions" -Filter *.ps1 -Recurse) { + . $file.FullName +} + +foreach ($file in Get-ChildItem -Path "$PSScriptRoot/functions" -Filter *.ps1 -Recurse) { + . $file.FullName +} + +foreach ($file in Get-ChildItem -Path "$PSScriptRoot/internal/scripts" -Filter *.ps1 -Recurse) { + . $file.FullName +} \ No newline at end of file From bfdea17bd7bf403343cc3ffae22acc68df589d5f Mon Sep 17 00:00:00 2001 From: Friedrich Weinmann Date: Tue, 19 Apr 2022 19:34:07 +0200 Subject: [PATCH 8/8] adding outputtype --- .../functions/templating/Invoke-PSMDTemplate.ps1 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/PSModuleDevelopment/functions/templating/Invoke-PSMDTemplate.ps1 b/PSModuleDevelopment/functions/templating/Invoke-PSMDTemplate.ps1 index 911986d..a33d922 100644 --- a/PSModuleDevelopment/functions/templating/Invoke-PSMDTemplate.ps1 +++ b/PSModuleDevelopment/functions/templating/Invoke-PSMDTemplate.ps1 @@ -82,6 +82,7 @@ #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSPossibleIncorrectUsageOfAssignmentOperator", "")] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', '')] + [OutputType([PSModuleDevelopment.Template.TemplateResult])] [Alias('imt')] [CmdletBinding(SupportsShouldProcess = $true)] param ( @@ -304,6 +305,7 @@ function New-TemplateItem { [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")] + [OutputType([PSModuleDevelopment.Template.TemplateResult])] [CmdletBinding()] param ( [PSModuleDevelopment.Template.TemplateItemBase]