From b0acf020c2fe4b02a29ff80cadf833c85a901226 Mon Sep 17 00:00:00 2001 From: Andrew Davidson Date: Sat, 1 May 2021 19:23:10 +0100 Subject: [PATCH 1/9] Fix problems when there are no scripts in the scripts folder --- Source/PSQualityCheck/PSQualityCheck.psd1 | 2 +- .../Public/Invoke-PSQualityCheck.ps1 | 52 +++++++++++++++++++ Source/PSQualityCheck/data/Script.Checks.ps1 | 2 +- Tests/Invoke-UnitTest.ps1 | 8 --- build-functions.psm1 | 2 +- 5 files changed, 55 insertions(+), 11 deletions(-) diff --git a/Source/PSQualityCheck/PSQualityCheck.psd1 b/Source/PSQualityCheck/PSQualityCheck.psd1 index ee781ea..28bc3bd 100644 --- a/Source/PSQualityCheck/PSQualityCheck.psd1 +++ b/Source/PSQualityCheck/PSQualityCheck.psd1 @@ -12,7 +12,7 @@ RootModule = 'PSQualityCheck.psm1' # Version number of this module. - ModuleVersion = '2.0.0' + ModuleVersion = '2.0.1' # Supported PSEditions # CompatiblePSEditions = @() diff --git a/Source/PSQualityCheck/Public/Invoke-PSQualityCheck.ps1 b/Source/PSQualityCheck/Public/Invoke-PSQualityCheck.ps1 index edf84b9..0c6f065 100644 --- a/Source/PSQualityCheck/Public/Invoke-PSQualityCheck.ps1 +++ b/Source/PSQualityCheck/Public/Invoke-PSQualityCheck.ps1 @@ -238,6 +238,15 @@ function Invoke-PSQualityCheck { } else { Write-Error "Project Path $ProjectPath does not exist" + $projectResults = + @{ + 'Count' = 0 + 'TotalCount' = 0 + 'NotRunCount' = 0 + 'PassedCount' = 0 + 'FailedCount' = 0 + 'SkippedCount' = 0 + } } } @@ -418,6 +427,26 @@ function Invoke-PSQualityCheck { $extractionResults = Invoke-Pester -Configuration $PesterConfiguration } + else { + $moduleResults = + @{ + 'Count' = 0 + 'TotalCount' = 0 + 'NotRunCount' = 0 + 'PassedCount' = 0 + 'FailedCount' = 0 + 'SkippedCount' = 0 + } + $extractionResults = + @{ + 'Count' = 0 + 'TotalCount' = 0 + 'NotRunCount' = 0 + 'PassedCount' = 0 + 'FailedCount' = 0 + 'SkippedCount' = 0 + } + } if ($runScriptCheck -eq $true -and (Test-Path -Path $extractPath -ErrorAction SilentlyContinue)) { @@ -428,6 +457,18 @@ function Invoke-PSQualityCheck { $container3 = New-PesterContainer -Path (Join-Path -Path $modulePath -ChildPath 'Data\Script.Checks.ps1') -Data @{ Source = $extractedScriptsToTest; ScriptAnalyzerRulesPath = $ScriptAnalyzerRulesPath; HelpRulesPath = $HelpRulesPath } $PesterConfiguration.Run.Container = $container3 $extractedScriptResults = Invoke-Pester -Configuration $PesterConfiguration + + } + else { + $extractedScriptResults = + @{ + 'Count' = 0 + 'TotalCount' = 0 + 'NotRunCount' = 0 + 'PassedCount' = 0 + 'FailedCount' = 0 + 'SkippedCount' = 0 + } } # Tidy up and temporary paths that have been used @@ -447,6 +488,17 @@ function Invoke-PSQualityCheck { $scriptResults = Invoke-Pester -Configuration $PesterConfiguration } + else { + $scriptResults = + @{ + 'Count' = 0 + 'TotalCount' = 0 + 'NotRunCount' = 0 + 'PassedCount' = 0 + 'FailedCount' = 0 + 'SkippedCount' = 0 + } + } # Show/Export results in the various formats diff --git a/Source/PSQualityCheck/data/Script.Checks.ps1 b/Source/PSQualityCheck/data/Script.Checks.ps1 index 02c3631..11f8b26 100644 --- a/Source/PSQualityCheck/data/Script.Checks.ps1 +++ b/Source/PSQualityCheck/data/Script.Checks.ps1 @@ -44,7 +44,7 @@ BeforeDiscovery { Describe "Script Tests" -Tag "Script" { - Context "Script: <_.Name> at <_.Directory>" -Foreach $scriptFiles { + Context "Script: <_.Name> at <_.Directory>" -ForEach $scriptFiles { BeforeAll { diff --git a/Tests/Invoke-UnitTest.ps1 b/Tests/Invoke-UnitTest.ps1 index 7e785ac..41fef86 100644 --- a/Tests/Invoke-UnitTest.ps1 +++ b/Tests/Invoke-UnitTest.ps1 @@ -25,14 +25,6 @@ $configuration.Run.PassThru = $false $configuration.Should.ErrorAction = 'Stop' # Dot load all the module ready to test -Get-ChildItem -Path "..\Source\PSQualityCheck.Functions\Public" -Filter *.ps1 | ForEach-Object { - . $_.FullName -} - -Get-ChildItem -Path "..\Source\PSQualityCheck.Functions\Private" -Filter *.ps1 | ForEach-Object { - . $_.FullName -} - Get-ChildItem -Path "..\Source\PSQualityCheck\Public" -Filter *.ps1 | ForEach-Object { . $_.FullName } diff --git a/build-functions.psm1 b/build-functions.psm1 index 36dfc16..f218410 100644 --- a/build-functions.psm1 +++ b/build-functions.psm1 @@ -73,7 +73,7 @@ function Install-BuiltModule { [string]$ModuleName ) - Install-Module -Name $ModuleName -Repository "$ModuleName-local" + Install-Module -Name $ModuleName -Repository "$ModuleName-local" -Force } From be174bc312c8c1baaea26e973ef9137ccc39e9f2 Mon Sep 17 00:00:00 2001 From: Andrew Davidson Date: Thu, 18 Jan 2024 09:36:27 +0000 Subject: [PATCH 2/9] Updated readme to remove 2 year old Coming soon banner; code reformat using standard tooling --- README.md | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 11c9f39..308e0c7 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,6 @@ ## Summary -### **NEW** PSQualityCheck v2.0.0 and **COMING SOON!** its companion module PSQualityTempate - This is a PowerShell module which runs a series of Pester 5 tests to validate code quality. It uses a combination of Pester tests, PSScriptAnalyzer and a set of quality standards to ensure consistent quality on PowerShell scripts and modules. For more information please see the wiki here [Wiki](https://github.com/andrewrdavidson/PSQualityCheck/wiki) @@ -32,20 +30,20 @@ Is available here [Release History](https://github.com/andrewrdavidson/PSQuality This module requires: -* PowerShell 5.1 or PowerShell 7.1 or later -* Pester 5.1 or later -* PSScriptAnalyzer 1.19.1 or later -* ModuleBuilder 2.0.0 or later (to build) -* PowerShellGet 2.2.5 or later (to build) -* InvokeBuild 5.8.0 pr later (to build) -* Cofl.Util 1.2.2 or later (to build) +- PowerShell 5.1 or PowerShell 7.1 or later +- Pester 5.1 or later +- PSScriptAnalyzer 1.19.1 or later +- ModuleBuilder 2.0.0 or later (to build) +- PowerShellGet 2.2.5 or later (to build) +- InvokeBuild 5.8.0 pr later (to build) +- Cofl.Util 1.2.2 or later (to build) Optional items: -* Extra PSScriptAnalyzer rules (used by SonarQube) are available here:
[https://github.com/indented-automation/ScriptAnalyzerRules](https://github.com/indented-automation/ScriptAnalyzerRules) -* Extra PSScriptAnalyzer rules (used by VSCode) are available here:
[https://github.com/PowerShell/PSScriptAnalyzer/tree/master/Tests/Engine/CommunityAnalyzerRules](https://github.com/PowerShell/PSScriptAnalyzer/tree/master/Tests/Engine/CommunityAnalyzerRules) -* InjectionHunter rules are available here:
[https://www.powershellgallery.com/packages/InjectionHunter](https://www.powershellgallery.com/packages/InjectionHunter)
-[https://github.com/matt2005/InjectionHunter](https://github.com/matt2005/InjectionHunter) +- Extra PSScriptAnalyzer rules (used by SonarQube) are available here:
[https://github.com/indented-automation/ScriptAnalyzerRules](https://github.com/indented-automation/ScriptAnalyzerRules) +- Extra PSScriptAnalyzer rules (used by VSCode) are available here:
[https://github.com/PowerShell/PSScriptAnalyzer/tree/master/Tests/Engine/CommunityAnalyzerRules](https://github.com/PowerShell/PSScriptAnalyzer/tree/master/Tests/Engine/CommunityAnalyzerRules) +- InjectionHunter rules are available here:
[https://www.powershellgallery.com/packages/InjectionHunter](https://www.powershellgallery.com/packages/InjectionHunter)
+ [https://github.com/matt2005/InjectionHunter](https://github.com/matt2005/InjectionHunter) ## Installation From c86daf66e1a855728e0dacd1c4b4d39b27ffb22a Mon Sep 17 00:00:00 2001 From: Andrew Davidson Date: Thu, 18 Jan 2024 09:37:28 +0000 Subject: [PATCH 3/9] Fix bug that occurs by not passing in HelpRulesPath properly --- .../Public/Invoke-PSQualityCheck.ps1 | 1292 ++++++++--------- 1 file changed, 640 insertions(+), 652 deletions(-) diff --git a/Source/PSQualityCheck/Public/Invoke-PSQualityCheck.ps1 b/Source/PSQualityCheck/Public/Invoke-PSQualityCheck.ps1 index 0c6f065..e0bfd4b 100644 --- a/Source/PSQualityCheck/Public/Invoke-PSQualityCheck.ps1 +++ b/Source/PSQualityCheck/Public/Invoke-PSQualityCheck.ps1 @@ -1,652 +1,640 @@ -function Invoke-PSQualityCheck { - <# - .SYNOPSIS - Invoke the PSQualityCheck tests - - .DESCRIPTION - Invoke a series of Pester-based quality tests on the passed files - - .PARAMETER Path - A string array containing paths to check for testable files - - .PARAMETER File - A string array containing testable files - - .PARAMETER Recurse - A switch specifying whether or not to recursively search the path specified - - .PARAMETER ScriptAnalyzerRulesPath - A path the the external PSScriptAnalyzer rules - - .PARAMETER ShowCheckResults - Show a summary of the Check results at the end of processing - Note: this cannot be used with -Passthru - - .PARAMETER ExportCheckResults - Exports the Check results at the end of processing to file - - .PARAMETER Passthru - Returns the Check results objects back to the caller - Note: this cannot be used with -ShowCheckResults - - .PARAMETER PesterConfiguration - A Pester configuration object to allow configuration of Pester - - .PARAMETER Include - An array of test tags to run - - .PARAMETER Exclude - An array of test tags to not run - - .PARAMETER ProjectPath - A path to the root of a Project - - .PARAMETER HelpRulesPath - A path to the HelpRules parameter file - - .PARAMETER IgnoreFile - A path to the .psqcignore file which excludes files/path from the tests. This is in the .gitignore format - - .EXAMPLE - Invoke-PSQualityCheck -Path 'C:\Scripts' - - This will call the quality checks on single path - - .EXAMPLE - Invoke-PSQualityCheck -Path 'C:\Scripts' -Recurse - - This will call the quality checks on single path and sub folders - - .EXAMPLE - Invoke-PSQualityCheck -Path @('C:\Scripts', 'C:\MoreScripts') - - This will call the quality checks with multiple paths - - .EXAMPLE - Invoke-PSQualityCheck -ProjectPath 'C:\Project' -IgnoreFile ".psqcignore" - - This will call the project quality checks on the C:\Project folder with the .psqcignore file - - .EXAMPLE - Invoke-PSQualityCheck -File 'C:\Scripts\Script.ps1' - - This will call the quality checks with single script file - - .EXAMPLE - Invoke-PSQualityCheck -File 'C:\Scripts\Script.psm1' - - This will call the quality checks with single module file - - .EXAMPLE - Invoke-PSQualityCheck -File 'C:\Scripts\Script.psd1' - - This will call the quality checks with single datafile file - Note: The datafile test will fail as it is not a file that is accepted for testing - - .EXAMPLE - Invoke-PSQualityCheck -File @('C:\Scripts\Script.ps1','C:\Scripts\Script2.ps1') - - This will call the quality checks with multiple files. Files can be either scripts or modules - - .EXAMPLE - Invoke-PSQualityCheck -File 'C:\Scripts\Script.ps1' -ScriptAnalyzerRulesPath 'C:\ScriptAnalyzerRulesPath' - - This will call the quality checks with single file and the extra PSScriptAnalyzer rules - - .EXAMPLE - Invoke-PSQualityCheck -Path 'C:\Scripts' -ShowCheckResults - - This will display a summary of the checks performed (example below uses sample data): - - Name Files Tested Total Passed Failed Skipped - ---- ------------ ----- ------ ------ ------- - Module Tests 2 14 14 0 0 - Extracting functions 2 2 2 0 0 - Extracted function script tests 22 330 309 0 21 - Total 24 346 325 0 21 - - For those who have spotted that the Total files tested isn't a total of the rows above, this is because the Module Tests and Extracting function Tests operate on the same file and are not counted twice - - .LINK - Website: https://github.com/andrewrdavidson/PSQualityCheck - SonarQube rules are available here: https://github.com/indented-automation/ScriptAnalyzerRules - - #> - [CmdletBinding()] - [OutputType([System.Void], [HashTable], [System.Object[]])] - param ( - [Parameter(Mandatory = $true, ParameterSetName = "Path")] - [String[]]$Path, - [Parameter(Mandatory = $true, ParameterSetName = "File")] - [String[]]$File, - [Parameter(Mandatory = $true, ParameterSetName = "ProjectPath")] - [String]$ProjectPath, - - [Parameter(Mandatory = $false, ParameterSetName = "Path")] - [switch]$Recurse, - - [Parameter(Mandatory = $false)] - [String[]]$ScriptAnalyzerRulesPath, - - [switch]$ShowCheckResults, - - [switch]$ExportCheckResults, - - [switch]$Passthru, - - [Parameter(Mandatory = $false)] - [System.Object]$PesterConfiguration, - - [Parameter(Mandatory = $false)] - [String[]]$Include, - - [Parameter(Mandatory = $false)] - [String[]]$Exclude, - - [Parameter(Mandatory = $false)] - [String]$HelpRulesPath, - - [Parameter(Mandatory = $false)] - [String]$IgnoreFile - - ) - - Set-StrictMode -Version Latest - - # External Modules - Import-Module -Name 'Pester' -MinimumVersion '5.1.0' -Force - Import-Module -Name 'PSScriptAnalyzer' -MinimumVersion '1.19.1' -Force - - $modulePath = (Get-Module -Name 'PSQualityCheck').ModuleBase - - # Validate any incoming parameters for clashes - if ($PSBoundParameters.ContainsKey('ShowCheckResults') -and $PSBoundParameters.ContainsKey('Passthru')) { - - Write-Error "-ShowCheckResults and -Passthru cannot be used at the same time" - break - - } - - $scriptsToTest = @() - $modulesToTest = @() - - $projectResults = $null - $moduleResults = $null - $extractionResults = $null - $extractedScriptResults = $null - $scriptResults = $null - - if ($PSBoundParameters.ContainsKey('HelpRulesPath')) { - - if ( -not (Test-Path -Path $HelpRulesPath)) { - - Write-Error "-HelpRulesPath does not exist" - break - - } - - } - else { - - $helpRulesPath = (Join-Path -Path $modulePath -ChildPath "Data\HelpRules.psd1") - - } - - if ($PSBoundParameters.ContainsKey('PesterConfiguration') -and $PesterConfiguration -is [PesterConfiguration]) { - - # left here so that we can over-ride passed in object with values we require - - } - else { - # Default Pester Parameters - $PesterConfiguration = [PesterConfiguration]::Default - $PesterConfiguration.Run.Exit = $false - $PesterConfiguration.CodeCoverage.Enabled = $false - $PesterConfiguration.Output.Verbosity = 'Detailed' - $PesterConfiguration.Run.PassThru = $true - $PesterConfiguration.Should.ErrorAction = 'Stop' - } - - # Analyse the incoming Path and File parameters and produce a list of Modules and Scripts - if ($PSBoundParameters.ContainsKey('Path') -or $PSBoundParameters.ContainsKey('ProjectPath')) { - - if ($PSBoundParameters.ContainsKey('ProjectPath')) { - - if (Test-Path -Path $ProjectPath) { - - $container1 = New-PesterContainer -Path (Join-Path -Path $modulePath -ChildPath 'Data\Project.Checks.ps1') -Data @{ Path = $ProjectPath } - $PesterConfiguration.Run.Container = $container1 - $projectResults = Invoke-Pester -Configuration $PesterConfiguration - - # setup the rest of the Path based tests - # this needs to include the module/public module/private and scripts folder only, not the data or any other folders - $ProjectPath = (Resolve-Path -Path $ProjectPath) - $sourceRootPath = (Join-Path -Path $ProjectPath -ChildPath "Source") - $scriptPath = (Join-Path -Path $ProjectPath -ChildPath "Scripts") - $Path = @($scriptPath) - - # Get the list of Modules - $modules = Get-ChildItem -Path $sourceRootPath -Directory - - foreach ($module in $modules) { - - $Path += (Join-Path -Path $module -ChildPath "Public") - $Path += (Join-Path -Path $module -ChildPath "Private") - - } - - } - else { - Write-Error "Project Path $ProjectPath does not exist" - $projectResults = - @{ - 'Count' = 0 - 'TotalCount' = 0 - 'NotRunCount' = 0 - 'PassedCount' = 0 - 'FailedCount' = 0 - 'SkippedCount' = 0 - } - } - - } - - if ($Path -isnot [string[]]) { - $Path = @($Path) - } - - foreach ($item in $Path) { - - # Test whether the item is a directory (also tells us if it exists) - if (Test-Path -Path $item -PathType Container) { - - $getFileListSplat = @{ - 'Path' = $item - } - - if ($PSBoundParameters.ContainsKey('IgnoreFile')) { - $getFileListSplat.Add('IgnoreFile', (Resolve-Path -Path $IgnoreFile)) - } - else { - if ($PSBoundParameters.ContainsKey('Recurse') -or - $PSBoundParameters.ContainsKey('ProjectPath')) { - $getFileListSplat.Add('Recurse', $true) - } - } - - $scriptsToTest += GetFileList @getFileListSplat -Extension '.ps1' - $modulesToTest += GetFileList @getFileListSplat -Extension '.psm1' - - } - else { - - Write-Warning -Message "$item is not a directory, skipping" - - } - - } - - } - - if ($PSBoundParameters.ContainsKey('File')) { - - if ($File -isnot [string[]]) { - $File = @($File) - } - - foreach ($item in $File) { - - # Test whether the item is a file (also tells us if it exists) - if (Test-Path -Path $item -PathType Leaf) { - - $getFilteredItemSplat = @{ - 'Path' = $item - } - - if ($PSBoundParameters.ContainsKey('IgnoreFile')) { - $getFilteredItemSplat.Add('IgnoreFile', (Resolve-Path -Path $IgnoreFile)) - } - - $itemProperties = Get-FilteredChildItem @getFilteredItemSplat - - switch ($itemProperties.Extension) { - - '.psm1' { - $modulesToTest += $itemProperties - } - - '.ps1' { - $scriptsToTest += $itemProperties - } - - } - - } - else { - - Write-Warning -Message "$item is not a file, skipping" - - } - - } - - } - - # Get the list of test tags from the Data files - if ($PSBoundParameters.ContainsKey('Include') -or - $PSBoundParameters.ContainsKey('Exclude')) { - - - ($moduleTags, $scriptTags) = GetTagList - $moduleTagsToInclude = @() - $moduleTagsToExclude = @() - $scriptTagsToInclude = @() - $scriptTagsToExclude = @() - $runModuleCheck = $false - $runScriptCheck = $false - - } - else { - $runModuleCheck = $true - $runScriptCheck = $true - } - - if ($PSBoundParameters.ContainsKey('Include')) { - - if ($Include -eq 'All') { - $moduleTagsToInclude = $moduleTags - $scriptTagsToInclude = $scriptTags - $runModuleCheck = $true - $runScriptCheck = $true - } - else { - # Validate tests to include from $Include - $Include | ForEach-Object { - if ($_ -in $moduleTags) { - $moduleTagsToInclude += $_ - $runModuleCheck = $true - #* To satisfy PSScriptAnalyzer - $runModuleCheck = $runModuleCheck - $runScriptCheck = $runScriptCheck - } - } - $Include | ForEach-Object { - if ($_ -in $scriptTags) { - $scriptTagsToInclude += $_ - $runScriptCheck = $true - #* To satisfy PSScriptAnalyzer - $runModuleCheck = $runModuleCheck - $runScriptCheck = $runScriptCheck - } - } - } - $PesterConfiguration.Filter.Tag = $moduleTagsToInclude + $scriptTagsToInclude - - } - - if ($PSBoundParameters.ContainsKey('Exclude')) { - - # Validate tests to exclude from $Exclude - $Exclude | ForEach-Object { - if ($_ -in $moduleTags) { - $moduleTagsToExclude += $_ - $runModuleCheck = $true - #* To satisfy PSScriptAnalyzer - $runModuleCheck = $runModuleCheck - $runScriptCheck = $runScriptCheck - } - } - $Exclude | ForEach-Object { - if ($_ -in $scriptTags) { - $scriptTagsToExclude += $_ - $runScriptCheck = $true - #* To satisfy PSScriptAnalyzer - $runModuleCheck = $runModuleCheck - $runScriptCheck = $runScriptCheck - } - } - $PesterConfiguration.Filter.ExcludeTag = $moduleTagsToExclude + $scriptTagsToExclude - - } - - if ($modulesToTest.Count -ge 1) { - - # Location of files extracted from any passed modules - $extractPath = Join-Path -Path ([IO.Path]::GetTempPath()) -ChildPath (New-Guid).Guid - - if ($runModuleCheck -eq $true) { - - # Run the Module tests on all the valid module files found - $container1 = New-PesterContainer -Path (Join-Path -Path $modulePath -ChildPath 'Data\Module.Checks.ps1') -Data @{ Source = $modulesToTest } - $PesterConfiguration.Run.Container = $container1 - $moduleResults = Invoke-Pester -Configuration $PesterConfiguration - - # Extract all the functions from the modules into individual .ps1 files ready for testing - $container2 = New-PesterContainer -Path (Join-Path -Path $modulePath -ChildPath 'Data\Extraction.ps1') -Data @{ Source = $modulesToTest; ExtractPath = $extractPath } - $PesterConfiguration.Run.Container = $container2 - $extractionResults = Invoke-Pester -Configuration $PesterConfiguration - - } - else { - $moduleResults = - @{ - 'Count' = 0 - 'TotalCount' = 0 - 'NotRunCount' = 0 - 'PassedCount' = 0 - 'FailedCount' = 0 - 'SkippedCount' = 0 - } - $extractionResults = - @{ - 'Count' = 0 - 'TotalCount' = 0 - 'NotRunCount' = 0 - 'PassedCount' = 0 - 'FailedCount' = 0 - 'SkippedCount' = 0 - } - } - - if ($runScriptCheck -eq $true -and (Test-Path -Path $extractPath -ErrorAction SilentlyContinue)) { - - # Get a list of the 'extracted' function scripts .ps1 files - $extractedScriptsToTest = Get-ChildItem -Path $extractPath -Include '*.ps1' -Recurse - - # Run the Script tests against all the extracted functions .ps1 files - $container3 = New-PesterContainer -Path (Join-Path -Path $modulePath -ChildPath 'Data\Script.Checks.ps1') -Data @{ Source = $extractedScriptsToTest; ScriptAnalyzerRulesPath = $ScriptAnalyzerRulesPath; HelpRulesPath = $HelpRulesPath } - $PesterConfiguration.Run.Container = $container3 - $extractedScriptResults = Invoke-Pester -Configuration $PesterConfiguration - - } - else { - $extractedScriptResults = - @{ - 'Count' = 0 - 'TotalCount' = 0 - 'NotRunCount' = 0 - 'PassedCount' = 0 - 'FailedCount' = 0 - 'SkippedCount' = 0 - } - } - - # Tidy up and temporary paths that have been used - - if ( Test-Path -Path $ExtractPath -ErrorAction SilentlyContinue) { - Get-ChildItem -Path $ExtractPath -Recurse -ErrorAction SilentlyContinue | Remove-Item -Force -Recurse - Remove-Item $ExtractPath -Force -ErrorAction SilentlyContinue - } - - } - - if ($scriptsToTest.Count -ge 1 -and $runScriptCheck -eq $true) { - - # Run the Script tests against all the valid script files found - $container3 = New-PesterContainer -Path (Join-Path -Path $modulePath -ChildPath 'Data\Script.Checks.ps1') -Data @{ Source = $scriptsToTest; ScriptAnalyzerRulesPath = $ScriptAnalyzerRulesPath } - $PesterConfiguration.Run.Container = $container3 - $scriptResults = Invoke-Pester -Configuration $PesterConfiguration - - } - else { - $scriptResults = - @{ - 'Count' = 0 - 'TotalCount' = 0 - 'NotRunCount' = 0 - 'PassedCount' = 0 - 'FailedCount' = 0 - 'SkippedCount' = 0 - } - } - - # Show/Export results in the various formats - - if ($PSBoundParameters.ContainsKey('ShowCheckResults')) { - - $qualityCheckResults = @() - $filesTested = $total = $passed = $failed = $skipped = 0 - - if ($null -ne $projectResults) { - $qualityCheckResults += - @{ - 'Test' = 'Project Tests' - 'Files Tested' = 0 - 'Total' = ($projectResults.TotalCount - $projectResults.NotRunCount) - 'Passed' = $projectResults.PassedCount - 'Failed' = $projectResults.FailedCount - 'Skipped' = $projectResults.SkippedCount - } - $filesTested += 0 - $total += ($projectResults.TotalCount - $projectResults.NotRunCount) - $passed += $projectResults.PassedCount - $failed += $projectResults.FailedCount - $skipped += $projectResults.SkippedCount - } - - if ($null -ne $moduleResults) { - $qualityCheckResults += - @{ - 'Test' = 'Module Tests' - 'Files Tested' = $ModulesToTest.Count - 'Total' = ($moduleResults.TotalCount - $moduleResults.NotRunCount) - 'Passed' = $moduleResults.PassedCount - 'Failed' = $moduleResults.FailedCount - 'Skipped' = $moduleResults.SkippedCount - } - $filesTested += $ModulesToTest.Count - $total += ($moduleResults.TotalCount - $moduleResults.NotRunCount) - $passed += $moduleResults.PassedCount - $failed += $moduleResults.FailedCount - $skipped += $moduleResults.SkippedCount - } - - if ($null -ne $extractionResults) { - $qualityCheckResults += - @{ - 'Test' = 'Extracting functions' - 'Files Tested' = $ModulesToTest.Count - 'Total' = ($extractionResults.TotalCount - $extractionResults.NotRunCount) - 'Passed' = $extractionResults.PassedCount - 'Failed' = $extractionResults.FailedCount - 'Skipped' = $extractionResults.SkippedCount - } - $total += ($extractionResults.TotalCount - $extractionResults.NotRunCount) - $passed += $extractionResults.PassedCount - $failed += $extractionResults.FailedCount - $skipped += $extractionResults.SkippedCount - } - - if ($null -ne $extractedScriptResults) { - $qualityCheckResults += - @{ - 'Test' = 'Extracted function script tests' - 'Files Tested' = $extractedScriptsToTest.Count - 'Total' = ($extractedScriptResults.TotalCount - $extractedScriptResults.NotRunCount) - 'Passed' = $extractedScriptResults.PassedCount - 'Failed' = $extractedScriptResults.FailedCount - 'Skipped' = $extractedScriptResults.SkippedCount - } - $filesTested += $extractedScriptsToTest.Count - $total += ($extractedScriptResults.TotalCount - $extractedScriptResults.NotRunCount) - $passed += $extractedScriptResults.PassedCount - $failed += $extractedScriptResults.FailedCount - $skipped += $extractedScriptResults.SkippedCount - } - - if ($null -ne $scriptResults) { - $qualityCheckResults += - @{ - 'Test' = "Script Tests" - 'Files Tested' = $scriptsToTest.Count - 'Total' = ($scriptResults.TotalCount - $scriptResults.NotRunCount) - 'Passed' = $scriptResults.PassedCount - 'Failed' = $scriptResults.FailedCount - 'Skipped' = $scriptResults.SkippedCount - } - $filesTested += $scriptsToTest.Count - $total += ($scriptResults.TotalCount - $scriptResults.NotRunCount) - $passed += $scriptResults.PassedCount - $failed += $scriptResults.FailedCount - $skipped += $scriptResults.SkippedCount - } - - $qualityCheckResults += - @{ - 'Test' = "Total" - 'Files Tested' = $filesTested - 'Total' = $total - 'Passed' = $passed - 'Failed' = $failed - 'Skipped' = $skipped - } - - # This works on PS5 and PS7 - $qualityCheckResults | ForEach-Object { - [PSCustomObject]@{ - 'Test' = $_.Test - 'Files Tested' = $_.'Files Tested' - 'Total' = $_.total - 'Passed' = $_.passed - 'Failed' = $_.failed - 'Skipped' = $_.skipped - } - } | Format-Table -AutoSize - - # This works on PS7 not on PS5 - # $qualityCheckResults | Select-Object Name, 'Files Tested', Total, Passed, Failed, Skipped | Format-Table -AutoSize - - } - - if ($PSBoundParameters.ContainsKey('ExportCheckResults')) { - - $projectResults | Export-Clixml -Path "projectResults.xml" - $moduleResults | Export-Clixml -Path "moduleResults.xml" - $extractionResults | Export-Clixml -Path "extractionResults.xml" - $scriptResults | Export-Clixml -Path "scriptsToTest.xml" - $extractedScriptResults | Export-Clixml -Path "extractedScriptResults.xml" - - } - - if ($PSBoundParameters.ContainsKey('Passthru')) { - - if ($PesterConfiguration.Run.PassThru.Value -eq $true) { - - $resultObject = @{ - 'project' = $projectResults - 'module' = $moduleResults - 'extraction' = $extractionResults - 'script' = $scriptResults - 'extractedscript' = $extractedScriptResults - } - - return $resultObject - - } - else { - Write-Error "Unable to pass back result objects. Passthru not enabled in Pester Configuration object" - } - - } - -} +function Invoke-PSQualityCheck { + <# + .SYNOPSIS + Invoke the PSQualityCheck tests + + .DESCRIPTION + Invoke a series of Pester-based quality tests on the passed files + + .PARAMETER Path + A string array containing paths to check for testable files + + .PARAMETER File + A string array containing testable files + + .PARAMETER Recurse + A switch specifying whether or not to recursively search the path specified + + .PARAMETER ScriptAnalyzerRulesPath + A path the the external PSScriptAnalyzer rules + + .PARAMETER ShowCheckResults + Show a summary of the Check results at the end of processing + Note: this cannot be used with -Passthru + + .PARAMETER ExportCheckResults + Exports the Check results at the end of processing to file + + .PARAMETER Passthru + Returns the Check results objects back to the caller + Note: this cannot be used with -ShowCheckResults + + .PARAMETER PesterConfiguration + A Pester configuration object to allow configuration of Pester + + .PARAMETER Include + An array of test tags to run + + .PARAMETER Exclude + An array of test tags to not run + + .PARAMETER ProjectPath + A path to the root of a Project + + .PARAMETER HelpRulesPath + A path to the HelpRules parameter file + + .PARAMETER IgnoreFile + A path to the .psqcignore file which excludes files/path from the tests. This is in the .gitignore format + + .EXAMPLE + Invoke-PSQualityCheck -Path 'C:\Scripts' + + This will call the quality checks on single path + + .EXAMPLE + Invoke-PSQualityCheck -Path 'C:\Scripts' -Recurse + + This will call the quality checks on single path and sub folders + + .EXAMPLE + Invoke-PSQualityCheck -Path @('C:\Scripts', 'C:\MoreScripts') + + This will call the quality checks with multiple paths + + .EXAMPLE + Invoke-PSQualityCheck -ProjectPath 'C:\Project' -IgnoreFile ".psqcignore" + + This will call the project quality checks on the C:\Project folder with the .psqcignore file + + .EXAMPLE + Invoke-PSQualityCheck -File 'C:\Scripts\Script.ps1' + + This will call the quality checks with single script file + + .EXAMPLE + Invoke-PSQualityCheck -File 'C:\Scripts\Script.psm1' + + This will call the quality checks with single module file + + .EXAMPLE + Invoke-PSQualityCheck -File 'C:\Scripts\Script.psd1' + + This will call the quality checks with single datafile file + Note: The datafile test will fail as it is not a file that is accepted for testing + + .EXAMPLE + Invoke-PSQualityCheck -File @('C:\Scripts\Script.ps1','C:\Scripts\Script2.ps1') + + This will call the quality checks with multiple files. Files can be either scripts or modules + + .EXAMPLE + Invoke-PSQualityCheck -File 'C:\Scripts\Script.ps1' -ScriptAnalyzerRulesPath 'C:\ScriptAnalyzerRulesPath' + + This will call the quality checks with single file and the extra PSScriptAnalyzer rules + + .EXAMPLE + Invoke-PSQualityCheck -Path 'C:\Scripts' -ShowCheckResults + + This will display a summary of the checks performed (example below uses sample data): + + Name Files Tested Total Passed Failed Skipped + ---- ------------ ----- ------ ------ ------- + Module Tests 2 14 14 0 0 + Extracting functions 2 2 2 0 0 + Extracted function script tests 22 330 309 0 21 + Total 24 346 325 0 21 + + For those who have spotted that the Total files tested isn't a total of the rows above, this is because the Module Tests and Extracting function Tests operate on the same file and are not counted twice + + .LINK + Website: https://github.com/andrewrdavidson/PSQualityCheck + SonarQube rules are available here: https://github.com/indented-automation/ScriptAnalyzerRules + + #> + [CmdletBinding()] + [OutputType([System.Void], [HashTable], [System.Object[]])] + param ( + [Parameter(Mandatory = $true, ParameterSetName = 'Path')] + [String[]]$Path, + [Parameter(Mandatory = $true, ParameterSetName = 'File')] + [String[]]$File, + [Parameter(Mandatory = $true, ParameterSetName = 'ProjectPath')] + [String]$ProjectPath, + + [Parameter(Mandatory = $false, ParameterSetName = 'Path')] + [switch]$Recurse, + + [Parameter(Mandatory = $false)] + [String[]]$ScriptAnalyzerRulesPath, + + [switch]$ShowCheckResults, + + [switch]$ExportCheckResults, + + [switch]$Passthru, + + [Parameter(Mandatory = $false)] + [System.Object]$PesterConfiguration, + + [Parameter(Mandatory = $false)] + [String[]]$Include, + + [Parameter(Mandatory = $false)] + [String[]]$Exclude, + + [Parameter(Mandatory = $false)] + [String]$HelpRulesPath, + + [Parameter(Mandatory = $false)] + [String]$IgnoreFile + + ) + + Set-StrictMode -Version Latest + + # External Modules + Import-Module -Name 'Pester' -MinimumVersion '5.1.0' -Force + Import-Module -Name 'PSScriptAnalyzer' -MinimumVersion '1.19.1' -Force + + $modulePath = (Get-Module -Name 'PSQualityCheck').ModuleBase + + # Validate any incoming parameters for clashes + if ($PSBoundParameters.ContainsKey('ShowCheckResults') -and $PSBoundParameters.ContainsKey('Passthru')) { + + Write-Error '-ShowCheckResults and -Passthru cannot be used at the same time' + break + + } + + $scriptsToTest = @() + $modulesToTest = @() + + $projectResults = $null + $moduleResults = $null + $extractionResults = $null + $extractedScriptResults = $null + $scriptResults = $null + + if ($PSBoundParameters.ContainsKey('HelpRulesPath')) { + + if ( -not (Test-Path -Path $HelpRulesPath)) { + + Write-Error '-HelpRulesPath does not exist' + break + + } + + } else { + + $helpRulesPath = (Join-Path -Path $modulePath -ChildPath 'Data\HelpRules.psd1') + + } + + if ($PSBoundParameters.ContainsKey('PesterConfiguration') -and $PesterConfiguration -is [PesterConfiguration]) { + + # left here so that we can over-ride passed in object with values we require + + } else { + # Default Pester Parameters + $PesterConfiguration = [PesterConfiguration]::Default + $PesterConfiguration.Run.Exit = $false + $PesterConfiguration.CodeCoverage.Enabled = $false + $PesterConfiguration.Output.Verbosity = 'Detailed' + $PesterConfiguration.Run.PassThru = $true + $PesterConfiguration.Should.ErrorAction = 'Stop' + } + + # Analyse the incoming Path and File parameters and produce a list of Modules and Scripts + if ($PSBoundParameters.ContainsKey('Path') -or $PSBoundParameters.ContainsKey('ProjectPath')) { + + if ($PSBoundParameters.ContainsKey('ProjectPath')) { + + if (Test-Path -Path $ProjectPath) { + + $container1 = New-PesterContainer -Path (Join-Path -Path $modulePath -ChildPath 'Data\Project.Checks.ps1') -Data @{ Path = $ProjectPath } + $PesterConfiguration.Run.Container = $container1 + $projectResults = Invoke-Pester -Configuration $PesterConfiguration + + # setup the rest of the Path based tests + # this needs to include the module/public module/private and scripts folder only, not the data or any other folders + $ProjectPath = (Resolve-Path -Path $ProjectPath) + $sourceRootPath = (Join-Path -Path $ProjectPath -ChildPath 'Source') + $scriptPath = (Join-Path -Path $ProjectPath -ChildPath 'Scripts') + $Path = @($scriptPath) + + # Get the list of Modules + $modules = Get-ChildItem -Path $sourceRootPath -Directory + + foreach ($module in $modules) { + + $Path += (Join-Path -Path $module -ChildPath 'Public') + $Path += (Join-Path -Path $module -ChildPath 'Private') + + } + + } else { + Write-Error "Project Path $ProjectPath does not exist" + $projectResults = + @{ + 'Count' = 0 + 'TotalCount' = 0 + 'NotRunCount' = 0 + 'PassedCount' = 0 + 'FailedCount' = 0 + 'SkippedCount' = 0 + } + } + + } + + if ($Path -isnot [string[]]) { + $Path = @($Path) + } + + foreach ($item in $Path) { + + # Test whether the item is a directory (also tells us if it exists) + if (Test-Path -Path $item -PathType Container) { + + $getFileListSplat = @{ + 'Path' = $item + } + + if ($PSBoundParameters.ContainsKey('IgnoreFile')) { + $getFileListSplat.Add('IgnoreFile', (Resolve-Path -Path $IgnoreFile)) + } else { + if ($PSBoundParameters.ContainsKey('Recurse') -or + $PSBoundParameters.ContainsKey('ProjectPath')) { + $getFileListSplat.Add('Recurse', $true) + } + } + + $scriptsToTest += GetFileList @getFileListSplat -Extension '.ps1' + $modulesToTest += GetFileList @getFileListSplat -Extension '.psm1' + + } else { + + Write-Warning -Message "$item is not a directory, skipping" + + } + + } + + } + + if ($PSBoundParameters.ContainsKey('File')) { + + if ($File -isnot [string[]]) { + $File = @($File) + } + + foreach ($item in $File) { + + # Test whether the item is a file (also tells us if it exists) + if (Test-Path -Path $item -PathType Leaf) { + + $getFilteredItemSplat = @{ + 'Path' = $item + } + + if ($PSBoundParameters.ContainsKey('IgnoreFile')) { + $getFilteredItemSplat.Add('IgnoreFile', (Resolve-Path -Path $IgnoreFile)) + } + + $itemProperties = Get-FilteredChildItem @getFilteredItemSplat + + switch ($itemProperties.Extension) { + + '.psm1' { + $modulesToTest += $itemProperties + } + + '.ps1' { + $scriptsToTest += $itemProperties + } + + } + + } else { + + Write-Warning -Message "$item is not a file, skipping" + + } + + } + + } + + # Get the list of test tags from the Data files + if ($PSBoundParameters.ContainsKey('Include') -or + $PSBoundParameters.ContainsKey('Exclude')) { + + + ($moduleTags, $scriptTags) = GetTagList + $moduleTagsToInclude = @() + $moduleTagsToExclude = @() + $scriptTagsToInclude = @() + $scriptTagsToExclude = @() + $runModuleCheck = $false + $runScriptCheck = $false + + } else { + $runModuleCheck = $true + $runScriptCheck = $true + } + + if ($PSBoundParameters.ContainsKey('Include')) { + + if ($Include -eq 'All') { + $moduleTagsToInclude = $moduleTags + $scriptTagsToInclude = $scriptTags + $runModuleCheck = $true + $runScriptCheck = $true + } else { + # Validate tests to include from $Include + $Include | ForEach-Object { + if ($_ -in $moduleTags) { + $moduleTagsToInclude += $_ + $runModuleCheck = $true + #* To satisfy PSScriptAnalyzer + $runModuleCheck = $runModuleCheck + $runScriptCheck = $runScriptCheck + } + } + $Include | ForEach-Object { + if ($_ -in $scriptTags) { + $scriptTagsToInclude += $_ + $runScriptCheck = $true + #* To satisfy PSScriptAnalyzer + $runModuleCheck = $runModuleCheck + $runScriptCheck = $runScriptCheck + } + } + } + $PesterConfiguration.Filter.Tag = $moduleTagsToInclude + $scriptTagsToInclude + + } + + if ($PSBoundParameters.ContainsKey('Exclude')) { + + # Validate tests to exclude from $Exclude + $Exclude | ForEach-Object { + if ($_ -in $moduleTags) { + $moduleTagsToExclude += $_ + $runModuleCheck = $true + #* To satisfy PSScriptAnalyzer + $runModuleCheck = $runModuleCheck + $runScriptCheck = $runScriptCheck + } + } + $Exclude | ForEach-Object { + if ($_ -in $scriptTags) { + $scriptTagsToExclude += $_ + $runScriptCheck = $true + #* To satisfy PSScriptAnalyzer + $runModuleCheck = $runModuleCheck + $runScriptCheck = $runScriptCheck + } + } + $PesterConfiguration.Filter.ExcludeTag = $moduleTagsToExclude + $scriptTagsToExclude + + } + + if ($modulesToTest.Count -ge 1) { + + # Location of files extracted from any passed modules + $extractPath = Join-Path -Path ([IO.Path]::GetTempPath()) -ChildPath (New-Guid).Guid + + if ($runModuleCheck -eq $true) { + + # Run the Module tests on all the valid module files found + $container1 = New-PesterContainer -Path (Join-Path -Path $modulePath -ChildPath 'Data\Module.Checks.ps1') -Data @{ Source = $modulesToTest } + $PesterConfiguration.Run.Container = $container1 + $moduleResults = Invoke-Pester -Configuration $PesterConfiguration + + # Extract all the functions from the modules into individual .ps1 files ready for testing + $container2 = New-PesterContainer -Path (Join-Path -Path $modulePath -ChildPath 'Data\Extraction.ps1') -Data @{ Source = $modulesToTest; ExtractPath = $extractPath } + $PesterConfiguration.Run.Container = $container2 + $extractionResults = Invoke-Pester -Configuration $PesterConfiguration + + } else { + $moduleResults = + @{ + 'Count' = 0 + 'TotalCount' = 0 + 'NotRunCount' = 0 + 'PassedCount' = 0 + 'FailedCount' = 0 + 'SkippedCount' = 0 + } + $extractionResults = + @{ + 'Count' = 0 + 'TotalCount' = 0 + 'NotRunCount' = 0 + 'PassedCount' = 0 + 'FailedCount' = 0 + 'SkippedCount' = 0 + } + } + + if ($runScriptCheck -eq $true -and (Test-Path -Path $extractPath -ErrorAction SilentlyContinue)) { + + # Get a list of the 'extracted' function scripts .ps1 files + $extractedScriptsToTest = Get-ChildItem -Path $extractPath -Include '*.ps1' -Recurse + + # Run the Script tests against all the extracted functions .ps1 files + $container3 = New-PesterContainer -Path (Join-Path -Path $modulePath -ChildPath 'Data\Script.Checks.ps1') -Data @{ Source = $extractedScriptsToTest; ScriptAnalyzerRulesPath = $ScriptAnalyzerRulesPath; HelpRulesPath = $HelpRulesPath } + $PesterConfiguration.Run.Container = $container3 + $extractedScriptResults = Invoke-Pester -Configuration $PesterConfiguration + + } else { + $extractedScriptResults = + @{ + 'Count' = 0 + 'TotalCount' = 0 + 'NotRunCount' = 0 + 'PassedCount' = 0 + 'FailedCount' = 0 + 'SkippedCount' = 0 + } + } + + # Tidy up and temporary paths that have been used + + if ( Test-Path -Path $ExtractPath -ErrorAction SilentlyContinue) { + Get-ChildItem -Path $ExtractPath -Recurse -ErrorAction SilentlyContinue | Remove-Item -Force -Recurse + Remove-Item $ExtractPath -Force -ErrorAction SilentlyContinue + } + + } + + if ($scriptsToTest.Count -ge 1 -and $runScriptCheck -eq $true) { + + # Run the Script tests against all the valid script files found + $container3 = New-PesterContainer -Path (Join-Path -Path $modulePath -ChildPath 'Data\Script.Checks.ps1') -Data @{ Source = $scriptsToTest; ScriptAnalyzerRulesPath = $ScriptAnalyzerRulesPath; HelpRulesPath = $HelpRulesPath } + $PesterConfiguration.Run.Container = $container3 + $scriptResults = Invoke-Pester -Configuration $PesterConfiguration + + } else { + $scriptResults = + @{ + 'Count' = 0 + 'TotalCount' = 0 + 'NotRunCount' = 0 + 'PassedCount' = 0 + 'FailedCount' = 0 + 'SkippedCount' = 0 + } + } + + # Show/Export results in the various formats + + if ($PSBoundParameters.ContainsKey('ShowCheckResults')) { + + $qualityCheckResults = @() + $filesTested = $total = $passed = $failed = $skipped = 0 + + if ($null -ne $projectResults) { + $qualityCheckResults += + @{ + 'Test' = 'Project Tests' + 'Files Tested' = 0 + 'Total' = ($projectResults.TotalCount - $projectResults.NotRunCount) + 'Passed' = $projectResults.PassedCount + 'Failed' = $projectResults.FailedCount + 'Skipped' = $projectResults.SkippedCount + } + $filesTested += 0 + $total += ($projectResults.TotalCount - $projectResults.NotRunCount) + $passed += $projectResults.PassedCount + $failed += $projectResults.FailedCount + $skipped += $projectResults.SkippedCount + } + + if ($null -ne $moduleResults) { + $qualityCheckResults += + @{ + 'Test' = 'Module Tests' + 'Files Tested' = $ModulesToTest.Count + 'Total' = ($moduleResults.TotalCount - $moduleResults.NotRunCount) + 'Passed' = $moduleResults.PassedCount + 'Failed' = $moduleResults.FailedCount + 'Skipped' = $moduleResults.SkippedCount + } + $filesTested += $ModulesToTest.Count + $total += ($moduleResults.TotalCount - $moduleResults.NotRunCount) + $passed += $moduleResults.PassedCount + $failed += $moduleResults.FailedCount + $skipped += $moduleResults.SkippedCount + } + + if ($null -ne $extractionResults) { + $qualityCheckResults += + @{ + 'Test' = 'Extracting functions' + 'Files Tested' = $ModulesToTest.Count + 'Total' = ($extractionResults.TotalCount - $extractionResults.NotRunCount) + 'Passed' = $extractionResults.PassedCount + 'Failed' = $extractionResults.FailedCount + 'Skipped' = $extractionResults.SkippedCount + } + $total += ($extractionResults.TotalCount - $extractionResults.NotRunCount) + $passed += $extractionResults.PassedCount + $failed += $extractionResults.FailedCount + $skipped += $extractionResults.SkippedCount + } + + if ($null -ne $extractedScriptResults) { + $qualityCheckResults += + @{ + 'Test' = 'Extracted function script tests' + 'Files Tested' = $extractedScriptsToTest.Count + 'Total' = ($extractedScriptResults.TotalCount - $extractedScriptResults.NotRunCount) + 'Passed' = $extractedScriptResults.PassedCount + 'Failed' = $extractedScriptResults.FailedCount + 'Skipped' = $extractedScriptResults.SkippedCount + } + $filesTested += $extractedScriptsToTest.Count + $total += ($extractedScriptResults.TotalCount - $extractedScriptResults.NotRunCount) + $passed += $extractedScriptResults.PassedCount + $failed += $extractedScriptResults.FailedCount + $skipped += $extractedScriptResults.SkippedCount + } + + if ($null -ne $scriptResults) { + $qualityCheckResults += + @{ + 'Test' = 'Script Tests' + 'Files Tested' = $scriptsToTest.Count + 'Total' = ($scriptResults.TotalCount - $scriptResults.NotRunCount) + 'Passed' = $scriptResults.PassedCount + 'Failed' = $scriptResults.FailedCount + 'Skipped' = $scriptResults.SkippedCount + } + $filesTested += $scriptsToTest.Count + $total += ($scriptResults.TotalCount - $scriptResults.NotRunCount) + $passed += $scriptResults.PassedCount + $failed += $scriptResults.FailedCount + $skipped += $scriptResults.SkippedCount + } + + $qualityCheckResults += + @{ + 'Test' = 'Total' + 'Files Tested' = $filesTested + 'Total' = $total + 'Passed' = $passed + 'Failed' = $failed + 'Skipped' = $skipped + } + + # This works on PS5 and PS7 + $qualityCheckResults | ForEach-Object { + [PSCustomObject]@{ + 'Test' = $_.Test + 'Files Tested' = $_.'Files Tested' + 'Total' = $_.total + 'Passed' = $_.passed + 'Failed' = $_.failed + 'Skipped' = $_.skipped + } + } | Format-Table -AutoSize + + # This works on PS7 not on PS5 + # $qualityCheckResults | Select-Object Name, 'Files Tested', Total, Passed, Failed, Skipped | Format-Table -AutoSize + + } + + if ($PSBoundParameters.ContainsKey('ExportCheckResults')) { + + $projectResults | Export-Clixml -Path 'projectResults.xml' + $moduleResults | Export-Clixml -Path 'moduleResults.xml' + $extractionResults | Export-Clixml -Path 'extractionResults.xml' + $scriptResults | Export-Clixml -Path 'scriptsToTest.xml' + $extractedScriptResults | Export-Clixml -Path 'extractedScriptResults.xml' + + } + + if ($PSBoundParameters.ContainsKey('Passthru')) { + + if ($PesterConfiguration.Run.PassThru.Value -eq $true) { + + $resultObject = @{ + 'project' = $projectResults + 'module' = $moduleResults + 'extraction' = $extractionResults + 'script' = $scriptResults + 'extractedscript' = $extractedScriptResults + } + + return $resultObject + + } else { + Write-Error 'Unable to pass back result objects. Passthru not enabled in Pester Configuration object' + } + + } + +} From 55d47e044d55914502ca8eb3122ab70c15d7f18e Mon Sep 17 00:00:00 2001 From: Andrew Davidson Date: Thu, 18 Jan 2024 10:05:16 +0000 Subject: [PATCH 4/9] Remove empty files --- Tests/scripts/readme.md | 0 scripts/readme.md | 0 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 Tests/scripts/readme.md delete mode 100644 scripts/readme.md diff --git a/Tests/scripts/readme.md b/Tests/scripts/readme.md deleted file mode 100644 index e69de29..0000000 diff --git a/scripts/readme.md b/scripts/readme.md deleted file mode 100644 index e69de29..0000000 From ca1c0ba586270abf56e65154cceb2724c8bc5abb Mon Sep 17 00:00:00 2001 From: Andrew Davidson Date: Thu, 18 Jan 2024 10:05:35 +0000 Subject: [PATCH 5/9] Change version to 2.0.2 --- Source/PSQualityCheck/PSQualityCheck.psd1 | 266 +++++++++++----------- 1 file changed, 133 insertions(+), 133 deletions(-) diff --git a/Source/PSQualityCheck/PSQualityCheck.psd1 b/Source/PSQualityCheck/PSQualityCheck.psd1 index 28bc3bd..a081097 100644 --- a/Source/PSQualityCheck/PSQualityCheck.psd1 +++ b/Source/PSQualityCheck/PSQualityCheck.psd1 @@ -1,133 +1,133 @@ -# -# Module manifest for module 'PSQualityCheck' -# -# Generated by: Andrew Davidson -# -# Generated on: 21/04/2021 -# - -@{ - - # Script module or binary module file associated with this manifest. - RootModule = 'PSQualityCheck.psm1' - - # Version number of this module. - ModuleVersion = '2.0.1' - - # Supported PSEditions - # CompatiblePSEditions = @() - - # ID used to uniquely identify this module - GUID = '9daebff2-9a44-48e4-9d4b-bed18c3c8e4b' - - # Author of this module - Author = 'Andrew Davidson' - - # Company or vendor of this module - CompanyName = 'kelrys.com' - - # Copyright statement for this module - Copyright = '(c) Andrew Davidson. All rights reserved.' - - # Description of the functionality provided by this module - Description = 'PSQualityCheck' - - # Minimum version of the PowerShell engine required by this module - PowerShellVersion = '5.1' - - # 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 = '' - -} - - +# +# Module manifest for module 'PSQualityCheck' +# +# Generated by: Andrew Davidson +# +# Generated on: 21/04/2021 +# + +@{ + + # Script module or binary module file associated with this manifest. + RootModule = 'PSQualityCheck.psm1' + + # Version number of this module. + ModuleVersion = '2.0.2' + + # Supported PSEditions + # CompatiblePSEditions = @() + + # ID used to uniquely identify this module + GUID = '9daebff2-9a44-48e4-9d4b-bed18c3c8e4b' + + # Author of this module + Author = 'Andrew Davidson' + + # Company or vendor of this module + CompanyName = 'kelrys.com' + + # Copyright statement for this module + Copyright = '(c) Andrew Davidson. All rights reserved.' + + # Description of the functionality provided by this module + Description = 'PSQualityCheck' + + # Minimum version of the PowerShell engine required by this module + PowerShellVersion = '5.1' + + # 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 = '' + +} + + From 080e6e7feeffa805998ade191690c1942a92931f Mon Sep 17 00:00:00 2001 From: Andrew Davidson Date: Thu, 18 Jan 2024 10:06:06 +0000 Subject: [PATCH 6/9] Added requirement for running as administrtor; code reformatting --- install.depend.ps1 | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/install.depend.ps1 b/install.depend.ps1 index ce893a6..c56c95a 100644 --- a/install.depend.ps1 +++ b/install.depend.ps1 @@ -1,37 +1,38 @@ -Write-Output "Checking for nuget.exe" +#requires -RunAsAdministrator + +Write-Output 'Checking for nuget.exe' if (-not ($NuGetPath = (Get-Command 'nuget.exe' -ErrorAction SilentlyContinue).Path)) { - if (-not (Test-Path -Path ".\bin" -ErrorAction SilentlyContinue)) { - New-Item -Path "bin" -ItemType Directory + if (-not (Test-Path -Path '.\bin' -ErrorAction SilentlyContinue)) { + New-Item -Path 'bin' -ItemType Directory } - Write-Output "nuget.exe not found, downloading into project bin path" - $NuGetPath = Resolve-Path -Path ".\bin" - $NuGetFile = Join-Path -Path $NuGetPath -ChildPath "nuget.exe" + Write-Output 'nuget.exe not found, downloading into project bin path' + $NuGetPath = Resolve-Path -Path '.\bin' + $NuGetFile = Join-Path -Path $NuGetPath -ChildPath 'nuget.exe' Invoke-WebRequest -Uri 'https://dist.nuget.org/win-x86-commandline/latest/nuget.exe' -OutFile $NuGetFile $path = [Environment]::GetEnvironmentVariable('Path', 'Machine') - $environmentPaths = $path.Split(";") + $environmentPaths = $path.Split(';') if (-not ($NuGetPath -contains $environmentPaths)) { - Write-Output "Updating System Environment path" + Write-Output 'Updating System Environment path' $path += ";$NuGetPath" $env:Path = $path - [Environment]::SetEnvironmentVariable("Path", $path, 'Machine') + [Environment]::SetEnvironmentVariable('Path', $path, 'Machine') } } # Bootstrap environment -Write-Output "Bootstrap NuGet PackageProvider" +Write-Output 'Bootstrap NuGet PackageProvider' Get-PackageProvider -Name 'NuGet' -ForceBootstrap | Out-Null # Install PSDepend module if it is not already installed if (-not (Get-Module -Name 'PSDepend' -ListAvailable)) { - Write-Output "PSDepend is not yet installed, installing PSDepend" + Write-Output 'PSDepend is not yet installed, installing PSDepend' Install-Module -Name 'PSDepend' -Scope 'CurrentUser' -Force -} -else { - Write-Output "PSDepend already installed" +} else { + Write-Output 'PSDepend already installed' } # Install build dependencies @@ -47,4 +48,4 @@ $invokePSDependParams = @{ } Invoke-PSDepend @invokePSDependParams -Write-Output "Finished installing all dependencies" +Write-Output 'Finished installing all dependencies' From 376fa9e2fa485aa0538adb39d71debf392c48ddb Mon Sep 17 00:00:00 2001 From: Andrew Davidson Date: Thu, 18 Jan 2024 10:07:05 +0000 Subject: [PATCH 7/9] Removed broken build code; code reformatting --- build.ps1 | 149 ++++++++++++++++-------------------------------------- 1 file changed, 44 insertions(+), 105 deletions(-) diff --git a/build.ps1 b/build.ps1 index 3b6e67a..4f5354a 100644 --- a/build.ps1 +++ b/build.ps1 @@ -4,9 +4,9 @@ param ( [switch]$Install ) -Import-Module -Name Pester -MinimumVersion 5.1.0 +Import-Module -Name Pester -MinimumVersion 5.5.0 Import-Module -Name Cofl.Util -MinimumVersion 1.2.2 -Import-Module -Name ".\build-functions.psm1" -Force +Import-Module -Name '.\build-functions.psm1' -Force $InformationPreference = 'Continue' $ErrorActionPreference = 'Stop' @@ -19,32 +19,31 @@ $PesterConfiguration.Output.Verbosity = 'Detailed' $PesterConfiguration.Run.PassThru = $true $PesterConfiguration.Should.ErrorAction = 'Stop' -$ScriptRules = @( - '../ScriptAnalyzerRules/Indented.CodingConventions/' - #, './Analyzer/PSScriptAnalyzer/Tests/Engine/CommunityAnalyzerRules/' - #, './Analyzer/InjectionHunter/' -) +# $ScriptRules = @( +# '../ScriptAnalyzerRules/Indented.CodingConventions/' +# #, './Analyzer/PSScriptAnalyzer/Tests/Engine/CommunityAnalyzerRules/' +# #, './Analyzer/InjectionHunter/' +# ) -$projectPath = Resolve-Path -Path ".\" +$projectPath = Resolve-Path -Path '.\' $sourcePath = Resolve-Path -Path "$projectPath\source" -$scriptsPath = Resolve-Path -Path "$projectPath\scripts" $testsPath = Resolve-Path -Path "$projectPath\tests" -$ignoreFile = Resolve-Path -Path ".psqcignore" -$moduleName = "PSQualityCheck" +$ignoreFile = Resolve-Path -Path '.psqcignore' +$moduleName = 'PSQualityCheck' -$buildFolder = Join-Path -Path "$projectPath" -ChildPath "build" -$artifactsFolder = Join-Path -Path "$projectPath" -ChildPath "artifacts" +$buildFolder = Join-Path -Path "$projectPath" -ChildPath 'build' +$artifactsFolder = Join-Path -Path "$projectPath" -ChildPath 'artifacts' if (-not (Test-Path -Path $artifactsFolder -ErrorAction SilentlyContinue)) { - New-Item -Path $artifactsFolder -ItemType "directory" -Force + New-Item -Path $artifactsFolder -ItemType 'directory' -Force } if (-not (Test-Path -Path $buildFolder -ErrorAction SilentlyContinue)) { - New-Item -Path $buildFolder -ItemType "directory" -Force + New-Item -Path $buildFolder -ItemType 'directory' -Force } $modules = Get-ChildItem -Path $sourcePath -Directory -Write-Host "BUILD> Build bootstrap version of PSQualityCheck" -ForegroundColor Black -BackgroundColor Gray +Write-Host 'BUILD> Build bootstrap version of PSQualityCheck' -ForegroundColor Black -BackgroundColor Gray # Create a bootstrap built version of the module (pre-testing) # to allow us to use this module (PSQualityCheck) to test itself whilst building @@ -52,7 +51,6 @@ try { foreach ($module in $modules) { $repositoryName = "$module-local" - # QUERY: Why not just do Remove-Module -Name $module ? It will do nothing if there is no module loaded ? if ($module -in ((Get-Module) | Select-Object -Property Name)) { Remove-Module $module } @@ -70,8 +68,7 @@ try { Install-BuiltModule -Module $moduleName } -} -catch { +} catch { # try and tidy up? # foreach ($module in $modules) { # Uninstall-BuiltModule -Module $module @@ -81,36 +78,38 @@ catch { break } -# Start of Project Based checks -Write-Host "BUILD> Running PSQualityCheck Project checks" -ForegroundColor Black -BackgroundColor Gray +## Commented out running PSQualityCheck on this code as it doesn't work -$qualityCheckSplat = @{ - 'ProjectPath' = $projectPath - 'ScriptAnalyzerRulesPath' = $ScriptRules - 'HelpRulesPath' = (Resolve-Path -Path '.\HelpRules.psd1') - 'Passthru' = $true - 'PesterConfiguration' = $PesterConfiguration - 'IgnoreFile' = $ignoreFile -} -$qualityCheckResult = Invoke-PSQualityCheck @qualityCheckSplat -# End of Project Based checks +# # Start of Project Based checks +# Write-Host 'BUILD> Running PSQualityCheck Project checks' -ForegroundColor Black -BackgroundColor Gray -# unpublish and remove the bootstrap version of the modules -Write-Host "BUILD> Uninstall and Unpublish bootstrap modules" -ForegroundColor Black -BackgroundColor Gray -foreach ($module in $modules) { - Uninstall-BuiltModule -Module $module.Name - Unpublish-BuiltModule -Module $module.Name -SourceFolder $sourcePath -ArtifactsFolder $artifactsFolder -} +# $qualityCheckSplat = @{ +# 'ProjectPath' = $projectPath +# 'ScriptAnalyzerRulesPath' = $ScriptRules +# 'HelpRulesPath' = (Resolve-Path -Path '.\HelpRules.psd1') +# 'Passthru' = $true +# 'PesterConfiguration' = $PesterConfiguration +# 'IgnoreFile' = $ignoreFile +# } +# $qualityCheckResult = Invoke-PSQualityCheck @qualityCheckSplat +# # End of Project Based checks -# Running tests -if ($qualityCheckResult.Script.FailedCount -ne 0 -or $qualityCheckResult.Project.FailedCount -ne 0) { +# # unpublish and remove the bootstrap version of the modules +# Write-Host 'BUILD> Uninstall and Unpublish bootstrap modules' -ForegroundColor Black -BackgroundColor Gray +# foreach ($module in $modules) { +# Uninstall-BuiltModule -Module $module.Name +# Unpublish-BuiltModule -Module $module.Name -SourceFolder $sourcePath -ArtifactsFolder $artifactsFolder +# } - Write-Error -Message "Project quality check failed" +# # Running tests +# if ($qualityCheckResult.Script.FailedCount -ne 0 -or $qualityCheckResult.Project.FailedCount -ne 0) { -} +# Write-Error -Message 'Project quality check failed' + +# } # Run the unit tests for the public functions of any modules in the project -Write-Host "BUILD> Running unit tests for functions" -ForegroundColor Black -BackgroundColor Gray +Write-Host 'BUILD> Running unit tests for functions' -ForegroundColor Black -BackgroundColor Gray $unitTestResults = @() @@ -121,7 +120,7 @@ foreach ($module in $modules) { # Get the public functions (minus any excluded by the ignore file) $functionFiles = @() - $functionFiles += Get-FilteredChildItem -Path (Join-Path -Path $module.FullName -ChildPath "public") -IgnoreFileName $ignoreFile + $functionFiles += Get-FilteredChildItem -Path (Join-Path -Path $module.FullName -ChildPath 'public') -IgnoreFileName $ignoreFile # If there are any scripts in the private folder with corresponding tests then run those too # $privateFunctionFiles += Get-ChildItem -Path (Join-Path -Path $Module.FullName -ChildPath "private") @@ -162,46 +161,12 @@ if ($unitTestFailedCount -ne 0 ) { # End of running tests -# Run any available unit tests for files in Scripts folder -Write-Host "BUILD> Running unit tests for scripts" -ForegroundColor Black -BackgroundColor Gray - -$scriptFiles = @() -$scriptTestResults = @() -$scriptTestFailedCount = 0 -$scriptFiles = Get-FilteredChildItem -Path $scriptsPath -IgnoreFileName $ignoreFile -foreach ($scriptFile in $scriptFiles) { - - $scriptFolder = $scriptFile.FullName -ireplace [regex]::Escape($scriptsPath.Path), '' - $scriptFolder = $scriptFolder -ireplace [regex]::Escape($scriptFile.Name), '' - - $fileContent = Get-FunctionFileContent -Path $scriptFile.FullName - try { - $testFile = Resolve-Path -Path "$testsPath\scripts$scriptFolder\$($scriptFile.BaseName).Tests.ps1" - - $container = New-PesterContainer -Path $testFile -Data @{FileContent = $fileContent } - $PesterConfiguration.Run.Container = $container - - $scriptTestResults += Invoke-Pester -Configuration $PesterConfiguration - } - catch { - Write-Output "No test file" - } - -} - -foreach ($result in $scriptTestResults) { - $scriptTestFailedCount += $result.FailedCount -} -if ($scriptTestFailedCount -ne 0 ) { - Write-Error -Message 'One or more scripts failed unit test' - throw $_ -} ## End of bootstrap build and tests # Start of final module build # Build the module(s) only if there are no unit/integration test failures -Write-Host "BUILD> Building final version of module" -ForegroundColor Black -BackgroundColor Gray +Write-Host 'BUILD> Building final version of module' -ForegroundColor Black -BackgroundColor Gray try { foreach ($module in $modules) { @@ -214,37 +179,11 @@ try { Write-Host $buildPropertiesFile Build-Module -SourcePath $buildPropertiesFile } -} -catch { +} catch { throw $_ break } -# If there are no script failures then copy the scripts to the build folder and archive to the Artifacts folder -Write-Host "BUILD> Building script archive" -ForegroundColor Black -BackgroundColor Gray -$builtScriptsFolder = Join-Path -Path $buildFolder -ChildPath "scripts" - -if (-not (Test-Path -Path $builtScriptsFolder -ErrorAction SilentlyContinue)) { - New-Item -Path $buildFolder -Name "scripts" -ItemType 'Directory' -Force -} - -Copy-Item -Path "Scripts" -Destination $buildFolder -Recurse -Force -Container -# End of script copy - -$archiveFile = "$artifactsFolder\scripts.zip" - -if (Test-Path -Path $archiveFile) { - Remove-Item -Path $archiveFile -Force -} -# Create archive of scripts into artifacts -$compressSplat = @{ - Path = $builtScriptsFolder - CompressionLevel = "Fastest" - DestinationPath = "$artifactsFolder\scripts.zip" -} -Compress-Archive @compressSplat -# End of create archive - # End of final module build # Publish the final built modules From 140c59472cd6dbabb645bef12c29a462bf129fc4 Mon Sep 17 00:00:00 2001 From: Andrew Davidson Date: Thu, 18 Jan 2024 10:07:21 +0000 Subject: [PATCH 8/9] Change Pester version to 5.5.0 --- install.depend.psd1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/install.depend.psd1 b/install.depend.psd1 index b8e3d58..bbd12e9 100644 --- a/install.depend.psd1 +++ b/install.depend.psd1 @@ -6,7 +6,7 @@ Configuration = 'Latest' Pester = @{ Name = 'Pester' - Version = '5.1.1' + Version = '5.5.0' Parameters = @{ SkipPublisherCheck = $true } @@ -15,5 +15,5 @@ PowerShellGet = 'Latest' PSScriptAnalyzer = 'Latest' InvokeBuild = 'Latest' - "Cofl.Util" = 'Latest' + 'Cofl.Util' = 'Latest' } From bf160d80030c4a91f8c14943150b2189ae49da41 Mon Sep 17 00:00:00 2001 From: Andrew Davidson Date: Thu, 18 Jan 2024 10:07:41 +0000 Subject: [PATCH 9/9] Removed bin directory from build process --- Source/PSQualityCheck/build.psd1 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/PSQualityCheck/build.psd1 b/Source/PSQualityCheck/build.psd1 index 2927f8b..0468234 100644 --- a/Source/PSQualityCheck/build.psd1 +++ b/Source/PSQualityCheck/build.psd1 @@ -1,10 +1,10 @@ # Use this file to override the default parameter values used by the `Build-Module` # command when building the module (see `Get-Help Build-Module -Full` for details). @{ - ModuleManifest = "PSQualityCheck.psd1" + ModuleManifest = 'PSQualityCheck.psd1' # Subsequent relative paths are to the ModuleManifest - OutputDirectory = "../../build/PSQualityCheck" + OutputDirectory = '../../build/PSQualityCheck' VersionedOutputDirectory = $true - CopyDirectories = @('data', 'bin') + CopyDirectories = @('data') }