Skip to content

Commit 23b8c1b

Browse files
authored
Add Analyze step for script analyzer. (#148)
* Resolve most scriptanalyzer warnings * Add Analyze task to run PSScriptAnalyzer * Deal with further PSScriptAnalyzer warnings * Improve analyze task control * Merge analyze task skip and control variables * Rename script analysis variables * Remove PSSA rule suppression from test files * Reorder build tasks, fix incorrect required variable * Add PSScriptAnalyzer module to appveyor config * Remove extended character set symbols
1 parent e7ce642 commit 23b8c1b

File tree

7 files changed

+121
-13
lines changed

7 files changed

+121
-13
lines changed

appveyor.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ install:
1010
Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force | Out-Null
1111
Install-Module Pester -MinimumVersion 3.4.0 -Scope CurrentUser -Force | Out-Null
1212
Install-Module psake -Scope CurrentUser -Force | Out-Null
13+
Install-Module PSScriptAnalyzer -Scope CurrentUser -Force | Out-Null
1314
1415
build_script:
1516
- ps: |

build.psake.ps1

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ Task Clean -requiredVariables ReleaseDir {
7474
}
7575
}
7676

77-
Task Build -depends BuildImpl, Sign, PostBuild {
77+
Task Build -depends BuildImpl, Analyze, Sign, PostBuild {
7878
}
7979

8080
Task BuildImpl -depends Init, Clean, PreBuild -requiredVariables SrcRootDir, OutDir {
@@ -134,6 +134,41 @@ Task Sign -depends BuildImpl -requiredVariables SettingsPath, SignScripts {
134134
}
135135
}
136136

137+
Task Analyze -depends BuildImpl -requiredVariables ScriptAnalysisAction, OutDir {
138+
if ((Get-Host).Name -in $SkipScriptAnalysisHost) {
139+
$ScriptAnalysisAction = 'Skip'
140+
}
141+
142+
if ($ScriptAnalysisAction -eq 'Skip') {
143+
"Script analysis is not enabled. Skipping Analyze task."
144+
return
145+
}
146+
147+
$analysisResult = Invoke-ScriptAnalyzer -Path $OutDir -Recurse -Verbose:$VerbosePreference
148+
$analysisResult | Format-Table
149+
switch ($ScriptAnalysisAction) {
150+
'Error' {
151+
Assert -conditionToCheck (
152+
($analysisResult | Where-Object Severity -eq 'Error').Count -eq 0
153+
) -failureMessage 'One or more Script Analyzer errors were found. Build cannot continue!'
154+
}
155+
'Warning' {
156+
Assert -conditionToCheck (
157+
($analysisResult | Where-Object {
158+
$_.Severity -eq 'Warning' -or $_.Severity -eq 'Error'
159+
}).Count -eq 0) -failureMessage 'One or more Script Analyzer warnings were found. Build cannot continue!'
160+
}
161+
'None' {
162+
return
163+
}
164+
default {
165+
Assert -conditionToCheck (
166+
$analysisResult.Count -eq 0
167+
) -failureMessage 'One or more Script Analyzer issues were found. Build cannot continue!'
168+
}
169+
}
170+
}
171+
137172
Task GenerateMarkdown -depends Build, PreBuildHelp -requiredVariables DocsRootDir, ModuleName, OutDir {
138173
if ($null -eq $DefaultLocale) {
139174
$DefaultLocale = 'en-US'
@@ -194,7 +229,7 @@ Task InstallImpl -depends BuildHelp, PreInstall -requiredVariables OutDir {
194229
Copy-Item -Path $OutDir\* -Destination $InstallPath -Verbose:$VerbosePreference -Recurse -Force
195230
}
196231

197-
Task Test -depends Build -requiredVariables TestRootDir, ModuleName {
232+
Task Test -depends Analyze -requiredVariables TestRootDir, ModuleName {
198233
Import-Module Pester
199234

200235
try {
@@ -375,6 +410,7 @@ function PromptUserForCredentialAndStorePassword {
375410
}
376411

377412
function AddSetting {
413+
[System.Diagnostics.CodeAnalysis.SuppressMessage('PSShouldProcess', '', Scope='Function')]
378414
param(
379415
[Parameter(Mandatory)]
380416
[string]$Key,

build.settings.ps1

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,23 @@ Properties {
5555
[System.Diagnostics.CodeAnalysis.SuppressMessage('PSUseDeclaredVarsMoreThanAssigments', '', Scope='*', Target='CertSubjectName')]
5656
$CertSubjectName = $null
5757

58+
# -------------------- Script Analysis properties ------------------------------
59+
60+
# The script analysis task step will run, unless your host is in the array defined below.
61+
# This allows you to control whether code analysis is executed, for hosts where script
62+
# analysis is included in the product.
63+
[System.Diagnostics.CodeAnalysis.SuppressMessage('PSUseDeclaredVarsMoreThanAssigments', '', Scope='*', Target='SkipCodeAnalysisHost')]
64+
$SkipScriptAnalysisHost = @(
65+
'Visual Studio Code Host',
66+
'My Custom Host with scriptanalyzer support'
67+
)
68+
69+
# To control the failure of the build with specific script analyzer rule severities,
70+
# the CodeAnalysisStop variable can be used. The supported values for this variable are
71+
# 'Warning', 'Error', 'All', 'None' or 'Skip'. Invalid input will stop on all rules.
72+
# 'Skip' will skip over the code analysis step all together.
73+
[System.Diagnostics.CodeAnalysis.SuppressMessage('PSUseDeclaredVarsMoreThanAssigments', '', Scope='*', Target='CodeAnalysisStop')]
74+
$ScriptAnalysisAction = 'Error'
5875

5976
# -------------------- Publishing properties ------------------------------
6077

src/InvokePlaster.ps1

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,13 @@ Please follow the scripting style of this file when adding new script.
2424
General notes
2525
#>
2626
function Invoke-Plaster {
27+
[System.Diagnostics.CodeAnalysis.SuppressMessage('PSAvoidUsingWriteHost', '', Scope='Function')]
28+
[System.Diagnostics.CodeAnalysis.SuppressMessage('PSAvoidShouldContinueWithoutForce', '', Scope='Function', Target='CopyFileWithConflictDetection')]
2729
[System.Diagnostics.CodeAnalysis.SuppressMessage('PSShouldProcess', '', Scope='Function', Target='CopyFileWithConflictDetection')]
2830
[System.Diagnostics.CodeAnalysis.SuppressMessage('PSShouldProcess', '', Scope='Function', Target='ProcessFile')]
2931
[System.Diagnostics.CodeAnalysis.SuppressMessage('PSShouldProcess', '', Scope='Function', Target='ProcessModifyFile')]
3032
[System.Diagnostics.CodeAnalysis.SuppressMessage('PSShouldProcess', '', Scope='Function', Target='ProcessNewModuleManifest')]
33+
[System.Diagnostics.CodeAnalysis.SuppressMessage('PSAvoidUsingConvertToSecureStringWithPlainText', '', Scope='Function', Target='ProcessParameter')]
3134
[System.Diagnostics.CodeAnalysis.SuppressMessage('PSShouldProcess', '', Scope='Function', Target='ProcessRequireModule')]
3235
[System.Diagnostics.CodeAnalysis.SuppressMessage('PSAvoidShouldContinueWithoutForce', '', Scope='Function', Target='ProcessFile')]
3336
[CmdletBinding(SupportsShouldProcess=$true)]
@@ -709,7 +712,8 @@ function Invoke-Plaster {
709712
# Copy over empty directories - if any.
710713
$gciParams.Remove('File')
711714
$gciParams['Directory'] = $true
712-
$dirs = @(Microsoft.PowerShell.Management\Get-ChildItem @gciParams | Where {$_.GetFileSystemInfos().Length -eq 0})
715+
$dirs = @(Microsoft.PowerShell.Management\Get-ChildItem @gciParams |
716+
Where-Object {$_.GetFileSystemInfos().Length -eq 0})
713717
foreach ($dir in $dirs) {
714718
$dirSrcPath = $dir.FullName
715719
$relPath = $dirSrcPath.Substring($srcRelRootPathLength)
@@ -1112,13 +1116,9 @@ function Invoke-Plaster {
11121116
}
11131117
}
11141118

1115-
<#
1116-
██ ██ ███████ ██ ██████ ███████ ██████ ███████
1117-
██ ██ ██ ██ ██ ██ ██ ██ ██ ██
1118-
███████ █████ ██ ██████ █████ ██████ ███████
1119-
██ ██ ██ ██ ██ ██ ██ ██ ██
1120-
██ ██ ███████ ███████ ██ ███████ ██ ██ ███████
1121-
#>
1119+
###############################################################################
1120+
# Helper functions
1121+
###############################################################################
11221122

11231123
function InitializePredefinedVariables([string]$TemplatePath, [string]$DestPath) {
11241124
# Always set these variables, even if the command has been run with -WhatIf
@@ -1212,7 +1212,7 @@ function WriteContentWithEncoding([string]$path, [string[]]$content, [string]$en
12121212
'utf8' { $noBomEncoding = New-Object System.Text.UTF8Encoding($false) }
12131213
}
12141214

1215-
if ($content -eq $null) {
1215+
if ($null -eq $content) {
12161216
$content = [string]::Empty
12171217
}
12181218

src/Templates/NewModule/build.psake.ps1

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ Task Clean -requiredVariables ReleaseDir {
7474
}
7575
}
7676

77-
Task Build -depends BuildImpl, Sign, PostBuild {
77+
Task Build -depends BuildImpl, Analyze, Sign, PostBuild {
7878
}
7979

8080
Task BuildImpl -depends Init, Clean, PreBuild -requiredVariables SrcRootDir, OutDir {
@@ -134,6 +134,41 @@ Task Sign -depends BuildImpl -requiredVariables SettingsPath, SignScripts {
134134
}
135135
}
136136

137+
Task Analyze -depends BuildImpl -requiredVariables ScriptAnalysisAction, OutDir {
138+
if ((Get-Host).Name -in $SkipScriptAnalysisHost) {
139+
$ScriptAnalysisAction = 'Skip'
140+
}
141+
142+
if ($ScriptAnalysisAction -eq 'Skip') {
143+
"Script analysis is not enabled. Skipping Analyze task."
144+
return
145+
}
146+
147+
$analysisResult = Invoke-ScriptAnalyzer -Path $OutDir -Recurse -Verbose:$VerbosePreference
148+
$analysisResult | Format-Table
149+
switch ($ScriptAnalysisAction) {
150+
'Error' {
151+
Assert -conditionToCheck (
152+
($analysisResult | Where-Object Severity -eq 'Error').Count -eq 0
153+
) -failureMessage 'One or more Script Analyzer errors were found. Build cannot continue!'
154+
}
155+
'Warning' {
156+
Assert -conditionToCheck (
157+
($analysisResult | Where-Object {
158+
$_.Severity -eq 'Warning' -or $_.Severity -eq 'Error'
159+
}).Count -eq 0) -failureMessage 'One or more Script Analyzer warnings were found. Build cannot continue!'
160+
}
161+
'None' {
162+
return
163+
}
164+
default {
165+
Assert -conditionToCheck (
166+
$analysisResult.Count -eq 0
167+
) -failureMessage 'One or more Script Analyzer issues were found. Build cannot continue!'
168+
}
169+
}
170+
}
171+
137172
Task GenerateMarkdown -depends Build, PreBuildHelp -requiredVariables DocsRootDir, ModuleName, OutDir {
138173
if ($null -eq $DefaultLocale) {
139174
$DefaultLocale = 'en-US'
@@ -194,7 +229,7 @@ Task InstallImpl -depends BuildHelp, PreInstall -requiredVariables OutDir {
194229
Copy-Item -Path $OutDir\* -Destination $InstallPath -Verbose:$VerbosePreference -Recurse -Force
195230
}
196231

197-
Task Test -depends Build -requiredVariables TestRootDir, ModuleName {
232+
Task Test -depends Analyze -requiredVariables TestRootDir, ModuleName {
198233
Import-Module Pester
199234

200235
try {
@@ -375,6 +410,7 @@ function PromptUserForCredentialAndStorePassword {
375410
}
376411

377412
function AddSetting {
413+
[System.Diagnostics.CodeAnalysis.SuppressMessage('PSShouldProcess', '', Scope='Function')]
378414
param(
379415
[Parameter(Mandatory)]
380416
[string]$Key,

src/Templates/NewModule/build.settings.ps1

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,23 @@ Properties {
5555
[System.Diagnostics.CodeAnalysis.SuppressMessage('PSUseDeclaredVarsMoreThanAssigments', '', Scope='*', Target='CertSubjectName')]
5656
$CertSubjectName = $null
5757

58+
# -------------------- Script Analysis properties ------------------------------
59+
60+
# The script analysis task step will run, unless your host is in the array defined below.
61+
# This allows you to control whether code analysis is executed, for hosts where script
62+
# analysis is included in the product.
63+
[System.Diagnostics.CodeAnalysis.SuppressMessage('PSUseDeclaredVarsMoreThanAssigments', '', Scope='*', Target='SkipCodeAnalysisHost')]
64+
$SkipScriptAnalysisHost = @(
65+
'Visual Studio Code Host',
66+
'My Custom Host with scriptanalyzer support'
67+
)
68+
69+
# To control the failure of the build with specific script analyzer rule severities,
70+
# the CodeAnalysisStop variable can be used. The supported values for this variable are
71+
# 'Warning', 'Error', 'All', 'None' or 'Skip'. Invalid input will stop on all rules.
72+
# 'Skip' will skip over the code analysis step all together.
73+
[System.Diagnostics.CodeAnalysis.SuppressMessage('PSUseDeclaredVarsMoreThanAssigments', '', Scope='*', Target='CodeAnalysisStop')]
74+
$ScriptAnalysisAction = 'Error'
5875

5976
# -------------------- Publishing properties ------------------------------
6077

src/TestPlasterManifest.ps1

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#>
2727
function Test-PlasterManifest {
2828
[CmdletBinding()]
29+
[OutputType([System.Xml.XmlDocument])]
2930
param(
3031
# Specifies a path to a plasterManifest.xml file.
3132
[Parameter(Position=0,

0 commit comments

Comments
 (0)