• База знаний
  • /
  • Блог
  • /
  • Wiki
  • /
  • ONLINE CHAT
+380 (44) 364 05 71

Статья также доступна на украинском (перейти к просмотру).

git push to deploy

 

Оглавление

Любая из известных на сегодняшний день архитектуры развертывания программного обеспечения (ПО) имеет стадию development или разработки, на которой происходит непосредственно разработка, тестирование и последующая фиксация внесенных изменений в локальных и удаленных репозиториях. Детали реализации этого процесса зависят напрямую от методологии или технологии разработки ПО. Механизм push-to-deploy является одним из путей реализации этого процесса. Его внедрение позволяет упростить процесс развертывания ПО. Рассмотрим его применение на практике.

Общие концепции развертывания программ

Наиболее распространенные архитектуры развертывания ПО являются 4-х ярусными, на каждом из которых реализуется тот или иной этап подготовки ПО. Прежде всего, это разработка (development), тестирование (testing), пре-продакшн (staging) и продакшн (production) или live.

Стадия development, как правило, разделяется на два этапа – подготовка кода в локальной среде разработчика или песочницы и итоговая обработка кода в интеграционной среде. На местных рабочих местах происходит конкретно создание кода, его проверка, локальное тестирование и фиксация в репозиториях. На этапе интеграции происходит сбор кода всех разработчиков в одном «стволе» дерева разработки и их передача на другой уровень иерархии. Эта стадия в целом имеет наименьшие ресурсные затраты за счет использования отдельных удаленных рабочих мест разработчиков, которые могут быть от одного до нескольких тысяч, в зависимости от конкретного проекта.

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

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

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

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

Реализовать указанные функции можно только благодаря использованию VCS (Version Control System) – систем контроля версий, наиболее известными из которых являются: SVN, ClearCase, Perforce, Git, Mercurial. Первые три являются централизованными, то есть имеют центральный репозиторий, доступный всем разработчикам. Последние две – Git и Mercurial – относятся к децентрализованным, или DVCS системам. Это более современный вариант подобных средств, позволяющих работать со многими репозиториями, разнесенными по всей сети. Децентрализованные модели совместной работы предполагают, что каждый разработчик использует свою копию репозитория со своей историей и структурой ветвей. Такая структура позволяет упростить слияние ветвей дерева разработки и значительно повысить скорость работы с кодом по сравнению с централизованными VCS или CVCS.

Модель Push-to-deploy

Сущность применения модели push-to-deploy по управлению системами развертывания ПО заключается в автоматическом запуске сценариев на стороне сервера при отправке push-сигнала из локальной среды разработки. Если сервер локальный, вполне возможно использование для этой цели модели commit-to-deploy, когда функции push-сигнала выполняет обычный коммит. Но для удаленных серверов этот вариант не подойдет.

Модель push-to-deploy уже используется для указанных целей некоторыми компаниями, например, это касается сервиса GitHub Actions, позволяющего обеспечить определенный уровень параллелизма при работе с Git в разветвленной среде. Процессы на стороне сервера здесь инициируются в случаях, когда идет отправка данных в главную ветвь (push-сигнал), або якщо ініціюється запит на витягування, тобто отримання даних з репозиторію, або у випадку ініціювання процесу у ручному режимі. Це підтверджує тезу про те, що запуск сценаріїв на сервері є можливим після виконання клієнтом будь-яких інших дій, а не тільки передача даних. Отже, було б більш коректно назвати вказану модель xxx-to-deploy.

Организация смешанной системы развертывания ПО на основе Git

Альтернативой сервиса GitHub Actions при разработке пользовательских или даже серверных приложений является более простой вариант организации локальной среды разработки, при котором локальная рабочая копия продукта обновляется «по запросу» разработчика с помощью коммита, который инициирует процесс обновления рабочей копии продукта в локальной среде. То есть здесь для обновления кода применена модель commit-to-deploy. После проверки и тестирования внесенного кода разработчик с помощью push-сигнала по протоколу ssh отправляет изменения в удаленный репозиторий, где реализуется этап интеграции внесенных всеми участниками проекта изменений в «стволе» дерева разработки.

Ниже мы продемонстрируем использование указанного подхода на практике при организации смешанной системы развертывания ПО. Рассмотрим основные этапы ее создания.

На первом этапе нами будет настроена локальная среда разработки, включающая каталог разработчика вместе с активированным git-репозиторием и локальный веб-сервер с рабочей копией проекта, который будет обновляться при осуществлении каждого коммита разработчиком (модель commit-to-deploy).

На втором этапе будет настроен удаленный веб-сервер с открытым git-репозиторием для нашего проекта и создан сценарий или git-хук типа post-receive, который будет запускаться при отправке изменений из локальной среды в общее дерево разработки проекта с помощью push-сигнала. Именно запуск указанного сценария обеспечит периодическое обновление рабочей среды проекта (модель push-to-deploy). Удаленный сервер будет активирован нами в системе Git как production-сервер, то есть он будет обеспечивать рабочую среду для готового программного продукта. Следует отметить, что на практике такой сервер может выполнять функции пре-продакшн сервера, то есть реализовывать промежуточный уровень staging иерархии архитектуры развертывания ПО. Всё зависит от выбранной методологии разработки в каждом конкретном случае.

Третий этап будет посвящен непосредственно процессу использования созданной системы развертывания ПО в реальной рабочей среде, в составе которой будет зарегистрирован в Git удаленный production-сервер.

Настройка локальной среды разработчика

Для создания указанной локальной среды на нашей машине была установлена ??операционная система Ubuntu 20.04. Процесс разобьем на несколько этапов:

  1. Обновление системы;
  2. Установка веб-сервера;
  3. Создание пустого git-репозитория и его инициализация;
  4. Создание git-хука типа post-commit;
  5. Написание и размещение кода веб-проекта;
  6. Демонстрация процесса работы с кодом в git-системе и обновление рабочей копии проекта.

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

$ sudo apt-get update

Обновление пакетов

Список пакетов успешно обновлен.

Установим веб-сервер Apache:

sudo apt-get install apache2

Установка Apache

Подтвердим согласие на выделение 7511 kB дискового пространства и продолжим процесс установки.

Процесс установки Apache

Процесс установки Apache

Процесс установки успешно завершен.

Для возможности изменения сценарием типа post-commit содержимого корневого каталога веб-проекта установим права на запись для /var/www/html. Для этого введем следующую команду:

$ sudo chown -R `whoami`:`id -gn` /var/www/html

Изменение прав на запись каталога

Теперь создадим пустой каталог для репозитория и перейдем к нему:

$ mkdir develop_deploy
$ cd develop_deploy

Создание каталога и переход в него

Инициализируем новый git-репозиторий:

$ git init

Инициализация git репозитория

Итак, репозиторий инициализирован. Выведен путь к нему: /root/develop_deploy/.git. Это означает, что git-система отныне будет отслеживать изменения в существующем каталоге.

Перейдем к непосредственно репозиторию и просмотрим его содержимое:

$ cd .git
$ ls -F

Просмотр содержимого репозитория

Выведена структура репозитория, которая выглядит следующим образом:

HEAD  branches/  config  description  hooks/  info/  objects/  refs/

В каталоге hooks хранятся примеры допустимых типов сценариев или git-хуков. Просмотрим его содержимое:

$ cd hooks
$ ls -l

Переход в катлог и просмотр его содержимого

Наличие конструкции «.sample» в названии файлов сценариев говорит об отключении указанных хуков. При удалении указанной конструкции из названия сценарий будет активирован и готов к работе.

Настроим хук post-commit для созданного репозитория. Указанный тип сценария вызывается сразу после осуществления коммита, поэтому он не может повлиять на сам коммит. Используется для оповещения. Параметры не предусмотрены.

Вызовем редактор кода и введем код, который приведен ниже:

$ nano post-commit
#!/bin/bash
unset GIT_INDEX_FILE
git --work-tree=/var/www/html --git-dir=/root/develop_deploy/.git checkout -f

Редактирование файла post-commit

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

Вторая строчка кода отключает переменную среды GIT_INDEX_FILE,которая связана с путем к рабочему каталогу и имеет значение «.git/index». Но поскольку в нашем случае там отсутствует указанный файл, то при запуске сценария будет выдаваться ошибка. Именно поэтому мы и отключили указанную переменную.

Третья строчка кода выполняет несколько функций. Во-первых, с помощью параметра «work-tree» мы объявляем рабочий каталог проекта. В данном случае это корневой каталог веб-сервера /var/www/html. Во-вторых, с помощью параметра «git-dir» объявляется директория, являющаяся git-репозиторием. В-третьих, с помощью конструкции «checkout -f» мы указываем на необходимость копирования последней версии проекта в локальный рабочий каталог, то есть осуществление принудительного обновления кода.

Сохраним изменения (ctrl+O, Enter) и закроем указанный файл (ctrl+X).

Вернемся в каталог разработки:

$ cd .. ..

Сделаем файл исполняемым с помощью следующей команды:

$ chmod +x .git/hooks/post-commit

Замена прав на файл

Вызовем редактор кода для создания первого файла нашего проекта и вставим код, приведенный ниже:

$ nano index.html
<h1>Разработка и развертывание кода на веб-сервере</h1>
<p> На первом этапе развертывания кода будет производиться только на локальный веб-сервер при выполнении каждого хука </p>

 Редактирование файла index.html

Сохраним файл проекта на диске, после чего добавим его в индекс, чтобы git-система смогла в дальнейшем отслеживать его. Для этого введем в терминале:

git add .

Добавление файла в индекс

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

Перечень переменных которые нужно указать

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

$ git config --global user.email "alexandr7500@meta.ua"
$ git config --global user.name "Alexandr"

Заполнение значений переменных

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

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

git commit -m "Это первый проверочный хук"

Фиксация изменений репозитория

Как видим, фиксация произошла.

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

Проверка работы проекта

Итак, проект рабочий.

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

$ echo "<p>Это первые внесенные изменения в код приложения на локальном сервере.</p>" >> index.html

Внесение изменений в файле проекта

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

$ git add .
$ git commit -m "Первое обновление кода"

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

Обновляем браузер и просматриваем результат:

Результат обновления репозитория

Все совпадает – локальная среда успешно отлажена.

Настройка удаленного сервера

В настоящее время на сервере развернута ОС Ubuntu 20.04. Перечислим шаги, которые мы должны предпринять на указанном сервере:

  1. Обновить систему;
  2. Установить веб-сервер;
  3. Установить Git;
  4. Создать и инициализировать открытый репозиторий;
  5. Создать git-хук типа post-receive.

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

Для начала передадим права на document root текущему пользователю:

sudo chown -R `whoami`:`id -gn` /var/www/html

Передача прав на документ пользователю

Установим git на эту машину:

sudo apt-get install git

Установка git

Как видим из сообщения, система уже существует на этой машине: «git is already the newest version (1:2.25.1-1ubuntu3.11). git set to manually installed.».

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

$ mkdir remote_deploy
$ cd remote_deploy

Создание каталога и переход в него

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

git init --bare

Инициализация открытого репозитория

Итак, инициализация прошла удачно. Путь к репозиторию: /root/remote_deploy. Поскольку здесь отсутствует рабочий каталог, все каталоги и файлы репозитория находятся в основном в каталоге remote_deploy, в чем легко убедиться с помощью команды просмотра содержимого каталога:

$ ls -F

Просмотр содержимого каталога

Как видим, каталог .git здесь отсутствует, а все остальные объекты находятся в основном каталоге.

Создадим git-хук типа post-receive. Такие скрипты предназначены для запуска на удаленных репозиториях после обновления всех ссылок, и потому прервать процесс они не могут. Настройки отсутствуют. Данные сценарий получает через стандартный ввод в формате: значение старой ревизии, значение новой ревизии, ref-ссылки.

Запустим редактор для создания файла сценария и введем в него следующий код:

$ nano hooks/post-receive

Код сценария:

#!/bin/bash

while read oldrev newrev ref
do
if [[ $ref =~ .*/master$ ]];
then
echo "Объект ref ветки Master получен. Ветка Master разворачивается на рабочем сервере..."
git --work-tree=/var/www/html --git-dir=/root/remote_deploy checkout -f 
else
echo "Ссылка $ref получена. Изменений внесено не будет, поскольку на сервере можно развернуть только основную ветвь."
fi
done

Код сценария в файле post-receive

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

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

Как известно, для серверных хуков git способен передавать сообщения клиенту в обратном направлении сразу после получения информации через стандартный ввод. Это позволяет клиентской машине получить результат обработки скрипта или хука. Для этого мы ввели соответствующие сообщения по результатам выполнения оператора if.

В случае, если принятая сценарием информация относится к основной ветви, изменения будут приняты, и одновременно с помощью конструкции «checkout –f», которую мы уже рассматривали, будет обновлен рабочий сервер проекта. Если же информация поступила из неголовной ветви, тогда будет выдано соответствующее сообщение, но изменений не будет внесено и, соответственно, сервер не обновится.

Сохраним внесенные изменения и выйдем из редактора.

Сделаем скрипт исполняемым:

$ chmod +x hooks/post-receive

Ecnfyjdrf прав на файл

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

Система развертывания ПО в процессе использования

Теперь можно начинать работу в построенной нами разветвленной системе развертывания кода. Но перед этим мы должны зарегистрировать в git-системе удаленный репозиторий в качестве production сервера. Для этого вернемся на клиентский сервер (разработки) и перейдем в каталог разработки репозитория:

$ cd develop_deploy

Переход к каталогу разработки

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

Введем в терминале:

$ git remote add production root@178.20.157.229:remote_deploy

Подключение к удаленному серверу

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

echo "<p>Проверка работы №1.</p>" >> index.html

Редактирование кода проекта

git add .
git commit -m "Второе обновление кода"

Сохранение обновлений в проекте

echo "<p>Проверка работы №2.</p>" >> index.html

Еще одно изменение в коде проекта

git add .
git commit -m "Третье обновление кода"

Сохранение обновлений в проекте

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

Результат обновлений в проекте

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

Теперь с помощью push-сигнала внесем зафиксированные изменения в удаленный репозиторий и, соответственно, обновим уже функционирующий проект. Для этого загрузим ветку master на production-сервер:

$ git push production master

Внесение изменний в удаленный репозиторий

В результате мы получили сообщение от remote-сервера: «Объект ref ветки Master получен. Ветвь Master разворачивается на рабочем сервере…». Это означает, что наш код принят, а значит, рабочий сервер обновлен. Проверим это, указав IP-адрес remote-сервера в адресной строчке браузера. Результат приводим.

Результат на удаленном сервере

Таким образом, все наши изменения прошли и код проекта успешно обновлен.

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

Создадим новую ветвь new_branch в локальной среде разработки. Для этого введем в терминале:

git checkout -b new_branch

Создание новой ветки

Мы получили сообщение, что «Switched to a new branch 'new_branch'». То есть, ветвь успешно создана и совершен переход на нее указателя git-системы. Это означает, что теперь все изменения, которые мы будем вносить в код, будут относиться только к новой ветви. Проверим это на практике. Для этого осуществим очередное вмешательство в код проекта:

echo "<p>Проверка работы №3. Внесение изменений в новую ветку new_branch</p>" >> index.html

Изменнения в коде проекта

Зафиксируем изменения в репозитории:

git add .
git commit -m "Четвертое обновление кода"

Сохранение изменений в проекте

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

Результат обновлений проекта

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

Теперь загрузим новую ветвь new_branch на удаленный рабочий сервер:

git push production new_branch

Загрузка новой ветки на удаленный сервер

В результате мы получили сообщение с сервера: «Ссылка refs/heads/new_branch получена. Изменения внесены не будут, поскольку на сервере можно развернуть только основную ветвь». Все так же, как и планировалось – изменения могут вноситься только в главную ветвь. Но на всякий случай проверим, что выводит браузер на удаленном сервере. Вот результат:

Подтверждения что обновления не применились

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

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

Сначала перейдем к ветке master, то есть сделаем ее текущей. Это можно сделать с помощью следующей команды:

git checkout master

Переход в главную ветку

Сообщения системы: «Switched to branch master», а значит, переход на главную ветвь состоялся.

Теперь объединим ее с веткой new_branch:

git merge new_branch

Объдинение с главной веткой

Таким образом, мы добавили новую функцию в главную ветвь.

Загрузим изменения на production-сервер, чтобы развернуть новую функцию:

git push production master

Загрузка изменений проекта на удаленный сервер

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

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

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

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

Если вы ведете совместную разработку, вам точно понадобится инструмент для хранения и управления репозиториями Git. Для этого дата-центр FREEhost.UA предлагает облачный сервер VPS с GitLab. Через несколько минут после выбора этого шаблона сервер со всем необходимым программным обеспечением будет настроен и готов к работе.

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

Подписывайтесь на наш телеграм-канал https://t.me/freehostua, чтобы быть в курсе новых полезных материалов.

Смотрите наш канал Youtube на https://www.youtube.com/freehostua.

Мы в чем-то ошиблись, или что-то пропустили?

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

Дата: 30.06.2023
Автор: Евгений
Голосование

Авторам статьи важно Ваше мнение. Будем рады его обсудить с Вами:

comments powered by Disqus
navigate
go
exit
Спасибо, что выбираете FREEhost.UA