我已将检查 (.NET) 生成步骤添加到 TeamCity (v8) 项目中,该项目由单个虚拟 C# 类的 Visual Studio 2010 解决方案生成步骤组成。
构建步骤具有失败条件,如果我收到任何检查错误或警告,则设置为失败。
我的虚拟类只生成 2 个建议,但构建失败声明
"指标更改时构建失败:检查警告的数量太多 大:3"。
有没有办法让团队城市步骤忽略建议?
我启用了调试输出,但该步骤中肯定没有警告:
<!-- Generated by InspectCode 2.0.0.0 -->
<Report ToolsVersion="2.0">
<Information>
<Solution>Demo.sln</Solution>
<InspectionScope><Element>Solution</Element></InspectionScope>
</Information>
<IssueTypes><IssueType Id="InconsistentNaming" Category="Constraints Violations" Description="Inconsistent Naming" Severity="SUGGESTION"/>
<IssueType Id="UnusedMember.Global" Category="Redundancies in Symbol Declarations" Description="Type or type member is never used: Non-private accessibility" Severity="SUGGESTION"/>
</IssueTypes>
<Issues>
<Project Name="Demo">
<Issue TypeId="UnusedMember.Global" File="DemoClass1.cs" Offset="36-42" Line="3" Message="Class 'Class1' is never used"/>
<Issue TypeId="UnusedMember.Global" File="DemoClass1.cs" Offset="71-76" Line="5" Message="Field 'maybe' is never used"/>
<Issue TypeId="InconsistentNaming" File="DemoClass1.cs" Offset="71-76" Line="5" Message="Name 'maybe' does not match rule 'Fields (not private)'. Suggested name is 'Maybe'."/>
</Project>
</Issues>
</Report>
虚拟类如下:
namespace Demo
{
public class Class1
{
public bool maybe = true;
}
}
请注意,我仍然希望在 Visual Studio 中报告建议和提示,因此在 ReSharper 设置中将所有非警告和错误更改为不报告不是一个选项(或创建和维护此类设置文件仅供 TeamCity 使用)。
按照前面建议的技术,我编写了一个运行 InspectCode 的 PowerShell 脚本,然后执行输出文件的 XSLT 转换并将结果导入 TeamCity。可以将其作为 PowerShell 生成步骤运行,将解决方案文件名作为第一个脚本参数传递,将变量 %system.teamcity.build.tempDir% 作为第二个参数传递。
TransformResults.xslt:
(这应该与PowerShell脚本位于同一文件夹中)
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="xml" omit-xml-declaration="yes" indent="yes" />
<xsl:strip-space elements="*"/>
<xsl:key name="issueType" match="IssueTypes/IssueType" use="@Id" />
<!--
Template to strip out issues where the severity is HINT or SUGGESTION
-->
<xsl:template match="Issues//Issue">
<xsl:choose>
<xsl:when test="not(contains('HINT SUGGESTION', key('issueType', @TypeId)/@Severity))" >
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:when>
</xsl:choose>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
RunInspectCode.ps1:
param(
[Parameter(Mandatory = $true)][string]$solutionFile,
[Parameter(Mandatory = $true)][string]$buildTempDir)
# Runs the Jetbrains Resharper code inspection utility (InspectCode)
# - see https://confluence.jetbrains.com/display/NETCOM/Introducing+InspectCode
# We don't want to use the built-in TeamCity inspection plugin because it reports
# HINT and SUGGESTION issues, which we don't want to make mandatory.
# Basically we run InspectCode to generate an intermediate XML report, then we
# transform that report via XSLT to strip out the issues we don't want to see.
$ErrorActionPreference = "Stop"
# Required if Powershell < 3.0
#$PSScriptRoot = Split-Path $script:MyInvocation.MyCommand.Path
# General-purpose function to transform XML
function Transform-Xml {
param([string]$stylesheetPath=$(throw '$stylesheetPath is required'),
[string[]]$xmlPath)
begin {
# Compile the stylesheet
$compiledXslt = New-Object System.Xml.Xsl.XslCompiledTransform
$compiledXslt.Load($stylesheetPath)
function transformXmlDoc {
param([xml]$xml, [System.Xml.Xsl.XslCompiledTransform]$xslt = $(throw '$xslt param is required'))
$output = New-Object System.IO.MemoryStream
$arglist = new-object System.Xml.Xsl.XsltArgumentList
$outputReader = new-object System.IO.StreamReader($output)
$xmlReader = New-Object System.Xml.XmlNodeReader($xml)
$xslt.Transform($xmlReader, $arglist, $output)
$output.position = 0
$transformed = [string]$outputReader.ReadToEnd()
$outputReader.Close()
return $transformed
}
function applyStylesheetToXml([xml]$xml) {
$result = transformXmlDoc $xml $compiledXslt
[string]::join([environment]::newline, $result)
}
function applyStylesheetToXmlFile($sourcePath) {
$rpath = resolve-path $sourcePath
[xml]$xml = Get-Content $rpath
$result = transformXmlDoc $xml $compiledXslt
[string]::join([environment]::newline, $result)
}
}
process {
if ($_) {
if ($_ -is [xml]) {
applyStylesheetToXml $_
}
elseif ($_ -is [IO.FileInfo]) {
applyStylesheetToXmlFile $_.FullName
}
elseif ($_ -is [string]) {
if (test-path -type Leaf $_) {
applyStylesheetToXmlFile $_
}
else {
applyStylesheetToXml $_
}
}
else {
throw "Pipeline input type must be one of: [xml], [string] or [IO.FileInfo]"
}
}
}
end {
if ($xmlPath) {
foreach ($path in $xmlPath) {
applyStylesheetToXmlFile $path
}
}
}
}
$solutionPath = Resolve-Path $solutionFile
$tempDir = Resolve-Path $buildTempDir
# Locate inspectcode
if (-Not (Test-Path Env:RESHARPER_TOOLS_PATH)) {
throw 'RESHARPER_TOOLS_PATH environment variable not set'
}
$inspectcode = Join-Path $env:RESHARPER_TOOLS_PATH 'inspectcode.exe'
if (-Not (Test-Path -type Leaf $inspectcode)) {
throw 'InpectCode executable not found'
}
# Path to XSLT transformation file
$fullXsltPath = Resolve-Path (Join-Path $PSScriptRoot 'TransformResults.xslt')
# Names of intermediate and final output files
$intermediateOutput = Join-Path $tempDir 'inspectcode-intermediate.xml'
$outputPath = Join-Path $tempDir 'inspectcode-final.xml'
# Run InspectCode
& $inspectcode "/o=$intermediateOutput" $solutionPath
# Transform the inspection output to remove HINT and SUGGESTION
$transformed = Transform-Xml $fullXsltPath @($intermediateOutput)
# The PowerShell Out-File cmdlet always adds a UTF8 Byte Order Marker so we need to take steps to
# ensure this is not emitted, as the TeamCity XML importer will choke on it
$encoding = New-Object System.Text.UTF8Encoding($false)
[System.IO.File]::WriteAllLines($outputPath, $transformed, $encoding)
# When PowerShell is started through TeamCity's Command Runner, the standard
# output will be wrapped at column 80 (a default). This has a negative impact
# on service messages, as TeamCity quite naturally fails parsing a wrapped
# message. The solution is to set a new, much wider output width. It will
# only be set if TEAMCITY_VERSION exists, i.e., if started by TeamCity.
$host.UI.RawUI.BufferSize = New-Object System.Management.Automation.Host.Size(8192,50)
Write-Output "##teamcity[importData type='ReSharperInspectCode' path='$outputPath']"
这在TeamCity 9中仍然是不可能的(它开始让JetBrains感到尴尬,因为这个功能真的是一个笑话,不能仅限于警告和错误)。
但是有一个自己动手的解决方法
使用免费的Resharper命令行工具"检查代码",可以为所有Resharper问题生成XML报告:
inspectcode.exe /o=codeInspectionReport.xml solution.sln
此报告仍包含所有问题,但随后可以在报告中抛出 XPath 查询以计算错误和警告的数量。
以下是我在 Psake 构建文件中的操作方法:
Task ReportInspectCode {
[xml]$xml = Get-Content 'codeInspectionReport.xml'
$nodes = $xml.selectNodes("/Report/IssueTypes/IssueType[@Severity='ERROR' or (@Severity='WARNING' and @Id!='InconsistentNaming')]")
if ($nodes.Count -gt 0) {
Echo $nodes
throw "There are code inspection errors or warnings, see Resharper -> Inspect -> Code Issues in Solution"
}
else {
Echo "Code inspection completed without warnings or errors"
}
}
如您所见,我还必须过滤掉虚假InconsistentNaming
警告,但如果您不需要它,您可以删除该部分。
当然,您可以在 XSLT 转换中使用类似的 xpath 查询来消除所有非警告和非错误。这样,您可以使用 TeamCity 处理生成的文件并将其显示为代码检查结果。
作为解决方法,您可以在检查代码选项中添加--severity=WARNING
参数到检查代码.exe