Автоматизация сборки web-приложения на платформе .NET

    NAnt logo
    Добрый день!

    Я попробовал описать здесь свой опыт автоматизации сборки приложений .NET (в основном, речь идет о web-приложениях).

    Т.к. получилось много букв пришлось разбить статью две на части. Сейчас выкладываю первую часть, если это будет нужно кому-то, выложу остальное. Не пинайте сильно.



    Предположим, имеются следующие задачи


    1. 1. Необходимо из исходных кодов, находящихся в системе контроля версий, собрать веб-приложение, настроить его определенным образом и выложить на сервер (а также обновить структуру БД, с которой работает приложение. Например, такая задача может возникнуть во время разработки, когда нужно выложить текущую версию для тестировщиков.
    2. 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, с другой стороны, здесь мы имеет больший контроль. В общем, Вам решать, что лучше подходит.

    Продолжение следует..?
    Поделиться публикацией

    Комментарии 28

      +2
      что скажете по поводу того, что nant скорее мертв, чем жив и что не обновлялся уже несколько лет? вообще после создания своего CI и пляски с msbuild'ом, nant'ом у меня возникло стойкое отвращение к описанию build процесса в xml'е при отсутствии визуальных средств.
      сейчас прикрутил psake — рад нещадно github.com/JamesKovacs/psake
        +1
        > при отсутствии визуальных средств
        вот сюда гляньте: www.attrice.info/msbuild/index.htm
          0
          спасибо, но это за деньги. да косяков у msbuild'а хватает, чего стоит, что properties исполняются с include=* на момент парсинга конфига, а не в момент использования — от чего вылезают очень интересные косяки, если вам, например, надо что то сделать с файлами после build'а посредством properties. в баню этот msbuild — я за скриптовой build скрипт.
          0
          nant в этом году ожил.
          не могу сейчас посмотреть точно (пишу комментарий с телефона) но вроде как последняя версия 0.91alpha была в июне этого года.
          +1
          Следует!
            +3
            Мы щас пытаемся уйти с nant, на чистый msbuild. Отличия минимальны, а вот расхаоды на интеграцию какието ненормальные. Чего тока стоит эпопея с потдержкой .NET 4.0. Хотя надо отдать должность, Win SDK в отличии от нанта в реопзитарий не положиш.
              0
              Кстати, для второго пункта есть еще третяя опция (ИМХО правильная). Это Microsoft.WebApplication.targets и Microsoft.Web.Publishing.targets. Там уже все есть для паблишенга. Правда слету разобратся сложновато.
                0
                я особо не разбирался с ними, но вроде WDP как раз их и использует
                0
                Публикуйте вторую часть. Думаю, многим будет интересно.
                  0
                  полюбому надо вторую статью, ато как то не полно получилось

                  у нас все на чистом msbuild но геморно добавлять новые проекты

                  так же интересно (хотя это уже не совсем в тему) как быть с базой и с откатами
                    0
                    MSBuild.Community.Tasks
                    MSBuild.ExtensionPack
                    спасут вас:) там много вкусного
                      +1
                      Откаты это прибыльно.
                      +1
                      Используем для тех же целей MSBuild. Хотя от XML в конфигурациях просто тошнит — особенно противно от WiX. Надо что-то с этим делать, чтобы был intellisense и все плюшки не только для конфига но и для файлов настройки. p.s.: xsd для intellisense не предлагать — знаю, пользуюсь, плююсь.
                        0
                        Я понимаю, что на определеном этапе развития .NET было оправдано адаптировать технологии из Java — тот же NAnt, NHibernate и т.д.
                        Но сейчас-то появляются продукты, разработанные именно для .net и без Java'вских косяков, тот же MSBuild, Linq2SQL и т.д.

                        В чем же прикол до сих пор использовать в новых продуктах устаревшие фреймворки?
                          0
                          Насколько я знаю, разработка Linq2SQL прекращена, в отличие от NHibernate.
                          На счет MSBuild — по возможностям он практически повторяет NAnt.

                          Можете привести конкретные причины, по которым Вы считаете NAnt и NHibernate «устаревшими фреймворками» (а также интересуют примеры «Java'вских косяков»)?
                            0
                            На смену Linq2SQL пришел Linq2Entities с еще более широкими возможностями. К слову сказать я в своих проектах до сих пор использую Linq2SQL, поскольку его возможностей, быстродействия и удобства мне вполне хватает. Ну а если требуется что-то экстра-ординарное, то хранимые процедуры ни один фреймворк не перебьет. Так что явных бонусов перехода на Linq2Entities я для себя не вижу, хотя за развитием слежу, чтобы не оказаться за бортом.

                            Так вот, с Linq2SQL я работаю напрямую из Visual Studio, в графическом радакторе. NHibernate — как обычно в Java-world, засучил рукава и вперед — лопатить xml в редакторе в обнимку с доками, потому как очень легко облажаться в синтаксисе.

                            Реально это и есть самый главный косяк переноса из Java в .net — большая любовь все законфигурить через xml, не предоставляя инструментов как это удобно сделать из Visual Studio.

                            С NAnt я знаком чисто из любопытства, на работе у нас MS Build. Чисто из интереса — есть ли какая-то причина чтобы я выбрал NAnt вместо MS native MS Build?
                              0
                              Несомненно Linq2SQL и Linq2Entities (наверно, Вы все-таки имели в виду Entity Framework) отличные средства для работы с данными.

                              К сожалению, это все же относительно новые и незрелые инструменты, по сравнению с NHibernate. В т.ч. они содержат некоторые проблемы, которые в NH уже давно решены. Например, даже последний EF 4 не поддерживает пакетную запись/чтение данных.
                              Кроме того, в EF значительно сложнее сделать что-то, что выходит за пределы возможностей, предоставляемых фреймворком. NHibernate же в большинстве случаев легко расширяется.

                              Для NHibernate существует большое количество различных утилит, облегчающих настройку мэппинга (в т.ч. и с GUI), так что, можно сказать, «самый главный косяк переноса из Java в .NET» отсутствует. (А если честно, то никакие утилиты и не нужны. Настройка мэппинга в XML только кажется страшной — на самом деле, там все просто.)

                              Более того, (я вижу, что Вам нравится использовать LINQ) для NHibernate реализован LINQ-провайдер (правда, стоит признать, что реализован не так хорошо, как для Entity Framework).

                              — Я пишу все это не для того, чтобы сказать «NHibernate лучше, чем Entity Framework». Я думаю, что оба этих продукта прекрасно выполняют свои функции и выбор, какой продукт использовать, зависит от конкретной задачи и от предпочтений конкретного разработчика. Просто попробовал обратить Ваше внимание на достоинства NHibernate.
                                0
                                >Linq2Entities (наверно, Вы все-таки имели в виду Entity Framework)
                                Да, разумеется — где-то подхватил ангину, голова плохо соображает.

                                Конечно, каждому фреймворку — свое место, нужно смотреть на конкретную задачу.
                                0
                                На счет MsBuild vs NAnt — на мой взгляд, нет объективных причин для выбора одного из них.
                                Эти инструменты содержат практически одинаковый набор возможностей и одинаковые неудобства.

                                Лично мне субъективно нравится NAnt и его конфиги мне легче понять.

                                Если Вы — сторонник MsBuild — то могу сказать, что Вы также выбрали отличный инструмент для автоматизации сборки приложений.
                                  0
                                  главный косяк переноса из java в .net чудесным образом затронул unity application block — там, стыдно признаться, тоже можно и нужно конфигурить контейнер через xml…
                                  0
                                  «Насколько я знаю, разработка Linq2SQL прекращена»
                                  Откуда дровишки?
                                    0
                                    http://ayende.com/Blog/archive/2008/10/31/microsoft-kills-linq-to-sql.aspx

                                    http://blogs.msdn.com/b/adonet/archive/2008/10/29/update-on-linq-to-sql-and-linq-to-entities-roadmap.aspx

                                    Если честно, подробности не узнавал. Есть вероятность, что я что-то не так понял.
                                      0
                                      Да, не так поняли. По второй ссылке написано: «We are listening to customers regarding LINQ to SQL and will continue to evolve the product based on feedback we receive from the community as well.» Т.е., «мы будем продолжать развивать продукт, основываясь на».

                                      А дальше все зависит от степени паникерства читающего.

                                        0
                                        Рад, что неверно понял.
                                        Хоть я никогда и не использовал l2s в реальных проектах, я очень рад, что он жив :)
                                        Уверен, что есть люди, которым он нужен.
                                0
                                не могу найти вторую часть. она была?
                                  0
                                  Добрый вечер!

                                  Вторая часть в черновиках уже несколько лет. Она готова на 90%, но мне она не нравится и я не хотел бы ее выкладывать. Если хотите, могу ее прислать.

                                  На мой взгляд, для автоматизации достаточно знать основы, описанные здесь, а все остальное — это связано с особенностями конкретных задач и легко ищется в гугле. Собственно, во второй части у меня получилось объемное описание этих особенностей, от которых без реальных задач мало пользы.
                                    0
                                    >>Если хотите, могу ее прислать.

                                    NAnt — очень актуальная сейчас для меня тема. Я был бы невероятно признателен, если бы Вы прислали или опубликовали вторую часть статьи (эта написана очень доступно и вдруг многое для меня прояснила). Таже, возможно, у Вас есть подборка ссылок с хорошими статьями про NAnt?
                                      0
                                      Вторая часть здесь, но это на другую тему, чем планировалось изначально.
                                      Черновик первого варианта: http://sdrv.ms/1fefUNn.

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

                                Самое читаемое