Search code examples
msbuildbatching

MSBuild batching iterator different within same iteration


I just started using batching in one of my MSBuild scripts in order to deploy a project one time for each customer in a list. Everything seemed to to go according to the plan, but then I discovered a strange issue: At the end of each iteration the task is supposed to make a copy of an MSI file and put it in a customer-specific directory, with a customer-specific file name. What happens is that the MSI file is given the appropriate name, BUT both of the MSI files are copied into the same folder (belonging to "Customer2").

When I look at the build logs I can see that both of the copy tasks are done at the end of the build. Can someone explain why this is happening? What I want is for the entire "Deploy" target to run before proceeding to the next customer.

Here is the MSBuild code. I have snipped out some things that should not be relevant:

<PropertyGroup>
    <Customers>Customer1;Customer2</Customers>
  </PropertyGroup>

  <ItemGroup>
    <Customer Include="$(Customers)"/>
  </ItemGroup>

  <Target Name="Deploy">

    <PropertyGroup>
      <DeploymentDirectory>$(Root)MyApplication_%(Customer.Identity)_ci</DeploymentDirectory>
      <SolutionDir>../MyApplication</SolutionDir>
      <ProjectFile>$(SolutionDir)/MyApplication/MyApplication.csproj</ProjectFile>
    </PropertyGroup>

    <MSBuild Projects="web_application_deploy.msbuild" Properties="
             ProjectFile=$(ProjectFile);
             SolutionFile=$(SolutionDir)\MyApplication.sln;
             AppName=MyApplication_%(Customer.Identity)_ci;
             TestDll=$(SolutionDir)/MyApplication.Tests/bin/Release/MyApplication.Tests.dll" />


    <!-- Build WIX project-->
    <MSBuild Condition="$(BuildWix) == true"
          Projects="$(SolutionDir)\MyApplication.Wix\MyApplication.Wix.wixproj"
          Properties="DeploymentDirectory=$(DeploymentDirectory);VersionNumber=$(BUILD_NUMBER)" />

    <!-- Copying the installer file to correct path, and renaming with version number -->
    <Exec Condition="$(BuildWix) == true"
          Command="copy &quot;$(SolutionDir)\MyApplication.Wix\bin\$(Configuration)\MyApplication.msi&quot; &quot;$(DeploymentDirectory)\MyApplication-%(Customer.Identity)-v$(BUILD_NUMBER).MSI&quot;"></Exec>
  </Target>

Update: It works if I reference the Iterator %(Customer.Identity) directly instead of using the $(DeploymentDirectory) property in the "Exec" call. Like this:

<Exec Condition="$(BuildWix) == true"
          Command="copy &quot;$(SolutionDir)\DataGateway.Wix\bin\$(Configuration)\DataGateway.msi&quot; &quot;$(CiRoot)DataGateway_%(Customer.Identity)_ci\DataGateway-%(Customer.Identity)-v$(BUILD_NUMBER).MSI&quot;"></Exec>

So it seems like the property called "DeploymentDirectory" is not updated with the correct customer when it is referenced. Is there something else I can do to make sure the property is "refreshed" in each iteration of the loop?


Solution

  • I think your doing something like this:

    <Target Name="DeployNotBatching" >
          <Message Text="Deployment to server done here.  Deploying to server: %(Customer.Identity)" />
          <Message Text="Also called" />
    
    </Target>
    

    Which gives:

      Deployment to server done here.  Deploying to server: Customer1
      Deployment to server done here.  Deploying to server: Customer2
      Also called
    

    When you really want to do this?

    <Target Name="Deploy" Inputs="@(Customer)" Outputs="%(Identity)">
          <Message Text="Deployment to server done here.  Deploying to server: %(Customer.Identity)" />
          <Message Text="Also called" />
    
    </Target>
    

    That results in :

    Deploy:
      Deployment to server done here.  Deploying to server: Customer1
      Also called
    Deploy:
      Deployment to server done here.  Deploying to server: Customer2
      Also called
    

    So the whole target is iterated rather than the individual command?