Resolve a $ path in TeamBuild
There are some really useful TeamBuild tasks whose purpose or usage is not immediate. Such is WorkspaceItemConverterTask: it allows to transform a $ path — that is the path to a file or folder in TFS Version Control — to the physical path that the file assume during the TeamBuild.
To see how it’s used, you have to look into Microsoft.TeamFoundation.Build.targets (this file is located under %ProgramFiles(x86)%\MSBuild\Microsoft\VisualStudio\TeamBuild), and it simple to use: ServerItems gets an ItemGroup to resolve and LocalItems will held the list of resolved paths. The other parameters are needed but are always the same: they represent the context of evaluation.
I found this task useful when I needed to add some post-processing to my solutions in TeamBuild: I attached some custom metadata to the Items representing the solutions to build and iterated through them in a late build step, like PackagingBinaries.
This sample code may help understand its usage.
1: <Target Name="ResolveSolutionPathsForDeploy"
2: Condition="'$(IsDesktopBuild)' != 'true'">
3: <WorkspaceItemConverterTask
4: Condition="'@(SolutionToBuild)' != ''"
5: TeamFoundationServerUrl="$(TeamFoundationServerUrl)"
6: BuildUri="$(BuildUri)"
7: WorkspaceName="$(WorkspaceName)"
8: WorkspaceOwner="$(WorkspaceOwner)"
9: ServerItems="@(SolutionToBuild)">
10: <Output TaskParameter="LocalItems" ItemName="LocalSolutionToBuild" />
11: </WorkspaceItemConverterTask>
12: </Target>
13:
14:
15: <Target Name="LocalDeploy" DependsOnTargets="ResolveSolutionPathsForDeploy" Condition="'$(DeployLocally)'=='true'">
16:
17: <PropertyGroup>
18: <_DeployScript Condition="'%(LocalSolutionToBuild.PsDeploy)'=='true'">
19: %(LocalSolutionToBuild.RootDir)%(LocalSolutionToBuild.Directory)%(LocalSolutionToBuild.Filename).Deployment\%(LocalSolutionToBuild.Filename).Deploy.ps1
20: </_DeployScript>
21: <_UndeployScript Condition="'%(LocalSolutionToBuild.PsDeploy)'=='true'">
22: %(LocalSolutionToBuild.RootDir)%(LocalSolutionToBuild.Directory)%(LocalSolutionToBuild.Filename).Deployment\%(LocalSolutionToBuild.Filename).Undeploy.ps1
23: </_UndeployScript>
24: </PropertyGroup>
25:
26: <Powershell ScriptFile="$(_UndeployScript)" Arguments="SolutionName=%(LocalSolutionToBuild.Filename)" Condition="'%(LocalSolutionToBuild.PsDeploy)'=='true'" />
27: <Powershell ScriptFile="$(_DeployScript)" Arguments="SolutionName=%(LocalSolutionToBuild.Filename)" Condition="'%(LocalSolutionToBuild.PsDeploy)'=='true'" />
28:
29: </Target>
The solution has the appropriate metadata to activate the previous code, as follows.
1: <ItemGroup>
2: <!-- SOLUTIONS -->
3: <SolutionToBuild Include="$(BuildProjectFolderPath)/../../Sources/Services/Service1/Service1.sln">
4: <PsDeploy>true</PsDeploy>
5: </SolutionToBuild>
6: <SolutionToBuild Include="$(BuildProjectFolderPath)/../../Sources/Common/Common.sln">
7: <MsiDeploy>true</MsiDeploy>
8: </SolutionToBuild>
9: <SolutionToBuild Include="$(BuildProjectFolderPath)/../../Sources/Web/Site.sln">
10: <PsDeploy>true</PsDeploy>
11: </SolutionToBuild>
12: </ItemGroup>
Happy Build!
Comments
Anonymous
September 16, 2010
The comment has been removedAnonymous
September 16, 2010
The comment has been removedAnonymous
September 16, 2010
I tried this : <Target Name="CopyFiles"> <Copy SourceFiles="@(ConfigurationFiles)" DestinationFiles="@(ConfigurationFiles->'$(OutDir)%(RecursiveDir)%(Filename)%(Extension)')" /> </Target> Where : <ItemGroup> <ConfigurationFiles Include="$(SolutionRoot)Configuration***.*"/> </ItemGroup> I skimmed the logfile for errors, there were none. No warnings related to this as well. any other thoughts?Anonymous
September 16, 2010
I suggest to add some logging to your code so to better understand what is happening, e.g. <Target Name="CopyFiles"> <Message Text="In CopyFiles ConfigurationFiles is @(ConfigurationFiles)" /> <Copy SourceFiles="@(ConfigurationFiles)" DestinationFiles="@(ConfigurationFiles->'$(OutDir)%(RecursiveDir)%(Filename)%(Extension)')" /> </Target> This way you can determine if the target is being called, at what point in the process, and the values it gets.