ASP.NET Web Application (MVC) Автоматизация развертывания и Subversion - PullRequest
7 голосов
/ 29 декабря 2010

Мы пытаемся автоматизировать процесс сборки для наших промежуточных серверов, но столкнулись с проблемой, хотя и незначительной. Мы используем функцию публикации, встроенную в VS2010, фиксируем в Subversion, а затем стороннее приложение (Beanstalk) автоматически извлекает обновленные файлы и передает их по FTP на промежуточный сервер.

Проблема, с которой мы столкнулись, заключается в том, что у нас есть только следующие варианты:

  • (Меньшее из 2 зол) Если мы решим использовать «Заменить совпадающие файлы локальными копиями», это прекрасно работает, за одним исключением: эта опция не удаляет файлы, которые были удалены из проекта. Это приведет к появлению нежелательных и / или проблем с безопасностью для неопрятных файлов прежних времен.
  • Если мы решим использовать «Удалить все существующие файлы перед публикацией», это удалит всю структуру папок, включая скрытые папки .SVN, которые Subversion использует для отслеживания обновлений и т. Д. Это кажется лучшим решением с точки зрения точности. , но это действительно разрушает локальную среду SVN, которая является посредником в этой автоматизации.

Мой вопрос: есть ли простой способ обойти это или совершенно другой вариант развертывания, который мы пропускаем (мы не хотим публиковать напрямую на сервер из VS, так как мы хотим отслеживать, кто / что / когда развертывание происходит)? Единственное, с чем я столкнулся, это вручную удалить содержимое файла перед публикацией, оставив структуру папки без изменений, а затем развернув ее с помощью команды «Заменить соответствующие файлы локальными копиями». К сожалению, это приводит к совершенно новому значению слова «автоматизация».

Есть идеи, как лучше всего это сделать?

Ответы [ 4 ]

4 голосов
/ 11 января 2011

Возможно, вы захотите использовать NAnt или что-то подобное для задач, которые вы хотите автоматизировать, таких как создание и публикация в Subversion.Это большая часть моего файла сборки для проекта WebApplication.Это может быть иначе для MVC.Если так, я уверен, что вы можете использовать это в качестве отправной точки.Я ни в коем случае не эксперт NAnt, поэтому могут быть некоторые недостатки, но это определенно работает для меня.

Мне пришлось добавить цель PublishToFileSystem в каждый файл .csproj, который я хотел опубликовать.Источник для этого можно найти здесь .

Файл сборки также доступен на Pastebin

<?xml version="1.0"?>
<project name="deploy" default="all">
    <property name="nant.settings.currentframework" value="net-4.0" />  
    <!-- Any of these can be passed through the command line -->
    <property name="sourceDirectory" value="${project::get-base-directory()}" />
    <property name="publishDirectory" value="${sourceDirectory}\build" />
    <property name="MSBuildPath" value="${framework::get-assembly-directory(framework::get-target-framework())}\msbuild.exe" />
    <!-- The build configuration to use when publishing and transforming the web.config file. This is useful when you have multiple environments for which you create builds -->
    <property name="buildConfiguration" value="Release" /> 
    <!-- Set these as needed -->
    <property name="svn.username" value="" />
    <property name="svn.password" value="" />

    <target name="SvnPrep">
        <property name="svn.dir" value="${publishDirectory}\.svn" />
        <property name="svn.update" value="true" readonly="false" />
        <echo>env.svn.path = svn</echo>
        <echo>svn.dir = ${svn.dir}</echo>
        <mkdir dir="${publishDirectory}" unless="${directory::exists(publishDirectory)}" />
        <!-- Check if there's a .svn dir already. If not: checkout, else: update. -->
        <if test="${not directory::exists(svn.dir)}">
            <exec program='svn.exe' workingdir="${publishDirectory}" verbose="true">
                <arg line='co ${svn.builduri} --username ${svn.username} --password ${svn.password} --non-interactive ./' />
            </exec>
            <property name="svn.update" value="false" readonly="false" />
        </if>
        <if test="${svn.update}">
            <exec program='svn.exe' workingdir="${publishDirectory}\" verbose="true">
                <arg line='up --username ${svn.username} --password ${svn.password} --non-interactive --force ./' />
            </exec>
        </if>
        <!-- Force any conflicts to be resolved with the most recent code -->
        <exec program='svn.exe' workingdir="${publishDirectory}\" verbose="true">
            <arg line='resolve --accept theirs-full -R ./' />
        </exec>
    </target>   

    <target name="DeleteFiles">
        <!-- Delete only the files (retain directory structure) in the directory to which you are going to publish/build. NAnt excludes svn directories by default. -->
        <delete includeemptydirs="false">
            <fileset basedir="${publishDirectory}">
                <include name="**/*.*" /> 
            </fileset>
        </delete>
    </target>
    <target name="Publish">
        <!-- I know there's an MSBuild task, I don't know why I didn't use it, but this works. -->
        <!-- Build and publish frontend -->
        <exec program="${MSBuildPath}">
            <arg line='"${sourceDirectory}\YourProject.csproj"' />
            <arg value='"/p:Platform=AnyCPU;Configuration=${buildConfiguration};PublishDestination=${publishDirectory}"' />
            <arg value="/target:PublishToFileSystem" />
        </exec>
        <!-- Transform the correct web.config and copy it to the build folder. PublishToFileSystem doesn't transform the web.config, unfortunately. -->
        <exec program="${MSBuildPath}">
            <arg line='"${sourceDirectory}\YourProject.csproj"' />
            <arg value='"/p:Platform=AnyCPU;Configuration=${buildConfiguration};PublishDestination=${publishDirectory}"' />
            <arg value="/target:TransformWebConfig" />
        </exec>
        <copy file="${sourceDirectory}\YourProject\obj\${buildConfiguration}\TransformWebConfig\transformed\Web.config" tofile="${publishDirectory}\YourProject\web.config" overwrite="true" />     
    </target>

    <target name="SvnCommit">       
        <!-- add any new files -->
        <exec program='svn.exe' workingdir="${publishDirectory}" verbose="true">
            <arg line='add --force .' />
        </exec>
        <!-- delete any missing files, a modification of this http://stackoverflow.com/questions/1071857/how-do-i-svn-add-all-unversioned-files-to-svn -->
        <!-- When there's nothing to delete it looks like this fails (to NAnt) but it is actually fine, that's why failonerror is false -->     
        <exec program='cmd.exe' workingdir="${publishDirectory}\" verbose="true" failonerror="false" 
            commandline='/C for /f "usebackq tokens=2*" %i in (`svn status ^| findstr /r "^\!"`) do svn del "%i %j"' >
        </exec>
        <exec program='svn.exe' workingdir="${publishDirectory}" verbose="true">
            <arg line='commit -m "Automated commit from build runner"' />
        </exec>
    </target>

    <target name="ShowProperties">
        <script language="C#" prefix="util" >
            <code>
                <![CDATA[
                public static void ScriptMain(Project project) 
                {
                    foreach (DictionaryEntry entry in project.Properties)
                    {
                        Console.WriteLine("{0}={1}", entry.Key, entry.Value);
                    }
                }
                ]]>
            </code>
        </script>
    </target>

    <target name="all">
        <call target="ShowProperties" />
        <call target="SvnPrep" />
        <call target="DeleteFiles" />
        <call target="Publish" />
        <call target="SvnCommit" />
    </target>
</project>
0 голосов
/ 04 января 2011

Я бы сказал «к счастью», это привносит совершенно новое значение в слово «автоматизация» :) То, что вы описываете, известно как «Автоматизация выпуска приложений», также иногда называемая «Автоматизация развертывания». Если вы действительно хотите знать, кто что сделал и где, каков был результат и т. Д., То вы ищете такой продукт, как Nolio ASAP (http://www.noliosoft.com). Пожалуйста, дайте мне знать, если это поможет, поскольку из того, что вы описываете, это кажется идеальной парой.

+ Daniel

0 голосов
/ 05 января 2011

Почему вы публикуете сайт в папке, которая обрабатывается Subversion?

Я бы сделал это непосредственно с файлами в папках, обработанных SVN.Как только я что-то совершаю, бобовый стебель вытаскивает его в зону подготовки.Таким образом, удаленные файлы всегда удаляются из репозитория, и вам не нужно об этом беспокоиться.Все всегда синхронизировано.

Если вы чувствуете, что в область подготовки слишком много файлов, вы все равно можете использовать сценарии и команды Visual Studio для публикации сайта.Но я не уверен, насколько хорошо Beanstalk интегрируется с этим сценарием.Я знаю CC.net и многие другие альтернативы.

0 голосов
/ 02 января 2011

Мы также развернули из SVN и столкнулись с той же проблемой. Наше решение состоит в том, чтобы по существу ветвить проект для «значительных» обновлений - ситуаций, в которых мы добавляли и удаляли файлы, а не просто исправляли небольшие ошибки и вносили изменения, которые обычно можно обработать с помощью xcopy. Svn макет выглядит так:

--project
---production
----20100101
----20100213
[etc, etc]

Процедура довольно проста - если есть достаточно большие изменения, проверьте соответствующие артефакты сборки.

Еще одна вещь, которую вы, возможно, захотите попробовать, особенно если вы не можете заставить свои рабочие биты легко «переключать» ветви, - это использовать что-то более изощренное, например powershell, для выполнения команды удаления файлов, которая могла бы отфильтровать * .svn папки.

...