2013-12-08 3 views
2

Я пытаюсь создать сценарий сборки для развертывания нашего кода в нескольких средах. Код выглядит следующим образом:Как я могу заставить целевую партию MSBuild работать

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0"> 

<PropertyGroup> 
    <TargetEnv>Production</TargetEnv> 
</PropertyGroup> 

<ItemGroup Condition="'$(TargetEnv)' == 'Integration'"> 
    <Server Include="int1"> 
     <ip>172.0.0.1</ip> 
    </Server> 
</ItemGroup> 

<ItemGroup Condition="'$(TargetEnv)' == 'Production'"> 
    <Server Include="prod1"> 
     <ip>172.0.2.1</ip> 
    </Server> 
    <Server Include="prod2"> 
     <ip>172.0.2.2</ip> 
    </Server> 
</ItemGroup> 

<Target Name="Deploy"> 
    <CallTarget Targets="DeployIntegration" /> 
    <CallTarget Targets="DeployServers" /> 
</Target> 

<Target Name="DeployIntegration" Condition="'$(TargetEnv)' == 'Integration'" Outputs="%(Server.Identity)"> 
    <Message Text="= specific int server thing need access to variable %(Server.Identity) =" Importance="high" /> 
</Target> 

<Target Name="DeployServers" Condition="'$(TargetEnv)' != 'Integration'" Outputs="%(Server.Identity)"> 
    <Message Text="= specific prod thing here need access to variable %(Server.Identity) =" Importance="high" /> 
</Target> 

<Target Name="RemoveServerFromLoadBalancer" AfterTargets="DeployServers" Condition="'$(TargetEnv)' != 'Integration'"> 
    <Message Text="= removing %(Server.Identity) from load balancer =" Importance="high" /> 
</Target> 

<Target Name="IgnoreRemoveServerFromLoadBalancer" AfterTargets="DeployServers" Condition="'$(TargetEnv)' == 'Integration'"> 
    <Message Text="= ignore removing %(Server.Identity) from load balancer =" Importance="high" /> 
</Target> 

<Target Name="CopyFilesAndCreateFolderLinks" AfterTargets="RemoveServerFromLoadBalancer;IgnoreRemoveServerFromLoadBalancer"> 
    <Message Text=" = creating and copying files %(Server.Identity) =" Importance="high" /> 
</Target> 

<Target Name="SetWebFarmServerName" AfterTargets="UpdateWebConfig" Condition="'$(TargetEnv)' != 'Integration'"> 
    <Message Text=" = app setting CMSWebFarmServerName set to %(Server.Identity) =" Importance="high" /> 
</Target> 

<Target Name="DisableWebFarmForIntegration" AfterTargets="UpdateWebConfig" Condition="'$(TargetEnv)' == 'Integration'"> 
    <Message Text=" = Disabled webfarm setting for Integration - %(Server.Identity) =" Importance="high" /> 
</Target> 

<Target Name="AddBackToLoadBalancer" AfterTargets="DisableWebFarmForIntegration" Condition="'$(TargetEnv)' != 'Integration'"> 
    <Message Text=" = Putting server %(Server.Identity) back on load balancer =" Importance="high" /> 
</Target> 

</Project> 

Этот код в XML (сохраняется в папке 11.0) файл и я запустить его с помощью команды MSBuild:

C:\Program Files (x86)\Microsoft Visual Studio 11.0>msbuild buildtest.xml /t:Deploy 

Этот код возвращает это, когда я запускаю сборка задача для производства:

DeployServers: 
     = specific prod thing here need access to variable prod1 = 
    DeployServers: 
     = specific prod thing here need access to variable prod2 = 
    RemoveServerFromLoadBalancer: 
     = removing prod1 from load balancer = 
     = removing prod2 from load balancer = 
    CopyFilesAndCreateFolderLinks: 
     = creating and copying files prod1 = 
     = creating and copying files prod2 = 

Я в принципе хочу, чтобы убедиться, что, если я нахожусь на интеграции, он не работает конкретные задачи, такие как балансировки нагрузки задачи, связанные как есть только одна машины для него , Я имею в виду, возвращаемое значение должно выглядеть следующим образом:

DeployServers: 
     = specific prod thing here need access to variable prod1 = 
    RemoveServerFromLoadBalancer: 
     = removing prod1 from load balancer = 
    CopyFilesAndCreateFolderLinks: 
     = creating and copying files prod1 = 

    DeployServers: 
     = specific prod thing here need access to variable prod2 = 
    RemoveServerFromLoadBalancer:  
     = removing prod2 from load balancer = 
    CopyFilesAndCreateFolderLinks:  
     = creating and copying files prod2 = 

Извините за длинный пост, это MSBuild вещи немного сложнее. Я ценю ваш вклад.

ответ

1

бетонным MSBuild выполняет здесь правильно, думать об этом: вы попросите его Message для текста %(Server.Identity) так что собирается сделать столько серверов, как он знает, и нет никаких причин, она собирается ждать OTER целей между ними. Таким образом, чтобы получить то, что вы хотите, вам нужно будет выполнить все требуемые задачи один раз на сервер. Кроме того, ваша общая структура слишком сложна. Условия на объектах неуправляемы: только тот факт, что вы повторяете одно и то же условие x раз, уже является признаком того, что что-то не так, потому что оно просто говорит, что нарушает принцип DIY. Также, если вы добавите еще один TargetEnv? А потом еще один? Да, вы поняли это: не будет приятно:] Вторая возможная будущая ловушка - это использование AfterTargets: хорошо, когда у вас только пара, но через некоторое время вы продолжаете добавлять цели, и вы не будете знать, что такое заказ , вам в основном придется пройти весь файл, чтобы понять, что происходит. Также, если вы добавите больше целей, которые являются общими для каждого TargetEnv? Или если вы добавите еще один TargetEnv. Снова не будет приятно, так как вам придется исправить это в нескольких местах.

Теперь из-за того, что вы смешали эти два осложнения и бросили дозатор над ним, все стало неясным. Вернитесь к началу и подумайте о том, что вам действительно нужно: если TargetEnv - это A, вы хотите делать X и Y и Z, если TargetEnv - это B, который вы хотите сделать, и Q и Z. Вот и все. Вы можете рассматривать это как две отдельные обязанности: выбор чего-либо на основе состояния и ведение списков действий для каждого условия. Итак, давайте выражаем это в методе msbuild.

Вот часть условия, теперь в новой цели развертывания. Остальные цели перемещаются в другой файл. Развертывание вызовет цель (которая зависит от условия) в другом файле msbuild с именем deploy.targets в том же каталоге, что и текущий файл. Поскольку пакетная обработка теперь находится на более высоком уровне, она будет автоматически выполняться так, как вы хотите: один раз на сервер. Обратите внимание, что выбранный сервер передается как свойство другому файлу. Есть и другие способы сделать это, но, как и в случае с кодом, приятно иметь пару небольших файлов вместо одного большого дела.

<Target Name="Deploy"> 
    <PropertyGroup> 
    <TargetsFile>$(MsBuildThisFileDirectory)deploy.targets</TargetsFile> 
    <TargetToCall Condition="$(TargetEnv)=='Production'">DeployServers</TargetToCall> 
    <TargetToCall Condition="$(TargetEnv)=='Integration'">DeployIntegration</TargetToCall> 
    </PropertyGroup> 
    <MSBuild Projects="$(TargetsFile)" Targets="$(TargetToCall)" Properties="Server=%(Server.Identity)" /> 
</Target> 

И вот новый файл, который имеет все цели, и два «мастер» цели, что теперь точно указать, какие другие цели они хотят звала, больше нет необходимости в условиях, не более AfterTargets.

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0"> 

    <PropertyGroup> 
    <CommonTargets>CopyFilesAndCreateFolderLinks</CommonTargets> 
    </PropertyGroup> 

    <Target Name="DeployIntegration"> 
    <Message Text="= specific int server thing need access to variable $(Server) =" Importance="high" /> 
    <CallTarget Targets="IgnoreRemoveServerFromLoadBalancer;$(CommonTargets)"/> 
    </Target> 

    <Target Name="DeployServers"> 
    <Message Text="= specific prod thing here need access to variable $(Server) =" Importance="high" /> 
    <CallTarget Targets="RemoveServerFromLoadBalancer;AnotherTargetJustForDeploy;$(CommonTargets)"/> 
    </Target> 

    <Target Name="RemoveServerFromLoadBalancer"> 
    <Message Text="= removing $(Server) from load balancer =" Importance="high" /> 
    </Target> 

    <Target Name="AnotherTargetJustForDeploy"> 
    <Message Text="= AnotherTargetJustForDeploy for $(Server) =" Importance="high" /> 
    </Target> 

    <Target Name="IgnoreRemoveServerFromLoadBalancer"> 
    <Message Text="= ignore removing $(Server) from load balancer =" Importance="high" /> 
    </Target> 

    <Target Name="CopyFilesAndCreateFolderLinks"> 
    <Message Text=" = creating and copying files $(Server) =" Importance="high" /> 
    </Target> 

</Project> 
+1

Это был отличный ответ. Вы не только воспитывали то, что происходило, но также говорили о плюсах и минусах и будущих соображениях. Ваш пример помог мне переписать задачи сборки и сделать их намного проще в использовании и обновлении, а также добавленную премию за самодокументирование. Спасибо. –

+0

Добро пожаловать! – stijn

Смежные вопросы