How do I get files from a second project on an Azure DevOps Agent via tf.exe?

98 Views Asked by At

My build pipeline gets sources in the local sources folder via "Get sources". I would like to get some other files from a different project.

Conditions

  • Azure DevOps Server on Premise
  • Self hosted build agent
  • TFVC (not git)
  • There is an existing mapping in ..\w\XXX\s\ to $projectA\subdir\branch
  • I want to get files from another project $projectB\subdir\branch
  • $projectB is not mapped
  • Only Powershell and tf.exe - I know the extra mapping function in the pipeline UI, but I would like to script that

I tried:

$collection = "well my collection..."
$tfsProjectTargetPath = "`$/projectB/subdir/branch"
$localWorkDir = $env:SYSTEM_DEFAULTWORKINGDIRECTORY
$workspaceName = $env:Build_Repository_Tfvc_Workspace
& $tf vc workfold /map /workspace:$workspaceName $localWorkDir /collection:$collection /noprompt

That runs into "TF14061: The workspace ws_XXX_YYYY;user does not exist.".

I also tried creating a new workspace:

$workspaceName = "some new name"
& $tf vc workspace /new /location:local /permission:Public $workspaceName /collection:$collection /noprompt

That runs into "The path ..\w\220\s\projectA\subidr\branch is already mapped in workspace ws_XXX_YYYY;Build\<guid>".

To me it seems the value of $workspaceName + user is the issue. Somehow the $workspaceName is coupled to a "build:" user. My powershell runs with a different user than the workspace.

Any suggestions or ideas?

2

There are 2 best solutions below

0
tomwaitforitmy On BEST ANSWER

I found the solution:

  • You have to delete the existing workspace, before you can create a second
  • Deletion is tricky, because of the name of the workspace
  • The name consists of <workspacename>;Build\<collectionId>
  • Workspacename is available in the list of the predefined variables: $Build_Repository_Tfvc_Workspace
  • Collection Id was not obvious to me. I figured it out by checking which variable has which value.

In Powershell, getting files from another project can be achieved with:

$tf = [System.IO.Path]::Combine($env:AGENT_HOMEDIRECTORY, "externals", "tf", "tf.exe")
$workspaceName = $env:Build_Repository_Tfvc_Workspace
$workspaceNameWithUser = $workspaceName + ";Build\" + $env:SYSTEM_COLLECTIONID
& $tf vc workspace /delete $workspaceNameWithUser

Now you can create a new workspace and a new mapping, like I mentioned in my question:

$collection = "well my collection..."
$tfsProjectTargetPath = "`$/projectB/subdir/branch"
$localWorkDir = $env:SYSTEM_DEFAULTWORKINGDIRECTORY
$workspaceName = "choose a new name"
& $tf vc workspace /new /location:local /permission:Public $workspaceName /collection:$collection /noprompt $commandLogin
& $tf vc workfold /unmap /workspace:$workspaceName $/ /collection:$collection /noprompt $commandLogin
& $tf vc workfold /map /workspace:$workspaceName $tfsProjectTargetPath $localWorkDir /collection:$collection /noprompt
& $tf vc get /recursive /overwrite $localWorkDir /noprompt
3
Shayki Abramczyk On

You can use the TFVC Get extension which do it for you.

If you want to do it by yourself you can use the Items - Get Items Batch Rest API, for example:

POST https://dev.azure.com/fabrikam/_apis/tfvc/itembatch?api-version=5.1

{
  "itemDescriptors": [
    {
      "path": "$/Fabrikam-Fiber-TFVC/AuthSample/AuthSample/Program.cs",
      "version": 5,
      "versionType": "changeset"
    },
    {
      "path": "$/Fabrikam-Fiber-TFVC/AuthSample",
      "recursionLevel": "Full"
    }
  ]
}