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

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

Archive for the ‘Microsoft’ Category

Динамическое изменение свойств веб приложений при развертывании релизов 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 »

Как установить порог качества для развертывания релиза в TFS и VSTS

Posted by Shamrai Alexander на Май 15, 2018

Возможности TFS/VSTS Release Management позволяют обеспечить «врата качества» не только на основе утверждения от какого-то участника команды разработки, когда он в ручном режиме «дает добро» на развертывание релиза на необходимом стенде, но и на основе привязки к запросам по рабочим элементам. Это позволяет обеспечить следующие правила проверки для развертывания на стенде:

  1. Не превысили ли мы порог количества высоко приоритетных или важных ошибок на релиз или продукт.
  2. Все ли требования для данного релиза покрыты тестами.
  3. Все ли тесты для релиза закрыты после проверки.
  4. И т.д.

Приведем небольшой пример: на момент выкатки релиза не должно быть ошибок с критической важностью. Для этого нужно выполнить следующие шаги:

  • Предварительно необходимо подготовить запрос по рабочим элементам, который отберет необходимые ошибки:

  • Далее перейти на страницу редактирования релиза:

  • Перейти на свойства предварительных условий для развертывания в необходимой среде:

  • Выбрать в разделе Gates пункт Query Work Items

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

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

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

  • При просмотре журнала развертывания можно увидеть примерно следующий результат:

  • На основе полученной информации выполняются необходимые действия. Например, можно закрыть важные ошибки, если это забыли сделать тестировщики (что вряд ли). После этого релиз развернется автоматически через определенное время, которое тоже указывается в настройках. Либо можно отклонить развертывание, а потом отклонить релиз и заняться исправлением незакрытых проблем. Пример отмены выполнения развертывания:

Posted in Microsoft, Release Management FAQ, Team Foundation Server FAQ | Отмечено: , , , , | Leave a Comment »

Динамическая обработка событий TFS/VSTS на основе скриптового выполнения С# кода и REST API

Posted by Shamrai Alexander на Март 30, 2018

Подготовка различных синхронизационных «мостиков» между системами или обработка событий для отдельной системы и выполнение в ней изменений заставляет создавать отдельные модули (веб-сервисы, исполняемые модули и т.д.). Это в свою очередь включает необходимость прохождения циклов тестирования, остановки сервисов, развертывания при их изменении в дальнейшем и т.д. Конечно можно идти через использование скриптовых языков, например, Perl для IBM Rational или PowerShell для TFS/VSTS для выполнения каких-либо действий. Но в данном случае необходимо расширять свои знания на необходимые области, что требует дополнительных усилий и времени. Поэтому можно также воспользоваться возможностью написать скрипт на основе языка, который используется для создания интеграционного механизма. Например, можно рассмотреть .Net C#. Для данного языка существует nugget пакет, который позволяет запускать код .Net C# в виде скриптов, которые можно формировать динамически. При этом можно использовать не только стандартные (системные) наборы библиотек, а также можно подключать собственные или внешние библиотеки.

Рассмотрим использование такой возможности на примере обработки событий в TFS (примеры перехвата таких событий можно посмотреть здесь и здесь). Задача для примера будет простая: записать в комментарий при изменение рабочего элемента типа «Bug», что событие было перехвачено. Пошаговая инструкция:

  • Для решения необходимо применить пакет для выполнения C# скриптов Scripting API Samples.
  • Также необходим пакет для взаимодействия с TFS/VSTS (в этом случае через REST API) Microsoft.TeamFoundationServer.Client.
  • Далее необходимо подготовить скрипт, который будет проверять: событие, которое пришло, удовлетворяет ли нашим критериям. Пример скрипта:

    «bool CheckConditionUpdated(WorkItemEvent.WorkItemEventUpdated InputWorkItem)

    {

    if (InputWorkItem == null) return false;

    if (InputWorkItem.resource.fields.ContainsKey(«»System.History»») && InputWorkItem.resource.fields[«»System.History»»].newValue == «»Changes from script»») return false;

    if (InputWorkItem.resource.revision.fields[«»System.WorkItemType»»] == «»Bug»») return true;

    return false;

    }

    CheckConditionUpdated(InputWorkItem)»;

    Смысл простой: проверяем переданный параметр с событием на наличие информации; проверяем, что событие, которые пришло, не является следствием изменения рабочего элемента самим сервисом; проверяем, что тип рабочего элемента – Bug. Скрипт возвращает true или false.

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

    var ScrOpt = ScriptOptions.Default.AddReferences(

    Assembly.GetAssembly(typeof(WorkItemEvent.WorkItemEventUpdated))

    ).AddImports(«System», «TFTypesLib»);

    Пример запуска скрипта с передачей параметров:

    _result = CSharpScript.RunAsync<bool>(_src, ScrOpt, new ScriptWiUpdatedHost { InputWorkItem = pInputWorkItem }).Result.ReturnValue;

  • Далее формируем скрипт для обработки события:

    «bool ProcessEvent(WorkItemEvent.WorkItemEventUpdated InputWorkItem)

    {

    if (InputWorkItem == null) return false;

    JsonPatchDocument PatchDocument = new JsonPatchDocument();

    PatchDocument.Add(

            new JsonPatchOperation()

    {

    Operation = Operation.Add,

    Path = «»/fields/System.History»»,

    Value = «»Changes from script»»

    }

    );

    VssCredentials Cred = new VssCredentials(true);

    WorkItemTrackingHttpClient WIClient = new WorkItemTrackingHttpClient(new Uri(«»http://tfs-srv:8080/tfs/DefaultCollection»&#187;), Cred);

    WorkItem result = WIClient.UpdateWorkItemAsync(PatchDocument, InputWorkItem.resource.revision.id).Result;

    return true;

    }

    ProcessEvent(InputWorkItem);»

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

    var ScrOpt = ScriptOptions.Default.AddReferences(

    Assembly.GetAssembly(typeof(WorkItemTrackingHttpClient)),

    Assembly.GetAssembly(typeof(JsonPatchDocument)),

    Assembly.GetAssembly(typeof(VssCredentials)),

    Assembly.GetAssembly(typeof(WorkItemEvent.WorkItemEventUpdated)),

    Assembly.GetAssembly(typeof(Uri))

    ).AddImports(


    «Microsoft.TeamFoundation.WorkItemTracking.WebApi»,


    «Microsoft.TeamFoundation.WorkItemTracking.WebApi.Models»,


    «Microsoft.VisualStudio.Services.WebApi.Patch.Json»,


    «Microsoft.VisualStudio.Services.WebApi.Patch»,


    «Microsoft.VisualStudio.Services.Common»,


    «System»,


    «TFTypesLib»

    );

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

Полный пример можно посмотреть здесь: https://github.com/ashamrai/tfevents/tree/master/TFSServicesMVCRoslyn

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

Использование решения на основе веб-приложения ASP .Net Core для обработки веб-хуков TFS и VSTS

Posted by Shamrai Alexander на Март 1, 2018

Данная публикация является развитием предыдущей статьи и базовые элементы берутся из нее: Создание WCF сервиса для обработки событий из Team Foundation Server или Team Services.

Если говорить о различиях создания сервиса обработки на основе ASP .Net Core и WCF, то как можно выделить следующее:

  • WCF сервис не умеет разбирать списки в приходящих json. Для того, чтобы «научить» его делать это, необходимо использовать Newtonsoft.Json и дополнительный код в классах, что незначительно повышает трудоемкость поддержки. Веб-Api на основе ASP .Net Core в свою очередь не требует никакой дополнительной доработки для разбора json в теле запроса, только лишь необходимо правильно составить класс, структуру которого можно подсмотреть при тестировании запроса:

Рисунок 1. Отображение структуры json при тестировании запроса

Таблица 1. Реализация класса для обработки json

Реализация WCF и Newtonsoft.Json Реализация ASP .Net Core
public class WorkItemEventCore
{

[JsonProperty(«subscriptionId»)]
public string subscriptionId;
[JsonProperty(«notificationId»)]
public int notificationId;
[JsonProperty(«id»)]
public string id;
[JsonProperty(«eventType»)]
public string eventType;
[JsonProperty(«publisherId»)]
public string publisherId;
[JsonProperty(«message»)]
public MessageClass message;
[JsonProperty(«detailedMessage»)]
public DetailedMessageClass detailedMessage;
[JsonProperty(«resourceVersion»)]
public string resourceVersion;
[JsonProperty(«resourceContainers»)]
public Dictionary<string, ResourceContainerClass> resourceContainers;
[JsonProperty(«createdDate»)]
public string createdDate;

}

public class WorkItemEventCore
{
public string subscriptionId;

public int notificationId;

public string id;

public string eventType;

public string publisherId;

public MessageClass message;
public DetailedMessageClass detailedMessage;

public string resourceVersion;

public Dictionary<string, ResourceContainerClass> resourceContainers;

public string createdDate;

}

  • WCF решение можно размещать и на веб-сервере, и как отдельно стоящий сервис. Веб-приложение ASP .Net Core в свою очередь может также работать через веб-сервер, как сервис, но и дополнительно решение может являться мульти платформенным.

Поэтому, исходя из возможностей и перспектив развития своего решения, выбираем необходимую платформу. В текущем случае — веб-приложение ASP .Net Core. Для создания данного решения необходимо выполнить следующие шаги:

  • Создать веб-приложение ASP.Net Core

Рисунок 2. Создание веб-приложения

  • Выбрать шаблон проекта Веб-API

Рисунок 3. Выбор решения веб-api

namespace TFSServices.Controllers

{

[Produces(«application/json»)]

[Route(«api/TS/workitems/created»)]
public class TeamServicesWICreatedController : Controller

{
// POST: api/TS/workitems/created

[HttpPost]
public void Post([FromBody]TSEvents.WorkItemEvent.WorkItemEventCreated value)

{

}

}

[Produces(«application/json»)]

[Route(«api/TS/workitems/updated»)]


public class TeamServicesWIUpdatedController : Controller

{
// POST: api/TS/workitems/updated

[HttpPost]
public void Post([FromBody]TSEvents.WorkItemEvent.WorkItemEventUpdated value)

{

}

}

}

  • Далее тестируем запрос, при этом указываем относительный адрес, который присутствует при определении контроллера ([Route(«api/TS/workitems/updated»)]), и получаем следующий результат:

Рисунок 4. Указание необходимого адреса и тестирование решение

Рисунок 5. Отладка решения

Пример решения данной статьи находится здесь: https://github.com/ashamrai/tfevents

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

Дополнительная настройка стандартных RDL отчетов Team Foundation Server

Posted by Shamrai Alexander на Февраль 23, 2018

Отчеты на основе SQL Server Reporting Services, которые поставляются «из коробки» в TFS, предоставляют достаточно информации для понимания ситуации с качеством и текущими требованиями в работе. Весь список отчетов можно посмотреть здесь: https://docs.microsoft.com/en-us/vsts/report/sql-reports/reporting-services-reports. Команде конечно может хватать оперативных отчетов, которые предоставляет TFS (VSTS) на основе отчетов от запросов по рабочим элементам, цифровым панелям и т.д.: https://docs.microsoft.com/en-us/vsts/report/dashboards/overview. Но, если же нет желания предоставлять доступ к проектам и исходному коду внешним пользователям, а на это может быть достаточно причин, то можно воспользоваться отчетам SQL Server Reporting Services и Power BI. В рамках данной статьи мы рассмотрим, как можно дополнительно настроить один из стандартных отчетов SQL Server Reporting Services.

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

  • Включена ли отчетность SQL Server Reporting Services. Если нет, то ее можно подключить этими шагами: https://docs.microsoft.com/en-us/vsts/report/admin/add-reports-to-a-team-project
  • Есть ли отчеты для выбранного проекта. Если нет, то можно подключить следующими шагами: https://ashamray.wordpress.com/2018/02/16/create_tfs_default_reports/
  • Выбрать отчет для дополнительной настройки. В нашем случае отчет «Обзор требований» из проекта на основе шаблона CMMI, который дает полную информацию о состоянии реализации требований и их тестирования.

Рисунок 1. Пример отчета

  • Выбрать инструмент для реализации изменений. Тут будем использовать SQL Server Report Builder.
  • Открыть отчет через выбранный инструмент:

Рисунок 2. Открытие отчета

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

Рисунок 3. Настройка параметра отчета

Параметры, которые имеет смысл настраивать:

  • IncludeTasks – отображать ли дочерние задачи в отчете. По умолчанию отображаются только требования без какой-либо декомпозиции. Если необходимо отображать задачи, то в значении по умолчанию устанавливаем =1.

Рисунок 4. Включение дочерних задач

Рисунок 5. Пример работы отчета

  • DisplayOwnValues – учитывать ли в трудозатратах их значение в суммарных задачах. По умолчанию установлено, что учитываются только значения конечных задач.
  • DeliverableCategory – список типов рабочих элементов, которые считаются как поставляемые типы рабочих элементов. По молчанию это требования и пользовательские истории. Но если мы хотим видеть декомпозицию выше, то мы можем добавить функции:

Рисунок 6. Добавление функции в общую структуру работ

Рисунок 7. Пример работы отчета

Вышеприведенные настройки по сути позволяют немного расширить представляемую информацию. Ниже рассмотрим еще два примера:

  1. Включение новых задач в отчет. По умолчанию учитываются только те задачи, которые были выведены из инициирующего состояния, т.е. взяты работу и потом выполнены. Все новые задачи при работе отчета игнорируются.
  2. Добавление дополнительного поля в общую таблицу отчета. Отчет отбирает достаточное количество полей, например, идентификатор, тип рабочего элемента. Но иногда есть необходимость отобразить какое-то свое пользовательское поле.

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

Рисунок 8. Изменение запроса

Рисунок 9. Пример запроса

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

Для того, чтобы включить в запрос новые задачи, необходимо закомментировать строки, которые отбрасывают эти задачи при построении иерархии данных. Это строка 98 в запросе:

Рисунок 10. Установка комментария вместо отбрасывания предложенных задач

Далее добавим поле, которого нет в стандартном наборе полей. По умолчанию список отбираемых полей можно посмотреть в свойствах набора данных:

Рисунок 11. Поля запроса

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

Рисунок 12. Создание нового набора данных

В конструкторе запроса необходимо выбрать представление CurrentWorkItemView и найти необходимое поле (Microsoft_VSTS_Common_Priority). Как правило, названия колонок для полей, которые подвергаются отчетности, именуются также как свойство Reference Name с заменой точек на подчеркивания.

Рисунок 13. Поле Важность

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

  • Добавить дополнительную колонку в таблицу Rollups (строка 227)

Рисунок 14. Новая колонка для отбора приоритета

  • Добавить извлечение поля приоритета (строка 259):

Рисунок 15. Получение приоритета из представления

  • Добавить столбец при обработке собственных значений (строка 390):

Рисунок 16. Добавление приоритета для собственных значений

  • Добавить колонку при создании результирующего набора данных (строка 431):

Рисунок 17. Добавление приоритета в результирующие данные

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

Рисунок 18. Добавление нового столбца таблицу отчета

Рисунок 19. Назначение в столбец поля приоритета

Кроме этого можно поправить форматирование, чтоб поле приоритета не выстраивалось в виде дерева.

Рисунок 20. Вызов свойства поля

Рисунок 21. Исправление отступа

Сохраняем изменения и в результате получим следующий вид:

Рисунок 22. Рабочий отчет

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

Как создать отчеты по умолчанию в Reporting Services для проекта Team Foundation Server

Posted by Shamrai Alexander на Февраль 16, 2018

<< Перейти в раздел «Team Foundation Server Admin FAQ»

По умолчанию, когда проект создается в TFS из веб-интерфейса, отчеты на основе Reporting Services не создаются. Однако отчеты дают неплохие возможности для подключения внешних заинтересованных лиц, включая возможность экспорта отчетов и подписки на отчеты, без необходимости обеспечения непосредственного доступа к проектам. Для того, чтобы «вернуть» набор отчетов по умолчанию, необходимо воспользоваться командой TfsConfig addProjectReports с параметрами:

/collection:’url к колекции проектов’

/teamProject:’имя проекат’

/template:’Шаблон для отчетов: CMMI, Agile или Scrum’

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

Детальная информация о команде: AddProjectReports

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

Создание WCF сервиса для обработки событий из Team Foundation Server или Team Services

Posted by Shamrai Alexander на Январь 24, 2018

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

Данная функция очень полезна, если необходимо добавить дополнительною автоматизацию, которую TFS/VSTS не поддерживают. Например, создание пула дочерних задач, при переводе рабочего элемента в определенное состояние, или установка критической даты рассмотрения дефекта в зависимости от его важности и т.д.

В этой статье мы рассмотрим возможность создания wcf сервиса, который будет в состоянии «слушать» сообщения, которые приходят из TFS или VSTS.

Пример, как создать wcf сервис, который способен принимать входящие сообщения через метод POST, можно посмотреть здесь: https://www.codeproject.com/Articles/275279/Developing-WCF-Restful-Services-with-GET-and-POST.

Основные моменты, которые стоит отметить при создании сервиса:

  • В файле определения сервиса «имя_сервиса.svc» добавить атрибут:

Factory=»System.ServiceModel.Activation.WebServiceHostFactory»

  • Для метода, который будет в дальнейшем использовать для приема сообщений от TFS/VSTS указать атрибуты, которые будут укажут, что метод POST и работать он будет в json формате.

[OperationContract]

[WebInvoke(Method = «POST», RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare)]

  • Указать входящий параметр для метода как поток, который в дальнейшем будет преобразован в строку, а потом в нужный класс:

void WorkItemChangedEvent(Stream EventData);

Для конвертирования некоторой базовой информации можно использовать следующий пример класса:

public class WorkItemEventCore

{

[JsonProperty(«subscriptionId«)]

public string subscriptionId;

[JsonProperty(«notificationId«)]

public int notificationId;

[JsonProperty(«id«)]

public string id;

[JsonProperty(«eventType«)]

public string eventType;

[JsonProperty(«publisherId«)]

public string publisherId;

[JsonProperty(«message«)]

public MessageClass message;

[JsonProperty(«resourceVersion«)]

public string resourceVersion;

[JsonProperty(«createdDate«)]

public string createdDate;

}

Данный класс используется в методе при десериализации строки в экземпляр с помощью библиотек Newtonsoft.Json:

StreamReader _reader = new StreamReader(pEventData, Encoding.UTF8);

string _eventStr = _reader.ReadToEnd();

WorkItemEventCore _wieventcorre = JsonConvert.DeserializeObject<WorkItemEventCore>(_eventStr);

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

Указывается адрес, на который отсылать сообщения, включая сервис и метод:

И после нажатия кнопки Test, можно получить информацию об успешности исполнения и пример отправленной нотификации:

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

Пример решения данной статьи находится здесь: https://github.com/ashamrai/tfevents

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

Как синхронизировать GIT репозитории между TFS, VSTS и GitHUB

Posted by Shamrai Alexander на Январь 17, 2018

<< Перейти в раздел «Team Foundation Version Control FAQ»

Интересная статья по синхронизации TFS 2015, VSTS и GitHub через сервис сборки: https://blogs.microsoft.co.il/leonj/2017/01/24/synchronizing-tfs-2015-and-vsts-with-github/

Posted in Microsoft, Team Foundation Server FAQ, Version Control FAQ, Visual Studio | Отмечено: , , , | Leave a Comment »

Salma for Word v2.0.4

Posted by Shamrai Alexander на Декабрь 21, 2017

Выпустил очередное обновление для  Salma for Word: https://github.com/ashamrai/Salma/releases/tag/v2.0.4

Что нового:

1. Отказ от использования TFS Object Model в сторону Microsoft Team Foundation Server Extended Client. Это позволило обеспечить простую поддержку Visual Studio Team Services.

2. Добавлена функция для «устаревания» рабочих элементов. Очень часто возникает вопрос: что делать, если требование устарело? С точки зрения TFS/VSTS можно выполнить следующие шаги:

  • Просто перевести требование из закрытого состояния в активное. Но это в свою очередь «подтягивает» все ссылки, которые есть в требовании, допустим, уже закрытые работы, что будет потом отображаться в планах.
  • Можно выполнить копирование требования стандартными функциями, но в этом случае, если была декомпозиция требования на дочерние, связи не будут перенесены. А также необходимо как-то пометить требование источник, что оно уже не актуально.

Поэтому из инструмента можно выполнить:

  • Копирование требования со всем содержимым в новое требование.
  • Перенести или скопировать необходимые ссылки в новое требование.
  • Пометить старое требование в его наименовании и/или с помощью тега.
  • Сохранить ссылку на требование источник.

obs_req

3. Автоматически связывать требование и документ. Если документ, находится в сетевом доступе, то можно выполнить настройку, чтоб при создании нового требования, автоматически вставлял ссылка на документ, в котором это требование «родилось». Соответственно, из требования всегда можно открыть документ-источник и просмотреть его контекст.

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

Вебинар «Организация конвейера по производству ПО на основе VSTS» — Видео

Posted by Shamrai Alexander на Декабрь 13, 2017

Видео

Презентация

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

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