Что имелось вначале
Крупная enterprise-система, являющаяся основной платформой компании. В состав входит ядро системы и набор плагинов под разные задачи. Плагины развиваются независимо друг от друга, требуют внесения изменений и расширений в общие библиотеки.
При развитии и ветвлении системы нахождение всех плагинов в общем проекте усложнило поддержку кода. Постоянно существовало несколько веток в репозитории, что приводило к большим трудностям при подготовке релизов и слиянии изменений.
Поэтому было принято волевое решение создать инфраструктуру и настроить сценарии для автоматизации сборки проекта под разные плагины.
При решении задачи использовались следующие инструменты: NuGet, TeamCity, NAnt, Visual Studio 2010, SlowCheetah.
Зачем это нужно
Воспользуйтесь Тестом Джоэла для оценки своей работы. Действия, описанные в моем посте, покрывают пункты 2 и 3.
Решение задачи
Постепенно проект эволюционировал до разделения всех плагинов в отдельные проекты, создания под каждый проект своего репозитория в VCS (Version Control System). Проекты получили жесткие версии, устанавливаемые на билд-сервере (TeamCity). Версия файлов сборок составлялась из 4 цифр: мажорная и минорная версии функционала, номер ревизии в VCS и номер попытки запуска билд-конфигурации.
[assembly: AssemblyVersion("1.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
Основные модули объединялись по функциональному назначению в несколько пакетов с помощью NuGet-а. Состав пакетов был описан nuspec-файлами, и пакеты пересобирались с новой версией после каждого коммита в ветку для релиза (срабатывал триггер в TeamCity). NuGet-пакеты хранились на билд-сервере и были доступны по локальной сети через расшаренный каталог.
Пример nuspec-файла
<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>Core</id>
<version>1.0.0.0</version>
<authors>DefaultCompanyName</authors>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>
Ключевые проекты приложения
</description>
<frameworkAssemblies>
<frameworkAssembly assemblyName="System.Configuration" targetFramework="net35" />
<frameworkAssembly assemblyName="System.Core" targetFramework="net35"/>
<frameworkAssembly assemblyName="System.Drawing" targetFramework="net35"/>
<frameworkAssembly assemblyName="System.Runtime.Serialization" targetFramework="net35"/>
<frameworkAssembly assemblyName="System.ServiceModel" targetFramework="net35"/>
<frameworkAssembly assemblyName="System.Windows.Forms" targetFramework="net35"/>
<frameworkAssembly assemblyName="System.Xml" targetFramework="net35"/>
</frameworkAssemblies>
</metadata>
<files>
<file src="corebinRelease*.dll" target="lib" />
</files>
</package>
Основным инструментом сборки был выбран NAnt и MSBuild. Проекты csproj расширялись дополнительными инструкциями для трансформации конфигов и скачивания зависимых библиотек.
При сборке проектов происходило определение зависимостей. Функция NuGet-а Enable-PackageRestore (с версии 1.6 включена в расширение для Visual Studio) позволяет выполнять автоматический поиск и скачивание nuget-пакетов нужных версий в процессе компиляции. Нет необходимости храненить бинарные файлы используемых библиотек в VCS. При выполнении сборки проекта на билд-сервере выполнялся аналогичный сценарий. Достаточно в репозитории проекта хранить саму утилиту NuGet с набором target-ов для MSBuild-а.
Изменения в файле проекта
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
...
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..</SolutionDir>
<RestorePackages>true</RestorePackages>
...
<SlowCheetahTargets Condition=" '$(SlowCheetahTargets)'=='' ">...slowCheetahSlowCheetah.Transforms.targets</SlowCheetahTargets>
...
<Import Project="$(SolutionDir).nugetNuGet.targets" />
<Import Project="$(SlowCheetahTargets)" Condition="Exists('$(SlowCheetahTargets)')" />
</Project>
Каждому плагину требовалось модифицировать конфигурацию системы, добавляя или изменяя элементы в файл конфига. Я использовал проект SlowCheetah, выполняющий трансформацию xml-файлов. Файлы конфигов включались в nuget-пакеты с указанием target=«content» и добавлялись как файл проекта. Трансформация добавляла два файла. Например, для файла Client.config создаются файлы Client.Debug.config и Client.Release.config. В зависимости от текущей конфигурации, используемой при построении проекта, применятся та или иная трансформация.
Можно настроить артефакты, чтобы собраные проекты были доступны для скачивания с TeamCity через веб-интерфейс в виде zip-файла.
Заключение
В результате мы получаем отлаженный механизм, автоматизирующий сборку приложений. Основные достоинства — быстрота сборки и снижение до минимума количетсва глупых ошибок.
Ссылки
NuGet
TeamCity
NAnt
SlowCheetah
Автор: e1ywka