Customizing PSCodeHealth's compliance rules according to your metrics goals

As seen in the page Check if my code meets metrics goals, PSCodeHealth comes with a set of default compliance rules which help determining if the analyzed code is doing well (or not so well) for any given metric.

These default compliance rules are based on community consensus, thresholds from reference projects, or other code quality tools.
But your requirements or metrics goals for different project(s) may differ from these defaults, so you may need to customize the warning/fail thresholds for 1, some, or all metrics.

As a reminder, here is how to view all the default compliance rules :

PS C:\> Get-PSCodeHealthComplianceRule

Metric Name                   Metric Group       Warning Threshold Fail Threshold    Higher Is Better 
-----------                   ------------       ----------------- --------------    ---------------- 
LinesOfCode                   PerFunctionMetrics 30                60                False            
ScriptAnalyzerFindings        PerFunctionMetrics 7                 12                False            
TestCoverage                  PerFunctionMetrics 80                70                True             
CommandsMissed                PerFunctionMetrics 6                 12                False            
Complexity                    PerFunctionMetrics 15                30                False            
MaximumNestingDepth           PerFunctionMetrics 4                 8                 False            
LinesOfCodeTotal              OverallMetrics     1000              2000              False            
LinesOfCodeAverage            OverallMetrics     30                60                False            
ScriptAnalyzerFindingsTotal   OverallMetrics     30                60                False            
ScriptAnalyzerErrors          OverallMetrics     1                 3                 False            
ScriptAnalyzerWarnings        OverallMetrics     10                20                False            
ScriptAnalyzerInformation     OverallMetrics     20                40                False            
ScriptAnalyzerFindingsAverage OverallMetrics     7                 12                False            
NumberOfFailedTests           OverallMetrics     1                 3                 False            
TestsPassRate                 OverallMetrics     99                97                True             
TestCoverage                  OverallMetrics     80                70                True             
CommandsMissedTotal           OverallMetrics     200               400               False            
ComplexityAverage             OverallMetrics     15                30                False            
ComplexityHighest             OverallMetrics     30                60                False            
NestingDepthAverage           OverallMetrics     4                 8                 False            
NestingDepthHighest           OverallMetrics     8                 16                False            

Defining custom compliance rules

The default compliance rules built into PSCodeHealth are stored in the file PSCodeHealthSettings.json in the module root. To customize the thresholds for some metrics, it is strongly NOT recommended to modify this file, but to create a new JSON file containing the rules you need to override.

For example, you may have a specific project which requires Switch statements containing large numbers of clauses.
This has a high impact on the Complexity metric, even though in this particular case the code is still fairly easy to read and maintain.
In other words, the Complexity metric (based on Cyclomatic Complexity) doesn't properly reflect the complexity of your particular project.
So you decide to increase all the complexity-related thresholds by 10.

To view the default compliance rules for all complexity-related metrics, run the following command :

PS C:\> Get-PSCodeHealthComplianceRule -MetricName Complexity,ComplexityAverage,ComplexityHighest

Metric Name                   Metric Group       Warning Threshold Fail Threshold    Higher Is Better 
-----------                   ------------       ----------------- --------------    ---------------- 
Complexity                    PerFunctionMetrics 15                30                False            
ComplexityAverage             OverallMetrics     15                30                False            
ComplexityHighest             OverallMetrics     30                60                False            

Open a new file in your editor of choice and enter a JSON object for each compliance rule you need to override. For our current example, the content of the file would be :

{
    "PerFunctionMetrics": [
        {
            "Complexity": {
                "WarningThreshold": 25,
                "FailThreshold": 40,
                "HigherIsBetter": false
            }
        }
    ],
    "OverallMetrics": [
        {
            "ComplexityAverage": {
                "WarningThreshold": 25,
                "FailThreshold": 40,
                "HigherIsBetter": false
            }
        },
        {
            "ComplexityHighest": {
                "WarningThreshold": 40,
                "FailThreshold": 70,
                "HigherIsBetter": false
            }
        }
    ]
}

Any metric not specified in this file will use the default compliance rule.
Save this file with the '.json' extension, like MyProjectSettings.json to a location of your choice.

Viewing the compliance rules, including custom rules

To view all the compliance rules which are currently in effect (including your custom compliance rules), run Get-PSCodeHealthComplianceRule with the CustomSettingsPath parameter to specify the path of the file containing your custom rules :

PS C:\> Get-PSCodeHealthComplianceRule -CustomSettingsPath .\MyProjectSettings.json

Metric Name                   Metric Group       Warning Threshold Fail Threshold    Higher Is Better 
-----------                   ------------       ----------------- --------------    ---------------- 
LinesOfCode                   PerFunctionMetrics 30                60                False            
ScriptAnalyzerFindings        PerFunctionMetrics 7                 12                False            
TestCoverage                  PerFunctionMetrics 80                70                True             
CommandsMissed                PerFunctionMetrics 6                 12                False            
Complexity                    PerFunctionMetrics 25                40                False            
MaximumNestingDepth           PerFunctionMetrics 4                 8                 False            
LinesOfCodeTotal              OverallMetrics     1000              2000              False            
LinesOfCodeAverage            OverallMetrics     30                60                False            
ScriptAnalyzerFindingsTotal   OverallMetrics     30                60                False            
ScriptAnalyzerErrors          OverallMetrics     1                 3                 False            
ScriptAnalyzerWarnings        OverallMetrics     10                20                False            
ScriptAnalyzerInformation     OverallMetrics     20                40                False            
ScriptAnalyzerFindingsAverage OverallMetrics     7                 12                False            
NumberOfFailedTests           OverallMetrics     1                 3                 False            
TestsPassRate                 OverallMetrics     99                97                True             
TestCoverage                  OverallMetrics     80                70                True             
CommandsMissedTotal           OverallMetrics     200               400               False            
ComplexityAverage             OverallMetrics     25                40                False            
ComplexityHighest             OverallMetrics     40                70                False            
NestingDepthAverage           OverallMetrics     4                 8                 False            
NestingDepthHighest           OverallMetrics     8                 16                False           

To verify that the complexity-related compliance rules are overridden by your custom rules, run the following :

PS C:\> $ComplexityMetrics = 'Complexity','ComplexityAverage','ComplexityHighest'

PS C:\> Get-PSCodeHealthComplianceRule -CustomSettingsPath .\MyProjectSettings.json -MetricName $ComplexityMetrics

Metric Name                   Metric Group       Warning Threshold Fail Threshold    Higher Is Better 
-----------                   ------------       ----------------- --------------    ---------------- 
Complexity                    PerFunctionMetrics 25                40                False            
ComplexityAverage             OverallMetrics     25                40                False            
ComplexityHighest             OverallMetrics     40                70                False            

Checking if your code meets your customized compliance rules

Now, that you have compliance rules matching the metrics goals for your particular project/needs, you can use PSCodeHealth to verify how your PowerShell code is doing against these goals, like so :

PS C:\> $HealthReport = Invoke-PSCodeHealth .\coveralls .\coveralls

PS C:\> Test-PSCodeHealthCompliance -HealthReport $HealthReport -CustomSettingsPath .\MyProjectSettings.json

Metric Name                   Warning Threshold  Fail Threshold    Value             Result           
-----------                   -----------------  --------------    -----             ------           
LinesOfCode                   30                 60                39                Warning          
ScriptAnalyzerFindings        7                  12                2                 Pass             
TestCoverage                  80                 70                0                 Fail             
CommandsMissed                6                  12                20                Fail             
Complexity                    25                 40                41                Warning             
MaximumNestingDepth           4                  8                 3                 Pass             
LinesOfCodeTotal              1000               2000              204               Pass             
LinesOfCodeAverage            30                 60                22.67             Pass             
ScriptAnalyzerFindingsTotal   30                 60                4                 Pass             
ScriptAnalyzerErrors          1                  3                 1                 Pass             
ScriptAnalyzerWarnings        10                 20                3                 Pass             
ScriptAnalyzerInformation     20                 40                0                 Pass             
ScriptAnalyzerFindingsAverage 7                  12                0.44              Pass             
NumberOfFailedTests           1                  3                 2                 Warning          
TestsPassRate                 99                 97                84.62             Fail             
TestCoverage                  80                 70                39.6              Fail             
CommandsMissedTotal           200                400               61                Pass             
ComplexityAverage             25                 40                24                Pass             
ComplexityHighest             40                 70                41                Warning             
NestingDepthAverage           4                  8                 1.11              Pass             
NestingDepthHighest           8                  16                3                 Pass             

Looking at the Warning Threshold and Fail Threshold columns above, we can see that the complexity-related metrics get the custom thresholds defined in the file MyProjectSettings.json.

Also, the compliance results for the complexity-related metrics are now based on the customized thresholds.
For example, the average complexity value of 24, would be a Warning according to the default compliance rule for this metric, but it is now a Pass.