Pregunta

He estado investigando las nuevas funciones 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 implementar en múltiples 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 construye, ejecuta mis pruebas y luego se implementa en uno de mis servidores de prueba (que tiene el MSDePloyAgentService ejecutándose). Funciona bien, y cada proyecto web se implementa según lo configurado en su archivo de proyecto. Los argumentos 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: implementiisapppath = "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? Como algo como un segundo /p: msdeployserviceUrl argumento que especifica otro servidor?

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

Vi una pregunta casi exacta aquí publicada hace 2 meses: TFS 2010: desplegue en múltiples 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 muchas vistas, pero de nuevo, no hay respuestas.

¿Fue útil?

Solución

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

Primero cree una variable con nombre ProjectName. Luego agregue una actividad de asignación a la secuencia "Compilar el proyecto". Esto se encuentra en la secuencia "Intente compilar el proyecto". Aquí están las propiedades de la asignación:

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

Estas son las propiedades de nuestra actividad de InvokeProcess que implementa 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 comando a continuación desde su carpeta de compilación:

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

Otros consejos

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, al mismo tiempo que me mantengo en línea con el ya proporcionado MSBuildArguments Método que ha sido promovido mucho. Así que creé una nueva plantilla de construcción y agregué un nuevo argumento de flujo de trabajo TFS llamado MSBuildArguments2 En la pestaña Argumentos del flujo de trabajo.

alt text

Busqué a través del flujo de trabajo BuiltTemplate para todas las ocurrencias de la MSBuildArguments (Hubo dos ocurrencias).

Las dos tareas que usan MSBuildArguments son llamados Run MSBuild for Project. Directamente debajo de esta tarea, agregué un nuevo bloque "if" con la condición:

Not String.IsNullOrEmpty(MSBuildArguments2)

Luego copié la tarea "Ejecutar MSBuild para Project" y la pegué en el nuevo bloque "Entonces" de IF, actualizando su título en consecuencia. También deberá actualizar la propiedad ConmMandlinearGuments de la nueva tarea para usar su nuevo argumento.

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

Después de estas modificaciones, el flujo de trabajo se ve así:

alt text

Guarde y consulte el nuevo flujo de trabajo. 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 Misc con el nuevo argumento listo para ser utilizado. Debido a que simplemente estoy usando este nuevo argumento para la implementación, copié exactamente los mismos argumentos para los que usé MSBuild Arguments y actualizó MSDePloyServiceUrl a mi segundo servidor de implementación.

alt text

Y eso es eso. Supongo que un método más elegante sería convertir MSBuildarGuments en una variedad de cadenas y luego recorrerlos durante el proceso de flujo de trabajo. Pero esto se adapta a nuestros 2 requisitos del servidor.

¡Espero que esto ayude!

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 la inclusión sea condicional en una propiedad de "dodeployment" de conjunto externo. Además, cada proyecto define la propiedad DeploymentServerGroup para que los servidores de destino se filtren correctamente dependiendo del tipo de proyecto que sea.

Como puede ver hacia la parte inferior, simplemente estoy ejecutando el archivo de comando 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>

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 MSBuild -Shyc posterior al procesamiento. Ese parece ser el más elegante, pero aún esperaba encontrar algo un poco menos intrusivo.

No estoy seguro de si eso podría ayudarte con TFS 2010, pero tengo una publicación de blog para TFS 2012: Implementación de proyectos web múltiples desde TFS 2012 a NLB habilitado para el entorno.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top