У сучасній розробці програмного забезпечення надзвичайно важливо розуміти, навіщо потрібен пайплайн безперервної інтеграції (Continuous Integration, CI) та як його побудувати так, щоб він автоматично перевіряв якість коду застосунку і навіть пропонував виправлення для виявлених проблем. Для розробників програмного забезпечення, особливо тих, хто працює на інженерних посадах, ці знання є вкрай цінними та безпосередньо застосовуються в щоденній роботі.
Уявімо, що ви працюєте в команді розробників над певною функціональністю. Команда використовує Git-workflow під назвою trunk-based development, який є стандартним підходом у багатьох DevOps-орієнтованих середовищах. За такого підходу основна гілка завжди підтримується у стані, готовому до релізу. Будь-яка зміна коду, відправлена в основну гілку, автоматично запускає CI/CD-пайплайн.
Цей пайплайн є повністю автоматизованим і не містить вузьких місць, тобто на жодному етапі не потрібне ручне втручання. Код автоматично збирається, тестується та розгортається щонайменше в середовищі розробки. За умови хорошого покриття тестами розгортання може доходити до staging-середовища або навіть production без ручного тестування чи перевірок коду. Проте для надійної роботи такої схеми необхідна велика кількість автоматизованих тестів, які гарантують, що все, що потрапляє в основну гілку, безпечно випускати для кінцевих користувачів.
Типи тестів у релізному пайплайні
Надійний релізний пайплайн містить кілька типів тестів, кожен з яких перевіряє окремий аспект коду:
Модульні та інтеграційні тести, які перевіряють бізнес-логіку коду з різними вхідними даними та сценаріями.
Тести безпеки, що сканують залежності та бібліотеки на відомі вразливості, виявляють жорстко закодовані секрети та перевіряють дотримання кращих практик безпеки в логіці застосунку.
Тести якості коду, які оцінюють не функціональність і не безпеку, а зручність супроводу та чистоту коду.
Навіть якщо застосунок працює коректно та є безпечним, погана якість коду може призвести до серйозних проблем у майбутньому. Типові приклади — дублювання коду замість винесення логіки у функції, використання застарілих бібліотек або API, ризик виникнення null-pointer винятків у Java-застосунках чи недостатнє покриття тестами. Саме такі проблеми і виявляють перевірки якості коду.
Git-workflow та важливість раннього тестування
Хоча trunk-based development часто вважається ідеальним підходом, на практиці багато команд використовують workflow з feature-гілками. У такому підході вся розробка функціональності відбувається в окремих гілках, а не безпосередньо в основній. Розробники створюють feature-гілку, працюють у ній ізольовано, а потім створюють merge request.
Merge request виконує роль «фільтра»: всі автоматизовані тести запускаються до злиття з основною гілкою та визначають, чи перебуває код у стані, готовому до релізу. Це критично важливо, оскільки якщо проблемний код потрапить в основну гілку, він може заблокувати роботу всієї команди. Навіть якщо інші розробники виправлять власні помилки, реліз буде неможливим, доки не усунуть початкову проблему.
Однак тестування лише на рівні merge request має свої недоліки. Якщо у feature-гілці накопичилося багато комітів, проблеми можуть бути виявлені занадто пізно. Їх виправлення може зайняти години або навіть дні, особливо якщо код із самого початку був побудований на основі застарілих або небезпечних бібліотек.
Безперервна інтеграція та цикл зворотного зв’язку
Саме тут з’являється безперервна інтеграція (CI). CI — це практика частих комітів невеликих змін коду з автоматичним запуском тестів для кожного коміту. Такий підхід створює швидкий цикл зворотного зв’язку та дозволяє виправляти проблеми одразу після їх появи.
Наприклад, розробник додає нову бібліотеку та робить коміт. CI-пайплайн одразу виявляє, що з цією бібліотекою пов’язані проблеми. Розробник може негайно виправити ситуацію і рухатися далі. Для junior-інженерів це особливо корисно, оскільки вони навчаються кращих практик програмування завдяки постійному зворотному зв’язку.
CI-пайплайни для feature-гілок не містять етапів розгортання — вони призначені виключно для тестування. З часом тестування зсувається все раніше в процесі розробки, що відомо як концепція shift-left testing.
Локальні перевірки коду та необхідність централізованої автоматизації
Деякі проблеми коду можна виявити ще до запуску CI. Сучасні IDE, такі як IntelliJ IDEA, мають вбудовані інспекції, які підсвічують дублювання коду, потенційні помилки та можливості для покращення безпосередньо під час написання коду. Часто вони також пропонують автоматичні виправлення, наприклад оновлення версії бібліотеки або рефакторинг логіки.
Однак розробники можуть ігнорувати ці підказки або не знати, як ними користуватися. Саме тому не можна покладатися лише на особисту уважність окремих членів команди. Централізовані автоматизовані перевірки в CI-пайплайнах забезпечують сталі стандарти якості для всього проєкту.
Кілька рівнів контролю якості коду
Зазвичай перевірки якості коду виконуються на кількох рівнях:
Локально в IDE розробника
У CI-пайплайні feature-гілки
У пайплайні merge request
Після злиття коду в основну гілку
Такий багаторівневий підхід гарантує, що проблеми, спричинені взаємодією змін від різних розробників, будуть виявлені якомога раніше.
Побудова CI-пайплайна для перевірки якості коду
Після усвідомлення важливості CI наступним кроком стає створення пайплайна для автоматизованих перевірок якості коду. У цьому прикладі використовується GitHub Actions як CI-сервер та Kodana, інструмент від JetBrains, для аналізу коду.
Kodana використовує той самий механізм інспекцій, що й IDE JetBrains. Він сканує код, знаходить проблеми та пропонує виправлення, але робить це централізовано в межах CI-пайплайна. Інструмент підтримує багато популярних мов програмування, зокрема Java, JavaScript, Python, PHP та інші, що позбавляє потреби використовувати різні інструменти для кожної мови.
Для налаштування потрібно лише два кроки:
Створити workflow GitHub Actions для CI-пайплайна
Створити конфігураційний файл
kodana.yml, який визначає правила аналізу
Завдяки інтеграції з IDE обидва файли можуть бути згенеровані автоматично, що суттєво спрощує старт.
Інтеграція Kodana з GitHub Actions
CI-workflow налаштовується так, щоб запускатися при кожному pull request до основної гілки. Він містить два ключові кроки:
отримання вихідного коду репозиторію
запуск аналізу Kodana за допомогою спеціального action
Для зручної візуалізації результатів пайплайн підключається до Kodana Cloud, який надає веб-інтерфейс із детальними даними про знайдені проблеми, рівні їхньої серйозності та файли, у яких вони виникли.
Аналіз і керування результатами перевірок
Після завершення виконання пайплайна результати доступні в кількох місцях:
безпосередньо в інтерфейсі GitHub Actions
у Kodana Cloud з можливістю детальної фільтрації та сортування
Розробники можуть розглядати кожну проблему окремо, зосереджуватися на помилках із високим рівнем критичності та точно розуміти їх походження.
Автоматичне виправлення коду в CI-пайплайні
Kodana також підтримує автоматичне виправлення проблем. У разі ввімкнення цієї функції CI-пайплайн самостійно застосовує запропоновані виправлення та створює pull request із зміненим кодом. Серед прикладів таких виправлень:
видалення зайвого або невикористовуваного коду
додавання перевірок на null
інтеграція бібліотек на кшталт Lombok
усунення дублювання бізнес-логіки
Такі pull request можна перевірити та об’єднати вручну, зберігаючи повний контроль над змінами.
Підтримка якості коду в довгостроковій перспективі
Усі результати сканувань зберігаються з часом, формуючи історію, за якою можна відслідковувати тенденції — чи покращується якість коду, чи навпаки погіршується. Це особливо корисно для великих команд із різним рівнем досвіду розробників.
Висновок
Добре спроєктований CI-пайплайн є невід’ємною частиною сучасної розробки програмного забезпечення. Інтеграція автоматизованих перевірок якості коду в CI-workflow забезпечує ранній зворотний зв’язок, зменшує технічний борг і запобігає потраплянню проблем у production.
Централізована автоматизація зменшує потребу в ручних перевірках, знижує навантаження на senior-інженерів і допомагає всій команді писати чистіший, стабільніший та легший у підтримці код. Зрештою, CI-пайплайни з перевірками якості стають основою надійних, масштабованих і професійних DevOps-процесів.