
Добрый день!
Я попробовал описать здесь свой опыт автоматизации сборки приложений .NET (в основном, речь идет о web-приложениях).
Т.к. получилось много букв пришлось разбить статью две на части. Сейчас выкладываю первую часть, если это будет нужно кому-то, выложу остальное. Не пинайте сильно.
Предположим, имеются следующие задачи
- 1. Необходимо из исходных кодов, находящихся в системе контроля версий, собрать веб-приложение, настроить его определенным образом и выложить на сервер (а также обновить структуру БД, с которой работает приложение. Например, такая задача может возникнуть во время разработки, когда нужно выложить текущую версию для тестировщиков.
- 2. Есть несколько клиентов компании, для каждого из которых нужно подготовить отдельный дистрибутив веб-приложения, настроенный конкретно под этого клиента.
Обычно эти задачи, появившись один раз, начинают периодически повторяться (причем иногда повторяются очень часто). Попробуем автоматизировать решение данных задач при помощи NAnt.
Сразу несколько замечаний:
— давно на хабре была ссылка на отличную статью о построении процесса разработки на платформе .NET. Хотя в ней описывается решение немного другой задачи, там очень хорошо рассказано про NAnt. Кроме того, в данной статье есть много интересной и полезной информации о других этапах процесса разработки. Очень рекомендую к прочтению.
— существует утилита MsBuild — аналог NAnt от Microsoft — она обладает почти тем же самым набором возможностей. Выбор средств для автоматизации билда — личное дело каждого разработчика. Мне субъективно больше нравится NAnt. Буду рад обсудить в комментариях преимущества и недостатки.
Для начала кратко расскажу, что представляет из себя NAnt
Nant — это консольная утилита для автоматизации процесса сборки ПО. Действия, которые должен выполнить NAnt задаются в специальном конфигурационном файле (обычно такой файл имеет расширение .build) в формате XML.
При запуске NAnt через параметр комендной строки -buildfile передается путь к нужному build-файлу. Если в рабочей директории находится только один build-файл, то параметр -buildfile можно не указывать.
Пример командной строки для запуска NAnt
NAnt -buildfile:..\main.build
Корневой элемент файла .build — «проект» («project»). Проект содержит набор «задач» («target»), каждая из котрых содержит описание некоторой последовательности действия.
Содержание build-файла
Пример структуры build-файла:
<project>
<target>
<действие_1 />
<действие_2 />
<действие_3 />
</target>
<target>
<действие_1 />
<действие_2 />
</target>
</project>
(список «действий» можно найти здесь)
Кроме того, в build-файле можно задавать «свойства» («property»). Свойство представляет собой пару «имя-значение», которая может быть указана как внутри элемента «project», так и внутри элемента «target» (во втором случае значение свойства будет установлено только при выполнении элемента «target», в котором находится свойство).
<property name="zip.filename" value="..\build\application.zip" />
Значения свойств можно передавать через параметры командной строки при запуске NAnt ( параметр: -D:property=value)
NAnt -buildfile:..\main.build -D:zip.filename=..\build\application.zip
Для задачи можно указать список задач, от которых она зависит (для правильного порядка выполнения) и условия, при которых разрешено ее выполнение. Для большинства действий также можно указать условие их выполнения.
<target name="pack" depends="compile, configure" "${property::exists('zip.filename')}" >
...
</target>
Как можно видеть в предыдущем примере, в качестве параметров элементов конфигурационного файла можно использовать встроенные выражения. Например, выражение "${property::exists('zip.filename')}" проверяет, определено ли свойство «zip.filename». Список выражений можно посмотреть здесь.
Также стоит отметить, что при редактировании build-файлов в Visual Studio (2008, 2010) есть подсветка синтаксиса (аналогичная XLM-файлам) и работает IntelliSense (в т.ч. для встроенных выражений).
Перейдем к написанию build-файла
Вот наш план действий по сборке приложения:
1. Скомпилировать приложение из исходных кодов;
2. Удалить «лишние» файлы (например, *.aspx.cs, *.csproj и т.д.) и скопировать недостающие (не используемые во время разработки);
3. Сконфигурировать приложение;
4. Прогнать скрипты, чтобы привести БД в нужное для приложения состояние;
5. Выполнить модульные тесты
6. Скопировать приложение в рабочую директорию.
1. Сборка приложения из исходных кодов
Есть несколько способов компиляции приложения с использованием NAnt. Самый удобный из них — использовать для компиляции MsBuild (только для компиляции).
Дело в том, что, в любом случае, приложение будет компилироваться при помощи компилятора (например, csc.exe для C#). Для сборки проекта компилятору нужно передать пути ко всем файлам, входящим в проект, список всех подключаемых внешних сборок (References), список файлов ресурсов и т.д. Т.е. компилятор не умеет обрабатывать файлы вроде *.sln и *.csproj и все параметры нужно передать в него руками.
Файлы *.sln и файлы проектов — не что иное, как конфигурационные файлы MsBuild, которые Visual Studio автоматически генерирует во время работы с проектом. Соответственно, когда Вы нажимаете Ctrl+Shift+B или билдите проект в VS любым другим способом, Visual Studio использует MsBuild, для запуска компилятора с нужными параметрами.
Соответственно, самый легкий способ собрать приложение из исходных кодов — подобно VS, запустить MsBuild, передав в параметрах путь к файлу .sln или файлу проекта. NAnt позволяет сделать это следующими способами:
— При помощи команды EXEC
<property name="msbuild.path" value="C:/WINDOWS/Microsoft.NET/Framework/v3.5/MSBuild.exe" />
<exec program="${msbuild.path}">
<arg value="src\test.sln" />
<arg value="/p:Configuration=Release" />
<arg value="/p:WarningLevel=0" />
</exec>
Команда EXEC позволяет запустить любую программу. Элементы «arg» соответствуют параметрам командной строки.
— При помощи команды MSBUILD, находящейся в проекте NAntContrib. Для того, чтобы воспользоваться этим способом, нужно положить в папку с файлами NAnt библиотеку NAnt.Contrib.Tasks.dll + библиотеки, от которых она зависит.
<msbuild project="src\test.sln">
<property name="Configuration" value="Release" />
<property name="Platform" value="Any CPU" />
</msbuild>
В этом случае не нужно указывать путь к MsBuild. В настройках NAnt есть пути к различным утилитам, в зависимости от версии .NET (в т.ч. к MsBuild). При выполнении команды MsBuild автоматически будет использован нужный путь. Элементы «property» соответствуют параметрам командной строки.
— Можно также использовать команды CSC (для C#), VBC (для VB) и т.д., что будет аналогично ручному запуску компилятора. Описание этих команд можно найти в документации по NAnt (например, о команде csc можно прочитать здесь).
На мой взгляд, наиболее удобный способ — использовать команду MSBUILD из библиотеки NAntContrib. Сразу же встает вопрос: если мы используем MsBuild для сборки приложения, почему бы все остальные действия не выполнять при помощи него. Как я уже говорил, различия между MsBuild и NAnt не очень большие и выбор во многом зависит от предпочтений разработчика. Лично мне удобнее использовать NAnt. Готов обсудить этот вопрос в комментариях.
2. Подготовка сайта к выкладке
При компиляции в папке с веб-приложением остается некоторое количество файлов, нужных при разработке, но не нужных во время работы приложения (например, *.csproj, *.cspx.cs, *.pdb и т.д.). Перед выкладкой необходимо почистить приложение от этих файлов. Опять же, для этого есть несколько способов.
— Воспользоваться проектом WebDeploymentProject (для VS2008, для VS2010). Проект типа WebDeploymentProject можно создать только для существующего проекта веб-приложения. В Visual Studio в свойствах проекта WebDeploymentProject можно настроить различные параметры приложения (например, подписывание сборок, автоматическое создание виртуального каталога в IIS и т.д.). Если Вы попробуете сбилдить проект типа в WebDeploymentProject, то на выходе получите готовое к работе приложение, с которым связан данны WebDeploymentProject и в котором будут отсутствовать файлы, необходимые для разработки.
— Воспользоваться утилитой aspnet_compiler.exe.
WebDeploymentProject, как и остальные проекты VS по сути является просто конфигурационным файлом для MsBuild. Во время билда проекта WebDeploymentProject подготовка приложения к работе выполняется при помощи утилиты aspnet_compiler.exe (также, в зависимости от настроек WebDeploymentProject, могут быть запущены aspnet_merge.exe, aspnet_regiis.exe и т.д.). Ничто не мешает нам руками запустить эту утилиту. В NAnt это можно сделать следующим способом:
<property name="aspnet_compiler.dir" value="C:\Windows\Microsoft.NET\Framework64\v2.0.50727\" />
<property name="publish.project.dir" value="C:\Work\MyWebSite\" />
<property name="publish.output.dir" value="C:\Published\MyWebSite\" />
<exec program="aspnet_compiler.exe" basedir="${aspnet_compiler.dir}" >
<arg value="-p" />
<arg value="${publish.project.dir}" />
<arg value="${publish.output.dir}" />
</exec>
Минус данного способа в том, что нужно явно указывать путь к aspnet_compiler.exe.
Узнать более подробно про утилиту aspnet_compiler.exe можно здесь.
Описание инструментов командной строки ASP.NET здесь.
— Руками удалить лишние файлы (или скопировать приложение в другую папку, за исключением не нужных файлов, чтобы не портить папку с исходными кодами). При помощи NAnt это можно сделать командой COPY:
<copy todir="${destination.dir}">
<fileset basedir="${app.dir}">
<include name="**\*"/>
<exclude name="**\*.cs" />
<exclude name="**\*.scc"/>
<exclude name="**\*.pdb" />
<exclude name="**\*.csproj" />
<exclude name="**\*.vspscc" />
<exclude name="**\PageList.xml*" />
<exclude name="**\*.csproj.user" />
</fileset>
</copy>
С одной стороны, этот способ менее удобен, чем WebDeploymentProject, с другой стороны, здесь мы имеет больший контроль. В общем, Вам решать, что лучше подходит.
Продолжение следует..?