Это актуально когда код продукта разделён на несколько проектов, и они зависят друг от друга.
В данной статье я хочу рассказать, как это можно сделать, используя TFS сервер.
Пусть у нас есть два проект «Assembly1» и «Assembly2».
Для проекта «Assembly1» настроено два построения: «ClassLibrary1» и «ClassLibrary2».
Для проекта «Assembly2» тоже настроено два построения: «A2.t2» и «A2.t3».
Нам требуется после запуска построения «ClassLibrary1» запустить последовательно «ClassLibrary2» и «A2.t2».
1. Простой и медленный способ (мы так делали раньше).
Настраиваем построения «ClassLibrary2» и «A2.t2» специальным образом:
Указываем построение при check-in.
Добавляем рабочие папки от предыдущего контроллера построения.
Для построения «A2.t2» выполняются аналогичные действия.
Преимущество здесь одно – не требуется модифицировать используемый рабочий процесс для построения.
А вот недостатков больше:
— Чем больше используется «рабочих каталогов», тем дольше осуществляется построение.
— Последовательность построений невозможно запустить вручную, только check-in.
— Последовательность построений может выполниться в произвольном порядке, что не всегда хорошо.
В нашем случае мы не знаем, какое построение выполнится раньше «ClassLibrary2» или «A2.t2».
2. Используем TFS API.
— Создаём новый проект «ClassLibrary».
— Добавляем новый элемент «CodeActivity».
— Создаём два входных параметра «BuildDetail» и «TfsProjectAndBuildDefinition» первый используется для получения и управления BuildServer’ом.
— Разбираем список проектов и построений.
— Данный список состоит из строк, где каждая строка определяет имя проекта, для которого осуществляется построение и имя построения разделённых точкой с запятой.
Ниже приведён код:
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; } } } }
Для использования данной «activity» делаем копию «TfvcTemplate.12.xaml»
Модифицируем процесс построения:
Создаём новый аргумент «QueueNewBuild» типа массив строк.
В блоке «Выполение в агенте» создаём переменную «buildDetail» типа «IBuildDetail».
После блока «Try» добавляем «activity» «GetBuildDetail» и «QueueNewBuild».
В блоке «GetBuildDetail» в качестве результата «Result» задаём «buildDetail».
В блоке «QueueNewBuild» в качестве параметра «BuildDetail» задаём значение «buildDetail» полученное на предыдущем шаге и в качестве параметра «TfsProjectAndBuildDefinition» задаём значение «QueueNewBuilds».
Сохраняем изменения, компилируем и добавляем в TFS сервер (данные пункты думаю не имеет смысла расписывать, т.к. они подробно расписаны например тут: www.ewaldhofman.nl/post/2010/05/27/Customize-Team-Build-2010-e28093-Part-7-How-is-the-custom-assembly-found.aspx ).
Для построения «ClassLibrary1» выполняем настройку.
Выбираем модифицированный процесс. У меня он называется «TfvcTemplate.12.2.xaml».
Задаём последовательность построения.
Сохраняем, запускаем построение и наслаждаемся последовательно выполняющимся построением.
Результаты можно обнаружить в лог файле.
Код доступен на Git: github.com/Serg2DFX/QueueNewBuilds/.
ссылка на оригинал статьи http://habrahabr.ru/post/215369/
Добавить комментарий