-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add function Merge-PSCodeHealthSetting to override default settings w…
…ith user-defined settings
- Loading branch information
1 parent
c441013
commit 8c58f97
Showing
6 changed files
with
292 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
Function Merge-PSCodeHealthSetting { | ||
<# | ||
.SYNOPSIS | ||
Merges user-defined settings (metrics thresholds, etc...) into the default PSCodeHealth settings. | ||
.DESCRIPTION | ||
Merges user-defined settings (metrics thresholds, etc...) into the default PSCodeHealth settings. | ||
The default PSCodeHealth settings are stored in PSCodeHealthSettings.json, but user-defined custom settings can override these defaults. | ||
The custom settings are stored in JSON format in a file (similar to PSCodeHealthSettings.json). | ||
Any setting specified in the custom settings file override the defaults and settings not specified in the custom settings file will use the defaults from PSCodeHealthSettings.json. | ||
.PARAMETER DefaultSettings | ||
PSCustomObject converted from the JSON data in PSCodeHealthSettings.json. | ||
.PARAMETER CustomSettings | ||
PSCustomObject converted from the JSON data in a user-defined custom settings file. | ||
.OUTPUTS | ||
System.Management.Automation.PSCustomObject | ||
#> | ||
[CmdletBinding()] | ||
[OutputType([PSCustomObject])] | ||
Param( | ||
[Parameter(Mandatory=$True,Position=0)] | ||
[PSCustomObject]$DefaultSettings, | ||
|
||
[Parameter(Mandatory=$True,Position=1)] | ||
[PSCustomObject]$CustomSettings | ||
) | ||
|
||
# Checking if $CustomSettings contains something | ||
$ContainsSettings = $CustomSettings | Get-Member -MemberType Properties | ||
If ( -not($ContainsSettings) ) { | ||
Write-VerboseOutput -Message 'Custom settings do not contain any data, the resulting settings will be the defaults.' | ||
return $DefaultSettings | ||
} | ||
|
||
$ContainsFunctionHealthRecordSettings = 'FunctionHealthRecordMetricsRules' -in $ContainsSettings.Name | ||
$ContainsOverallHealthReportSettings = 'OverallHealthReportMetricsRules' -in $ContainsSettings.Name | ||
|
||
If ( -not($ContainsFunctionHealthRecordSettings) -and -not($ContainsOverallHealthReportSettings) ) { | ||
Write-Warning -Message 'Custom settings do not contain any of the settings groups expected by PSCodeHealth.' | ||
return $DefaultSettings | ||
} | ||
|
||
If ( $ContainsFunctionHealthRecordSettings) { | ||
$CustomFunctionSettings = $CustomSettings.FunctionHealthRecordMetricsRules | Where-Object { $_ } | ||
|
||
# Casting to a list in case we need to add elements to it | ||
$DefaultFunctionSettings = ($DefaultSettings.FunctionHealthRecordMetricsRules | Where-Object { $_ }) -as [System.Collections.ArrayList] | ||
|
||
Foreach ( $CustomFunctionSetting in $CustomFunctionSettings ) { | ||
$MetricName = ($CustomFunctionSetting | Get-Member -MemberType Properties).Name | ||
Write-VerboseOutput -Message "Processing custom settings for metric : $MetricName" | ||
|
||
$DefaultFunctionSetting = $DefaultFunctionSettings | Where-Object { $_.$($MetricName) } | ||
If ( $DefaultFunctionSetting ) { | ||
Write-VerboseOutput -Message "The setting '$MetricName' is present in the default settings, overriding it." | ||
$DefaultFunctionSetting.$($MetricName) = $CustomFunctionSetting.$($MetricName) | ||
} | ||
Else { | ||
Write-VerboseOutput -Message "The setting '$MetricName' is absent from the default settings, adding it." | ||
$Null = $DefaultFunctionSettings.Add($CustomFunctionSetting) | ||
} | ||
} | ||
} | ||
|
||
If ( $ContainsOverallHealthReportSettings ) { | ||
$CustomOverallSettings = $CustomSettings.OverallHealthReportMetricsRules | Where-Object { $_ } | ||
|
||
# Casting to a list in case we need to add elements to it | ||
$DefaultOverallSettings = ($DefaultSettings.OverallHealthReportMetricsRules | Where-Object { $_ }) -as [System.Collections.ArrayList] | ||
|
||
Foreach ( $CustomOverallSetting in $CustomOverallSettings ) { | ||
$MetricName = ($CustomOverallSetting | Get-Member -MemberType Properties).Name | ||
Write-VerboseOutput -Message "Processing custom settings for metric : $MetricName" | ||
|
||
$DefaultOverallSetting = $DefaultOverallSettings | Where-Object { $_.$($MetricName) } | ||
If ( $DefaultOverallSetting ) { | ||
Write-VerboseOutput -Message "The setting '$MetricName' is present in the default settings, overriding it." | ||
$DefaultOverallSetting.$($MetricName) = $CustomOverallSetting.$($MetricName) | ||
} | ||
Else { | ||
Write-VerboseOutput -Message "The setting '$MetricName' is absent from the default settings, adding it." | ||
$Null = $DefaultOverallSettings.Add($CustomOverallSetting) | ||
} | ||
} | ||
} | ||
$MergedSettingsProperties = [ordered]@{ | ||
FunctionHealthRecordMetricsRules = $DefaultFunctionSettings | ||
OverallHealthReportMetricsRules = $DefaultOverallSettings | ||
} | ||
$MergedSettings = New-Object -TypeName PSCustomObject -Property $MergedSettingsProperties | ||
return $MergedSettings | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
$ModuleName = 'PSCodeHealth' | ||
Import-Module "$PSScriptRoot\..\..\..\$ModuleName\$($ModuleName).psd1" -Force | ||
|
||
Describe 'Merge-PSCodeHealthSetting' { | ||
InModuleScope $ModuleName { | ||
|
||
$DefaultSettings = ConvertFrom-Json (Get-Content -Path "$PSScriptRoot\..\..\..\PSCodeHealth\PSCodeHealthSettings.json" -Raw) | ||
|
||
Context 'Custom settings do not contain any data' { | ||
|
||
$CustomSettings = ConvertFrom-Json (Get-Content -Path "$PSScriptRoot\..\TestData\Empty.json" -Raw ) | ||
$Result = Merge-PSCodeHealthSetting -DefaultSettings $DefaultSettings -CustomSettings $CustomSettings | ||
|
||
It 'Should return an object of the type [PSCustomObject]' { | ||
$Result | Should BeOfType [PSCustomObject] | ||
} | ||
It 'Should return an object with the expected property "FunctionHealthRecordMetricsRules"' { | ||
$Result.FunctionHealthRecordMetricsRules | Should Be $DefaultSettings.FunctionHealthRecordMetricsRules | ||
} | ||
It 'Should return an object with the expected property "OverallHealthReportMetricsRules"' { | ||
$Result.OverallHealthReportMetricsRules | Should Be $DefaultSettings.OverallHealthReportMetricsRules | ||
} | ||
} | ||
Context 'Custom settings do not contain any of the expected settings groups' { | ||
|
||
$CustomSettings = ConvertFrom-Json (Get-Content -Path "$PSScriptRoot\..\TestData\NoSettingsGroup.json" -Raw ) | ||
$Result = Merge-PSCodeHealthSetting -DefaultSettings $DefaultSettings -CustomSettings $CustomSettings | ||
|
||
It 'Should return an object of the type [PSCustomObject]' { | ||
$Result | Should BeOfType [PSCustomObject] | ||
} | ||
It 'Should return an object with the expected property "FunctionHealthRecordMetricsRules"' { | ||
$Result.FunctionHealthRecordMetricsRules | Should Be $DefaultSettings.FunctionHealthRecordMetricsRules | ||
} | ||
It 'Should return an object with the expected property "OverallHealthReportMetricsRules"' { | ||
$Result.OverallHealthReportMetricsRules | Should Be $DefaultSettings.OverallHealthReportMetricsRules | ||
} | ||
} | ||
Context 'Custom settings contains only expected settings groups and metrics' { | ||
|
||
$CustomSettings = ConvertFrom-Json (Get-Content -Path "$PSScriptRoot\..\TestData\2SettingsGroups4Metrics.json" -Raw ) | ||
$Result = Merge-PSCodeHealthSetting -DefaultSettings $DefaultSettings -CustomSettings $CustomSettings | ||
|
||
It 'Should return an object of the type [PSCustomObject]' { | ||
$Result | Should BeOfType [PSCustomObject] | ||
} | ||
It 'Resulting settings are the same as the defaults for metric "LinesOfCode"' { | ||
$Result.FunctionHealthRecordMetricsRules.LinesOfCode.WarningThreshold | Should Be 20 | ||
$Result.FunctionHealthRecordMetricsRules.LinesOfCode.FailThreshold | Should Be 40 | ||
} | ||
It 'Resulting settings are the same as the defaults for metric "TestCoverage"' { | ||
$Result.FunctionHealthRecordMetricsRules.TestCoverage.WarningThreshold | Should Be 80 | ||
$Result.FunctionHealthRecordMetricsRules.TestCoverage.FailThreshold | Should Be 70 | ||
} | ||
It 'Resulting settings override the defaults for metric "Complexity"' { | ||
$Result.FunctionHealthRecordMetricsRules.Complexity.WarningThreshold | Should Be 17 | ||
$Result.FunctionHealthRecordMetricsRules.Complexity.FailThreshold | Should Be 33 | ||
} | ||
It 'Resulting settings override the defaults for metric "MaximumNestingDepth"' { | ||
$Result.FunctionHealthRecordMetricsRules.MaximumNestingDepth.WarningThreshold | Should Be 6 | ||
$Result.FunctionHealthRecordMetricsRules.MaximumNestingDepth.FailThreshold | Should Be 12 | ||
} | ||
It 'Resulting settings are the same as the defaults for metric "TestsPassRate"' { | ||
$Result.OverallHealthReportMetricsRules.TestsPassRate.WarningThreshold | Should Be 99 | ||
$Result.OverallHealthReportMetricsRules.TestsPassRate.FailThreshold | Should Be 97 | ||
} | ||
It 'Resulting settings are the same as the defaults for metric "CommandsMissedTotal"' { | ||
$Result.OverallHealthReportMetricsRules.CommandsMissedTotal.WarningThreshold | Should Be 20 | ||
$Result.OverallHealthReportMetricsRules.CommandsMissedTotal.FailThreshold | Should Be 40 | ||
} | ||
It 'Resulting settings override the defaults for metric "LinesOfCodeTotal"' { | ||
$Result.OverallHealthReportMetricsRules.LinesOfCodeTotal.WarningThreshold | Should Be 1500 | ||
$Result.OverallHealthReportMetricsRules.LinesOfCodeTotal.FailThreshold | Should Be 3000 | ||
} | ||
It 'Resulting settings override the defaults for metric "LinesOfCodeAverage"' { | ||
$Result.OverallHealthReportMetricsRules.LinesOfCodeAverage.WarningThreshold | Should Be 21 | ||
$Result.OverallHealthReportMetricsRules.LinesOfCodeAverage.FailThreshold | Should Be 42 | ||
} | ||
} | ||
Context 'Custom settings contains expected settings groups but contains metrics absent from the defaults' { | ||
|
||
$DefaultSettings = ConvertFrom-Json (Get-Content -Path "$PSScriptRoot\..\..\..\PSCodeHealth\PSCodeHealthSettings.json" -Raw) | ||
$CustomSettings = ConvertFrom-Json (Get-Content -Path "$PSScriptRoot\..\TestData\NewMetrics.json" -Raw ) | ||
$Result = Merge-PSCodeHealthSetting -DefaultSettings $DefaultSettings -CustomSettings $CustomSettings | ||
|
||
It 'Should return an object of the type [PSCustomObject]' { | ||
$Result | Should BeOfType [PSCustomObject] | ||
} | ||
It 'Resulting settings are the same as the defaults for metric "LinesOfCode"' { | ||
$Result.FunctionHealthRecordMetricsRules.LinesOfCode.WarningThreshold | Should Be 20 | ||
$Result.FunctionHealthRecordMetricsRules.LinesOfCode.FailThreshold | Should Be 40 | ||
} | ||
It 'Resulting settings are the same as the defaults for metric "TestCoverage"' { | ||
$Result.FunctionHealthRecordMetricsRules.TestCoverage.WarningThreshold | Should Be 80 | ||
$Result.FunctionHealthRecordMetricsRules.TestCoverage.FailThreshold | Should Be 70 | ||
} | ||
It 'Resulting settings are the same as the defaults for metric "Complexity"' { | ||
$Result.FunctionHealthRecordMetricsRules.Complexity.WarningThreshold | Should Be 15 | ||
$Result.FunctionHealthRecordMetricsRules.Complexity.FailThreshold | Should Be 30 | ||
} | ||
It 'Resulting settings are the same as the defaults for metric "MaximumNestingDepth"' { | ||
$Result.FunctionHealthRecordMetricsRules.MaximumNestingDepth.WarningThreshold | Should Be 4 | ||
$Result.FunctionHealthRecordMetricsRules.MaximumNestingDepth.FailThreshold | Should Be 8 | ||
} | ||
It 'Resulting settings are the same as the defaults for metric "TestsPassRate"' { | ||
$Result.OverallHealthReportMetricsRules.TestsPassRate.WarningThreshold | Should Be 99 | ||
$Result.OverallHealthReportMetricsRules.TestsPassRate.FailThreshold | Should Be 97 | ||
} | ||
It 'Resulting settings are the same as the defaults for metric "CommandsMissedTotal"' { | ||
$Result.OverallHealthReportMetricsRules.CommandsMissedTotal.WarningThreshold | Should Be 20 | ||
$Result.OverallHealthReportMetricsRules.CommandsMissedTotal.FailThreshold | Should Be 40 | ||
} | ||
It 'Resulting settings are the same as the defaults for metric "LinesOfCodeTotal"' { | ||
$Result.OverallHealthReportMetricsRules.LinesOfCodeTotal.WarningThreshold | Should Be 1000 | ||
$Result.OverallHealthReportMetricsRules.LinesOfCodeTotal.FailThreshold | Should Be 2000 | ||
} | ||
It 'Resulting settings are the same as the defaults for metric "LinesOfCodeAverage"' { | ||
$Result.OverallHealthReportMetricsRules.LinesOfCodeAverage.WarningThreshold | Should Be 20 | ||
$Result.OverallHealthReportMetricsRules.LinesOfCodeAverage.FailThreshold | Should Be 40 | ||
} | ||
It 'Resulting settings have metric absent from the defaults : "DummyMetric"' { | ||
$Result.FunctionHealthRecordMetricsRules.DummyMetric.WarningThreshold | Should Be 2 | ||
$Result.FunctionHealthRecordMetricsRules.DummyMetric.FailThreshold | Should Be 4 | ||
} | ||
It 'Resulting settings have metric absent from the defaults : "DummyMetric2"' { | ||
$Result.OverallHealthReportMetricsRules.DummyMetric2.WarningThreshold | Should Be 7 | ||
$Result.OverallHealthReportMetricsRules.DummyMetric2.FailThreshold | Should Be 8 | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
{ | ||
"FunctionHealthRecordMetricsRules": [ | ||
{ | ||
"Complexity": { | ||
"WarningThreshold": 17, | ||
"FailThreshold": 33 | ||
} | ||
}, | ||
{ | ||
"MaximumNestingDepth": { | ||
"WarningThreshold": 6, | ||
"FailThreshold": 12 | ||
} | ||
} | ||
], | ||
"OverallHealthReportMetricsRules": [ | ||
{ | ||
"LinesOfCodeTotal": { | ||
"WarningThreshold": 1500, | ||
"FailThreshold": 3000 | ||
} | ||
}, | ||
{ | ||
"LinesOfCodeAverage": { | ||
"WarningThreshold": 21, | ||
"FailThreshold": 42 | ||
} | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
{ | ||
"FunctionHealthRecordMetricsRules": [ | ||
{ | ||
"DummyMetric": { | ||
"WarningThreshold": 2, | ||
"FailThreshold": 4 | ||
} | ||
} | ||
], | ||
"OverallHealthReportMetricsRules": [ | ||
{ | ||
"DummyMetric2": { | ||
"WarningThreshold": 7, | ||
"FailThreshold": 8 | ||
} | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
[ | ||
{ | ||
"LinesOfCodeTotal": { | ||
"WarningThreshold": 1500, | ||
"FailThreshold": 3000 | ||
} | ||
}, | ||
{ | ||
"LinesOfCodeAverage": { | ||
"WarningThreshold": 21, | ||
"FailThreshold": 42 | ||
} | ||
} | ||
] |