CI/CD
Безперервна інтеграція — це не сервер, що ганяє ваші тести, а звичка зливатися в одну спільну гілку достатньо часто, щоб конфлікти лишалися малими; автоматизація існує, щоб зробити цю звичку безпечною. Безперервна доставка — друга половина: один артефакт, зібраний один раз і просунутий середовищами без перезбирання. На цій сторінці — як упорядкувати етапи, чому нестабільний тест руйнує авторитет конвеєра, чим насправді торгують стратегії розгортання і які чотири числа кажуть, чи все це працює.
- CI — це про
- Частоту злиття
- Артефакт
- Зібрано раз, просунуто
- Червона збірка
- Спиняє конвеєр
Три терміни, які не є синонімами
Ці слова вживають як взаємозамінні, а вони називають три різні зобовʼязання. Безперервна інтеграція — це практика про людей: усі зливаються в спільну гілку щонайменше щодня, тож жодна гілка не відходить настільки далеко, щоб її злиття стало подією. Автоматична збірка існує, щоб зробити це безпечним, — вона наслідок, а не визначення. Команда з розлогим конвеєром і тижневими гілками функцій не робить безперервної інтеграції: вона ганяє тести на сервері.
Безперервна доставка — це стан, коли будь-який коміт, що пройшов конвеєр, можна випустити просто зараз, за рішенням, а не за підготовкою. Безперервне розгортання йде на крок далі й прибирає рішення: кожен коміт, що пройшов, потрапляє у прод автоматично. Розрив між двома останніми — вибір бізнесу, а не техніки: чимало зрілих команд свідомо практикують доставку й ніколи не переходять до розгортання, бо людська брама — це саме те, чого вимагає їхній регулятор, їхні клієнти чи їхній календар релізів.
Правило з цієї схеми, що важить найбільше, — про артефакт. Зберіть придатну до розгортання річ один раз, із відомого коміту, і просувайте ту саму, побайтово однакову річ крізь усі середовища. Конвеєр, що перезбирає для проду, щойно розгорнув те, чого не тестувало жодне середовище: залежність розвʼязалася інакше, базовий образ зрушив, прапорець збірки відрізнявся, — і все, що показав стейджинг, стосувалося іншого артефакта. Якщо середовищу потрібна інша поведінка, ця різниця належить конфігурації, поданій під час виконання, а не другій збірці.
Порядок етапів і як тримати їх швидкими
У конвеєра є одна робота, важливіша за правильність: швидко сказати авторові. Розробник, що дістає відповідь за три хвилини, досі тримає зміну в голові; той, хто дістає її за сорок, уже почав інше — і ціна збою тепер не редагування, а перемикання контексту. Тож упорядковуйте етапи за їхньою дешевизною, а не за тим, як влаштований код: спершу форматування й статичний аналіз, далі юніт-тести, тоді збірка, а тоді все, що потребує бази чи браузера.
Три прийоми роблять більшу частину роботи з утримання цього часу. Виконуйте незалежні етапи паралельно: конвеєр повільний настільки, наскільки довгий його найдовший шлях, а не загальна сума. Кешуйте те, що дорого відтворити й дешево перевірити — дерево залежностей за хешем lock-файлу, вивід компілятора за вихідним кодом, — і подбайте, щоб ключ кешу змінювався разом із вводом, бо застарілий кеш — це хибна відповідь, подана швидко. А в пулл-реквесті ганяйте лише те, на що зміна може вплинути; повний набір ганяйте на спільній гілці, де повільніша відповідь прийнятна.
Секрети — інша річ, яку треба зробити правильно з першого ж конвеєра, а не лагодити потім. Нічого чутливого не має бути в репозиторії, зокрема й у самому описі конвеєра: платформа подає їх під час виконання й маскує в логах. Обмежуйте кожні облікові дані тією задачею, якій вони потрібні, тримайте продові облікові дані повністю поза прогонами пулл-реквестів — конвеєр, що виконує код із форку з доступом до проду, є відчиненими дверима, — і ротуйте за розкладом, а не після інциденту. Конвеєр — це машина з доступом до всього, і мішенню він є саме через це.
Як довести це до проду
Щойно артефакт існує, лишається питання, як робоча система переходить зі старої версії на нову. Стратегії різняться переважно тим, чого вони коштують і як швидко їх скасувати, а чесний спосіб обирати — спитати, наскільки поганий найгірший випадок і як швидко ви його помітите.
| Стратегія | Як працює | Чого коштує |
|---|---|---|
| Поступове | Заміняти примірники по кілька, тож під час зміни трафік обслуговують обидві версії. | Нічого зайвого не треба тримати — але ваш код має терпіти дві живі версії одночасно. |
| Синьо-зелене | Запустити нову версію поруч зі старою, а тоді перемкнути весь трафік одним кроком. | Подвійної потужності на час переходу — і перемикача, миттєвого в обидва боки. |
| Канаркове | Надіслати малу частку трафіку новій версії й дивитися метрики, перш ніж розширювати. | Керованої маршрутизації й метрик, яким довіряєте: без обох це просто повільна викотка. |
| Прапорець функції | Розгорнути код вимкненим, а тоді ввімкнути для обраних користувачів окремо від розгортання. | Прапорця, яким треба володіти й зрештою видалити: застарілі стають розгалуженням, у якому не розібратися. |
Що б ви не використовували, розгортання — лише половина зміни: друга половина — схема бази, і вона не відкочується. Саме тому існує послідовність «розширити й звузити»: додати нову колонку, писати в обидві, дозаповнити, перемкнути читання — і прибрати стару лише пізнішим розгортанням. Кожен крок сумісний із версією до нього й після нього, тож відкат коду ніколи не приземляється на схему, яка не може його обслужити. Міграція, що виконується в тому самому кроці, що й розгортання, якому вона потрібна, забирає у вас можливість повернутися рівно тієї миті, коли ви цього найбільше хочете.
А план відкату не є планом, доки ним хтось не скористався. Збій, з яким стикаються люди, — не в тому, що кнопки немає, а в тому, що ніхто не знає, чи безпечно її тиснути, бо востаннє це пробували під час інциденту. Прорепетируйте: відкотіть справжнє розгортання спокійного дня, засічіть час і зʼясуйте, що воно робить із запитами в польоті, з кешем і з чергою. Відкат, якого ніхто не виконував, — це надія з гарячою клавішею.
Як це виявляється в реальній поставці
Чотири вимірювання описують продуктивність поставки краще за будь-який інвентар інструментів, і їх варто вести, бо вони рухаються в протилежні боки, коли команда оптимізує не те. Скільки часу зміна йде від злиття до проду. Як часто ви розгортаєте. Яка частка розгортань спричиняє проблему. Скільки часу займає відновлення після неї. Команда, що розгортає рідко, зазвичай робить це тому, що розгортати страшно, а страшно тому, що кожен реліз несе місяці змін, — тож ці дві половини живлять одна одну в обидва боки.
Тримайте опис конвеєра в репозиторії поруч із кодом, який він збирає, і переглядайте в тому самому пулл-реквесті. Конвеєр, налаштований клацанням у вебінтерфейсі, не має ні історії, ні перегляду, ні способу відтворити збірку минулого місяця — і саме тому ніхто не може пояснити, чому задача почала падати. Той самий аргумент іде на крок далі, до самих середовищ: те, що створює інфраструктуру, теж має бути кодом у репозиторії, щоб перебудоване середовище збігалося з тим, яке воно замінило.
Один ризик, що перейшов із теоретичних у рутинні: конвеєр виконує сторонній код із вашими обліковими даними. Крок збірки, на який посилаються змінюваним тегом, може змінитися під вами між двома прогонами, а скомпрометований вивезе кожен секрет, який задача бачить. Фіксуйте дії збірки й базові образи за дайджестом, а не за тегом, переглядайте, що саме змінює оновлення залежності в конвеєрі, і давайте кожній задачі найвужчі права, з якими вона може зробити свою роботу. Ланцюг постачання — та частина конвеєра, якої ніхто не читає, доки вона не стане інцидентом.
Де це вироджується
- Довгі гілки функцій із причепленим конвеєром: це автоматизація без інтеграції.
- Перезбирання артефакта для кожного середовища: у прод іде те, чого не тестували.
- Кнопка повтору як політика проти нестабільності — аж поки червоний результат перестають читати.
- Найповільніші перевірки першими: автор уже пішов далі, перш ніж конвеєр відповів.
- Червона спільна гілка, лишена на ніч: вона блокує всіх і робить блокування нормою.
- Руйнівна міграція в тому самому кроці, що й розгортання: вона забирає можливість відкотитися.
- Конвеєр, налаштований клацанням: без історії, без перегляду й без способу відтворити збірку.
- Продові облікові дані, доступні прогонам пулл-реквестів, зокрема відкритих із форку.
- Прапорці функцій, що пережили свою функцію: лишається розгалуження, у якому не розібратися.
Коли це застосовувати
Застосовуйте, коли
- З першого тижня будь-якого проєкту, де більше одного учасника: тоді це день роботи, а не міграція.
- Скрізь, де реліз наразі є запланованою подією, до якої готуються, а не рутинною дією.
- Коли перед кожним розгортанням виконують ті самі ручні кроки: ці кроки і є специфікацією.
- Саме безперервне розгортання — коли частка збійних змін низька, а відновлення швидке й відрепетируване.
Уникайте, коли
- Автоматизація розгортання, якому ще не довіряють: спершу тести й відкат, інакше ви автоматизуєте інцидент.
- Конвеєр із дванадцяти етапів на прототипі, де супровід конвеєра довший за сам код.
- Безперервне розгортання там, де хибний реліз має правові чи фізичні наслідки, які не скасувати.
- Додавання етапів на компенсацію набору тестів, якому не вірять: час множиться, довіра — ні.
Було корисно?
Поділіться з тим, хто працює над тією ж задачею.