- | rssFeed | My book on MSBuild and Team Build | Archives and Categories Friday, 20 June 2008

MSBuild RE: Enforcing the Build Agent in a Team Build

This is a post that responds to a post by Michael Ruminer at Enforcing the Build Agent in a Team Build. I hope I correctly understand his situation. Here is my summary of it.

My solution to this problem is to create a property, AllowedBuildAgents, which will contain a semi-colon separated list of the allowed build agent names. Then this is converted into an item, AllowedBuildAgentsItem, so batching can be preformed over it. If you are not familiar with MSBuild batching you can see my previous postings at:

The main objective here is to create an item that contains all the allowed names, AllowedBuildAgentsItem, and batch over them. If the value for BuildAgentName is equal to any value in that item then we want to allow the build. I create a property BuildAgentAllowed which defaults to false, and if that condition is true then I set BuildAgentAllowed to true. So I created a target DetermineIfAuthorizedBuildAgent that depends will throw an error if BuildAgentAllowed is false. Also this target depends on the target that will actually populate that value, which is the GetBuildAgentAllowed target. The build script is placed below. I added a few elements that were for demo only. Those are; value for BuildAgentName and BeforeEndToEndIteration target. See comments in the file (which can be downloaded at the end of this post).

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="2.0"
         xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
         DefaultTargets="BeforeEndToEndIteration">

  <!--
  Assume that this value has been set already.
  I'm declaring it here for this demonstration.
  -->
  <PropertyGroup>
    <BuildAgentName>Sayed_001</BuildAgentName>
  </PropertyGroup>

 
 
  <PropertyGroup>
    <BeforeEndToEndIterationDependsOn>
      $(BeforeEndToEndIterationDependsOn);
      DetermineIfAuthorizedBuildAgent;
    </BeforeEndToEndIterationDependsOn>
  </PropertyGroup>

  <!--
  Define this here as a property so it can be passed
  via Properties from various callers.
  -->
  <PropertyGroup>
    <AllowedBuildAgents>Sayed_001;Sayed_003;Sayed_005</AllowedBuildAgents>
  </PropertyGroup>

  <!--
  Convert the property into an item so we can batch over it.
  -->
  <ItemGroup>
    <AllowedBuildAgentsItem Include="$(AllowedBuildAgents)"/>
  </ItemGroup>
  <!--
  Specify this value to false. If allowed it will be set to true.
  -->
  <PropertyGroup>
    <BuildAgentAllowed>false</BuildAgentAllowed>
  </PropertyGroup>
 
 

  <Target Name="PrintInfo">
    <Message Text="AllowedBuildAgentsItem: @(AllowedBuildAgentsItem,'%0a%0d')"/>
  </Target>

  <!-- Executing this target will make the GetBuildAgentAllowed target execute first -->
  <Target Name="DetermineIfAuthorizedBuildAgent"
          DependsOnTargets="GetBuildAgentAllowed">
    <Message Text="BuildAgentAllowed: $(BuildAgentAllowed)"/>
    <Error Text="This build can only be run on one of the following build agents: @(AllowedBuildAgentsItem)" 
           Condition="'$(BuildAgentAllowed)'=='false'" />
  </Target>
 
  <!--
  This target will be executed for each value in the AllowedBuildAgentsItem.
  If the BuildAgentName is equal to any value in AllowedBuildAgentsItem then the
  property BuildAgentAllowed will be set to true.
  -->
  <Target Name="GetBuildAgentAllowed" Outputs="%(AllowedBuildAgentsItem.Identity)">
    <Message Text="GetBuildAgentAllowed %25(AllowedBuildAgentsItem.Identity): %(AllowedBuildAgentsItem.Identity)"/>
   
    <CreateProperty Value="true" Condition="'$(BuildAgentName)'=='%(AllowedBuildAgentsItem.Identity)'">
      <Output PropertyName="BuildAgentAllowed" TaskParameter="Value"/>
    </CreateProperty>
   
  </Target>


 
  <!--
  This target is really executed by TeamBuild but I will
  put it here for demonstration. If this target executes then the build
  was allowed otherwise an error will be shown.
  -->
  <Target Name="BeforeEndToEndIteration" DependsOnTargets="$(BeforeEndToEndIterationDependsOn)">
    <Message Text="EndToEndIteration starting"/>
  </Target>
 
</Project>

The only reason that I have defined the allowed build agents in a property (AllowedBuildAgents) is because I want to allow external sources to specify it. You can specify properties through the command line or when using the MSBuild Task. Then the script converts this to an item. If I execute this project I would expect it to succeed because the defined value for BuildAgentName is contained in the list of AllowedBuildAgents. The results of executing this project are shown below.

Now we can change the value for BuildAgentName, by using the command msbuild.exe BuildAgent01.proj /p:BuildAgentName=Sayed_010. We would expect the build to fail. The results of this are below.

   

So the build failed as expected so we are good. Any questions?

   

BuildAgent01.proj

Sayed Ibrahim Hashimi

Friday, 20 June 2008 05:22:57 (GMT Daylight Time, UTC+01:00)  #     |