• База знань
  • /
  • Блог
  • /
  • 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

Встановлення прав на файл

Таким чином, ми налаштували середовище віддаленого серверу, щоб він був готовий прийняти 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