Automating Microsoft Team Foundation (TFS) check-ins

Have you ever wanted to automate code check-ins to TSF e.g. at the end of the day or at the custom interval you define? That’s easy to do using TFS remote API provided by Microsoft.

In our exercise we are going to use following packages to make the solution working:

<packages>
 <package id="Microsoft.AspNet.WebApi.Client" version="5.2.2" targetFramework="net452" />
 <package id="Microsoft.AspNet.WebApi.Core" version="5.2.2" targetFramework="net452" />
 <package id="Microsoft.IdentityModel.Clients.ActiveDirectory" version="2.16.204221202" targetFramework="net452" />
 <package id="Microsoft.TeamFoundationServer.Client" version="14.95.3" targetFramework="net452" />
 <package id="Microsoft.TeamFoundationServer.ExtendedClient" version="14.95.3" targetFramework="net452" />
 <package id="Microsoft.VisualStudio.Services.Client" version="14.95.3" targetFramework="net452" />
 <package id="Microsoft.VisualStudio.Services.InteractiveClient" version="14.95.3" targetFramework="net452" />
 <package id="Microsoft.WindowsAzure.ConfigurationManager" version="1.7.0.0" targetFramework="net452" />
 <package id="Newtonsoft.Json" version="6.0.8" targetFramework="net452" />
 <package id="System.IdentityModel.Tokens.Jwt" version="4.0.0" targetFramework="net452" />
 <package id="WindowsAzure.ServiceBus" version="3.3.1" targetFramework="net452" />
</packages>

As a authorization mechanism, we will use token which can be generated on your Visual Studio Online account.
Tokens are more secure and flexible than using standard user/pass credentials as we can safely share it and allow it to expire after a predefined period of time.

so, in our app.config we will have following settings:

 <add key="TfsURL" value="https://your_name.visualstudio.com/DefaultCollection/"/>
 <add key="workspaceName" value="AUTOMATED_CHECKINS"/>
 <add key="tfsServerFolderPath" value="$/remote_folder"/>
 <add key="localWorkingPath" value="D:\MyCodefolder"/>
 <add key="tfsUser" value="not-used"/>
 <add key="tfsPass" value="-your token--"/>
 <add key="tfsDomain" value=""/>

Our main function will look as following (see inline comments):

static void TFSCheckIn(string comment = "")
{
  var TfsURL = new Uri(ConfigurationManager.AppSettings["TfsURL"]);

  //use it for standard user/pass authentication
  //var credential = new NetworkCredential(ConfigurationManager.AppSettings["tfsUser"], ConfigurationManager.AppSettings["tfsPass"], ConfigurationManager.AppSettings["tfsDomain"]);
  //var collection = new TfsTeamProjectCollection(TfsURL, credential);
  //collection.EnsureAuthenticated();

  //token based authentication
  var simpleWebToken = new SimpleWebToken(ConfigurationManager.AppSettings["tfsPass"]);
  var networkCredential = new NetworkCredential(ConfigurationManager.AppSettings["tfsUser"], ConfigurationManager.AppSettings["tfsPass"]);
  
  var basicCredential = new BasicAuthCredential(networkCredential);
  var tfsCredentials = new TfsClientCredentials(basicCredential);
  tfsCredentials.AllowInteractive = false;
  var collection = new TfsTeamProjectCollection(TfsURL, tfsCredentials);
  collection.EnsureAuthenticated();

  var versionControl = (VersionControlServer)collection.GetService(typeof(VersionControlServer));

  Workspace WS = null;
  try
  {
    //Get the current workspace
    WS = versionControl.GetWorkspace(ConfigurationManager.AppSettings["workspaceName"], versionControl.AuthorizedUser);
  }
  catch (Exception)
  { }

  //create workspace if not yet created
  if (WS == null)
  {
     WS = versionControl.CreateWorkspace(ConfigurationManager.AppSettings["workspaceName"], versionControl.AuthorizedUser);
  }

  //map local folder if not already mapped
  if (!WS.IsLocalPathMapped(ConfigurationManager.AppSettings["localWorkingPath"]))
  {
    //Mapping TFS Server and code generated
    WS.Map(ConfigurationManager.AppSettings["tfsServerFolderPath"], ConfigurationManager.AppSettings["localWorkingPath"]);
  }
 
  //download remote changes (check-out)
  WS.Get();

 //auto-resolve conflicts
 Conflict[] conflicts = WS.QueryConflicts(new string[] { ConfigurationManager.AppSettings["tfsServerFolderPath"] }, true);
  
  foreach (Conflict conflict in conflicts)
  {
    if (WS.MergeContent(conflict, false))
    {
     conflict.Resolution = Resolution.AcceptTheirs;
     WS.ResolveConflict(conflict);
    }

   Console.WriteLine("conflict: " + conflict.FileName);
 }

 //Add all files just created to pending change
 int NumberOfChange = WS.PendAdd(ConfigurationManager.AppSettings["localWorkingPath"], true);

 //Get the list of pending changes
 PendingChange[] pendings = WS.GetPendingChanges(ConfigurationManager.AppSettings["tfsServerFolderPath"], RecursionType.Full);

  if (pendings.Any())
  {
    //Auto check in code to Server
     WS.CheckIn(pendings, "Auto check-in code (#changes: " + pendings.Count() + "). " + comment);
  }
 }

Need  custom solution tailored to your business needs? Contact us today!

1 Star2 Stars3 Stars4 Stars5 Stars (1 votes, average: 5.00 out of 5)
Loading...Loading...