Использование Сценариев Сборки На F#/C# В Tfs 2012.

Думаю, я не единственный, кто считает, что у Microsoft есть плохие слова, когда дело доходит до изменения и/или расширения так называемого шаблона процесса сборки в TFS. Под катом рассказ о том, как мы перешли от Xaml к скриптам на F#/C#.

Как мы пытались интегрировать Фальшивый в TFS, но в итоге я получил свое решение — AnFake .

Статья будет полезна тем, кто использует TFS в качестве CI-решения, но не в восторге от его шаблонов процессов сборки.

В ходе разработки нашего проекта (который, по сути, представляет собой бинарный поставляемый модуль для, по сути, продукта компании) мы поняли, что хотим иметь CI-процесс, который был бы немного сложнее, чем просто компиляция и запуск модульных тестов.

.

Вот так выглядел в наших глазах «идеальный» процесс.

Обычная сборка:

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

Поставлять:
  • создание примечаний к выпуску об ошибках и задачах из TFS;
  • публикация примечаний к выпуску на портале;
  • автоматическая регистрация номера сборки в багах и задачах;
  • выкладывание подготовленного архива поставки в определенное место для дальнейшего использования продукта.

Рабочий процесс в нашей компании полностью построен на TFS, включая отслеживание ошибок и задач; контроль версий и непрерывная интеграция.

Сборки CI в TFS указываются с использованием шаблона процесса (шаблона процесса сборки).

Первое, что мы попытались сделать для реализации нашего «идеала», — настроить шаблон процесса под себя и… столкнулись с рядом трудностей.

1. Часть логики сборки меняется по мере развития модуля (в частности, подготовки тестовых образцов), т.е.

желательно хранить эту логику в системе контроля версий вместе с другими исходниками модуля.

Но шаблон процесса в TFS 2012/2013 хранится отдельно и не версионируется (да, он есть в VCS, но всегда используется только последняя версия).

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

мы не можем собрать все ветки по одному шаблону.

Возможные решения:

  • Создайте версию шаблона вручную, добавив номер версии к имени файла шаблона.

    При этом при объединении веток нельзя забывать об объединении шаблонов.

    А если вдруг помимо редактирования шаблона вам понадобятся свои активности, то псевдоверсионность придется применять и к dll с этими активностями!

  • Поместите изменяющуюся логику в скрипт и вызовите этот скрипт из шаблона.

    Скрипт следует хранить вместе с остальными исходниками модуля.

Мы выбрали сценарий.

На первом этапе - обычный bat файл.

2. Использование скрипта привело нас к еще одной проблеме — резко упала информативность логирования.

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

Вы можете выделить только ошибку, написав сообщение в stderr. Но каждая строка, прочитанная TFS из stderr, будет восприниматься им как отдельная ошибка.

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

«Это некрасиво», но жить можно.

3. Скрипт начал разрастаться.

В дополнение к этапу подготовки образца вскоре он включал в себя тесты производительности и тесты FP/TP. Почему это? Казалось бы, запуск тестов должен быть в шаблоне.

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

Оставив их в шаблоне, мы имеем уже рассмотренную в пункте 1 проблему.

Более того.

Стало созревать желание иметь доступ из скрипта к свойствам текущей сборки (название ветки, номер версии и т.д.), а также общаться с другими сборками для организации конвейера.

На этом этапе стало понятно, что скрипт должен быть мощнее, чем просто батник.

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

Кандидатами на сценарий были: PSake , Грабли И Фальшивый .

После быстрого анализа PSake был удален из-за синтаксиса PowerShell; Рейк — т.к.

никто в нашей команде не был знаком с Руби; и остался Фейком.

Справедливости ради надо сказать, что F# на тот момент в команде тоже никто не знал, но F# поддерживается Visual Studio из коробки, поэтому мы остановились на нем.

К сожалению, Fake не дружит с TFS. А что, мы не программисты что ли?! Мы сами облажались.

Можно сказать, что проблемы 1 и 3 решены.

Однако проблема 2 усугубилась тем, что.

теперь вся сборка выполнялась в скрипте, результат, показанный в Visual Studio, выглядел удручающе - никаких предупреждений не было видно (в том числе и от компилятора); какие этапы были выполнены не видно; ошибки показаны как жуткие портянки.

Мы попытались решить эту проблему, написав расширение для Fake, но у Fake не было единой точки журналирования, из которой можно было бы перенаправить структурированный вывод в TFS. Попутно возникло еще несколько недовольств (подробнее можно прочитать о здесь ).

Тем не менее, мне понравилась идея использовать полноценный язык программирования для описания сборки.

В итоге я решил в свободное время реализовать идею Фейка в собственном исполнении.

Акцент был сделан на:

  • расширяемость (например, подключаемый html-отчет о сборке или публикация результатов тестирования в базу данных и т. д.);
  • интеграция с различными внешними системами (первой на очереди была TFS);
  • читаемый и понятный журнал и вывод ошибок.

Кроме того, вспоминая свои первые попытки разобраться в F#-скриптах, я подумал: «хорошо бы уметь писать скрипты и на C#», и включил это требование в объем работ. Да, вы можете написать ассемблерный скрипт на C#, однако, к сожалению, IntelliSense в этом случае не работает — студия не знает, что C# может быть скриптом.

В результате получился очень достойный инструмент (я назвал его AnFake = Another F# Make), который может пригодиться всем, кто «воюет» с TFS. Давайте посмотрим, как он выглядит и что он умеет (на данный момент AnFake в основном предназначен для TFS, поэтому дальнейшее обсуждение будет в контексте TFS).

Пусть у нас есть решение под названием Demo, которое находится в системе контроля версий TFS:

  
  
  
  
  
  
   

$/TeamProject/Demo /dev /Demo.App /Demo.Lib /Demo.Lib.Test Demo.sln

Давайте также создадим рабочую область «Demo.dev», настроенную с одним сопоставлением:

$/TeamProject/Demo/dev: C:\Projects\Demo.dev

(далее предполагается, что используется схема «одно рабочее пространство на филиал») Откройте C:\Projects\Demo.dev\Demo.sln в Visual Studio. Установите AnFake как пакет NuGet:

PM> Install-Package AnFake

При установке пакета в корневой папке решения будет создано несколько файлов:
  • build.fsx — базовый скрипт сборки, включающий вызов MSBuild и запуск тестов;
  • anf.cmd — псевдоним для вызова AnFake (чтобы не писать каждый раз .

    /packages/AnFake.x.y.z/bin/AnFake.exe);

  • .

    workspace — текстовый файл с описанием отображений из рабочей области, внутри которой было загружено текущее решение;

  • .

    nuget\NuGet.config — [создается, только если он не существует] содержит параметр DisableSourceControlIntegration, позволяющий предотвратить передачу двоичных файлов пакета в VCS.

(кстати, скрипт установки также является F#-скриптом для AnFake) Базовый скрипт build.fsx выглядит следующим образом:

Tfs.PlugIn() let out = ~~".

out" let productOut = out / "product" let testsOut = out / "tests" let tests = !!"*/*.

Test.csproj" let product = !!"*/*.

csproj" - tests "Clean" => (fun _ -> let obj = !!!"*/obj" let bin = !!!"*/bin" Folders.Clean obj Folders.Clean bin Folders.Clean out ) "Compile" => (fun _ -> MsBuild.BuildRelease(product, productOut) MsBuild.BuildRelease(tests, testsOut) ) "Test.Unit" => (fun _ -> VsTest.Run(testsOut % "*.

Test.dll") ) "Test" <== ["Test.Unit"] "Build" <== ["Compile"; "Test"]

.

то же самое в C#

Tfs.PlugIn(); var outDir = ".

out".

AsPath(); var productOut = out / "product"; var testsOut = out / "tests"; var tests = "*/*.

Test.csproj".

AsFileSet(); var product = "*/*.

csproj".

AsFileSet() - tests; "Clean".

AsTarget().

Do(() => { var obj = "*/obj".

AsFolderSet(); var bin = "*/bin".

AsFolderSet(); Folders.Clean(obj); Folders.Clean(bin); Folders.Clean(out); }); "Compile".

AsTarget().

Do(() => { MsBuild.BuildRelease(product, productOut); MsBuild.BuildRelease(tests, testsOut); }); "Test.Unit".

AsTarget().

Do(() => { VsTest.Run(testsOut % "*.

Test.dll"); }); "Test".

AsTarget().

DependsOn("Test.Unit"); "Build".

AsTarget().

DependsOn("Compile", "Test");

В принципе, этого уже достаточно для запуска локальной сборки:

PM> .

\anf Build

(здесь мы использовали консоль диспетчера пакетов, но AnFake можно запустить из любой консоли командной строки) В результате получаем примерно такой отчет:

Использование сценариев сборки на F#/C# в TFS 2012.

Мы видим, что компиляция прошла с одним предупреждением; Было выполнено 2 теста, один из которых был пропущен.

Хорошо, фиксируем изменения.

Коммит будет содержать файл .

nuget/packages.config (здесь NuGet записывает пакеты уровня решения) и файлы, созданные во время установки AnFake, в корневой папке решения.

Теперь запустим ту же сборку через TFS. Для этого вам необходимо установить специальный шаблон AnFakeTemplate.xaml (делается только один раз для командного проекта):

PM> .

\anf "[AnFakeExtras]/vs-setup.fsx" "BuiltTemplate" -p "TeamProject"

где вместо TeamProject, естественно, нужно подставить имя вашего проекта в TFS. Команда создаст временное рабочее пространство с именем AnFake.BuildTemplate.yyyymmdd.hhmmss; загрузится во временную папку $/TeamProject/BuildProcessTemplates; добавит шаблон AnFakeTemplate.xaml и несколько сопутствующих библиотек.

Команда НЕ ДЕЛАЕТ ничего автоматически, чтобы не вызвать бурю оправданного негодования.

Поэтому заходим в Visual Studio -> Team Explorer -> Pending Changes, переключаемся в рабочую область AnFake.BuildTemplate, просматриваем изменения (убедимся, что там нет ничего лишнего) и коммитируем.

Теперь мы можем создать определение сборки:

  • Перейдите в Visual Studio -> Team Explorer -> Сборки, выберите «Новое определение сборки».

  • На вкладке Процесс в разделе Шаблоны процессов сборки нажмите Показать подробности.

  • Нажмите «Создать» и в поле «Путь управления версиями» введите (или выберите через Source Control Explorer) $/TeamProject/BuildProcessTemplates/AnFakeTemplate.v2.xaml; Нажмите «ОК» (делается только один раз для командного проекта).

  • В раскрывающемся списке Файл процесса сборки выберите AnFakeTemplate.v2.xaml и сохраните.

Запускаем сборку, используя только что созданное определение: Queue Build в контекстном меню.

В результате получаем следующий отчет:

Использование сценариев сборки на F#/C# в TFS 2012.

AnFakeTemplate выполняет три простых шага:

  • Загружает решение из системы контроля версий.

  • Восстанавливает пакеты NuGet уровня решения (т. е.

    загружает сам AnFake).

  • Передает управление AnFake.
  • Все остальное определяется в сценарии.

Шаблон довольно прост и остается совместимым во многих версиях.

Таким образом, вы можете обновить пакет AnFake без необходимости обновлять шаблон.

У вас даже могут быть разные версии AnFake в разных решениях и они будут безопасно собраны по одному шаблону.

Я продемонстрировал базовый сценарий интеграции AnFake в TFS. Однако интеграция не ограничивается шаблоном: к свойствам текущей сборки можно обратиться из скрипта; получить доступ к артефактам из других сборок; есть даже возможность организовать конвейер.

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

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

В заключение хотелось бы сказать, что «идеальная» сборка, описанная в начале статьи, на данный момент полностью реализована и работает на AnFake. Я не могу показать наши реальные сценарии, но вы можете увидеть некоторые интересные отрывки.

Здесь .

Буду признателен за ваш отзыв.

Спасибо.

Теги: #автоматизация сборки #непрерывная интеграция #tfs #C++ #F# #.

NET #C++ #F#

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.