Разработка Для Microsoft Sql Server (И Не Только): Контроль Версий, Непрерывная Интеграция И Процедуры – Как Мы Это Делаем

Доброго времени суток уважаемые хабровчане.

Вкратце: год назад, когда я пришел на новую работу в качестве руководителя отдела разработки баз данных (на базе Microsoft SQL Server), я испытал глубочайший шок от увиденного.

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

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

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

90% технических деталей относятся непосредственно к разработке для Microsoft SQL Server, но наши процедурные изменения затронули веб-разработчиков, инженеров, аналитиков и тестировщиков.

Сразу оговорюсь: я не являюсь представителем компаний/рекламодателем программных продуктов, о которых упомяну в статье.

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

Кому интересны подробности — добро пожаловать под кат. Внимание: много текста, описаний процедур и процессов( что, возможно, никому не интересно ).



Отслеживание ошибок, планирование и отслеживание проектов

В качестве системы учета запросов было выбрано решение на базе Atlassian JIRA. Основными причинами стали: тесная интеграция с другими продуктами, о которых будет упомянуто в статье; чрезвычайно удобная работа по методологии гибкой разработки; широкие возможности для настройки и автоматизации процессов.

Мы решили придерживаться двухнедельных Agile-спринтов, планируя разработку и тестирование на 3 спринта (т. е.

на 1,5 месяца) вперед. Подробности самого процесса ниже.



Система контроля версий

Честно говоря, я фанат продуктов Atlassian. В качестве системы контроля версий была выбрана Atlassian Stash (Git).

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

Все коммиты происходят в основной ветке.

Для коммитов мы используем продукт RedGate Source Control (плагин для SSMS).

Здесь мы столкнулись с первой технической трудностью: я хотел, чтобы при нажатии кнопки «Commit» в SSMS код не только фиксировался, но и запихивался в репозиторий.

Это оправдано с точки зрения разработки на общей базе данных.

Пока идет разработка (изменения в коде хранимых процедур, изменения в структуре таблиц), изменения сохраняются в самой базе данных.

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

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

К сожалению, RedGate SC не может реализовать push из коробки.

Чтобы обойти это ограничение, для RedGate были написаны 2 bat-скрипта, которые используются в качестве перехватчиков pull и commit. Когда разработчик обновляет список изменений в окне плагина, выполняется Pull, при котором репозиторий на станции разработчика становится идентичным текущему состоянию репозитория.

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

После выбора изменений (например, хранимой процедуры и таблицы), которые необходимо зафиксировать, и нажатия кнопки «Зафиксировать», изменения попадают в локальный репозиторий, после чего автоматически происходит отправка в Git. Прикрепляю файл конфигурации RedGate Source Control, а также исходники pull.bat и commit.bat, которые в нем используются: CommandLineHooks.xml

  
  
   

<Эxml version="1.0" encoding="utf-8" standalone="yes"?> <!----> <HooksConfig version="1" type="HooksConfig"> <!-- The name of the config file that will be displayed in the SQL Source Control user interface --> <Name>Git_CompanyName</Name> <Commands type="Commands" version="2"> <element> <key type="string">GetLatest</key> <!-- Updates the local working folder with latest version in source control. --> <!-- Valid macros: ($ScriptsFolder) ($Message) --> <value version="1" type="GenericHookCommand"> <CommandLine>%UserProfile%\Documents\SQLSourceControl\projectname\Pull.bat</CommandLine> <Verify>exitCode == 0</Verify> </value> </element> <element> <key type="string">Add</key> <!-- Adds new files to the local working copy. Changes can then be committed to source control using the Commit command. --> <!-- Valid macros: ($ScriptsFolder) ($Message) ($Files) ($Folders) --> <value version="1" type="GenericHookCommand"> <CommandLine>"C:\Program Files (x86)\Git\bin\git" add ($Files)</CommandLine> <Verify>exitCode == 0</Verify> </value> </element> <element> <key type="string">Edit</key> <!-- Makes the local working copy of the file(s) available for editing. Changes can then be committed to source control using the Commit command. --> <!-- Valid macros: ($ScriptsFolder) ($Message) ($Files) ($Folders) --> <value version="1" type="GenericHookCommand"> <CommandLine></CommandLine> <Verify>exitCode == 0</Verify> </value> </element> <element> <key type="string">Delete</key> <!-- Deletes the file(s) from the local working copy. Changes can then be committed to source control using the Commit command. --> <!-- Valid macros: ($ScriptsFolder) ($Message) ($Files) ($Folders) --> <value version="1" type="GenericHookCommand"> <CommandLine>"C:\Program Files (x86)\Git\bin\git" rm ($Files)</CommandLine> <Verify>exitCode == 0</Verify> </value> </element> <element> <key type="string">Commit</key> <!-- Commits all changes in the local working folder to source control. --> <!-- Valid macros: ($ScriptsFolder) ($Message) --> <value version="1" type="GenericHookCommand"> <CommandLine>%UserProfile%\Documents\SQLSourceControl\projectname\Commit.bat "($Message)"</CommandLine> <Verify>exitCode == 0</Verify> </value> </element> <element> <key type="string">Revert</key> <!-- Undoes changes if an error occurs during a commit --> <!-- Valid macros: ($ScriptsFolder) --> <value version="1" type="GenericHookCommand"> <CommandLine>"C:\Program Files (x86)\Git\bin\git" checkout "($ScriptsFolder)\"</CommandLine> <Verify>exitCode == 0</Verify> </value> </element> </Commands> </HooksConfig>

Pull.bat

@echo off set HOME=%USERPROFILE% cd %UserProfile%\Documents\SQLSourceControl\projectname "C:\Program Files (x86)\Git\bin\git" remote add origin ssh://[email protected]:7999/projectname/projectname-sql.git "C:\Program Files (x86)\Git\bin\git" pull --force origin master

Commit.bat

@echo off set HOME=%USERPROFILE% set comment=%1 cd %UserProfile%\Documents\SQLSourceControl\projectname "C:\Program Files (x86)\Git\bin\git" remote add origin ssh://[email protected]:7999/projectname/projectname-sql.git "C:\Program Files (x86)\Git\bin\git" pull origin master "C:\Program Files (x86)\Git\bin\git" commit -m %comment% -o %UserProfile%\Documents\SQLSourceControl\projectname-sql "C:\Program Files (x86)\Git\bin\git" push origin master

Как видите, работа со Stash/Git осуществляется через SSH с авторизацией по ключам.

Первоначальная настройка Red-Gate документирована и по сути состоит из 2 шагов: установить плагин и запустить скрипт первоначальной настройки (который сам создаст необходимые папки в профиле пользователя и сделает первый клон репозитория).



Процесс разработки и тестирования

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

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

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

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

Вопросы с высоким приоритетом в очереди планирования рассматриваются и планируются в течение 24-48 часов, все остальное рассматривается и планируется раз в неделю на планерках команды.

Под «планированием» я подразумеваю определение сложности и этапов задачи, объема необходимой документации, общение с человеком, от которого поступила заявка (для выяснения деталей) и принятие решения о том, на каком Agile Sprint должно быть решение этой задачи.

быть помещен в.

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

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

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

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

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

Задачи могут находиться в следующих статусах:

  • Планирование (сортировка);
  • Отклоненный;
  • Разработка началась;
  • Разработка продолжается;
  • Препятствие - препятствие для дальнейшего развития );
  • Готов к тестированию (Ready for QA);
  • Готов к производству;
  • Решено;
Перемещение задач между статусами возможно только по следующей схеме:

Разработка для Microsoft SQL Server (и не только): контроль версий, непрерывная интеграция и процедуры – как мы это делаем

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

Лучше расскажу о том, чего не видно на схеме:

  1. Большие задачи делятся на подзадачи.

    Родительская задача не может находиться ни в одном из статусов, кроме «Готова к разработке», «Разработка начата» и «Препятствие»;

  2. Как только разработчик совершает коммит, для этого коммита создается проверка кода ( как это происходит, ниже );
  3. Вы можете сделать фиксацию только в том случае, если в комментарии есть ссылка на заявку JIRA, чтобы фиксация, а затем и проверка, были автоматически связаны с задачей;
  4. Мы решили рассматривать проверку кода как часть процесса разработки, поэтому, пока проверка продолжается, заявка находится в состоянии «Готово к разработке/Разработка началась».

    Переместить тикет в «Готов к QA» и тем более закрыть его, пока открыта проверка, невозможно;

  5. Если решение проблемы невозможно из-за наличия «блокирующей» задачи, используется соответствующая ссылка в JIRA. Пока заявка на блокировку не закрыта, задача будет находиться в статусе «Препятствие» и закрыть ее будет невозможно;
  6. Да-да, вы все правильно поняли, задания не открываются повторно.

    Если ошибка/проблема обнаруживается после релиза, создается новая проблема, связанная с предыдущей;

  7. После закрытия задачи изменения по ней будут автоматически применены к боевой базе при закрытии спринта ( как это происходит, также ниже );
Небольшое отступление: описанные процессы совместимы со стандартами проектирования IEEE.

Код-ревью

Мы используем Atlassian как решение для проверки изменений кода.

(Да неужели?!) Рыбий глаз/Тигель.

Полная интеграция с JIRA и Stash позволяет быстро перейти со страницы задачи к просмотру связанных коммитов и обзоров кода.

С интеграцией JIRA+Stash+Crucible/Fisheye никаких хитростей нет, поэтому больше мне по этой теме рассказать нечего.



Непрерывная интеграция

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

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

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

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

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

Все изменения в DEV публикуются в QA. Однако когда я говорю «все», я лгу.

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

Итак, вместо банальной синхронизации схем мы используем возможности RedGate SQL CI и нашего сервера сборки — Atlassian Bamboo. План MSBuild создается в Bamboo, который вызывает SQL CI. Как только происходит фиксация, SQL CI генерирует команды ALTER и CREATE и передает их в базу данных QA. Хотя я знаю, что «настоящей» непрерывной интеграцией следует считать ту же публикацию изменений в продакшене, у меня не хватает на это смелости.

Вместо этого мы используем RedGate SQL Compare для синхронизации схемы с QA при закрытии спринта.

Соответственно, если смотреть с точки зрения процесса, то база QA для нас — это производство.

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

В мире Microsoft SQL Server как базы данных для веб-приложений это означает, что при публикации версии процедур должны выполняться корректно и не вызывать взаимоблокировок.

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

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

В нашем случае это кажется возможным.



Заключение

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

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

Я хотел рассказать вам гораздо больше - о том, как организовано и интегрировано в этот процесс автоматизированное тестирование (автоматическое модульное тестирование и интеграционное тестирование), как мы используем Microsoft Data Quality Services для процесса QA, как организована документация, но там уже было слишком много текста.

Возможно, я сделаю это в отдельной статье.

А пока буду рад вопросам и конструктивной критике.

Теги: #Microsoft SQL Server #контроль версий #контроль версий #проверка кода #непрерывная интеграция #непрерывная интеграция #разработка баз данных #процессы #процессы разработки #atlassian #Jira #разработка баз данных #рабочий процесс #разработка #управление продуктами #разработка веб-сайтов # системы контроля версий #Microsoft SQL-сервер

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

Автор Статьи


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

Dima Manisha

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