📜 ⬆️ ⬇️

TFS Build Sequences

When using the continuous integration approach, there is often a need to run not just a single build, but to run a sequence of builds.

This is true when the product code is divided into several projects, and they depend on each other.
In this article I want to tell how this can be done using a TFS server.


')
Suppose we have two projects "Assembly1" and "Assembly2".
Two constructions are configured for the Assembly1 project: ClassLibrary1 and ClassLibrary2.
Two constructions are also configured for the project “Assembly2”: “A2.t2” and “A2.t3”.

After launching the construction of “ClassLibrary1” we need to start sequentially “ClassLibrary2” and “A2.t2”.

1. A simple and slow way (we did this before).

We customize the construction of "ClassLibrary2" and "A2.t2" in a special way:

Specify construction when check-in.



Add working folders from the previous build.



To build "A2.t2" similar actions are performed.

The advantage here is one - no need to modify the workflow used to build.
But more disadvantages:
- The more “working directories” are used, the longer is the construction.
- The sequence of constructions cannot be started manually, only the check-in.
- The sequence of constructions can be executed in any order, which is not always good.
In our case, we do not know what construction will be performed before “ClassLibrary2” or “A2.t2”.

2. We use TFS API.

- Create a new project «ClassLibrary».
- Add a new element "CodeActivity".
- Create two input parameters “BuildDetail” and “TfsProjectAndBuildDefinition”; the first is used to get and manage BuildServer.
- Parse the list of projects and constructions.
- This list consists of lines, where each line defines the name of the project for which the construction is carried out and the name of the construction separated by semicolons.
Below is the code:

using System; using System.Activities; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Text; using Microsoft.TeamFoundation.Build.Client; using Microsoft.TeamFoundation.Build.Workflow.Activities; using Microsoft.TeamFoundation.Build.Workflow.Services; using Microsoft.TeamFoundation.Client; namespace QueueNewBuilds { [BuildActivity(HostEnvironmentOption.Agent)] public sealed class QueueNewBuild : CodeActivity { // The Team Project that the build definition belongs to. [RequiredArgument] public InArgument<IBuildDetail> BuildDetail { get; set; } [RequiredArgument] public InArgument<String[]> TfsProjectAndBuildDefinition { get; set; } protected override void Execute(CodeActivityContext context) { String[] dirty = context.GetValue(this.TfsProjectAndBuildDefinition); IBuildDetail buildDetail = context.GetValue(this.BuildDetail); var pds = Parse(dirty); //var workspace = buildDetail.BuildDefinition.Workspace; IBuildServer buildServer = buildDetail.BuildServer; foreach (var pd in pds) { try { string message = string.Format("Queue new build \"{0}\"-\"{1}\"", pd.TfsProject, pd.BuildDefinition); context.TrackBuildMessage(message); IBuildDefinition buildDef = buildServer.GetBuildDefinition(pd.TfsProject, pd.BuildDefinition); buildServer.QueueBuild(buildDef); } catch (Exception ex) { string message = string.Format("Queue new build error \"{0}\"-\"{1}\", Exception : \"{2}\"", pd.TfsProject, pd.BuildDefinition, ex.Message); context.TrackBuildWarning(message); } } } private IEnumerable<ProjectDefinition> Parse(string[] dirty) { if (dirty == null) yield break; foreach (var item in dirty) { var t = item.Split(';'); if (t.Length == 2) { ProjectDefinition pd = new ProjectDefinition(); pd.TfsProject = t[0].Trim(); pd.BuildDefinition = t[1].Trim(); yield return pd; } } } class ProjectDefinition { public string TfsProject { get; set; } public string BuildDefinition { get; set; } } } } 


To use this "activity" we make a copy of "TfvcTemplate.12.xaml"
Modifying the build process:
Create a new “QueueNewBuild” argument of type array of strings.



In the “Agent Execution” block, create a “buildDetail” variable of the “IBuildDetail” type.
After the “Try” block, add “activity”, “GetBuildDetail” and “QueueNewBuild”.
In the “GetBuildDetail” block, as a result of “Result” we set “buildDetail”.
In the “QueueNewBuild” block, set the “BuildDetail” parameter as the “buildDetail” value obtained in the previous step and set the “QueueNewBuilds” parameter as the “TfsProjectAndBuildDefinition” parameter.



We save the changes, compile and add to the TFS server (I think it makes no sense to write these items, because they are described in detail, for example: www.ewaldhofman.nl/post/2010/05/27/Customize-Team-Build-2010- e28093-Part-7-How-is-the-custom-assembly-found.aspx ).

To build "ClassLibrary1" perform the configuration.
Select the modified process. I have it called "TfvcTemplate.12.2.xaml".



We set the sequence of construction.



Save, run the build, and enjoy the consistently running build.

Results can be found in the log file.



The code is available on Git: github.com/Serg2DFX/QueueNewBuilds .

Source: https://habr.com/ru/post/215369/


All Articles