7

Estamos tratando de automatizar el proceso de compilación a nuestros servidores de almacenamiento intermedio, pero hemos encontrado un inconveniente, aunque bastante menor. Estamos utilizando la funcionalidad de publicación integrada en VS2010, comprometiéndonos con Subversion, y luego una aplicación de terceros (Beanstalk) automáticamente extrae los archivos actualizados y los transfiere al servidor de etapas.ASP.NET Web Application (MVC) Deployment Automation and Subversion

El problema al que nos hemos topado es que sólo parecen tener las siguientes opciones:

  • (menor de los males 2) Si elegimos usar "Reemplazar los archivos que coinciden con las copias locales", esto funciona genial, con una excepción: esta opción no elimina ningún archivo que se haya eliminado del proyecto. Esto generará problemas de seguridad y/o basura para los archivos descuidados de los viejos tiempos.
  • Si elegimos utilizar "Eliminar todos los archivos existentes antes de publicar", esto borra toda la estructura de carpetas, incluidas las carpetas ocultas .SVN que Subversion usa para el seguimiento de actualizaciones, etc. Esta parece la mejor solución desde el punto de vista de la precisión , pero realmente destruye el entorno SVN local, que es el intermediario para esta automatización.

Mi pregunta: ¿Existe una solución fácil para esto, o una opción de implementación totalmente diferente que estamos pasando por alto (no queremos publicar directamente en el servidor de VS, ya que queremos rastrear quién/qué/cuando ocurre una implementación)? Lo único que me he encontrado es eliminar el contenido del archivo manualmente antes de la publicación, dejando intacta la estructura de la carpeta y luego implementarla con "Reemplazar los archivos que coincidan con las copias locales". Desafortunadamente, esto trae un significado totalmente nuevo de la palabra "automatización".

¿Alguna idea sobre la mejor manera de lograr esto?

+1

Justo a tiempo. También estoy buscando una solución. ¿Has intentado jugar con configuraciones de soluciones y eventos postconstruidos? –

+0

No, en absoluto, hasta ahora todas las implementaciones han sido manuales, lo que puede requerir bastante trabajo con un gran conjunto de cambios. Simplemente no puedo creer que no haya una mejor opción integrada que le proporcione una compilación precisa sin destruir las carpetas. – Keith

Respuesta

4

Es posible que desee considerar el uso de NAnt o algo similar para las tareas que desea automatizar, como crear y publicar en Subversion. Esta es la mayor parte de mi archivo de compilación para un proyecto de aplicación web. Puede ser diferente para MVC. Si es así, estoy seguro de que puedes usar esto como punto de partida. De ninguna manera soy un experto en NAnt, por lo que puede haber algunos defectos, pero esto definitivamente está funcionando para mí.

Tuve que agregar un objetivo PublishToFileSystem a cada archivo .csproj que quería publicar. La fuente de eso puede be found here.

Build file also available on 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

Parece prometedor, tendré que investigar esto cuando tenga oportunidad. Gracias. – Keith

+0

Comenzar con NAnt y otras herramientas de automatización puede llevar mucho tiempo, pero al final vale la pena. Déjame saber cómo te funciona o si tienes otras preguntas. –

+0

+1 nice answer @Alex ¿por qué tenerlo dentro de la carpeta fuente en lugar de una ubicación separada en svn? lo descargaría cuando alguien hace una actualización de svn y, además, tiene la configuración compartida para cualquier persona que tenga acceso a la fuente @Keith ¿la usó, cómo se ha ido, alguna diferencia con la que terminó? – eglasius

0

También implementamos desde SVN y encontramos el mismo problema. Nuestra solución es esencialmente ramificar el proyecto para actualizaciones "significativas", situaciones en las que estábamos agregando y eliminando archivos, no solo solucionando pequeños errores y realizando ajustes que generalmente se pueden manejar con xcopy. SVN diseño se parece a:

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

Procedimiento-sabia, es bastante simple - si hay cambios lo suficientemente grande, comprobar en artefactos de construcción según el caso.

Otra cosa que quizás quieras probar, especialmente si no puedes obtener tus bits de producción para "cambiar" las ramas fácilmente, sería usar algo más elegante como powershell para ejecutar el comando eliminar archivos, que podría filtrar el *. carpetas svn.

+1

El problema con una sucursal es que agrega un paso manual a un proceso que nos gustaría hacer completamente automático. Gracias por la entrada, pero definitivamente esta no es la dirección que estamos buscando; preferiríamos eliminar manualmente los archivos por ahora hasta que podamos encontrar algo más agradable. – Keith

+0

Hrm, teniendo en cuenta que usted y sus otras respuestas es posible que desee probar algo que rastree automáticamente los cambios en lugar de confiar en algo que deje de lado las pistas en todas partes. Mercurial viene a la mente. –

0

Yo diría que "afortunadamente" esto le da un significado completamente nuevo a la palabra automatización :) Lo que usted describe es lo que conoce como Automatización de la versión de la aplicación, también llamada a veces Automatización de la implementación. Si realmente quiere saber quién hizo qué y dónde, cuál fue el resultado, etc., entonces está buscando un producto como NOLIO ASAP (http://www.noliosoft.com). Por favor, avíseme si esto ayuda, ya que por lo que está describiendo, parece una combinación perfecta.

+ Daniel

+1

No es exactamente lo que estamos buscando, ya que no parece integrarse con Subversion (al menos no lo menciona directamente). Sin embargo, parece un producto muy agradable, pero ya tenemos una solución de implementación completa, con el problema menor descrito anteriormente. – Keith

0

¿Por qué publicar el sitio en una carpeta que está a cargo de la subversión?

La forma en que lo haría es trabajar directamente con los archivos en las carpetas manejadas SVN. Tan pronto como cometo algo, se tira de las habichuelas mágicas al área de preparación. De esta forma, los archivos eliminados siempre se eliminan del repositorio y no tiene que preocuparse por eso. Todo está siempre sincronizado.

Si cree que esto está colocando demasiados archivos en el área de preparación, aún puede usar scripts y comandos de Visual Studio para publicar el sitio. Pero no estoy seguro de qué tan bien Beanstalk se integra con este escenario. Sé que CC.net y muchas otras alternativas sí.

+1

En primer lugar, utilizamos nuestro servidor de etapas para "escenificar" lo que realmente se implementará en producción, que es código PRECOMPUESTO ... En segundo lugar, utilizamos las transformaciones de configuración para administrar cadenas de conexión y configuraciones de aplicaciones que varían según los diferentes entornos. Tener Beanstalk extraer la versión actual de web.config directamente desde SVN no va a funcionar. – Keith