Преобразование Процессов Разработки И Доставки Устаревшего Приложения

Наша команда отвечает за эксплуатацию и развитие крупного корпоративного продукта.

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

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

Пришло время перейти от слов к делу – к изменению процессов.

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

Начинать



Немного о системе

Приложение представляет собой классический пример монолитного корпоративного приложения «архитектурный разлив 2000-х»:
  • работает и развивается более 15 лет.
  • Это набор из полутора десятков WinForms, служб Windows и приложений ASP .

    Net, связанных с единой базой данных MS SQL.

  • Размер кодовой базы: ~1MLOC для C#, ~9000 объектов базы данных.

    Значительная часть бизнес-логики выполняется на стороне базы данных.

  • Приложение состоит из ~250+ решений для создания win/веб-клиента (по одному решению на группу связанных форм).

    Это наследие предыдущего процесса разработки и архитектуры клиента.

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

    При этом кодовая база приложения одинакова для всех клиентов.

  • Приложение развернуто и поддерживается на более чем 25 сайтах (каждый сайт является независимым экземпляром системы) и обслуживает в общей сложности несколько тысяч конечных пользователей в разных часовых поясах.



Процесс доставки до трансформации

  1. Разработку и сборку готового приложения и его компонентов осуществляет подрядчик.

  2. код хранился на стороне подрядчика (локальная версия MS TFS).

    Код передается заказчику ежемесячно в виде архива текущей версии основной ветки репозитория.

  3. доставка осуществлялась путем доставки «дельта-обновлений»: для приложения (набор dll, exe и т.д.) и компонентов базы данных (набор sql-скриптов создания/изменения).

    Приложение было собрано и дельта-пакеты подготовлены подрядчиком.

  4. процесс развертывания поддерживался транспортной системой, а изменения применялись автоматически.

Доставка осуществляется в рамках ежемесячных релизов (как это работает, я рассказывал здесь ранее Здесь ).



Существующие проблемы

Недостаток контроля
  • Несмотря на формальное владение кодом, фактическая сборка приложения заказчиком была невозможна.

  • в результате невозможно проверить работоспособность переданного заказчику кода.

  • изменения в коде не прозрачны для заказчика.

    Невозможно сравнить запрошенные и фактические изменения продукта.

  • анализ кода сложен для SQL и невозможен для компонентов C#
Трудоемкость и ошибки
  • Подготовка «дельта-пакетов» — трудоемкая процедура разработки, источник ошибок и определенных затрат на проект.
  • Развертывание приложения из набора «дельта-пакетов» требует отслеживания порядка пакетов.

    Ошибка нарушения порядка пакетов является серьезной проблемой развертывания и источником значительной части инцидентов.

  • Регулярно происходят регрессии: ошибки, которые, казалось бы, уже были исправлены и исправления выкачены в производство, появлялись снова.

Ограничения
  • возможность восстановить состояние системы на точку в прошлом (откатить изменения) практически отсутствует.
  • Возможность эффективного масштабирования ресурсов разработки и раннего тестирования за счет привлечения сотрудников заказчика практически отсутствует.


Ожидаемые результаты

В начале проекта мы ставим перед собой очевидные цели, призванные решить обозначенные выше проблемы.

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

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

Эшаги большого пути

Анализ текущего состояния процессов разработки

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

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

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

  1. Код базы данных и бизнес-логика для нее не обновлялись в репозитории.

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

    Это означает, что код в репозитории — это всего лишь документация.

  2. «Настоящая» версия кода базы данных находится в общей «базе данных разработки», которой пользуются десятки разработчиков.

  3. Код клиентского приложения (C#, ASP.NET) поддерживался в репозитории, но качество и своевременность коммитов не гарантировались.

  4. Компоненты (не все приложение) собирались на станциях разработчиков.

    Не совсем понятно, как код обновлялся перед сборкой.

    Собранный компонент выложил в общую общую папку.

    Далее для заказчика был сформирован «дельта-пакет».

  5. Полное отсутствие практики ведения веток разработки.

    По косвенным признакам мы это подозревали давно – но после погружения в процесс все стало очевидно.



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

Зависимость от платформ MS и корпоративных стандартов предопределила выбор среды разработки — Team Foundation Server. Однако к моменту фактического запуска проекта (апрель 2017 г.

) версия Visual Studio Team Services только что была выпущена.

Продукт показался очень интересным, был обозначен как стратегическое направление для MS, предлагал git-репозитории, сборку и развертывание для локальной и облачной среды.

Корпоративная локальная TFS отставала от VSTS по версии и функциональности; переход на новую версию был только в процессе обсуждения.

Мы не хотели ждать.

Мы решили сразу перейти на VSTS, потому что это сократило затраты на поддержку нашей платформы и дало нам полный контроль над тем, как и что мы делаем.

На момент начала изменений команда разработчиков имела опыт работы с TFSVC, и код приложения хранился в таком репозитории.

С другой стороны, GIT уже давно стал стандартом де-факто для ИТ-сообщества — перейти на эту систему рекомендовали заказчик и сторонние консультанты.

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

Мы развернули два проекта в VSTS с разными репозиториями — TFSVC и GIT. Был определен набор сценариев, которые предлагалось протестировать и оценить на предмет удобства использования в каждой из систем.

Среди оцененных сценариев были:

  • Создание и объединение ветвей
  • Организация совместной работы (по одной или разным отраслям)
  • Операции над цепочками изменений (фиксация, отмена)
  • Интеграция сторонних изменений
  • Возможность продолжать работу, когда сервер недоступен.

В итоге, как и ожидалось, был выбран GIT, о чем пока никто не пожалел.

Мы начали использовать GitFlow как процесс.

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

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

  2. Мы стараемся придерживаться практики «один тикет — один пул-реквест».

    Изменения из разных заявок никогда не объединяются в одно изменение.

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

  3. При слиянии в разработке все изменения объединяются в один коммит (сквош).

  4. Ветки релизов создаются из development.
  5. При необходимости вы можете добавить последние изменения выборочно (cherry-pick) или все (rebase) в ветку релиза.

    Мы не проводим исправления непосредственно в релизной ветке.

  6. После развертывания последней версии в продакшене она попадает в мастер-версию через push-force (только несколько человек имеют это право)


Автоматизация сборки изделий

Приложение состояло из большого количества сборок, сотен решений.

Как выяснилось в ходе аудита процесса, все это собиралось отдельно и «вручную».

На первом этапе мы решили не переделывать всё «с нуля» (чтобы не останавливать существующую поставку), а «обернуть» сборку набором скриптов msbuild — по одному скрипту на каждый компонент. Таким образом, мы быстро получили скрипты, выполнявшие все необходимые промежуточные артефакты, и в конце — готовый продукт. Отдельная история — проект базы данных.

К сожалению, система содержит несколько компонентов CLR, которые не очень хорошо структурированы.

Зависимости препятствуют простому развертыванию базы данных контента.

На данный момент это решается сценарием предварительного развертывания.

Кроме того, из-за неравномерности системного ландшафта (SQL Server версии 2008 и 2014 были установлены в разных точках) пришлось организовать сборку проекта базы данных для .

Net версий 2.0 и 4.0. Когда все сценарии были готовы и протестированы, они были использованы в сценарии сборки VSTS. Непосредственно перед началом сборки версии всех продуктов были обновлены до единого стандартного номера, включая сквозной номер сборки.

Такое же число было сохранено в сценарии после развертывания.

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



Развертывание на тестовом стенде

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

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

Развертывание «поверх» копии реальной базы данных показало множество конфликтов между сборкой и состоянием реальных систем:

  • Несовместимые версии в GIT и в реальной системе.

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



Стабилизация процесса развития

Об этом, конечно, странно говорить и тем более писать здесь, но самым серьёзным изменением для разработчиков стало введение принципа «если этого нет в git, то этого не существует».

Раньше код был зафиксирован «для отчетности перед заказчиком».

Теперь - без этого невозможно ничего поставить.

Самое сложное было с кодом базы данных.

После перехода к развертыванию базы данных из репозитория посредством сборки и развертывания с использованием sqlpackage подход «дельта» был заменен подходом «желаемого состояния».

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

Но! До полного перехода к новому процессу развертывания все еще необходимо внести изменения.

И делать это пришлось по старинке — «дельта-обновления».

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

Для этого мы организовали следующий процесс:

  1. Код из репозитория регулярно собирался и развертывался в пустую «модельную» базу данных.

  2. На основе «модельной» базы данных был подготовлен специальный автотест. Для каждого объекта «модельной» базы данных были рассчитаны контрольные суммы.

    Автотест содержит все эти контрольные суммы и при запуске вычисляет контрольные суммы соответствующих объектов «проверяемой» базы данных.

    Любое несоответствие в составе объектов или их контрольных суммах приводит к провалу теста.

  3. «Неудачный» тест автоматически запрещает передачу пакетов из тестовой среды дальше по ландшафту.

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

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

При этом разработчики начали привыкать к необходимости правильно и своевременно коммитить код в репозиторий.



Развертывание продукта в средах интеграционного тестирования

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

Мы полностью отказались от использования дельта-пакетов на тестовых системах и перешли на автоматическое развертывание с помощью VSTS. Именно с этого момента вся команда начала видеть первые плоды своих предыдущих усилий: развертывание произошло без каких-либо дополнительных усилий.

Зафиксированный код был автоматически собран, развернут и протестирован.

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

А потому дальше тестовой среды к QAS и PRD выходить было нечего.

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

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



Тестирование продукта в результате автоматической сборки

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

Нужно было убедиться, что приложение работает и ничего не потеряно.

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

К счастью, у нас был значительный набор автотестов, охватывающих критические области.

Но тестов на C# не было, поэтому все проверялось вручную.

Это был значительный объем работы, и проверка заняла некоторое время.



«Прыжок веры» — пилотное внедрение в производство

Несмотря на тестирование, впервые развертывать в производство было страшно.

Нам повезло — мы как раз планировали очередное развертывание системы на новой площадке.

И мы решили использовать этот шанс для пилотного внедрения.

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

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

За это время было выявлено несколько дефектов, которые были пропущены при тестировании.

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

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

Эта версия сборки стала первой стабильной версией мастер-ветки, и была обвешана праздничными тегами «fisrt_deployment» (мы, правда, не заказывали иконки с хешем коммита).



Масштабирование развертывания по всему производственному ландшафту

Как говорил Джеймс Бонд: «Второй раз гораздо легче».

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

Но у системы есть несколько типов использования – для одного типа может использоваться один функционал, а в других случаях – не использоваться.

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

Для проверки работоспособности остальных видов использования мы стали использовать активные проекты, находящиеся в разработке.

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

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

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

Net, Powershell и модули.

Все это заняло изрядное количество времени.

Подключение к сети На некоторых объектах подключение к сети просто не позволяло прокачать все компоненты сборки.

В процессе переноса были таймауты и повреждения.

Мы много чего проверили и попробовали — не очень удачно.

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

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

Конфликт с антивирусом Еще одна странная проблема, с которой мы столкнулись, — это конфликт антивирусного ПО и одного из этапов развертывания: когда из архивов артефактов начинают извлекать всякие «подозрительные» файлы, такие как .

js, .

dll, антивирус начинает внимательно посмотрите на них.

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

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



Совершенствование процессов

После стабилизации процессов сборки и развертывания мы перешли к «пошиву сапог для сапожников» — совершенствованию внутренних процессов.

  • построили базовую интеграцию корпоративной системы ИТ-поддержки (service-now.com) с VSTS для передачи заявок в виде рабочих элементов.

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

  • подключил CI ко всем ветвям функций.

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

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

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

    Любой разработчик или сотрудник отдела может инициировать развертывание; разрешение на развертывание дает сотрудник, ответственный за тип системы и координирующий тестирование.

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

    Теперь сборка продукта содержит код и тесты — как для веток разработки, так и для продукта в целом.

  • В качестве эксперимента мы установили VSTS-агенты на локальные компьютеры аналитиков, которые тестируют, и развернули там клиентскую часть, которую необходимо протестировать на сборку.

Полученные результаты

Текущая ситуация

  • Весь код приложения хранится и поддерживается в службах MS VisualStudio Team Services (в последнее время Azure Devops), управляемых клиентом.

    Системы контроля версий — GIT

  • Все изменения полностью прозрачны и привязаны к сервисным билетам (инцидентам/изменениям)
  • Благодаря переходу на git/GitFlow параллельная разработка стала значительно проще.

  • Введена процедура code review с участием представителя заказчика.

  • Приложение создано системой CI. Полная сборка проводится как для основной, так и для функциональной ветки, что позволяет провести раннее тестирование.

  • Приложение развертывается на всех целевых узлах на основе сценариев.

    Постепенно этапы развертывания приложения дополняются этапами настройки базовых компонентов и приложения.

  • Сотрудники ИТ-подразделения заказчика могут сами инициировать развертывание сборок (окончательных или промежуточных) в тестовых средах — для тестирования или ранней оценки.

    Бизнес-пользователи также имеют доступ к тестовым средам.

  • Мы по-прежнему придерживаемся основных циклов выпуска в 1 месяц.

    Хотя в последний месяц мы еженедельно выкатывали что-то практичное.

  • Шёл процесс «экспериментального» развертывания версии на некоторых сайтах.



Время по этапам

Описание сцены Продолжительность
1 От начала проекта до полного контроля над кодом, процессом сборки и доставки в тестовую среду.

6 месяцев
2 От первого развертывания в тестовой среде до первого пилотного выпуска и запуска в производство 3 месяца
3 От пилотного развертывания до производства и первого выпуска для всех экземпляров 5 месяцев
Общая продолжительность - 14 месяцев Продолжительность, особенно на заключительном этапе, во многом определялась координацией и согласованным графиком обслуживания системы.



Затраты на оплату труда

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

Теги: #vsts #трансформация #разработка #Управление разработкой #процесс разработки #DevOps #Управление разработкой #DevOps

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

Автор Статьи


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

Dima Manisha

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