deployment msbuild tfs2010 msdeploy build-definition

deployment - ¿Definición de compilación TFS2010 para implementar en varios servidores?



msbuild msdeploy (5)

Estuve investigando las nuevas características de compilación e implementación de TFS2010 con MSDeploy. Hasta ahora todo va bien (aunque ha sido difícil encontrar información sobre escenarios específicos).

¿Puedo modificar mi definición de compilación para especificar 2 o más servidores para implementar? Lo que necesito hacer es implementarlo en varios servidores (ya que tengo dos en mi entorno de prueba que usa un NLB).

Lo que tengo ahora es una definición de compilación que compila, ejecuta mis pruebas y luego se implementa en UNO de mis servidores de prueba (que tiene el MsDeployAgentService ejecutándose en él). Funciona bien, y cada proyecto web se implementa como configurado en su archivo de proyecto. Los argumentos de MSBuild que uso son:

* /p:DeployOnBuild=True * /p:DeployTarget=MsDeployPublish * /p:MSDeployServiceURL=http://oawww.testserver1.com.au/MsDeployAgentService * /p:CreatePackageOnPublish=True * /p:MsDeployPublishMethod=RemoteAgent * /p:AllowUntrustedCertificated=True * /p:UserName=myusername * /p:Password=mypassword

NB: No uso / p: DeployIISAppPath = "xyz" ya que no implementa todos mis proyectos y anula la configuración de mi proyecto.

¿Puedo agregar otro argumento de compilación para que llame a más de un MSDeployServiceURL? ¿Te gusta algo así como un argumento second / p: MSDeployServiceURL que especifica otro servidor?

¿O tengo que buscar otra solución, como editar el WF?

Vi una pregunta casi idéntica aquí publicada hace 2 meses: TFS 2010: implementar en varios servidores después de la compilación , por lo que no parece que soy el único que intenta resolver esto.

También publiqué en los foros de IIS.NET donde se discute MSDeploy: http://forums.iis.net/t/1170741.aspx . Ha tenido bastantes puntos de vista, pero de nuevo, no hay respuestas.


Soy el autor de la otra publicación similar. Todavía tengo que encontrar una solución. Creo que va a modificar el flujo de trabajo para agregar una tarea de sincronización MSBUILD posterior al procesamiento. Eso parece ser el más elegante, pero aún esperaba encontrar algo menos intrusivo.


No es necesario que construya el proyecto dos veces para implementarlo en dos servidores. El proceso de compilación construirá un conjunto de archivos de implementación. Luego puede usar InvokeProcess para implementar en varios servidores.

Primero crea una variable llamada ProjectName. A continuación, agregue una actividad Asignar a la secuencia "Compilar el proyecto". Esto se encuentra en la secuencia "Intentar compilar el proyecto". Estas son las propiedades de Assign:

To: ProjectName Value: System.IO.Path.GetFileNameWithoutExtension(localProject)

Estas son las propiedades de nuestra actividad InvokeProcess que se implementa en el servidor de prueba:

Arguments: "/y /M:<server> /u:<domain>/<user> /p:<password>" FileName: String.Format("{0}/{1}.deploy.cmd", BuildDetail.DropLocation, ProjectName) You will need to change <server>, <domain>, <user>, and <password> to the values that reflect your environment.

Si necesita implementar manualmente en un servidor, puede ejecutar el siguiente comando desde su carpeta de compilación:

deploy.cmd /y /M:<server> /u:<domain>/<user> /p:<password>


Mi solución a esto es un nuevo objetivo que se ejecuta después del paquete. Cada proyecto que necesita producir un paquete incluye este archivo de objetivos, y elegí hacer que Include sea condicional en una propiedad "DoDeployment" establecida externamente. Además, cada proyecto define la propiedad DeploymentServerGroup para que los servidores de destino se filtren adecuadamente según el tipo de proyecto que sea.

Como puede ver hacia abajo, simplemente estoy ejecutando el archivo de comandos con la lista de servidores, bastante simple.

<!-- This targets file allows a project to deploy its package As it is used by all project typesconditionally included from the project file

->

<UsingTask TaskName="Microsoft.TeamFoundation.Build.Tasks.BuildStep" AssemblyFile="$(TeamBuildRefPath)/Microsoft.TeamFoundation.Build.ProcessComponents.dll" /> <!-- Each Server needs the Group metadatum, either Webservers, Appservers, or Batch. --> <Choose> <When Condition="''$(Configuration)'' == ''DEV''"> <ItemGroup> <Servers Include="DevWebServer"> <Group>Webservers</Group> </Servers> <Servers Include="DevAppServer"> <Group>Appservers</Group> </Servers> </ItemGroup> </When> <When Condition="''$(Configuration)'' == ''QA''"> <ItemGroup> <Servers Include="QAWebServer1"> <Group>Webservers</Group> </Servers> <Servers Include="QAWebServer2"> <Group>Webservers</Group> </Servers> <Servers Include="QAAppServer1"> <Group>Appservers</Group> </Servers> <Servers Include="QAAppServer2"> <Group>Appservers</Group> </Servers> </ItemGroup> </When> </Choose> <!-- DoDeploy can be set in the build defintion --> <Target Name="StartDeployment" AfterTargets="Package"> <PropertyGroup> <!-- The _PublishedWebsites area --> <PackageLocation>$(WebProjectOutputDir)_Package</PackageLocation> <!-- Override for local testing --> <PackageLocation Condition="$(WebProjectOutputDirInsideProject)">$(IntermediateOutputPath)Package/</PackageLocation> </PropertyGroup> <Message Text="Tier servers are @(Servers)" /> <!-- A filtered list of the servers. DeploymentServerGroup is defined in each project that does deployment --> <ItemGroup> <DestinationServers Include="@(Servers)" Condition="''%(Servers.Group)'' == ''$(DeploymentServerGroup)''" /> </ItemGroup> <Message Text="Dest servers are @(DestinationServers)" /> </Target> <!-- Only perform the deployment if any servers fit the filters --> <Target Name="PerformDeployment" AfterTargets="StartDeployment" Condition="''@(DestinationServers)'' != ''''"> <Message Text="Deploying $(AssemblyName) to @(DestinationServers)" /> <!-- Fancy build steps so that they better appear in the build explorer --> <BuildStep TeamFoundationServerUrl="$(TeamFoundationServerUrl)" BuildUri="$(BuildUri)" Message="Deploying $(AssemblyName) to @(DestinationServers)..."> <Output TaskParameter="Id" PropertyName="StepId" /> </BuildStep> <!-- The deployment command will be run for each item in the DestinationServers collection. --> <Exec Command="$(AssemblyName).deploy.cmd /Y /M:%(DestinationServers.Identity)" WorkingDirectory="$(PackageLocation)" /> <BuildStep TeamFoundationServerUrl="$(TeamFoundationServerUrl)" BuildUri="$(BuildUri)" Id="$(StepId)" Status="Succeeded" Message="Deployed $(AssemblyName) to @(DestinationServers)"/> <OnError ExecuteTargets="MarkDeployStepAsFailed" /> </Target> <Target Name="MarkDeployStepAsFailed"> <BuildStep TeamFoundationServerUrl="$(TeamFoundationServerUrl)" BuildUri="$(BuildUri)" Id="$(StepId)" Status="Failed" /> </Target>



No pude encontrar la solución que estaba buscando, pero esto es lo que se me ocurrió al final.

Quería mantener la solución simple y configurable dentro de los argumentos de TFS y al mismo tiempo mantenerme en línea con el método MSBuildArguments ya proporcionado que se ha promocionado mucho. Así que creé una nueva plantilla de compilación y agregué un nuevo argumento TFS WorkFlow llamado MSBuildArguments2 en la pestaña Argumentos de WorkFlow.

Busqué en BuildTemplate WorkFlow todas las ocurrencias de MSBuildArguments (hubo dos ocurrencias).

Las dos tareas que usan MSBuildArguments se llaman Run MSBuild for Project . Justo debajo de esta tarea, agregué un nuevo bloque "Si" con la condición:

Not String.IsNullOrEmpty(MSBuildArguments2)

Luego copié la tarea "Ejecutar MSBuild for Project" y la pegué en el nuevo bloque "If Then" de If, ​​actualizando su título en consecuencia. También necesitará actualizar la nueva propiedad ConmmandLineArguments de la Tarea para usar su nuevo Argumento.

CommandLineArguments = String.Format("/p:SkipInvalidConfigurations=true {0}", MSBuildArguments2)

Después de estas modificaciones, WorkFlow se ve así:

Guarde y controle el nuevo WorkFlow. Actualice su Definición de compilación para usar este nuevo Flujo de trabajo, luego en la pestaña Proceso de la definición de compilación encontrará una nueva sección llamada Varios con el nuevo argumento listo para ser utilizado. Como simplemente estoy usando este nuevo argumento para la implementación, copié exactamente los mismos argumentos que utilicé para MSBuild Arguments y actualicé MSDeployServiceURL a mi segundo servidor de implementación.

Y eso es eso. Supongo que un método más elegante sería convertir MSBuildArguments en una matriz de cadenas y luego recorrerlas durante el proceso de WorkFlow. Pero esto se adapta a nuestros 2 requisitos de servidor.

¡Espero que esto ayude!