代码之家  ›  专栏  ›  技术社区  ›  Arkiliknam

要部署到多个服务器的tfs2010生成定义?

  •  9
  • Arkiliknam  · 技术社区  · 15 年前

    我一直在研究带有msdeploy的TFS2010新的构建和部署功能。到目前为止,一切都进展顺利(尽管很难找到有关特定场景的信息)。

    我可以修改构建定义以指定要部署到的2个或多个服务器吗?我需要做的是部署到多个服务器(因为我在使用NLB的测试环境中有两个服务器)。

    我现在拥有的是一个构建定义,它构建、运行我的测试,然后部署到我的一个测试服务器上(该服务器上运行msdeployagentservice)。它工作得很好,每个Web项目都是按照其项目文件中的配置部署的。我使用的msbuild参数是:

    * /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 
    

    注意:我不使用/p:deployiisapppath=“xyz”,因为它不会部署所有项目并覆盖我的项目配置。

    我可以添加另一个构建参数来让它调用多个msdeployServiceURL吗?像/p:msdeployserviceurl参数那样指定另一个服务器?

    或者我需要寻找其他解决方案,比如编辑WF?

    两个月前我在这里看到了一个几乎完全相同的问题: TFS 2010 - Deploy to Multiple Servers After Build 所以看起来我不是唯一一个想解决这个问题的人。

    我还在讨论msdeploy的IIS.net论坛上发布了: http://forums.iis.net/t/1170741.aspx . 它有很多观点,但还是没有答案。

    5 回复  |  直到 12 年前
        1
  •  7
  •   37Stars    14 年前

    您不必两次构建项目就可以部署到两个服务器上。生成过程将生成一组部署文件。然后可以使用invokeProcess部署到多个服务器。

    首先创建一个名为projectname的变量。然后将分配活动添加到“编译项目”序列中。这位于“尝试编译项目”序列中。以下是分配的属性:

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

    以下是部署到测试服务器的invokeProcess活动的属性:

    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.
    

    如果需要手动部署到服务器,可以从生成文件夹运行以下命令:

    deploy.cmd /y /M:<server> /u:<domain>\<user> /p:<password>
    
        2
  •  6
  •   Alexander    12 年前

    我找不到我要找的解决方案,但我最后想到的是。

    我希望在TFS参数中保持解决方案的简单性和可配置性,同时保持与已经提供的 msbuildArguments method一致,后者已被大量提升。因此,我创建了一个新的生成模板,并在工作流的“参数”选项卡中添加了一个名为 msbuildArguments2

    我在buildTemplate工作流中搜索了 msbuildArguments (有两个实例)。

    使用 msbuildArguments 的两个任务称为 run msbuild for project 。在这个任务的正下方,我添加了一个新的“if”块,条件是:

    not string.isNullOrEmpty(msBuildArguments2)
    < /代码> 
    
    

    然后,我复制了“run msbuild for project”任务,并将其粘贴到新的if的“then”块中,相应地更新其标题。您还需要更新新任务的conmmandlinearguments属性以使用新参数。

    commandlinearguments=string.format(“/p:skipinvalidconfigurations=true 0”,msbuildArguments2)

    在这些修改之后,工作流看起来如下:

    保存并签入新工作流。更新生成定义以使用此新工作流,然后在生成定义的“流程”选项卡中,您将找到一个名为misc的新节,其中包含准备使用的新参数。因为我只是使用这个新的部署参数,所以我复制了与用于msbuild arguments的参数完全相同的参数,并将msdeployserviceurl更新到了我的第二个部署服务器。

    就是这样。我认为更优雅的方法是将msbuildArguments转换为字符串数组,然后在工作流过程中循环它们。但这符合我们的2个服务器要求。

    希望这有帮助!

    最后我想到的是。

    我希望在TFS参数中保持解决方案的简单性和可配置性,同时保持与已经提供的一致性MSBuildArguments方法得到了很大的提升。所以我创建了一个新的构建模板,并添加了一个新的tfs工作流参数,名为MSBuildArguments2在工作流的“参数”选项卡中。

    alt text

    我在buildTemplate工作流中搜索msbuildArguments(有两次发生)。

    使用的两个任务msbuildArguments被称为Run MSBuild for Project. 在这个任务的正下方,我添加了一个新的“if”块,条件是:

    Not String.IsNullOrEmpty(MSBuildArguments2)
    

    然后,我复制了“run msbuild for project”任务,并将其粘贴到新的if的“then”块中,相应地更新其标题。您还需要更新新任务的conmmandlinearguments属性才能使用新参数。

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

    经过这些修改后,工作流如下所示:

    alt text

    保存并签入新工作流。更新生成定义以使用此新工作流,然后在生成定义的“流程”选项卡中,您将找到一个名为misc的新节,其中包含准备使用的新参数。因为我只是使用这个新的部署参数,所以我复制了与以前完全相同的参数MSBuild Arguments并将msdeployserviceurl更新到第二个部署服务器。

    alt text

    就是这样。我认为更优雅的方法是将msbuildArguments转换为字符串数组,然后在工作流过程中循环它们。但这符合我们的2个服务器需求。

    希望这有帮助!

        3
  •  2
  •   David Peters    13 年前

    我的解决方案是在包之后运行一个新的目标。需要生成包的每个项目都包含此目标文件,我选择使include以外部设置的“doDeployment”属性为条件。此外,每个项目都定义DeploymentServerGroup属性,以便根据项目的类型正确筛选目标服务器。

    正如您在底部看到的,我只是使用服务器列表执行命令文件,非常简单。

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

    ---GT;

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

        4
  •  0
  •   Aaron Corcoran    15 年前

    我是另一篇类似文章的作者。我还没有找到解决办法。我相信它将修改工作流以添加后处理msbuild-sync任务。这似乎是最优雅的,但仍希望能找到一些不那么具有侵入性的东西。

        5
  •  0
  •   Alexander    12 年前

    我不确定这是否有助于你的TFS 2010,但我有一篇关于TFS 2012的博客: Multiple web projects deployment from TFS 2012 to NLB enabled environment .