Заметки консультанта

Шамрай Александр Владимирович

Posts Tagged ‘vsts’

Автоматизация изменений состояний рабочих элементов Azure DevOps на основе состояний дочерних элементов

Posted by Shamrai Alexander на Февраль 19, 2019

На форумах часто встречается вопросы:

  1. Есть ли какой-то сервис для автоматического изменения состояния пользовательской истории, если отрыли любую дочернюю задачу.
  2. Как можно автоматически закрыть требование, если все дочерние задачи закрыты.

На сколько верно автоматизировать эти вопросы – это тема дискуссионная, и каждый сам для себя выбирает правильный ответ. Если все-таки есть желание автоматизировать изменение состояний, то для этого существуют отдельные сервисы, например, TFS Aggregator (Web Service) или другие кастомные сервисы.

Но т.к. задачи на самом деле с точки зрения разработки не очень сложные, то содержание отдельного сервиса может быть избыточным. Иногда можно обойтись небольшими задачами на основе библиотек для взаимодействия через REST API, которые будут выполняться через стандартный планировщик задач. Такой пример мы здесь и рассмотрим.

Тут будут следующие основные шаги:

  1. Подключение к сервису. Пример есть здесь: VSTS Rest Api. 1. Подключение к сервису.
  2. Выполнения запроса по рабочим элементам, чтобы иметь список интересующих нас «родителей». Пример выполнения запроса: Azure DevOps Services Rest Api. 4. Выполнение запросов по рабочим элементам
  3. Обновить состояние «родителям», которые удовлетворяют нашим условиям. Пример обновления: Azure DevOps Services Rest Api. 3. Создание и редактирование рабочих элементов

Изменение родителя, если любой дочерний элемент изменился

Примеры тут могут быть следующие:

  1. Открывается пользовательская история, если исполнитель отрыл дочернюю задачу.
  2. Открывается фича, если любая дочерняя пользовательская история открылась.

Это простой сценарий, т.к. нам нужно сделать запрос по рабочим элементам, который отберет пользовательские истории в состоянии New и с дочерними задачами в состоянии Active. Пример запроса в формате WIQL может быть следующий:

SELECT [System.Id] FROM WorkItemLinks WHERE ([Source].[System.TeamProject] = ‘Team project name’ AND [Source].[System.WorkItemType] = ‘User story’ AND [Source].[System.State] = ‘New’) And ([System.Links.LinkType] = ‘System.LinkTypes.Hierarchy-Forward’) And ([Target].[System.WorkItemType] = ‘Task’ AND [Target].[System.State] = ‘Active’) ORDER BY [System.Id] mode(MustContain)

Нас интересуют только идентификаторы рабочих элементов верхнего, которые в результате выполнения запроса не имеют участника Source. Пример обработки результата:

static List<int> GetParentIdsFromQueryResult(string pWiql)

{

Wiql _wiql = new Wiql { Query = pWiql };

WorkItemQueryResult result = WITClient.QueryByWiqlAsync(_wiql).Result;

if (result.WorkItemRelations != null)

return (from links in result.WorkItemRelations where links.Source == null select links.Target.Id).ToList();


return new List<int>();

}

Далее все найденные идентификаторы обновляем до активного состояния. При этом функция обновления проста, т.к. нам нужно обновить только одно поле:


static void UpdateWorkItemState(int parentId, string pDestinationState)

{

JsonPatchDocument patchDocument = new JsonPatchDocument();

patchDocument.Add(new JsonPatchOperation()

{

Operation = Operation.Add,

Path = «/fields/» + StateFieldName,

Value = pDestinationState

});

WorkItem _updatedWi = WITClient.UpdateWorkItemAsync(patchDocument, parentId).Result;

Console.WriteLine(«Work Item Has Been Updated:{0} — {1}», _updatedWi.Id, _updatedWi.Fields[«System.State»].ToString());

}

Изменение родителя, если все дочерние элементы в необходимом состоянии

Тут рассматривается вариант, если необходимо закрыть пользовательскую историю, когда все дочерние задачи закрыты.

В данном случае получение необходимых родителей схож с первым вариантом. Но нам необходимо знать: все ли дочерние задачи закрыты. Это одним запросом не выполнишь. Можно использовать два варианта:

  1. Получать родителя со всеми ссылками на дочерние элементы. Потом получать дочерние задачи, анализировать их состояние и принимать необходимое решение.
  2. Также можно выполнить два запроса для каждого родителя: количество всех дочерних задач и количество закрытых дочерних задач. Если они равны, то закрываем пользовательскую историю. Рассмотрим этот вариант.

Запросы для родительских пользовательских историй:

  1. Получить родителя и закрытые дочерние задачи:

SELECT[System.Id] FROM WorkItemLinks WHERE([Source].[System.TeamProject] = ‘Team project name’ AND [Source].[System.Id] = Parent_ID) And([System.Links.LinkType] = ‘System.LinkTypes.Hierarchy-Forward’) And ([Target].[System.WorkItemType] = ‘Task’ AND [Target].[System.State] = ‘Closed’) ORDER BY [System.Id] mode(MustContain)

  1. Получить родителя и все дочерние задачи

SELECT[System.Id] FROM WorkItemLinks WHERE([Source].[System.TeamProject] = ‘Team project name’ AND [Source].[System.Id] = Parent_ID) And ([System.Links.LinkType] = ‘System.LinkTypes.Hierarchy-Forward’) And ([Target].[System.WorkItemType] = ‘Task’) ORDER BY [System.Id] mode(MustContain)

Получить количество дочерних рабочих элементов из запроса можно следующим образом:


static int GetChildsCountFromQueryResult(string pWiql)

{

Wiql _wiql = new Wiql { Query = pWiql };

WorkItemQueryResult result = WITClient.QueryByWiqlAsync(_wiql).Result;


if (result.WorkItemRelations != null)


return (from links in result.WorkItemRelations where links.Source != null select links.Target.Id).Count();


return 0;

}

Затем сравниваем количество и обновляем тем же методом, как и в первом варианте.

Решение пример

Решение можно получить и скомпилировать отсюда: https://github.com/ashamrai/AzureDevOpsExtensions/tree/master/CustomNetTasks/UpdateParentState

Перед запуском приложения необходимо:

  1. Установить правильный адрес Azure DevOps сервиса или сервера в константу ServiceUrl.
  2. Сгенерировать Personal Access Token и вставить в константу PAT.
  3. Добавить в список _projects названия командных проектов для обработки: _projects.Add(«Yor team project name»);

Posted in Microsoft, Team Foundation Server, Visual Studio, visual studio team services | Отмечено: , , , , , | Leave a Comment »

Azure DevOps Services Rest Api. 12. Просмотр содержимого плана тестирования

Posted by Shamrai Alexander на Февраль 14, 2019

<< Перейти в радел «Azure DevOps Services (TFS/VSTS) Rest Api»

Примечание: Устарело с версии 16.150.0-preview. Новые подходы описаны здесь.

Для работы с объектами тестирования используется клиент TestManagementHttpClient. В рамках планирования тестирования используются следующие основные объекты:

  1. План тестирования – класс TestPlan. Он содержит в основном информацию о названии, планируемых датах тестирования и т.д.
  2. Набор тестов – класс TestSuite. Содержит дочерние наборы, а также сценарии тестирования. Наборы тестов могут быть статическими, наборам для требований (т.е. ссылаются на конкретное требование) и динамическими (на основе запроса по рабочим элементам).
  3. Тестовый сценарий – класс SuiteTestCase. Содержит информацию о рабочем элементе тестового сценария, тестировщике и конфигурации для тестирования.

Для того, чтобы получить информацию о всех объектах тестирования, необходимо:

  1. Получить план тестирования.
  2. Получить его основной набор тестов. Т.к. план тестирования кроме того, что имеет объект, который описывает его свойства, для него также сразу создается корневой набор тестов, который уже отражает содержимое плана тестирования на первом уровне.
  3. Получить содержимое набора тестов, т.е. дочерние наборы тестов и тестовые сценарии.

Для получения тестового плана используется метод GetPlanByIdAsync с использованием имени командного проекта и идентификатора. Идентификатор можно увидеть через интерфейс:

Рисунок 1. Редактирование плана тестирование

Рисунок 2. Идентификатор плана тестирования

Набор планов тестирования с использованием имени командного проекта можно получить через метод GetPlansAsync, который вернет список List планов тестирования.

Пример получения плана тестирования и его свойств:

TestPlan testPlan = TestManagementClient.GetPlanByIdAsync(TeamProjectName, TestPlanId).Result;
Console.WriteLine(«Test Plan : {0} : {1} : {2}», testPlan.Id, testPlan.State, testPlan.Name);
Console.WriteLine(«Area Path : {0} : Iteration Path : {1}», testPlan.Area.Name, testPlan.Iteration);

Console.WriteLine(«Plan Dates : {0} — {1}», testPlan.StartDate.ToShortDateString(), testPlan.EndDate.ToShortDateString());

Набор тестов можно получить через метод GetTestSuiteByIdAsync, который использует наименование проекта, идентификатор плана тестирования и идентификатор набора тесто, а также признак необходимости получения информации о дочерних объектах. Корневой набор тестов можно получить из свойств плана тестирования testPlan.RootSuite.Id. При этом существует метод GetTestSuitesForPlanAsync, который позволяет получить наборы тестов без необходимости получения корневого набора, но в рамках примера для обеспечения единого подхода, он не используется. Пример получения набора тестов:

TestSuite suiteDetail = TestManagementClient.GetTestSuiteByIdAsync(TeamProjectName, PlanId, suiteId, 1).Result;
Console.WriteLine(«Test Suite : {0} : {1} : {2}», suiteDetail.Id, suiteDetail.State, suiteDetail.Name);
//Sute Types: StaticTestSuite, RequirementTestSuite, DynamicTestSuite

Console.WriteLine(«Suite Type : {0} : {1}», suiteDetail.SuiteType,

(suiteDetail.SuiteType == «StaticTestSuite») ? «» :

(suiteDetail.SuiteType == «DynamicTestSuite») ? «\nQuery: « + suiteDetail.QueryString : «Requirement ID « + suiteDetail.RequirementId.ToString());

if (suiteDetail.Parent == null) Console.WriteLine(«This is a root suite»);

Информация о дочерних наборах тестов находится в suiteDetail.Suites, а информация о наличии тестовых сценариев в suiteDetail.TestCaseCount.

Список тестов в наборе тестов можно получить через метод GetTestCasesAsync, который использует наименование проекта, идентификатор плана тестирования и идентификатор набора тестирования. Пример получения списка тестов и их рабочих элементов:

List<SuiteTestCase> testCases = TestManagementClient.GetTestCasesAsync(TeamProjectName, PlanId, suiteId).Result;
foreach(SuiteTestCase testCase in testCases)
{

int testId = 0;

if (!int.TryParse(testCase.Workitem.Id, out testId)) continue;


WorkItem wi = WitClient.GetWorkItemAsync(testId).Result;


Console.WriteLine(«Test: {0} — {1}», wi.Id, wi.Fields[«System.Title»].ToString());

foreach(var config in testCase.PointAssignments)


Console.WriteLine(«Run for: {0} : {1}», config.Tester.DisplayName, config.Configuration.Name);

}

Пример тестового приложения можно посмотреть здесь:

https://github.com/ashamrai/TFRestApi/tree/master/12.TFRestApiAppTestPlanDelails

Posted in Microsoft, Team Foundation Server, Visual Studio, visual studio team services | Отмечено: , , , , , | Leave a Comment »

Azure DevOps Services Rest Api. 11. Перемещение рабочих элементов в другой командный проект

Posted by Shamrai Alexander на Январь 29, 2019

Перемещение рабочих элементов может понадобиться в различных случаях:

  1. Рабочий элемент не там изначально зарегистрировали.
  2. Для команды создали новый командный проект и необходимо забрать ее требования и ошибки.
  3. И т.д.

Сама операция переноса не очень сложная (Move a work item to another project), но если необходимо перенести тысячи рабочих элементов, то ручная работа займет много времени.

Для переноса рабочего элемента необходимо обновить всего три поля:

  1. Командный проект
  2. Путь итерации
  3. Путь области

В эти поля нужно установить наименование нового командного проекта. Пример будет базироваться на статьях Выполнение запросов по рабочим элементам и Создание и редактирование рабочих элементов.

Пример для обновления одного рабочего элемента очень прост:

static
int MoveWorkItem(int WIId, string NewTeamProject)

{

Dictionary<string, object> fields = new Dictionary<string, object>();

fields.Add(«System.TeamProject», NewTeamProject);

fields.Add(«System.AreaPath», NewTeamProject);

fields.Add(«System.IterationPath», NewTeamProject);


var editedWI = UpdateWorkItem(WIId, fields);

Console.WriteLine(«Work item has been moved: « + editedWI.Id.Value);


return editedWI.Id.Value;

}

static WorkItem UpdateWorkItem(int WIId, Dictionary<string, object> Fields)

{

JsonPatchDocument patchDocument = new JsonPatchDocument();


foreach (var key in Fields.Keys)

patchDocument.Add(new JsonPatchOperation()

{

Operation = Operation.Add,

Path = «/fields/» + key,

Value = Fields[key]

});


return WitClient.UpdateWorkItemAsync(patchDocument, WIId).Result;

}

Если же нам необходимо перенести большое количество рабочих элементов, то предварительно необходимо создать запрос по рабочим элементам, который выберет их все (Create and save managed queries with the query editor). Далее запрос можно выполнить и получить все идентификаторы и выполнить обновление каждого рабочего элемента:

List<int> wis = RunStoredQuery(teamProjectOld, queryPath);

foreach (int wiId in wis) MoveWorkItem(wiId, teamProjectNew);

В истории рабочего элемента будет соответствующая запись:

Пример тестового приложения можно посмотреть здесь:

https://github.com/ashamrai/TFRestApi/tree/master/11.TFRestApiAppMoveWorkItems

Posted in Microsoft, Team Foundation Server, Team Foundation Server FAQ, Visual Studio, visual studio team services | Отмечено: , , , , , | Leave a Comment »

Azure DevOps Services Rest Api. 10. Управление настройками команд

Posted by Shamrai Alexander на Декабрь 29, 2018

<< Перейти в радел «Azure DevOps Services (TFS/VSTS) Rest Api»

Настройки команды редактируются через клиент WorkHttpClient, который включает в себя как настройки команды, так и настройки журналов, досок, планов поставок, производительности команды и т.д. В рамках данной статьи мы рассмотрим только наиболее часто изменяемые настройки: путь итерации, путь области и используемые командой журналы.

Перед тем как приступить к работе с настройками команды, необходимо создать ее контекст. Для этого создается новый объект TeamContext, который инициализируется с двумя параметрами: имя проекта и имя команды. Если же нам необходимо получить контекст команды по умолчанию, то можно передавать только наименование проекта. Создание контекста для команды по умолчанию:

TeamContext teamContext = new TeamContext(TeamProjectName);

Итерации

Управление итерациями позволяет минимизировать трудозатраты администраторов команд. Если используются общие итерации во всех или многих командах, то их можно добавлять в автоматическом режиме сразу всем командам после добавления в командный проект. Также можно периодически очищать старые итерации, чтоб они не накапливались в настройках команды.

Перед добавлением итерации в команду, необходимо, чтобы она была уже создана в настройках проекта. Создание итерации рассматривалось в статье Управление областями и итерациями в командном проекте.

Для добавления итерации в команду используется метод PostTeamIterationAsync, который принимает в качестве аргументов TeamSettingsIteration и контекст команды. Для объекта TeamSettingsIteration важен только уникальный идентификатор итерации, который можно получить через метод GetClassificationNodeAsync класса WorkItemTrackingHttpClient. Пример добавления итерации:

WorkItemClassificationNode projectIt = WitClient.GetClassificationNodeAsync(TeamProjectName, TreeStructureGroup.Iterations, iterationName).Result; // get iteration from project

TeamSettingsIteration teamIt = WorkClient.PostTeamIterationAsync(new TeamSettingsIteration { Id = projectIt.Identifier }, teamContext).Result; //add iteration to a team by guid

Console.WriteLine(«Added iteration « + teamIt.Name);

Удаление итерации из настроек команды выполняется подобным методом через метод DeleteTeamIterationAsync, при этом передаются контекст команды и идентификатор итерации:

WorkItemClassificationNode projectIt = WitClient.GetClassificationNodeAsync(TeamProjectName, TreeStructureGroup.Iterations, iterationNameToRemove).Result;

WorkClient.DeleteTeamIterationAsync(teamContext, projectIt.Identifier).SyncResult(); //delete iteration from team settings by guid

Console.WriteLine(«Removed iteration « + projectIt.Name);

Просмотреть набор итераций, которые использует команда, можно через метод GetTeamIterationsAsync. Данный метод принимает в качестве параметров контекст команды и временной фрейм итерации (прошедшая, текущая и будущая). Пример выполнения метода:

TeamSettingsIteration currentiteration = (WorkClient.GetTeamIterationsAsync(teamContext, «Current»).Result).FirstOrDefault();

В результаты мы получаем объект TeamSettingsIteration, который включает:

  • Id – GUID итерации
  • Name – наименование итерации
  • Path – путь итерации
  • Attributes – дополнительные атрибуты итерации:
    • StartDate – дата начала итерации
    • FinishDate – дата окончания итерации
    • TimeFrame – фрейм итерации Past (прошедшая), Current (текущая), Future (будущая)

Пример использования:

List<TeamSettingsIteration> teamIterations = WorkClient.GetTeamIterationsAsync(teamContext).Result; //get all iterations

Console.WriteLine(«Team Iterations: «);

foreach (TeamSettingsIteration teamIteration in teamIterations)

Console.WriteLine(«{0} : {1} : {2}-{3}», teamIteration.Attributes.TimeFrame, teamIteration.Name, teamIteration.Attributes.StartDate, teamIteration.Attributes.FinishDate);

Области

Области имеет смысл автоматически обновлять, если основное управление ответственностями команд выполняется во внешней системе, например, через CMDB и их необходимо переносить в соответствующие команды Azure DevOps.

Как и с итерациями область должна быть сначала добавлена в настройки командного проекта (Управление областями и итерациями в командном проекте). Но оперирование областями в настройках команды отличается от управления итерациями.

Посмотреть список областей команды можно через метод GetTeamFieldValuesAsync, который вернет объект TeamFieldValues с атрибутами:

  • DefaultValue – строковое значение области по умолчанию.
  • Values – список областей TeamFieldValue, которые будет контролировать команда. TeamFieldValue включает наименование области Value и признак включения в контроль дочерних областей IncludeChildren.

Пример использования:

TeamFieldValues teamAreas = WorkClient.GetTeamFieldValuesAsync(teamContext).Result; //Get All Areas

Console.WriteLine(«Default Area: « + teamAreas.DefaultValue);

Console.WriteLine(«Team Areas : «);

foreach (TeamFieldValue teamField in teamAreas.Values)

Console.WriteLine(«\t» + teamField.Value + ((teamField.IncludeChildren)? » (include sub-areas)» : «»));

Обновление набора областей команды выполняется через один метод UpdateTeamFieldValuesAsync с параметром TeamFieldValuesPatch. TeamFieldValuesPatch включает те же атрибуты, что и TeamFieldValues. Т.е. для обновления настройки можно взять текущие значения и добавить или удалить необходимые:

string[] areas = { @»Application\WinClient», @»Application\WebClient» };

TeamFieldValues currentTeamAreas = WorkClient.GetTeamFieldValuesAsync(teamContext).Result; // get current areas

TeamFieldValuesPatch teamAreasPatch = new TeamFieldValuesPatch();

List<TeamFieldValue> newTeamAreas = new List<TeamFieldValue>(currentTeamAreas.Values); // just copy old areas. Here we may remove unneeded areas

foreach (string area in areas)

newTeamAreas.Add(new TeamFieldValue { Value = TeamProjectName + «\\» + area, IncludeChildren = false }); // add new areas

teamAreasPatch.DefaultValue = currentTeamAreas.DefaultValue;

teamAreasPatch.Values = newTeamAreas;

TeamFieldValues updatedTeamAreas = WorkClient.UpdateTeamFieldValuesAsync(teamAreasPatch, teamContext).Result;

Общие настройки

Изменение общих настроек редко когда может понадобиться через автоматизацию, возможно, если только основные журналы организации отличаются от настроек по умолчанию и их проще выполнить автоматически.

Получить текущие настройки можно через метод GetTeamSettingsAsync, который возвращает TeamSetting с атрибутами:

  • DefaultIteration – итерация, которая автоматически подставляется при создании нового рабочего элемента в контексте команды.
  • BacklogIteration – в рамках какой итерации отображаются рабочие элементы журнала требований.
  • DefaultIterationMacro – подстановка для определения текущей итерации: https://docs.microsoft.com/ru-ru/azure/devops/boards/queries/query-by-date-or-current-iteration?view=vsts#query-for-items-based-on-belonging-to-a-teams-current-iteration
  • BacklogVisibilities – список всех журналов, которые используются в проекте, и их отображение в команде.
  • WorkingDays – список дней, которые учитываются как рабочие для команды.

Пример выполнения:

TeamContext teamContext = new TeamContext(TeamProjectName, TeamName);

TeamSetting teamSetting = WorkClient.GetTeamSettingsAsync(teamContext).Result;

Console.WriteLine(«Settings for the team « + TeamName);

Console.WriteLine(«Backlog Iteration : « + teamSetting.BacklogIteration.Name);

Console.WriteLine(«Default Iteration : « + teamSetting.DefaultIteration.Name);

Console.WriteLine(«Macro of Iteration : « + teamSetting.DefaultIterationMacro);

Console.WriteLine(«Categories of backlog:»);

foreach(string bkey in teamSetting.BacklogVisibilities.Keys)


if (teamSetting.BacklogVisibilities[bkey]) Console.WriteLine(«\t» + bkey);

Console.WriteLine(«Working days :»);

foreach (var wday in teamSetting.WorkingDays) Console.WriteLine(«\t» + wday.ToString());

switch (teamSetting.BugsBehavior)

{

case BugsBehavior.AsRequirements:

Console.WriteLine(«Bugs Behavior: Bugs in a requirements backlog.»);

break;

case BugsBehavior.AsTasks:

Console.WriteLine(«Bugs Behavior: Bugs in a sprint backlog as tasks.»);

break;

case BugsBehavior.Off:

Console.WriteLine(«Bugs Behavior: Find bugs through queries.»);

break;

}

Обновление настроек выполняется через метод UpdateTeamSettingsAsync с параметром TeamSettingsPatch, который имеет те же атрибуты, как и TeamSetting. При этом будут обновляться только те настройки, атрибуты которых были проинициализированы. Обновление видимых команде журналов можно выполнить следующим образом:

TeamSetting teamSetting = WorkClient.GetTeamSettingsAsync(teamContext).Result;

TeamSettingsPatch teamSettingsPatch = new TeamSettingsPatch();

teamSettingsPatch.BacklogVisibilities = teamSetting.BacklogVisibilities;

if (teamSettingsPatch.BacklogVisibilities.ContainsKey(«Microsoft.EpicCategory») && teamSettingsPatch.BacklogVisibilities[«Microsoft.EpicCategory»])

teamSettingsPatch.BacklogVisibilities[«Microsoft.EpicCategory»] = false;

if (teamSettingsPatch.BacklogVisibilities.ContainsKey(«Microsoft.FeatureCategory») && teamSettingsPatch.BacklogVisibilities[«Microsoft.FeatureCategory»])

teamSettingsPatch.BacklogVisibilities[«Microsoft.FeatureCategory»] = false;

teamSetting = WorkClient.UpdateTeamSettingsAsync(teamSettingsPatch, teamContext).Result;

Пример тестового приложения можно посмотреть здесь:

https://github.com/ashamrai/TFRestApi/tree/master/10.TFRestApiAppManageTeamSettings

English version

Posted in Microsoft, Team Foundation Server, Team Foundation Server FAQ, Visual Studio, visual studio team services | Отмечено: , , , , | Leave a Comment »

Azure DevOps Services Rest Api. 9. Управление командами проекта

Posted by Shamrai Alexander на Декабрь 27, 2018

<< Перейти в радел «Azure DevOps Services (TFS/VSTS) Rest Api»

Управление командами выполняется довольно просто через TeamHttpClient. Для управления командами достаточно знать название команды и имя проекта, в котором она находится или будет находится. Классом, который содержит информацию о команде, является класс WebApiTeam со следующими основными свойствами:

  • Id – идентификатор.
  • Name – наименование команды.
  • Description – описание команды.
  • ProjectName – наименование проекта, в которую входит команда.
  • ProjectId – идентификатор проекта, в которую входит команда.

Для получения информации о команде используется метод GetTeamAsync, который использует только два параметра имя проекта и имя команды или их идентификаторы. Получить список всех команд можно через GetTeamsAsync, указав на вход только наименование проекта:

List<WebApiTeam> teams = TeamClient.GetTeamsAsync(TeamProjectName).Result;

Console.WriteLine(«Project Teams:»);

foreach (WebApiTeam team in teams) Console.WriteLine(team.Name);

Если необходимо получить информацию об участниках команды, то можно выполнить метод GetTeamMembersWithExtendedPropertiesAsync, в который передаются все те же имя проекта и имя команды. Участник команды описывается классом TeamMember, который содержит два свойства:

  • IsTeamAdmin – является ли участник команды администратором.
  • Identity – информация об учетной записи пользователя.

Пример изучения состава команды:

List<TeamMember> teamMembers = TeamClient.GetTeamMembersWithExtendedPropertiesAsync(TeamProjectName, TeamName).Result;

string teamAdminName = (from tm in teamMembers where tm.IsTeamAdmin == true
select tm.Identity.DisplayName).FirstOrDefault();

if (teamAdminName != null) Console.WriteLine(«Team Administrator:» + teamAdminName);

Console.WriteLine(«Team members:»);

foreach (TeamMember teamMember in teamMembers)

if (!teamMember.IsTeamAdmin) Console.WriteLine(teamMember.Identity.DisplayName);

 

Для создания и обновления команды используются методы CreateTeamAsync и UpdateTeam соответственно. Основные параметры это:

  • team – объект WebApiTeam, в котором устанавливаются наименование и описание команды.
  • projectId – наименование проекта команды
  • teamId – идентификатор существующей команды, который используется только при обновлении наименования или описания.

Пример обновления команды:

WebApiTeam team = TeamClient.GetTeamAsync(TeamProjectName, TeamName).Result;

WebApiTeam updatedTeam = new WebApiTeam {

Name = team.Name + » updated»,

Description = team.Description.Replace(«Created», «Updated»)

};

updatedTeam = TeamClient.UpdateTeamAsync(updatedTeam, team.ProjectName, team.Name).Result;

Console.WriteLine(«The team ‘{0}’ has been updated in the team project ‘{1}'», updatedTeam.Name, updatedTeam.ProjectName);

 

Для удаления команды используется метод DeleteTeamAsync с наименованием проекта и удаляемой команды:

TeamClient.DeleteTeamAsync(TeamProjectName, TeamName).SyncResult();

Пример тестового приложения можно посмотреть здесь:

https://github.com/ashamrai/TFRestApi/tree/master/09.TFRestApiAppManageTeams

English version

Posted in Microsoft, Team Foundation Server, Team Foundation Server FAQ, Visual Studio, visual studio team services | Отмечено: , , , , | Leave a Comment »

Azure DevOps Services Rest Api. 8. Управление областями и итерациями в командном проекте

Posted by Shamrai Alexander на Декабрь 26, 2018

<< Перейти в радел «Azure DevOps Services (TFS/VSTS) Rest Api»

Управление областями и итерациями выполняется через WorkItemTrackingHttpClient одинаковыми методами, отличаются только некоторые моменты. Общим классом, который описывает области и итерации, является класс WorkItemClassificationNode. Он включает следующие основные свойства:

  • Id – идентификатор области или итерации.
  • Name – наименование области или итерации.
  • StructureType – тип объекта: «TreeNodeStructureType.Area» и «TreeNodeStructureType.Iteration».
  • Attributes – содержит дату начала и окончания итерации, которые доступны через ключи startDate и finishDate.

Создание области и итерации выполняется через метод CreateOrUpdateClassificationNodeAsync, который включает в себя следующие параметры:

  • postedNode – объект WorkItemClassificationNode, который содержит наименование и атрибуты.
  • project – имя командного проекта, в котором будет создана область или итерация.
  • structureGroup – тип объекта: TreeStructureGroup.Areas или TreeStructureGroup.Iterations
  • path – путь к родительской области или итерации, если она необходима.

Пример для создания области. Для создания области важно только наименование и родительская область. Если родительская область не указана, то новая область будет размещена в корне командного проекта

WorkItemClassificationNode newArea = new WorkItemClassificationNode();

newArea.Name = AreaName;

WorkItemClassificationNode result = WitClient.CreateOrUpdateClassificationNodeAsync(newArea, TeamProjectName, TreeStructureGroup.Areas, ParentAreaPath).Result;

 

Пример для создания итерации. Итерация создается также, как и область, но кроме этого можно использовать дополнительные необязательные атрибуты startDate и finishDate.

WorkItemClassificationNode newIteration = new WorkItemClassificationNode();

newIteration.Name = IterationName;

newIteration.Attributes = new Dictionary<string, object>();

newIteration.Attributes.Add(«startDate», StartDate);

newIteration.Attributes.Add(«finishDate», FinishDate);

WorkItemClassificationNode result = WitClient.CreateOrUpdateClassificationNodeAsync(newIteration, TeamProjectName, TreeStructureGroup.Iterations, ParentIterationPath).Result;

 

Обновление области и итерации выполняется через UpdateClassificationNode с теми же параметрами, как и в CreateOrUpdateClassificationNodeAsync. При этом нужно обращать внимание на параметр path. Он будет обязательным для области или итерации, если она имеет родителя. Если для такой области или итерации не указать path, то она будет перемещена в корень командного проекта. Т.е. если нам нужно переименовать или изменить даты, то необходимо снова указать необходимый путь, в котором будет находится область или итерация.

Удаление области или итерации выполняется через DeleteClassificationNodeAsync с параметрами:

  • project – имя командного проекта, в котором находится область или итерация.
  • structureGroup – тип объекта: TreeStructureGroup.Areas или TreeStructureGroup.Iterations
  • path – путь удаляемой области или итерации.
  • reclassifyId – идентификатор новой области или итерации, в которую будут перемещены рабочие элементы, которые находятся в удаляемой области или итерации.

Пример удаления.

WorkItemClassificationNode newNode = WitClient.GetClassificationNodeAsync(

TeamProjectName,

treeStructureGroup,

NewNodePath, 4).Result;

WitClient.DeleteClassificationNodeAsync(TeamProjectName, treeStructureGroup, NodePath, newNode.Id).SyncResult();

 

Пример тестового приложения можно посмотреть здесь:

https://github.com/ashamrai/TFRestApi/tree/master/08.TFRestApiAppAreasAndIterations

English version

Posted in Microsoft, Team Foundation Server, Team Foundation Server FAQ, Visual Studio, visual studio team services | Отмечено: , , , , , | Leave a Comment »

(VSTS) Azure DevOps Services Rest Api. 3. Создание и редактирование рабочих элементов

Posted by Shamrai Alexander на Сентябрь 20, 2018

<< Перейти в радел «Azure DevOps Services (TFS/VSTS) Rest Api»

Для создания и редактирования рабочих элементов используется клиент WorkItemTrackingHttpClient с методами CreateWorkItemAsync и UpdateWorkItemAsync. Основным параметром, который используется для создания и обновления рабочих элементов, является JsonPatchDocument, который содержит информацию о полях в виде списка JsonPatchOperation.

JsonPatchOperation включает в себя следующие поля:

  • Operation – операция, выполняемая с полем:
    • Add – вставить новое значение.
    • Remove – удалить значение из поля.
    • Replace – заменить значение в поле.
    • Test – проверить значение в поле перед обновлением рабочего элемента.
  • Path – путь к полю, значение которого обновляется. Путь поля выглядит как «/fields/{Имя_поля}» или «/fields/{Ссылочное_имя_поля}»
  • Value – значение поля.

Создание выполняется через CreateWorkItemAsync с параметрами JsonPatchDocument, имя проекта и название типа рабочего элемента:

Dictionary<string, object> fields = new Dictionary<string, object>();
fields.Add(«Title», «Bug from app»);
fields.Add(«Repro Steps», «<ol><li>Run app</li><li>Crash</li></ol>»);
fields.Add(«Priority», 1);

var newBug = CreateWorkItem(«TFSAgile», «Bug», fields);

static WorkItem CreateWorkItem(string ProjectName, string WorkItemTypeName, Dictionary<string, object> Fields)
{

JsonPatchDocument patchDocument = new JsonPatchDocument();

foreach (var key in Fields.Keys)

patchDocument.Add(new JsonPatchOperation() {

Operation = Operation.Add,
Path = «/fields/» + key,
Value = Fields[key]

});

return WitClient.CreateWorkItemAsync(patchDocument, ProjectName, WorkItemTypeName).Result;

}

Обновление выполняется через UpdateWorkItemAsync с параметрами JsonPatchDocument и идентификатор рабочего элемента:

Dictionary<string, object> fields = new Dictionary<string, object>();
fields.Add(«Title», «Bug from app updated»);
fields.Add(«Repro Steps», «<ol><li>Run app</li><li>Crash</li><li>Updated step</li></ol>»);
fields.Add(«History», «Comment from app»);
var editedBug = UpdateWorkItem(WIId, fields);

static WorkItem UpdateWorkItem(int WIId, Dictionary<string, object> Fields)
{

JsonPatchDocument patchDocument = new JsonPatchDocument();

foreach (var key in Fields.Keys)

patchDocument.Add(new JsonPatchOperation()
{

Operation = Operation.Add,
Path = «/fields/» + key,
Value = Fields[key]

});

return WitClient.UpdateWorkItemAsync(patchDocument, WIId).Result;

}

Пример тестового приложения можно посмотреть здесь:

https://github.com/ashamrai/TFRestApi/tree/master/03.TFRestApiAppCreateEditWorkItems

English version

Posted in Microsoft, Team Foundation Server, Visual Studio, visual studio team services | Отмечено: , , , , | Leave a Comment »

VSTS Rest Api. 2. Получение рабочих элементов

Posted by Shamrai Alexander на Сентябрь 11, 2018

<< Перейти в радел «Azure DevOps Services (TFS/VSTS) Rest Api»

Для получения доступа к рабочим элементам и их типам используется клиент WorkItemTrackingHttpClient со следующими методами:

  • Для получения одного рабочего элемента GetWorkItemAsync или нескольких GetWorkItemsAsync со следующими основными параметрами:
    • Id – идентификатор рабочего элемента, который необходимо получить. Для GetWorkItemsAsync используется список идентификаторов.
    • fields – список полей, которые необходимо получить в рабочем элементе
    • asOf – строка, которая содержит дату, которой должно соответствовать содержание рабочего элемента.
    • expand – получить расширенные свойства рабочего элемента. Возможные варианты (на практике используются обычно all и relations):
      • all – получить все свойства.
      • fields – получить только поля.
      • links – получить дополнительно справочные ссылки.
      • none – без дополнительных свойств.
      • relations – получить дополнительно информацию о связях.
  • Для типов рабочих элементов GetWorkItemTypeAsync со следующими параметрами:
    • project – имя проекта
    • type – имя типа рабочего элемента

Класс рабочего элемента можно представить в следующем виде:

public class
WorkItem

{

public int? Id { get; set; }

public int? Rev { get; set; }

public
IDictionary<string, object> Fields { get; set; }

public
IList<WorkItemRelation> Relations { get; set; }

public
ReferenceLinks Links { get; set;
}

}

Поля класса:

  • Id – идентификатор рабочего элемента.
  • Rev – номер версии рабочего элемента.
  • Fields – словарь в виде «имя поля» — «его значение». Этот список содержит только поля, которые имеют установленные значения. Если нужно знать наличие поля в типе рабочего элемента, то его можно получить через GetWorkItemTypeAsync, как указано в примере.
  • Relations – список связей рабочего элемента.
  • Links – класс с дополнительными вспомогательными ссылками на сам рабочий элемент, его тип, поля, истории и т.д.

Пример вызовов методов для получения рабочих элементов:

  • Получить один рабочий элемент:


static WorkItem GetWorkItem(int Id)

{

return WitClient.GetWorkItemAsync(Id).Result;

}

  • Получить рабочий элемент и его связи:


static WorkItem GetWorkItemWithRelations(int Id)

{

return WitClient.GetWorkItemAsync(Id, expand: WorkItemExpand.Relations).Result;

}

  • Получить тип рабочего элемента:


static WorkItemType GetWorkItemType(WorkItem WI)

{

return WitClient.GetWorkItemTypeAsync((string)WI.Fields[«System.TeamProject»], (string)WI.Fields[«System.WorkItemType»]).Result;

}

Пример приложения можно посмотреть здесь:

https://github.com/ashamrai/TFRestApi/tree/master/02.TFRestApiAppGetWorkItems

English version

Posted in Microsoft, Visual Studio, visual studio team services | Отмечено: , , , , | Leave a Comment »

VSTS Rest Api. 1. Подключение к сервису

Posted by Shamrai Alexander на Август 30, 2018

<< Перейти в радел «Azure DevOps Services (TFS/VSTS) Rest Api»

Для того, чтобы взаимодействовать с VSTS или TFS, можно использовать несколько подходов:

  1. Разработать собственные библиотеки через HttpClient, что не является сложным, и пример можно посмотреть здесь.
  2. Использовать существующие nugget пакеты, чтобы упростить себе жизнь: Microsoft.TeamFoundationServer.Client.

Пример установки пакетов и результата отображен ниже.

Рисунок 1. Поиск пакета для установки

Рисунок 2. Обновленные ссылки проекта

Подключение можно выполнить через VssConnection несколькими методами:

  • Подключение к TFS с использованием текущего пользователя:

VssConnection connection = new VssConnection(new Uri(ServiceURL), new VssCredentials());

  • Подключение к TFS с указанием пользователя и его пароля:

VssConnection connection = new VssConnection(new Uri(ServiceURL), new WindowsCredential(new NetworkCredential(User, Password)));

VssConnection connection = new VssConnection(new Uri(ServiceURL), new VssBasicCredential(string.Empty, PAT));

Для дальнейшего взаимодействия необходимо создать клиентов следующим образом:

WitClient = Connection.GetClient<WorkItemTrackingHttpClient>();

BuildClient = Connection.GetClient<BuildHttpClient>();

ProjectClient = Connection.GetClient<ProjectHttpClient>();

GitClient = Connection.GetClient<GitHttpClient>();

TfvsClient = Connection.GetClient<TfvcHttpClient>();

TestManagementClient = Connection.GetClient<TestManagementHttpClient>();

Перечень основных клиентов:

  • WorkItemTrackingHttpClient – клиент для работы с рабочими элементами.
  • GitClient – клиент для работы с хранилищем исходного кода Git.
  • TfvsClient – клиент для работы с хранилищем исходного кода TFVC.
  • TestManagementClient – клиент для работы с тестовыми планами, тестами и т.д.
  • BuildClient – клиент для работы со сборками.
  • ProjectClient – клиент для работы с командными проектами.

Пример приложения можно посмотреть здесь: https://github.com/ashamrai/TFRestApi/tree/master/01.TFRestApiApp

 

English version.

Posted in Microsoft, Team Foundation Server FAQ, Visual Studio, visual studio team services, Work Item Tracking FAQ | Отмечено: , , , , | Leave a Comment »

Динамическое изменение свойств веб приложений при развертывании релизов Visual Studio Team Services

Posted by Shamrai Alexander на Июнь 29, 2018

При развертывании веб-приложений можно использовать различные Web.config или appsettings.json, чтобы применять различные строки подключении к базам, служебные логины и пароли и т.д. для различных сред, на которых веб приложение будет выполняться. Но, если хранить такие данные для среды разработки и тестовых стендов еще можно, то такие данные для промышленных сред желательно убрать от общих глаз. Одним из элементов, который позволяет упростить ситуацию с хранением учетных данных, строк подключения и т.д., является трансформация элементов конфигурации. Т.е. есть возможность динамически и прозрачно для разработчиков и поддержки устанавливать необходимые конфигурации в зависимости от среды развертывания. Данный элемент настраивается на шаге развертывания веб приложения в Azure или IIS. Пример для указания какие фалы изменять показан ниже:

А в свойствах определения релиза уже указываются: какие свойства необходимо заменить на какие значения, при этом конфиденциальные данные могут быть скрыты:

Posted in Microsoft, Team Foundation Server, Visual Studio, visual studio team services | Отмечено: , , , , | Leave a Comment »

 
%d такие блоггеры, как: