Интеграция StyleCop с процессом сборки CI (Criuse Control, Nant, msbuild и StyleCop)


Меня попросили интегрировать StyleCop в наш процесс сборки CI таким образом, чтобы:

  • индивидуальный файл проекта в нашем (большие) решения не затрагиваются
  • мне не нужно использовать какую-либо третью сторону инструмент

Первое требование (и я еще не до конца это понимаю) связано с тем, что мы не хотим запускать StyleCop сразу на всем нашем решении. По-видимому, когда StyleCop запускается изнутри VS, он игнорирует определенные атрибуты, которые указывают файлы на игнорировать. Из-за этого, если мы запустим его на машинах dev, мы будем постоянно сталкиваться с тысячами нарушений, с которыми мы еще не готовы иметь дело. Итак, суть в том, что мы хотим иметь возможность запускать его только на сервере сборки.

Наша среда сборки в настоящее время состоит из:

Круиз-контроль > задача nant, которая выполняет msbuild (через exec)

Задача nant находится ниже:

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

Когда я впервые посмотрел на это, я подумал, что это будет простой случай выполнения StyleCop аналогично тому, как выполняется msbuild.

Тем не менее, StyleCop поставляется в виде набора DLL...

Это значит, что я не могу сделать то, что намеревался......Я думаю....

Все статьи, которые я гуглил сегодня, говорили "используйте StyleCopCmd", что я также не могу сделать из-за ограничения инструмента 3-й стороны.

Я посмотрел на инструмент, и он, похоже, реализует пользовательскую задачу nant, которая запускает StyleCopConsole, подключается к нескольким событиям и выводит красиво оформленный отчет. Но для того, чтобы иметь возможность обосновать создание любого инструмента в доме, я должен быть в состоянии полностью объяснить, почему я не могу просто достичь того, что я хочу в файле конфигурации nant. Или любым другим способом, не связанным с созданием или использованием инструмента. И в идеале, это было бы быстрее, если бы мне не нужно было писать или использовать инструмент в любом случае.

Итак, мой вопрос в том, возможно ли это?
1 5

1 ответ:

Нам это удалось. Просто выполните следующие действия:

  • Создайте каталог в своем проекте и скопируйте туда все файлы StyleCop (Microsoft.StyleCop.Используется CSharp.dll, Microsoft.StyleCop.Целей и т. д.)

  • Редактировать Microsoft.StyleCop.Цели должны выглядеть следующим образом:

--

<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>
  • Добавьте следующие задачи в сценарий NAnt, где вы хотите запустить StyleCop. Просто замените свойства 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>