7 Stimmen

Automatisierung der Bereitstellung von ASP.NET-Webanwendungen (MVC) und Subversion

Wir versuchen, den Build-Prozess auf unseren Staging-Servern zu automatisieren, sind aber auf ein Problem gestoßen, wenn auch ein ziemlich kleines. Wir verwenden die in VS2010 integrierte Veröffentlichungsfunktionalität, die in Subversion übertragen wird, und dann zieht eine Drittanbieter-App (Beanstalk) automatisch die aktualisierten Dateien und überträgt sie per FTP auf den Staging-Server.

Das Problem, auf das wir gestoßen sind, ist, dass wir nur die folgenden Möglichkeiten zu haben scheinen:

  • (Das kleinere von 2 Übeln) Wenn wir uns für die Option "Ersetze passende Dateien durch lokale Kopien" entscheiden, funktioniert dies hervorragend, mit einer Ausnahme: Diese Option löscht keine Dateien, die aus dem Projekt gelöscht wurden. Dies führt zu Junk- und/oder Sicherheitsproblemen bei ungepflegten Dateien aus alten Tagen.
  • Wenn wir die Option "Alle vorhandenen Dateien vor der Veröffentlichung löschen" wählen, wird die gesamte Ordnerstruktur gelöscht, einschließlich der versteckten SVN-Ordner, die Subversion für die Aktualisierungsverfolgung usw. verwendet. Dies scheint vom Standpunkt der Genauigkeit die beste Lösung zu sein, aber es zerstört die lokale SVN-Umgebung, die der Mittler für diese Automatisierung ist.

Meine Frage: Gibt es eine einfache Lösung für dieses Problem oder eine völlig andere Bereitstellungsoption, die wir übersehen (wir möchten nicht direkt von VS auf dem Server veröffentlichen, da wir nachverfolgen möchten, wer/was/wann eine Bereitstellung stattfindet)? Das Einzige, was ich gefunden habe, ist das manuelle Löschen des Dateiinhalts vor der Veröffentlichung, wobei die Ordnerstruktur intakt bleibt, und dann die Bereitstellung mit "Ersetze passende Dateien durch lokale Kopien". Leider bekommt dadurch das Wort "Automatisierung" eine ganz neue Bedeutung.

Haben Sie eine Idee, wie Sie das am besten bewerkstelligen können?

4voto

Alexander Pendleton Punkte 215

Für Aufgaben, die Sie automatisieren möchten, wie z.B. das Erstellen und Veröffentlichen in Subversion, können Sie NAnt oder etwas Ähnliches verwenden. Dies ist der größte Teil meiner Build-Datei für ein WebApplication-Projekt. Für MVC könnte es anders sein. Wenn ja, bin ich sicher, Sie können dies als Ausgangspunkt verwenden. Ich bin keineswegs ein NAnt-Experte, so dass es einige Fehler sein kann, aber dies ist definitiv für mich arbeiten.

Ich musste zu jeder .csproj-Datei, die ich veröffentlichen wollte, ein PublishToFileSystem-Ziel hinzufügen. Die Quelle dafür kann finden Sie hier .

Build-Datei auch auf Pastebin verfügbar

<?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>

0voto

Wyatt Barnett Punkte 15500

Wir stellen auch aus SVN heraus bereit und stießen auf das gleiche Problem. Unsere Lösung besteht darin, das Projekt im Wesentlichen für "signifikante" Upgrades zu verzweigen - Situationen, in denen wir Dateien hinzufügen und löschen und nicht nur kleine Fehler beheben und Optimierungen vornehmen, die man normalerweise mit xcopy erledigen kann. Das Svn-Layout sieht so aus:

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

Vom Verfahren her ist es ziemlich einfach - wenn die Änderungen groß genug sind, werden die Build-Artefakte entsprechend eingecheckt.

Eine andere Sache, die Sie ausprobieren könnten, insbesondere wenn Sie Ihre Produktionsbits nicht dazu bringen können, Zweige einfach zu wechseln, wäre, etwas Ausgefalleneres wie Powershell zu verwenden, um den Befehl delete files auszuführen, der die *.svn-Ordner herausfiltern könnte.

0voto

Daniel Kushner Punkte 191

Ich würde sagen, "zum Glück" gibt das dem Wort Automatisierung eine ganz neue Bedeutung :) Was Sie beschreiben, nennt man Application Release Automation, manchmal auch Deployment Automation genannt. Wenn Sie wirklich wissen wollen, wer was und wo getan hat, was das Ergebnis war usw., dann suchen Sie nach einem Produkt wie Nolio ASAP (http://www.noliosoft.com). Bitte lassen Sie mich wissen, ob dies hilfreich ist, denn nach dem, was Sie beschreiben, scheint es eine perfekte Ergänzung zu sein.

+Daniel

0voto

Peter Evjan Punkte 2413

Warum veröffentlichen Sie die Website in einem Ordner, der von Subversion verwaltet wird?

Ich würde es so machen, dass ich direkt mit den Dateien in den SVN-Ordnern arbeite. Sobald ich etwas übertrage, wird es von Beanstalk in den Staging-Bereich gezogen. Auf diese Weise werden gelöschte Dateien immer auch aus dem Projektarchiv gelöscht, und man muss sich nicht darum kümmern. Alles ist immer synchronisiert.

Wenn Sie das Gefühl haben, dass dadurch zu viele Dateien in den Staging-Bereich gelangen, können Sie immer noch Skripte und Visual Studio-Befehle verwenden, um die Site zu veröffentlichen. Ich bin mir jedoch nicht sicher, wie gut sich Beanstalk in dieses Szenario integrieren lässt. Ich weiß, dass CC.net und viele andere Alternativen dies tun.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X