Розробка кастомних приватних CircleCI Orbs для CI/CD

Ми розробляємо приватні CircleCI Orbs під ключ: повторювані кроки збірки перетворюємо на перевикористовувані модулі зі зрозумілими версіями. Час на збірку скорочується в рази, дублікати конфігурацій зникають, а запуск нових проєктів прискорюється.
Часті запитання

CircleCI Orbs: чому конфігурація збірки розростається

У будь-якому репозиторії збірка живе в одному файлі конфігурації — .circleci/config.yml: встановлення залежностей, прогін тестів, збірка образу, публікація, розгортання. Коли проєктів стає десятки, ці кроки починають копіювати з репозиторію в репозиторій.

Саме тут з’являються CircleCI Orbs — винесена й версіонована спільна частина конфігурації, але до того як до них доходять, команда зазвичай встигає накопичити кілька поколінь копій одного й того самого сценарію.

Розбіжність майже не видно на старті. Потім виявляється, що в одному проєкті кеш залежностей ключується за іменем гілки, в іншому — за контрольною сумою файлу блокувань, у третьому ключ узагалі не змінювався з моменту створення.

Десь у крок тестів додано прапорець, десь ні, десь залишився застарілий образ-виконавець. Правку однієї речі — зміну кеш-ключа або порядку кроків — доводиться вносити в тридцять файлів, і половина з них залишається непоміченою.

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

Друге джерело зростання — умовна логіка всередині кроків. Гілки «якщо тег — публікуємо, якщо основна гілка — розгортаємо на стенд, інакше лише тести», окремі набори кроків під різні середовища, матриці запусків.

Файл розростається до сотень рядків, його перестають рев’юїти, а підтримка сценаріїв збірки перетворюється на ручну синхронізацію копій — кожна нова правка збільшує розбіжність замість того, щоб її скорочувати.

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

Ефект від перевикористовуваних модулів збірки

Перевикористовувані модулі збірки в CircleCI — це не «охайна структура конфігурації», а вимірювані ефекти, які видно у статистиці збірок уже в перший місяць роботи.

Час збірки на повторюваних кроках

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

Повторювані кроки перестають виконуватися заново в кожному репозиторії: збірка, яка тривала 11-12 хвилин, вкладається в 6-8, а очікування в черзі на спільний виконавець скорочується.

Частка ручних правок у конфігураціях

Раніше та сама логіка жила своєю редакцією в десятках файлів, і кожне виправлення доводилося повторювати руками. Тепер зміна вноситься в модуль, а проєкти лише піднімають його версію. Кількість місць, де стандарт доводиться правити окремо, скорочується до одного.

Усунений клас відмов через розбіжності середовищ

Модуль фіксує версії середовища, порядок кроків і склад перевірок перед публікацією — єдиний стандарт збірки стає обов’язковим для всіх сервісів. Відмови виду «тут працює, на збірці ні» зникають зі статистики: падіння тепер означає проблему в коді, а не в середовищі.

Швидкість підключення нового репозиторію

Підключення зводиться до зазначення модуля та його версії — перевірки, збірка й публікація вже описані всередині. Новий сервіс отримує робочий стандарт за годину замість дня, і інженеру не потрібно розбиратися у внутрішніх деталях збірки.

Варіанти перевикористання збірок: що і коли підходить

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

Нижче — порівняння за сценаріями та навантаженням на супровід: у кожного підходу свій клас обмежень, і видно, який із них упреться першим при зростанні кількості репозиторіїв.

Варіант Коли підходить Обмеження підходу
Спільний шаблон збірки в репозиторії Одна-дві команди, конфігурація змінюється рідко, потрібен повний контроль над кожним рядком Правка не доїжджає до сусідніх репозиторіїв: версії розходяться, шаблони живуть своїм життям
Приватний модуль збірки в спільному реєстрі Кілька команд зі спільними етапами й різними правами доступу, код закритий для зовнішніх Потрібен реєстр модулів і правило версіонування: оновлення зобов’язане залишатися зворотно сумісним
Спільний зовнішній модуль Типові кроки — перевірки стилю, публікація артефактів, сповіщення Залежність від зовнішнього супровідника: його зміни приходять поза вашим графіком і ламають збірку не у вас
Генерація конфігурації з метаданих проєкту Багато однотипних репозиторіїв, відмінності описуються параметрами З’являється проміжний шар: без генератора конфігурацію не прочитати й не поправити руками

На практиці підходи комбінуються: приватний модуль закриває спільні етапи, генерація — типові репозиторії, а шаблон залишається для рідкісних сервісів.

Перехід робиться без зупинки постачання — новий модуль підключається поряд зі старими кроками, дублі вирізаються в міру перенесення.

Як відбувається впровадження приватного реєстру модулів

Впровадження приватного реєстру модулів — це не встановлення сервісу, а перебудова того, як команди збирають і перевикористовують конфігурацію. Порядок робіт вибудуваний так, щоб кожен крок спирався на перевірений попередній, а збірки робочих сервісів не зупинялися ні на день.

  1. Аудит конфігурацій збірки. Робимо інвентаризацію: скільки файлів збірки, де дублюються кроки, які секрети лежать у відкритому вигляді, скільки триває типовий прогін. На виході — карта залежностей і список фрагментів, які справді варто виносити в модулі.
  2. Схема модулів і версіонування. Розмічаємо модулі за зонами відповідальності, домовляємося про схему тегів і діапазони сумісності, щоб оновлення одного модуля не ламало чужі збірки.
  3. Налаштування доступу до реєстру. Підключаємо приватний реєстр Orbs, видаємо командам токени з мінімально потрібними правами, розділяємо читання й публікацію, налаштовуємо кеш, щоб вибірка модуля не гальмувала запуск.
  4. Обкатка на одному сервісі. Переводимо найпоказовіший сервіс, порівнюємо час збірки та кількість ручних правок до і після, правимо інтерфейси модулів за фактичними незручностями.
  5. Перевірка відкатів збірки. Проганяємо сценарії: модуль відкликано, тег переписано, реєстр недоступний. Збірка має падати передбачувано або підніматися на зафіксованій версії — без ручної правки конфігів у момент інциденту.
  6. Передача та порядок робіт далі. Віддаємо регламент публікації, шаблон нового модуля й правила депрекації, навчаємо чергових розбирати типові збої.

Після цього решту сервісів переводять за накатаним маршрутом — по одному за спринт, без зупинки релізів.

Що залишається у вас: конфігурації, ролі, регламенти

Приватні орби та обв’язка навколо них залишаються у вашому контурі — разом із комплектом, за яким модулі підтримуються без зовнішньої команди. Усе передаємо у ваш репозиторій і супроводжуємо до моменту, коли інженери починають вносити зміни самі.

  • Конфігурації збірки — параметризовані описи завдань: кроки, кешування, умови запуску. За ними відтворюється той самий результат, що на еталонному стенді.
  • Схема залежностей — який модуль на що спирається і що зачепить правка спільного блоку. Видно, де зміна ізольована, а де потягне споживачів.
  • Політики доступу та ролі — хто випускає нову версію спільного модуля, а хто лише підключає його до свого проєкту. Секрети розділені за рівнями й не успадковуються автоматично.
  • Опис версіонування — домовленість про ломаючі та сумісні зміни: перше йде окремою гілкою, новий параметр приходить зі значенням за замовчуванням.
  • Регламент оновлень модулів — періодичність ревізії базових образів і залежностей та порядок обкатки на тестовому проєкті до переведення решти.
  • Документація — картка на кожен модуль: призначення, параметри, приклад підключення, відомі обмеження й типові збої.
  • Інструкція для інженерів — як додати крок, як відкотити випуск і куди дивитися при збої.

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

Кейс: час збірки скоротився, дублі конфігурацій зникли

Що було

Чотирнадцять сервісів, у кожного — свій файл конфігурації, скопійований у сусіднього й далі правлений вручну. Кроки збірки та публікації розійшлися до дев’яти варіантів однієї й тієї самої дії, а в трьох сервісів перевірки не запускалися взагалі.

Ціна розбіжностей: повний прогін тривав близько сорока хвилин — спільного кешу залежностей не було, кожен сервіс тягнув і збирав усе заново.

Приблизно кожен п’ятий збій на проді припадав не на код, а на неправильний крок у конфігурації, який в одному сервісі вже виправили, а в решті — ні.

Що стало

Зібрали приватні CircleCI Orbs — спільний модуль із командами збірки образу, кешування залежностей, прогону перевірок і публікації за тегом. Конфіг сервісу стиснувся до п’ятнадцяти рядків: указати образ і викликати спільну команду. Правка кроку тепер робиться в одному місці й підхоплюється всіма сервісами.

Прогін скоротився з сорока хвилин до тринадцяти завдяки кешу та паралельному запуску перевірок.

Копій кроку збірки стало одна замість дев’яти, збоїв через розбіжність конфігурацій — два за квартал замість п’яти-шести на місяць, і обидва ловляться на етапі підготовки, а не на проді.

Відкат теж став керованим: версія модуля фіксується тегом, повернення на попередню гілку спільного модуля повертає попередню поведінку всім сервісам одразу, без обходу репозиторіїв.

Далі розберемо, як такий модуль улаштований усередині й що в нього варто виносити, а що залишати в сервісі.

Чим приватні CircleCI Orbs відрізняються від шаблонів

Приватний Orb — упакований модуль: команди, завдання та виконавці з параметрами й значеннями за замовчуванням, опублікований у реєстрі CircleCI під вашим простором імен.

У конфігурації проєкту він підключається посиланням із зазначенням версії, тобто працює як зовнішня залежність, а не як скопійований файл. Шаблон у репозиторії — просто текст, розмножений по проєктах: зв’язок між копіями втрачається в момент копіювання.

Версіонування модулів і є головною відмінністю. Оновлення приватного Orb — одна публікація нової версії: проєкти, що зафіксували попередню, продовжують збиратися як раніше, а перехід на нову — окремий коміт у конфігурації, відкат вкладається в той самий рядок.

Із шаблоном будь-яка правка перетворюється на обхід десятків репозиторіїв, і частина з них неминуче відстає або розходиться в поведінці.

Права на спільний модуль розділяються за ролями: платформенна команда випускає версії, продуктові — лише підключають Orb і передають свої параметри.

Зміни проходять рев’ю в одному місці й не переписуються на ходу, на відміну від шаблону, який кожен може поправити під себе й розірвати спільну поведінку. Ізоляція змін тримається на версії, а не на дисципліні.

Один-два репозиторії, єдиний стек, немає зовнішніх споживачів — локального шаблону більш ніж достатньо: він не потребує публікації й простіший у підтримці.

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

Часті технічні сумніви перед початком робіт

П’ять питань зазвичай піднімають перед стартом, і всі вони про експлуатацію, а не про сам код. Нижче короткі відповіді; якщо у вас щось улаштовано інакше, скажіть на етапі обговорення — конфігурацію підлаштуємо під поточний контур.

Як оновлювати приватні модулі й не ламати збірки?

Версіонуємо за семантичними правилами: зворотно несумісні зміни йдуть лише в мажорну гілку, решта — у мінорні. Проєкти закріплюються на мажорній версії, а оновлення спочатку проганяється на тестовій гілці — розбіжність видно до злиття в основну.

Як видаються доступи до реєстру та збіркового середовища?

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

Кому належить реєстр після передачі?

Реєстр оформлюємо на вашу організацію, права власника залишаються у вас. Ми підключаємося як підрядник із правом публікації; після здачі ви змінюєте доступи в один крок і працюєте з модулями самостійно.

У нас кілька стеків — один модуль підійде?

Так, завдяки параметризації: мова, середовище виконання, набір кроків і образ передаються аргументами зі значеннями за замовчуванням. Один модуль закриває кілька стеків, дублювальних копій під кожен не заводимо.

У нас уже є свої шаблони — переписувати все заново?

Ні. Обгортаємо наявні шаблони в приватний модуль і переносимо по одному сервісу: старі збірки продовжують працювати, поки новий контур не закриє всі проєкти. Відкат будь-якого кроку — повернення до попереднього опису збірки.

Обговоримо вашу схему збірки й повернемося з планом

Щоб оцінка впровадження спиралася на факти, а не на здогадки, потрібен короткий обмін ввідними. Надішліть те, що вже є, — цього достатньо, щоб побачити вузькі місця й запропонувати схему.

Якщо частину збірок уже винесено в спільні Orbs і вони працюють, скажіть про це: не будемо переробляти те, що не заважає.

  • Список репозиторіїв і сервісів, які потрібно перевести на спільні збірки, із позначкою, які з них критичні для релізів.
  • Поточні файли конфігурації збірки та розгортання — як є, разом із тимчасовими обхідними рішеннями.
  • Схему галуження та правила випуску: що вважається релізом, хто і як його підтверджує.
  • Вимоги до доступів: які ролі потрібні інженерам, до яких середовищ, реєстрів образів і секретів.
  • Обмеження, які не можна порушувати: закритий код, ізольовані контури, вікна для важких збірок.
  • Цільові показники: час збірки, частка автоматичних перевірок, частота випусків.
  • Контакт відповідального за інфраструктуру — з ним узгодимо технічні деталі.

Далі порядок такий: розбираємо ввідні, повертаємося з оцінкою впровадження та планом робіт за етапами — від пілотного репозиторію до тиражування на решту.

Окремо фіксуємо порядок передачі: що залишається у вашому контурі, які права й документація переходять вашій команді, як результат підтримується після запуску. Опишіть завдання — повернемося з оцінкою та планом.

Наші компетенції:

Останні роботи

  • Розробка сайту компанії B2B ADVANCE
    Розробка сайту компанії B2B ADVANCE
    1542
  • Розробка веб-додатків для компанії FEEDME
    Розробка веб-додатків для компанії FEEDME
    1393
  • Розробка веб-сайту для компанії БЕЛФІНГРУП
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    1081
  • Розробка інтернет магазину для компанії FURNORO
    Розробка інтернет магазину для компанії FURNORO
    1368
  • Розробка логотипу компанії B2B Advance
    Розробка логотипу компанії B2B Advance
    815
  • Розробка веб-додатків для компанії Enviok
    Розробка веб-додатків для компанії Enviok
    1139