5

次のような方法で、CI ビルド プロセスに StyleCop を統合するように依頼されました。

  • (大規模な) ソリューションの個々のプロジェクト ファイルは影響を受けません
  • サードパーティのツールを使用する必要はありません

最初の要件 (まだ完全には理解していません) は、ソリューション全体で StyleCop を直接実行したくないという事実によるものです。どうやら、VS 内から StyleCop を実行すると、無視するファイルを指定する特定の属性が無視されます。このため、開発マシンで実行すると、まだ対処する準備ができていない何千もの違反に継続的に遭遇します。要するに、ビルド サーバーでのみ実行できるようにしたいということです。

私たちのビルド環境は現在、次のもので構成されています。

クルーズ コントロール > msbuild を実行する nant タスク (exec 経由)

nant タスクは以下のとおりです。

<target name="buildSolution">       
    <echo message="Building solution..." />
    <exec program="C:\WINDOWS\Microsoft.NET\Framework\v3.5\msbuild.exe"                     
        commandline="${Project.SolutionFile} /t:Rebuild /p:Configuration=${Project.SolutionBuildConfiguration} /v:q" workingdir="." />      
</target>  

これを最初に見たとき、msbuild が実行されているのと同様の方法で StyleCop を実行する単純なケースだと思いました。

ただし、StyleCop は dll のセットとして提供されます...

ということは、自分の意図したことができていないということ……だと思います……。

今日私がグーグルで検索したすべての記事は、「StyleCopCmd を使用する」と述べていますが、これもサードパーティのツールの制限のために実行できません。

このツールを調べたところ、StyleCopConsole を開始し、いくつかのイベントにフックして適切にフォーマットされたレポートを出力するカスタム nant タスクが実装されているようです。しかし、社内でツールを作成することを正当化できるようにするためには、nant 構成ファイルで目的を達成できない理由を完全に説明できる必要があります。または、ツールの作成または使用を伴わないその他の方法で。そして理想的には、とにかくツールを作成したり使用したりする必要がなければ、より高速になります。

だから私の質問は、それは可能ですか?

4

1 に答える 1

5

私たちはこれを行うことができました。次の手順に従ってください。

  • プロジェクトにディレクトリを作成し、そこにすべての StyleCop ファイル (Microsoft.StyleCop.CSharp.dll、Microsoft.StyleCop.Targets など) をコピーします。

  • Microsoft.StyleCop.Targets を次のように編集します。

--

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <UsingTask AssemblyFile="Microsoft.StyleCop.dll" TaskName="StyleCopTask" />
    <PropertyGroup>
        <BuildDependsOn>StyleCop</BuildDependsOn>
        <RebuildDependsOn>StyleCopForceFullAnalysis;StyleCop</RebuildDependsOn>
    </PropertyGroup>
    <PropertyGroup Condition="('$(SourceAnalysisForceFullAnalysis)' != '') and ('$(StyleCopForceFullAnalysis)' == '')">
        <StyleCopForceFullAnalysis>$(SourceAnalysisForceFullAnalysis)</StyleCopForceFullAnalysis>
    </PropertyGroup>
    <PropertyGroup Condition="'$(StyleCopForceFullAnalysis)' == ''">
        <StyleCopForceFullAnalysis>false</StyleCopForceFullAnalysis>
    </PropertyGroup>
    <PropertyGroup Condition="('$(SourceAnalysisCacheResults)' != '') and ('$(StyleCopCacheResults)' == '')">
        <StyleCopCacheResults>$(SourceAnalysisCacheResults)</StyleCopCacheResults>
    </PropertyGroup>
    <PropertyGroup Condition="'$(StyleCopCacheResults)' == ''">
        <StyleCopCacheResults>true</StyleCopCacheResults>
    </PropertyGroup>

    <!-- Define StyleCopTreatErrorsAsWarnings property. -->
    <PropertyGroup Condition="('$(SourceAnalysisTreatErrorsAsWarnings)' != '') and ('$(StyleCopTreatErrorsAsWarnings)' == '')">
        <StyleCopTreatErrorsAsWarnings>$(SourceAnalysisTreatErrorsAsWarnings)</StyleCopTreatErrorsAsWarnings>
    </PropertyGroup>
    <PropertyGroup Condition="'$(StyleCopTreatErrorsAsWarnings)' == ''">
        <StyleCopTreatErrorsAsWarnings>true</StyleCopTreatErrorsAsWarnings>
    </PropertyGroup>

    <PropertyGroup Condition="('$(SourceAnalysisEnabled)' != '') and ('$(StyleCopEnabled)' == '')">
        <StyleCopEnabled>$(SourceAnalysisEnabled)</StyleCopEnabled>
    </PropertyGroup>
    <PropertyGroup Condition="'$(StyleCopEnabled)' == ''">
        <StyleCopEnabled>true</StyleCopEnabled>
    </PropertyGroup>

    <!-- Define StyleCopOverrideSettingsFile property. -->
    <PropertyGroup Condition="('$(SourceAnalysisOverrideSettingsFile)' != '') and ('$(StyleCopOverrideSettingsFile)' == '')">
        <StyleCopOverrideSettingsFile>$(SourceAnalysisOverrideSettingsFile)</StyleCopOverrideSettingsFile>
    </PropertyGroup>
    <PropertyGroup Condition="'$(StyleCopOverrideSettingsFile)' == ''">
        <StyleCopOverrideSettingsFile> </StyleCopOverrideSettingsFile>
    </PropertyGroup>

    <!-- Define StyleCopOutputFile property. -->
    <PropertyGroup Condition="('$(StyleCopOutputPath)' == '')">
        <StyleCopOutputPath>$(IntermediateOutputPath)</StyleCopOutputPath>
    </PropertyGroup>
    <PropertyGroup Condition="'$(StyleCopOutputFile)' == ''">
        <StyleCopOutputFile Condition="!HasTrailingSlash('$(StyleCopOutputPath)')">$(StyleCopOutputPath)\$(AssemblyName).StyleCopViolations.xml</StyleCopOutputFile>
        <StyleCopOutputFile Condition="HasTrailingSlash('$(StyleCopOutputPath)')">$(StyleCopOutputPath)$(AssemblyName).StyleCopViolations.xml</StyleCopOutputFile>
    </PropertyGroup>

    <!-- Define all new properties which do not need to have both StyleCop and SourceAnalysis variations. -->
    <PropertyGroup>
        <!-- Specifying 0 will cause StyleCop to use the default violation count limit.
         Specifying any positive number will cause StyleCop to use that number as the violation count limit.
         Specifying any negative number will cause StyleCop to allow any number of violations without limit. -->
        <StyleCopMaxViolationCount Condition="'$(StyleCopMaxViolationCount)' == ''">100</StyleCopMaxViolationCount>
    </PropertyGroup>

    <!-- Define target: StyleCopForceFullAnalysis -->
    <Target Name="StyleCopForceFullAnalysis">
        <CreateProperty Value="true">
            <Output TaskParameter="Value" PropertyName="StyleCopForceFullAnalysis" />
        </CreateProperty>
    </Target>

    <!-- Define target: StyleCop -->
    <Target Name="StyleCop" Condition="'$(StyleCopEnabled)' != 'false'">
        <!-- Determine what files should be checked. Take all Compile items, but exclude those that have set ExcludeFromStyleCop=true or ExcludeFromSourceAnalysis=true. -->
        <CreateItem Include="@(Compile)" Condition="('%(Compile.ExcludeFromStyleCop)' != 'true') and ('%(Compile.ExcludeFromSourceAnalysis)' != 'true')">
            <Output TaskParameter="Include" ItemName="StyleCopFiles"/>
        </CreateItem>

        <Message Text="Forcing full StyleCop reanalysis." Condition="'$(StyleCopForceFullAnalysis)' == 'true'" Importance="Low" />

        <Message Text="Analyzing @(StyleCopFiles)" Importance="Low" />

        <!-- Run the StyleCop MSBuild task. -->
        <StyleCopTask
            ProjectFullPath="$(MSBuildProjectFile)"
            SourceFiles="@(StyleCopFiles)"
            AdditionalAddinPaths="@(StyleCopAdditionalAddinPaths)"
            ForceFullAnalysis="$(StyleCopForceFullAnalysis)"
            DefineConstants="$(DefineConstants)"
            TreatErrorsAsWarnings="$(StyleCopTreatErrorsAsWarnings)"
            CacheResults="$(StyleCopCacheResults)"
            OverrideSettingsFile="$(StyleCopOverrideSettingsFile)"
            OutputFile="$(StyleCopOutputFile)"
            MaxViolationCount="$(StyleCopMaxViolationCount)"
            />

        <!-- Make output files cleanable -->
        <CreateItem Include="$(StyleCopOutputFile)">
            <Output TaskParameter="Include" ItemName="FileWrites"/>
        </CreateItem>

        <!-- Add the StyleCop.cache file to the list of files we've written - so they can be cleaned up on a Build Clean. -->
        <CreateItem Include="StyleCop.Cache" Condition="'$(StyleCopCacheResults)' == 'true'">
            <Output TaskParameter="Include" ItemName="FileWrites"/>
        </CreateItem>
    </Target>
</Project>
  • StyleCop を実行する NAnt スクリプトに次のタスクを追加します。NAnt プロパティを、ビルド スクリプトに適したプロパティまたは値に置き換えるだけです。

        <msbuild project="${solutionfile}" target="ReBuild" verbosity="Quiet">
           <property name="CustomAfterMicrosoftCommonTargets" value="${path::combine(project:get-base-directory(), relative-path-to-Microsoft.StyleCop.Targets)}"/>
           <property name="Configuration" value="Release"/>
           <property name="StyleCopEnabled" value="true" />
           <property name="StyleCopOutputPath" value="${directory-to-dump-output-report-to}" />
           <arg value="/noconsolelogger" />
        </msbuild>
    
于 2009-08-19T09:31:44.467 に答える