ASP.NET Web应用程序(MVC)部署自动化和Subversion

我们正在尝试将构建过程自动化到我们的临时服务器,但遇到了一些障碍,虽然很小。 我们使用VS2010中内置的发布功能,提交给Subversion,然后第三方应用程序(Beanstalk)自动将更新后的文件和FTP发送到登台服务器。

我们遇到的问题是我们似乎只有以下选择:

  • (2个恶意中的较小者)如果我们选择使用“用本地副本替换匹配的文件”,这很好,但有一个例外:此选项不会删除从项目中删除的任何文件。 这将导致垃圾和/或安全问题从旧的蓬乱文件。
  • 如果我们选择使用“在发布之前删除所有现有文件”,这将删除整个文件夹结构,包括Subversion用于更新跟踪的.SVN隐藏文件夹等。从精度角度看,这似乎是最佳解决方案,但它真正摧毁了本地SVN环境,这是该自动化的中间人。
  • 我的问题:是否有一个简单的解决方法,或者我们忽略了一个完全不同的部署选项(我们不希望直接从VS发布到服务器,因为我们想要跟踪部署发生的时间和地点)? 我遇到的唯一情况是在发布之前手动删除文件内容,同时保持文件夹结构不变,然后使用“用本地副本替换匹配的文件”进行部署。 不幸的是,这带来了“自动化”这个词的全新含义。

    关于如何最好地完成这一任何想法?


    你可能想考虑使用NAnt或类似的方法来完成你想自动化的任务,比如构建和发布到Subversion。 这是我的WebApplication Project的大部分构建文件。 MVC可能会有所不同。 如果是这样,我相信你可以用它作为出发点。 我绝不是NAnt专家,所以可能会有一些缺陷,但这绝对是为我工作的。

    我不得不为每个我想发布的.csproj文件添加PublishToFileSystem目标。 这个来源可以在这里找到。

    构建文件也可用于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}YourProjectobj${buildConfiguration}TransformWebConfigtransformedWeb.config" tofile="${publishDirectory}YourProjectweb.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>
    

    我们还部署了SVN,并遇到了同样的问题。 我们的解决方案是基本上为“重大”升级项目进行分支 - 我们正在添加和删除文件的情况,而不仅仅是修复小问题并进行调整,您可以通过xcopy进行调整。 Svn布局看起来像:

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

    从过程角度来看,这非常简单 - 如果有足够大的更改,请根据需要签入构建工件。

    另一件你可能想要尝试的事情,特别是如果你不能让你的生产位很容易地“切换”分支,将会使用诸如powershell之类的fancier来执行删除文件命令,这可能会过滤出* .svn文件夹。


    我会说,“幸运的是”这给自动化这个词带来了全新的含义:)你所描述的是应用发布自动化,有时也称为部署自动化。 如果你真的想知道谁做了什么,在哪里,结果如何,那么你正在寻找像Nolio ASAP(http://www.noliosoft.com)这样的产品。 请让我知道,如果这有帮助,因为从你所描述的,它似乎是一个完美的匹配。

    +丹尼尔

    链接地址: http://www.djcxy.com/p/49541.html

    上一篇: ASP.NET Web Application (MVC) Deployment Automation and Subversion

    下一篇: FIle upload from a rest client to a rest server