Search code examples
tfstfsbuildtfvc

Check-in from TFS build the current code to another branch


We have TFS 2017 and we using TFVC.

We have vNext build definition with many source code mapping from many branches (all the code is required for the build).

At the end of the build (if he passed successfully) I want to take all the local code from the agent folder (with the local folder structure) and check-in all the code to separate branch ("release branch" for example) and keep the folders structure.

(We want one branch with all the "working" code, in the development, we can't work with one branch, because the build required many different sources).

I thought about something like this:

  • Create a new folder
  • Create a new workspace in this folder
  • Mapping the folder to "release branch"
  • Copy all the code to this folder
  • Check in the files to the branch

One thing to consider: we have many builds definitions and we want to do it for all, so for each build, we want to create a folder on the "release branch" and check in the code to there. so I need to check if the folder exist, if yes - check in, is not - create a folder and check in.

How can I do that? (tf.exe?)

UPDATE:

I succeed with tf.exe tool to achieve that unless one issue:

tf.exe can't detect automatically deleted files, I need to specify which items are deleted from the workspace. how can I do that? (I have a folder with hundreds of folders and subfolders)


Solution

  • I figure it out by creating a branch in each succeed build (not the best way but is not CI and we don't have many builds).

    Because tf barnch not create a branch (unless the source is from a branch) I copy all the source code from the agent to temp workspace, then I check-in to TFS, it creates a new folder with my code, then I convert the folder to a branch.

    Param(
    [string]$path
    )
    $newCodeFolderPath = "$($env:Agent_BuildDirectory)\newCode"
    $tempWorkspacePath =  "$($env:Agent_BuildDirectory)\tempWorkspace"
    
    New-Item -Path $newCodeFolderPath -ItemType directory
    
    Copy-Item -Path "$($env:Build_SourcesDirectory)/*" -Recurse -Destination $newCodeFolderPath 
    
    New-Item -Path $tempWorkspacePath -ItemType directory
    
    cd $tempWorkspacePath 
    
    $tfExe = "C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\Common7\IDE\CommonExtensions\Microsoft\TeamFoundation\Team Explorer\tf.exe"
    
    & $tfExe workspace /collection:{TfsCollection} /new "TempWorkspace" /noprompt
    
    & $tfExe workfold "$($path)/Release/$($env:Build_BuildNumber)" $tempWorkspacePath 
    
    Copy-Item -Path "$($newCodeFolderPath)/*" -Recurse -Destination $tempWorkspacePath 
    
    & $tfExe add * /recursive /noignore
    
    & $tfExe checkin /recursive /comment:"from vNext build"
    
    & $tfExe workspace /delete /collection:{TfsCollection} "Tempworkspace"
    
    cd c:/
    Remove-Item -Path $newCodeFolderPath -Force -Recurse
    Remove-Item -Path $tempWorkspacePath -Force -Recurse
    
    $releaseBranchPath = "$($path)/Release/$($env:Build_BuildNumber)
    Write-Host ("##vso[task.setvariable variable=releaseBranchPath;]$releaseBranchPath")
    

    In the build PowerShell task, I pass the $path variable, for example $/MyProject/V1/Name, the script will create folder Release (in the first time) and in the Release folder will create a folder with all the code.

    After that, I need to convert the folder to a branch, so I write a small tool in C# (you need TFS API libraries):

    try
    {
      string collectionUrl = {myCollection};
      string releaseBranchPath = Environment.GetEnvironmentVariable("releaseBranchPath");
      var tp = TfsTeamProjectCollection(new Uri (collectionUrl));
      var versionControl = tp.GetService<VersionControlServer>();
      versionControl.CreateaBranchPbject(new BranchProperties(new ItemIdentifier(releaseBranchPath)));
    }
    catch (Execption e)
    {
      Console.WriteLine(e.Message);
    }
    

    I compiled it and I run the .exe with Command Line task after the PowerShell task.