vyvchy
    Теми розділу

    09 · Git і CI/CD

    CI/CD: інтеграція, доставка, розгортання

    Зміст

    Уяви команду з десяти розробників, де кожен два тижні пише свою фічу у власній гілці й ні з ким не зливається. За два тижні всі одночасно намагаються влити код у спільну гілку — і починається те, що індустрія назвала інтеграційним пеклом (integration hell): конфлікти злиття на пів дня, «а в мене локально працювало», білд, який не збирається, тести, які ніхто не запускав, і ніхто не знає, чия саме зміна все зламала. Реліз, який планували на п'ятницю, з'їжджає на наступний тиждень. CI/CD — це відповідь індустрії на цей біль: не героїчно інтегруватися раз на спринт, а робити це маленькими порціями щодня й одразу автоматично перевіряти.

    Для AQA ця тема — не «щось про девопсів». Пайплайн (pipeline) — це середовище, у якому живуть твої автотести: вони запускаються там на кожен коміт, там падають з незрозумілих причин, там стають гейтом, що блокує реліз. На співбесіді junior/middle AQA майже гарантовано питають «чим CI відрізняється від CD», «що таке пайплайн» і «де в ньому QA» — і плутанина тут одразу видає рівень. Тож розберемо механізм, а не визначення з вікіпедії.

    «Інтеграційне пекло» і навіщо CI

    Чому інтеграція взагалі болить? Бо що довше дві гілки розходяться, то більше між ними накопичується прихованих несумісностей: конфлікти в одних файлах, мовчазні логічні конфлікти в різних (мій код і твій код окремо коректні, а разом ламають фічу), розбіжність залежностей. Складність інтеграції росте не лінійно, а різко — і вибухає саме тоді, коли часу вже немає.

    Безперервна інтеграція (continuous integration, CI) розвертає цю логіку: якщо інтегруватися боляче — роби це якнайчастіше, доки порція змін маленька. Кожен розробник щодня (а то й кілька разів на день) зливає свою роботу у спільну магістраль (trunk), і на кожне таке злиття автоматика збирає проєкт і ганяє тести. Дрібний конфлікт видно й лагодиться за хвилини, а не за пів дня наприкінці спринту.

    Ключова думка, яку люблять питати на співбесіді: CI — це передусім практика (дисципліна команди), а не інструмент. Можна поставити Jenkins чи GitHub Actions і не мати ніякого CI, якщо всі сидять по своїх гілках тижнями. І навпаки: суть CI — часте злиття в спільну гілку плюс автоматична перевірка кожного злиття. Інструмент лише автоматизує те, що команда й так вирішила робити.

    Три звички, без яких CI не працює:

    • Часті дрібні коміти в спільну гілку — не «велика фіча раз на два тижні», а маленькі порції щодня. Це прямо пов'язано з trunk-based development (див. розділ Pull Request і стратегії гілкування).
    • Автоматична перевірка на кожен коміт — білд і тести запускає машина, не людина за настроєм.
    • Зелена магістраль понад усе. Якщо перевірка червона — це стоп-сигнал: спільна гілка зламана, і команда лагодить її раніше, ніж додає нове. «Не зупиняй конвеєр із дефектом» — той самий принцип, що на реальному складальному конвеєрі.

    Continuous Integration: як це виглядає механічно

    Механіка проста й однакова майже всюди. Розробник робить git push (або відкриває Pull Request). CI-сервер помічає цю подію, бере свіжий код, у чистому середовищі збирає проєкт, проганяє тести й повертає статус: зелено або червоно. Статус видно прямо в Pull Request — червоний чек блокує злиття, зелений дозволяє.

    Що дає ця петля на практиці:

    • Регресію ловить машина за хвилини після коміту, а не тестувальник за тиждень перед релізом.
    • «В мене локально працювало» більше не аргумент: збірка йде в чистому, відтворюваному середовищі, однаковому для всіх (звідси природний перехід до контейнерів — див. Docker і тестові середовища).
    • Історія перевірок прив'язана до комітів: видно, який саме коміт зробив магістраль червоною.

    Тут і живуть твої автотести. У CI прогін відрізняється від локального: headless-браузер, інші ресурси агента, інші таймінги — і тест, зелений у тебе на машині, у CI може миготіти. Це окрема велика тема (див. Автотести в CI: стабільність і дебаг), але вже тут важливо засвоїти: нестабільний (flaky) тест руйнує весь сенс CI. Якщо пайплайн падає «через раз» без причини, команда перестає довіряти червоному кольору й починає його ігнорувати — а тоді гейт не гейт.

    CI vs Continuous Delivery vs Continuous Deployment

    Це найчастіше плутане місце, бо обидва CD — і Delivery, і Deployment — скорочуються однаково. Розберемо по межах відповідальності. Уяви конвеєр: коміт → білд → тести → готовий артефакт → деплой на staging → деплой на prod. Три практики покривають різні відрізки цього конвеєра.

    • Continuous Integration (CI) відповідає за відрізок від коміту до готового артефакта: інтегрувати, зібрати, протестувати. На виході — перевірена збірка. Куди й коли її котити — уже поза CI.
    • Безперервна доставка (continuous delivery) розширює конвеєр далі: кожна зелена збірка автоматично доводиться до стану «готова до релізу» — прогнана через усі стадії, розгорнута на staging, залишилося тільки натиснути кнопку. Рішення коли котити на prod ухвалює людина. Тобто prod-деплой — за один клік, але клік свідомий.
    • Безперервне розгортання (continuous deployment) прибирає й цю кнопку: кожна збірка, що пройшла всі перевірки, автоматично їде на prod без ручного апруву. Людина в петлю релізу вже не вмикається — її роль перенесена в автоматичні гейти й моніторинг.

    людина тисне кнопку

    автоматично, без людини

    Commit у спільну гілку

    Білд + автотести

    Артефакт, готовий до релізу

    Автодеплой на staging

    Реліз на prod

    Continuous Delivery

    Continuous Deployment

    людина тисне кнопку

    автоматично, без людини

    Commit у спільну гілку

    Білд + автотести

    Артефакт, готовий до релізу

    Автодеплой на staging

    Реліз на prod

    Continuous Delivery

    Continuous Deployment

    Головний водорозділ між двома CD — наявність ручного апруву перед prod. Continuous Delivery = «завжди готові релізнути одним кліком, але вирішує людина». Continuous Deployment = «релізимо самі, без кліку». Друге вимагає значно зрілішого автоматизованого контролю якості: раз людина не дивиться перед prod, то весь захист — це перевірки в пайплайні (і сильна спостережуваність з можливістю швидкого rollback, див. Середовища, деплой і релізи).

    ПрактикаЩо автоматизованоХто вирішує «котимо на prod»
    Continuous IntegrationЗлиття, білд, тестиРеліз узагалі поза скоупом
    Continuous DeliveryУсе аж до staging; prod — за одну діюЛюдина (свідомий клік)
    Continuous DeploymentУсе, включно з prodНіхто — автоматика, якщо перевірки зелені

    Практична підказка на співбесіду: якщо тебе просять «в двох словах» — CI про інтеграцію коду, Delivery про готовність релізу будь-коли, Deployment про автоматичний реліз без людини. Continuous Delivery — обов'язкова передумова Continuous Deployment, але не навпаки.

    Пайплайн як конвеєр якості

    Пайплайн — це автоматизована послідовність стадій, які код проходить від коміту до (потенційно) продакшену. Правильна ментальна модель — конвеєр контролю якості: на кожній станції стоїть перевірка, і деталь їде далі, лише якщо станцію пройдено. Не пройшов lint — далі не поїхав; впав unit-тест — до e2e справа не дійшла.

    Чому саме конвеєр, а не «купа перевірок». Порядок стадій вибирають за принципом fail fast — «впасти якомога раніше й дешевше»: спершу найшвидші й найдешевші перевірки, потім повільні й дорогі.

    червоно

    червоно

    червоно

    червоно

    Push / Pull Request

    Lint + перевірка типів
    секунди

    Unit-тести
    секунди-хвилини

    Integration / API
    хвилини

    E2E
    десятки хвилин

    Зелено: артефакт можна просувати далі

    Стоп + фідбек за секунди

    червоно

    червоно

    червоно

    червоно

    Push / Pull Request

    Lint + перевірка типів
    секунди

    Unit-тести
    секунди-хвилини

    Integration / API
    хвилини

    E2E
    десятки хвилин

    Зелено: артефакт можна просувати далі

    Стоп + фідбек за секунди

    Логіка тут економічна: немає сенсу тримати агента пів години на e2e, якщо код не проходить навіть перевірку типів — цю помилку треба показати автору за секунди. Порядок «lint → типи → unit → integration → e2e» прямо лягає на піраміду тестування (широка дешева основа знизу, вузький дорогий верх). Це і є конвеєр якості: кожна стадія — фільтр, а разом вони не пускають дефект далі по трубі.

    Детальну будову — стадії, джоби, тригери, артефакти джобів — розбирає окрема глава Будова пайплайна. А те, яка стадія має блокувати злиття і що ганяти на PR проти nightly, — це стратегія якості в пайплайні, канон теми — Стратегія якості в пайплайні. Тут важливий сам образ: не «набір скриптів», а впорядкована черга гейтів.

    Білд і артефакт

    Два слова, які junior часто вживає навмання. Розведемо їх.

    Білд (build) — це процес перетворення вихідного коду в форму, придатну до запуску чи розгортання. Для компільованих мов це буквально компіляція. Для веб-стека «збірка» теж є, хоч JavaScript і не компілюється в машинний код: встановити залежності, перевірити типи TypeScript, зібрати й мінімізувати бандл (Vite/webpack/esbuild), проставити хеші у назви файлів для cache busting (механіку версіонування ассетів дивись у главі Кешування). Білд — це дія, процес.

    Артефакт (artifact) — це результат білда: незмінний пакет, готовий до розгортання. Залежно від проєкту це зібраний бандл, Docker-образ, .jar, .zip, набір статичних файлів. Ключова властивість — незмінність.

    Головний принцип, який варто винести: build once, deploy many — «зібрати один раз, розгорнути багато разів». Артефакт збирають раз, а потім той самий незмінний артефакт просувають середовищами: staging → prod. Не перезбирають окремо під кожне середовище. Чому це критично саме для QA:

    • Ти тестуєш на staging той самий байт-у-байт артефакт, що поїде в prod. Якби під prod робили нову збірку, твоє тестування staging нічого б не гарантувало — у prod могла б заїхати інша збірка.
    • Артефакт трасується до конкретного коміту й версії. Зловив баг у prod — знаєш точну збірку й точний коміт, звідки вона зросла.
    • Різницю поведінки між середовищами треба шукати не в коді (він той самий), а в конфігурації та даних (див. Секрети та конфігурація в CI).

    Звідси й межа між білдом і деплоєм: білд виробляє артефакт, деплой ставить готовий артефакт у середовище. Це різні дії, і плутати їх — типова помилка новачка.

    Shift-left і швидкий фідбек

    Зсув уліво (shift-left) — це принцип «пересувати перевірки якості якомога раніше на часовій осі проєкту» (уліво, ближче до написання коду). Основа тут — відома крива вартості дефекту: чим пізніше знайдено баг, тим дорожче його виправити (детально — у розділі основ тестування). Баг, спійманий на коміті, коштує кількох хвилин; той самий баг у проді — інциденту, hotfix-у й репутації.

    CI — це головний технічний механізм shift-left: він переносить прогін тестів із «фази тестування наприкінці» на «кожен коміт». Тестування перестає бути окремим етапом після розробки й вплітається в саму розробку.

    Але shift-left працює лише за умови швидкого зворотного зв'язку (fast feedback). Уся цінність CI тримається на швидкості петлі «закомітив → дізнався результат». Якщо пайплайн іде дві години або миготить — петля розривається: люди перестають чекати результату, накопичують зміни великими пачками, зливаються рідше — і ти повертаєшся в те саме інтеграційне пекло, тільки з логотипом CI-системи згори. Тому швидкість і стабільність пайплайна — це не «зручність», а умова, за якої CI взагалі має сенс. (Питання спільного володіння автотестами й shift-left з боку автоматизації — окрема тема в розділі стратегії автоматизації.)

    Місце QA в CI/CD-культурі

    Найважливіший зсув, який приносить CI/CD, — якість не «пришивають» наприкінці, її вбудовують у конвеєр. Стара модель «розробники накодили → кинули QA через паркан → QA потиць руками → підписали реліз» у безперервній доставці не працює: релізів забагато й вони автоматичні. Роль QA не зникає — вона стає роллю стюарда автоматизованої мережі безпеки.

    Що QA реально робить у CI/CD-культурі:

    • Пише й володіє автоперевірками в пайплайні — тими самими тестами, що стоять гейтами на кожному коміті.
    • Визначає гейти якості — які перевірки блокують злиття, а які лише інформують; де e2e має бути блокувальним, а де винесеним у nightly (канон — Стратегія якості в пайплайні).
    • Тріажить падіння — червоний пайплайн це баг продукту, баг тесту чи інфраструктура? Це щоденна робота AQA, і плутати ці три причини дорого (див. Автотести в CI).
    • Тримає сьюту вартою довіри — бо, повторимо, один хронічно flaky тест знецінює весь гейт: команда починає ігнорувати червоне.
    • Рев'ює тестовий код у Pull Request нарівні з продуктовим — тести теж код, який гниє й ламається.

    Головна теза для співбесіди: у зрілій CI/CD-культурі якість — відповідальність усієї команди, але QA — це та людина, що проєктує й доглядає автоматизований механізм, який цю якість стереже. Це перехід від «тестувальника, що клікає» до інженера, що володіє захисною сіткою релізу.

    Типові помилки

    • «У нас є Jenkins, отже у нас CI» — виглядає як CI, а насправді інструмент ≠ практика. Якщо гілки живуть тижнями й зливаються рідко, ніякий сервер не робить це безперервною інтеграцією. CI — це дисципліна частого злиття, автоматика лише її обслуговує.
    • «Continuous Delivery і Continuous Deployment — те саме» — виглядає однаково (обидва CD), а насправді різниця в одному: чи є ручний апрув перед prod. Delivery — людина тисне кнопку; Deployment — кнопки немає.
    • «Білд і деплой — одне й те саме» — виглядає як один крок, а насправді білд виробляє артефакт, деплой ставить готовий артефакт у середовище. Артефакт збирають раз, деплоять багато разів.
    • «Зелений пайплайн = можна релізити» — виглядає як гарантія, а насправді зелене означає лише «перевірки, які ми написали, пройшли». Тонка сьюта чи flaky-тести дають зелене на дірявому покритті. Зелений колір рівно настільки цінний, наскільки чесні перевірки за ним.
    • «Впав пайплайн — просто перезапущу джобу» — виглядає як швидке рішення, а насправді перезапуск маскує flaky-тест або реальну регресію. «Перезапустив і позеленіло» — це не полагоджено, це відкладено; звичка так робити вбиває довіру до гейта.
    • «CI/CD — робота девопсів, не QA» — виглядає як чужа зона, а насправді саме гейти якості, тріаж падінь і здоров'я тестової сьюти — пряма відповідальність QA. Девопс володіє інфраструктурою, QA — вмістом перевірок.

    Підсумок

    • CI — це практика, а не інструмент: часте злиття дрібних змін у спільну гілку плюс автоматичний білд і тести на кожне злиття. Народилася вона з «інтеграційного пекла» — болю рідкісної інтеграції великих гілок.
    • CI → Delivery → Deployment — це розширення того самого конвеєра. CI доводить до артефакта; Continuous Delivery — до «готово релізити одним кліком людини»; Continuous Deployment — до автоматичного prod без кліку. Різниця двох CD — ручний апрув перед prod.
    • Пайплайн — конвеєр якості з fail-fast порядком: дешеві швидкі перевірки спершу, дорогі повільні потім; кожна стадія — фільтр, що не пускає дефект далі.
    • Артефакт збирають раз і просувають середовищами незмінним (build once, deploy many): тестуєш на staging рівно те, що поїде в prod.
    • CI — головний механізм shift-left, а його цінність тримається на швидкому й стабільному фідбеку. У CI/CD-культурі QA не гейт наприкінці, а стюард автоматизованої мережі безпеки.

    Що питають на співбесіді

    • «Чим CI відрізняється від CD?» — класика-пастка через подвійне «CD». Сильна відповідь одразу розводить Continuous Delivery і Continuous Deployment і називає водорозділ — ручний апрув перед prod. Інтерв'юер перевіряє, чи не каша в голові.
    • «Що таке CI своїми словами?» — тут дивляться, чи скажеш «часте злиття + автоматична перевірка на кожен коміт» і чи згадаєш, що це практика, а не просто «сервер, що ганяє тести». Згадка про «інтеграційне пекло» як причину — сильний плюс.
    • «Що таке пайплайн і в якому порядку йдуть стадії?» — очікують fail-fast: lint/типи → unit → integration → e2e, і пояснення чому саме так (дешеве й швидке раніше).
    • «Різниця між білдом і деплоєм? Що таке артефакт?» — перевіряють, чи розумієш build once, deploy many і чому важливо тестувати той самий артефакт, що піде в prod.
    • «Де роль QA у CI/CD?» — слабка відповідь: «QA тестує в кінці». Сильна: QA володіє гейтами якості, тріажить падіння, тримає сьюту стабільною, рев'ює тестовий код — якість вбудована в конвеєр, а не пришита наприкінці.
    • «Що таке shift-left?» — очікують зв'язку з вартістю дефекту й з CI як механізмом раннього виявлення, а не просто переклад слова.

    Джерела