With WMF 5.0 we can make use of the PowerShell static code
checker utility PSScriptAnalyzer to perform code analysis on PowerShell script
files and modules. PSScriptAnalyzer checks the quality of Windows PowerShell
code by running a set of rules. The rules are based on PowerShell best
practices identified by PowerShell Team and the community. PSScriptAnalyzer
generates DiagnosticResults (errors and warnings) to inform users about
potential code defects and suggests possible solutions for improvements.
You can download the entire module from PowerShell gallery
using the Install-Module cmdlet or create a pull request on the project at
Github and build it yourself. Once you have the module available on the
workstation you can perform code checking on PowerShell files by using the
Invoke-ScriptAnalyzer cmdlet.
By making use of this cmdlets and the post-build script
options from TFS build, you can now perform code checking on the PowerShell
projects from the build server and choose to fail the build based on the
results. Let’s see how this works.
First we need a function to do code checking using the
Invoke-ScriptAnalyzer cmdlet and parse the results. The below content describes the process
function Get-DiagnosticIssue
{
param
(
[Parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[ValidateScript({Test-Path $_})]
[string] $Path,
[Parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string] $Severity,
[bool] $FailOnIssues = $false
)
$logDirectory = Join-Path $Env:TF_BUILD_DROPLOCATION "Logs"
if(-not(Test-Path $logDirectory -ErrorAction SilentlyContinue))
{
New-Item -ItemType Directory -Force -Path $logDirectory
}
$logFile = Join-Path $logDirectory "PSScriptAnalyzerLogs.log"
Invoke-ScriptAnalyzer -Path $Path -Recurse |? {$_.Severity -ge $Severity} |fl | Out-File $logFile
if($FailOnIssues)
{
if((Get-Content $logFile) -ne $null)
{
$Host.UI.WriteErrorLine("PSScriptAnalyzer
check failed. Please refer to the file $($logFile) for more details.")
}
}
}
Export-ModuleMember *
The Get-DiagnosticIssue function accepts a Severity parameter to filter the issues
logged and a Path variable to perform analysis on all the scripts files and
modules under that location. The FailOnIssues parameter can be used to decide
whether the build should be failed or not. This module is called from a script
file that is used as the post-build script path in the TFS build definition.
param
(
[string] $Severity = "Information",
[string] $Filter,
[string] $FailOnIssues = "False"
)
$exitCode = 0
trap
{
$Host.UI.WriteErrorLine($error[0].Exception.Message)
$Host.UI.WriteErrorLine($error[0].Exception.StackTrace)
if ($exitCode -eq 0)
{
$exitCode = 1
}
}
$scriptName = $MyInvocation.MyCommand.Name
$scriptPath = Split-Path -Parent (Get-Variable MyInvocation -Scope Script).Value.MyCommand.Path
Push-Location $scriptPath
Import-Module .\PSScriptAnalyzerExtensions.psm1
$source = $env:TF_BUILD_BUILDDIRECTORY
if(-not ([string]::IsNullOrWhiteSpace($Filter)))
{
$source = Get-ChildItem -Directory $env:TF_BUILD_BUILDDIRECTORY -Filter $Filter -Recurse |? {$_.FullName.ToUpper().Contains("Solution\$Filter".ToUpper())} | select -expand FullName
}
$failBuild = $FailOnIssues -eq "True"
Get-DiagnosticIssue -Path $source -Severity $Severity -FailOnIssues:$failBuild
Pop-Location
exit $exitCode
This script file is used in the process template as
post-build script path with arguments as given below.
Next time the build is queued, it will trigger a code check
using PSScriptAnalyzer and you can see the results in the log file generated.