На моем месте работы у нас есть "Core" решение, содержащее ряд проектов, предоставляющих разные функции утилиты, которые упаковываются через nuget и публикуются на внутреннем сервере nuget. Чтобы получить пакет nuget из нашего CI, в настоящее время у нас есть сценарий MSBuild, который выглядит так:
<Exec Command="nuget pack "$(ProjectRoot)\Domain\Domain.csproj" -Properties Configuration=$(Configuration)" />
<Exec Command="nuget pack "$(ProjectRoot)\Logging\Logging.csproj" -Properties Configuration=$(Configuration)" />
<Exec Command="nuget pack "$(ProjectRoot)\Logging.NLog\Logging.NLog.csproj" -Properties Configuration=$(Configuration)" />
<Exec Command="nuget pack "$(ProjectRoot)\Persistence\Persistence.csproj" -Properties Configuration=$(Configuration)" />
<Exec Command="nuget pack "$(ProjectRoot)\Persistence.NHibernate\Persistence.NHibernate.csproj" -Properties Configuration=$(Configuration)" />
У нас около 20 проектов упакованы таким образом, и каждый раз, когда мы представляем новый проект, который должен быть упакован, мы должны добавить еще одну строку в сценарий MSBuild. Можно ли перечислить проекты в решении с помощью MSbuild и таким образом сконденсировать этот скрипт на что-то вроде...
<foreach project in solution>
<Exec Command="nuget pack project -Properties Configuration=$(Configuration)" />
</foreach>
Кроме того, нам нужно было бы допросить каждый проект в цикле, чтобы исключить тестовые проекты (все они находятся в каталоге Tests, поэтому это должно быть тривиально?)
EDIT: Другие вопросы касаются проблемы выполнения задач msbuild в цикле, но решения включают в себя ручную перечисление элементов, которые будут зацикливаться в ItemGroup, поэтому это приведет к немного более простому, но все же очень сложному коду. Я хочу избежать перечисления проектов вручную, если это возможно.
Вы можете использовать свойства SolutionDir
и SolutionName
чтобы найти файл решения, а затем написать пользовательскую цель, чтобы найти все проекты, включенные в ваше решение. Я сделал это так:
<Target Name="AfterBuild" DependsOnTargets="PublishNuGetPackages" />
<Target Name="PublishNuGetPackages">
<CollectNuGetProjects SolutionDir="$(SolutionDir)" SolutionName="$(SolutionName)">
<Output TaskParameter="NuGetProjects" ItemName="NuGetProjects" />
</CollectNuGetProjects>
<Message Text="Collected the following nuget projects: @(NuGetProjects)" Importance="high" />
<Exec Command="nuget pack "$(SolutionDir)\%(NuGetProjects.Identity)" -Properties Configuration=$(Configuration)" />
<!-- publish packages etc... -->
</Target>
<UsingTask TaskName="CollectNuGetProjects"
TaskFactory="CodeTaskFactory"
AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
<ParameterGroup>
<SolutionName ParameterType="System.String" Required="true" />
<SolutionDir ParameterType="System.String" Required="true" />
<NuGetProjects ParameterType="System.String[]" Output="true" />
</ParameterGroup>
<Task>
<Reference Include="System.Linq" />
<Using Namespace="System" />
<Using Namespace="System.Linq" />
<Using Namespace="System.Text.RegularExpressions" />
<Code Type="Fragment" Language="cs">
<![CDATA[
var solutionFile = Path.Combine(SolutionDir, SolutionName + ".sln");
var solutionText = File.ReadAllText(solutionFile);
NuGetProjects = Regex.Matches(solutionText, @"""(?<projectFile>[^""]+?\.(csproj|wixproj|vcxproj))""")
.Cast<Match>()
.Select(m => m.Groups["projectFile"].Value)
.Where(p => !p.Contains(@"\Tests\"))
.ToArray();
]]>
</Code>
</Task>
</UsingTask>
Кроме того, настраиваемая задача отфильтровывает проекты, находящиеся в папке " Tests
как вы хотели.