2

複数の環境にコードをデプロイするためのビルド スクリプトを作成しようとしています。コードは次のとおりです。

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

私は基本的に、統合している場合、ロードバランサー関連のタスクなどの特定のターゲットを実行しないようにしたいと考えています。これは、マシンが 1 つしかないためです。私は考えています、返される値は次のようになるはずです:

    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 は少しトリッキーです。ご意見をお待ちしております。

4

1 に答える 1

1

ここで MSBuild が実行するバッチ処理は正しいです。考えてみてください。Messageテキストを要求する%(Server.Identity)ので、知っている限り多くのサーバーに対してそれを実行し、その間に他のターゲットを待つ理由はありません。したがって、必要なものを取得するには、必要なすべてのタスクをサーバーごとに 1 回実行する必要があります。さらに、あなたの一般的な構造は少し複雑すぎます。ターゲットの状態は管理不能です。同じ状態を x 回繰り返すという事実は、簡単に言えば、DIY の原則に違反しているため、何かがおかしいという兆候です。また、別の TargetEnv を追加するとどうなりますか? そして、もう1つ?ええ、あなたはそれを考えました: 良くないでしょう:] 2番目に考えられる将来の落とし穴はの使用ですAfterTargets: 2 つしかない場合は便利ですが、しばらくするとターゲットを追加し続けると、順番がわからなくなります。何が起こっているのかを把握するには、基本的にファイル全体を調べる必要があります。また、各 TargetEnv に共通のターゲットをさらに追加するとどうなるでしょうか? または、別の TargetEnv を追加する場合。複数の場所でそれを修正する必要があるため、これも良くありません。

この 2 つの複雑な問題を混ぜ合わせて、その上にバッチ処理を追加したため、状況がかなり不明確になりました。最初に戻って、本当に必要なものを考えてみましょう。TargetEnv が A の場合は X と Y と Z を実行し、TargetEnv が B の場合は Q と Z を実行します。それだけです。条件に基づいて何かを選択することと、条件ごとにアクションのリストを維持することです。それでは、これを msbuild の方法で表現してみましょう。

これが条件部分で、新しい Deploy ターゲットになりました。残りのターゲットは別のファイルに移動されます。Deploy は、現在のファイルと同じディレクトリにある deploy.targets という別の msbuild ファイルのターゲット (条件によって異なります) を呼び出します。バッチ処理がより高いレベルになったため、必要な方法で自動的に実行されます (サーバーごとに 1 回)。選択したサーバーがプロパティとして他のファイルに渡されることに注意してください。これを行う方法は他にもありますが、コードの場合と同様に、1 つの大きなファイルですべてを行うのではなく、いくつかの小さなファイルを用意すると便利です。

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

そして、すべてのターゲットを含む新しいファイルと、呼び出したい他のターゲットを正確に指定する 2 つの「マスター」ターゲットが含まれています。これ以上、条件や 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>
于 2013-12-08T19:54:25.173 に答える