我一直在研究TFS2010与MSDeploy的新构建和部署功能。到目前为止一切进展顺利(虽然很难找到有关特定情况的信息)。
我可以修改构建定义以指定要部署的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?
我在2个月前发现了一个几乎完全相同的问题:TFS 2010 - Deploy to Multiple Servers After Build,所以看起来我不是唯一一个试图解决这个问题的人。
我还发布了讨论MSDeploy的IIS.NET论坛:http://forums.iis.net/t/1170741.aspx。它有很多观点,但同样没有答案。
答案 0 :(得分:7)
您不必两次构建项目即可部署到两台服务器。构建过程将构建一组部署文件。然后,您可以使用InvokeProcess部署到多个服务器。
首先创建一个名为ProjectName的变量。然后将“分配”活动添加到“编译项目”序列。它位于“尝试编译项目”序列中。以下是Assign:
的属性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>
答案 1 :(得分:6)
我找不到我想要的解决方案,但这就是我最终想出来的。
我希望在TFS参数中保持解决方案的简单性和可配置性,同时保持与已经提升了很多的已提供的MSBuildArguments
方法一致。所以我创建了一个新的构建模板,并在WorkFlow的Arguments选项卡中添加了一个名为MSBuildArguments2
的新TFS WorkFlow Argument。
我在BuildTemplate WorkFlow中搜索了MSBuildArguments
的所有出现(有两次出现)。
使用MSBuildArguments
的两个任务称为Run MSBuild for Project
。在这个任务的正下方,我添加了一个新的“If”块,条件为:
Not String.IsNullOrEmpty(MSBuildArguments2)
然后我复制了“运行MSBuild for Project”任务并将其粘贴到新的If的“Then”块中,相应地更新其标题。您还需要更新新Task的ConmmandLineArguments属性以使用新的Argument。
CommandLineArguments = String.Format("/p:SkipInvalidConfigurations=true {0}", MSBuildArguments2)
完成这些修改后,WorkFlow如下所示:
保存并检入新的WorkFlow。更新您的构建定义以使用这个新的WorkFlow,然后在构建定义的Process选项卡中,您将找到一个名为Misc的新部分,其中准备使用新参数。因为我只是使用这个新参数进行部署,所以我复制了我用于MSBuild Arguments
的完全相同的参数,并将MSDeployServiceURL更新为我的第二个部署服务器。
就是这样。我想更优雅的方法是将MSBuildArguments转换为字符串数组,然后在WorkFlow过程中循环遍历它们。但这符合我们的2服务器要求。
希望这有帮助!
答案 2 :(得分:2)
我的解决方案是在Package之后运行的新Target。需要生成包的每个项目都包含此目标文件,我选择在外部设置的“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>
答案 3 :(得分:0)
我是其他类似帖子的作者。我还没有找到解决方案。我相信它将修改工作流以添加后处理MSBUILD -sync任务。这似乎是最优雅的,但仍然希望找到一些不那么具有侵入性的东西。
答案 4 :(得分:0)
我不确定这是否可以帮助您使用TFS 2010,但我有一篇关于TFS 2012的博文:Multiple web projects deployment from TFS 2012 to NLB enabled environment。