Еволюція CI у команді мобільної розробки

Сьогодні більшість програмних продуктів розробляють у командах. Умови успіху командної розробки можна як простої схеми.

Еволюція CI у команді мобільної розробки

Написавши код, ви повинні переконатися, що він:

  1. Работает.
  2. Нічого не ламає, зокрема код, який написали ваші колеги.

Якщо обидві умови виконуються, ви на шляху до успіху. Щоб легко перевіряти ці умови та не згортати з вигідного шляху, вигадали Continuous Integration.

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

  • Люди дорогі. Час роботи будь-якого програміста коштує дорожче, ніж година будь-якого сервера.
  • Люди помиляються. Тому можуть виникнути ситуації, коли запустили тести не на тій гілці або зібрали не той коміт для тестувальників.
  • Люди лінуються. Періодично, коли я закінчую якесь завдання, у мене виникає думка: «Та що тут перевіряти? Я написав два рядки — стопудово все працює! Думаю, деяким із вас такі думки теж іноді спадають на думку. Але перевіряти треба завжди.

Як впроваджували та розвивали Continuous Integration у команді мобільної розробки Авіто, як дійшли від 0 до 450 збірок на день, і що білд-машини збирають 200 годин на день, розповідає Микола Нестеров.ннестеров) - учасник всіх еволюційних змін CI/CD Android-програми.

Розповідь побудована на прикладі Android-команди, але більшість підходів можна застосувати і на iOS теж.


Колись давно в Android-команді Авіто працювала одна людина. Йому за визначенням нічого з Continuous Integration було не потрібно: інтегруватися нема з ким.

Але додаток зростав, з'являлося дедалі більше нових завдань, відповідно, зростала команда. У якийсь момент настав час формальніше налагодити процес інтеграції коду. Вирішили використовувати Git flow.

Еволюція CI у команді мобільної розробки

Концепція Git flow відома: у проекті є одна спільна гілка develop, а для кожної нової фічі розробники зрізають окрему гілку, коммітують у неї, пушать, і коли хочуть влити свій код у гілку develop, відкривають pull request. Для обміну знаннями та обговорення підходів ми запровадили code review, тобто колеги повинні перевірити та підтвердити код один одного.

Перевірки

Дивитися код очима – це круто, але недостатньо. Тому вводяться автоматичні перевірки.

  • Насамперед перевіряємо складання АРК.
  • багато Junit-тестів.
  • Вважаємо code coverage, якщо вже запускаємо тести.

Щоб зрозуміти, як слід запускати ці перевірки, подивимося на процес розробки Авіто.

Схематично його можна так:

  • Розробник пише код свого ноутбука. Можна запустити перевірки інтеграції прямо тут або комміт-хуком, або просто ганяти перевірки у фоні.
  • Після того, як розробник запушив код, він відчиняє pull request. Щоб його код потрапив у гілку develop, необхідно пройти code review та зібрати потрібну кількість підтверджень. Можна включити перевірки та білди тут: поки не всі успішні білди, pull request злити не можна.
  • Після того, як pull request злитий і код потрапив у develop, можна вибрати зручний час: наприклад, вночі, коли всі сервери вільні, і ганяти перевірки скільки влізе.

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

Запускати перевірки вночі нам дуже сподобалося, тому що часу та серверів багато, можна розгулятися. Але, на жаль, коли код фічі потрапив у develop, у розробника вже набагато менше мотивації чинити помилки, які знайшов CI. Я періодично ловив себе на думці, коли дивився в ранковому звіті на всі знайдені помилки, що полагоджу їх колись пізніше, тому що зараз у Jira лежить круте нове завдання, яке так і хочеться почати робити.

Якщо перевірки блокують pull request, то мотивації достатньо, тому що поки білди не позеленіють, код не потрапить у develop, а значить, завдання не буде завершено.

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

На той момент усі наші збірки проходили досить швидко, тому ми просто включили блокером до pull request складання АРК, Junit-тести та розрахунок code coverage. Включили, подумали — і відмовилися від code coverage, бо вважали, що він нам не потрібний.

На все настроювання базового CI у нас пішло два дні (тут і далі тимчасова оцінка приблизна, потрібна для масштабу).

Після цього почали думати далі, а чи правильно ми взагалі перевіряємо? Чи правильно запускаємо білди на pull request?

Ми запускали збірку на останньому коміті гілки, з якої відкрито pull request. Але перевірки цього комміту можуть показати лише те, що код, який написав розробник, працює. Але вони не доводять, що він нічого не зламав. Насправді потрібно перевіряти стан гілки develop після того, як у неї буде влита фіча.

Еволюція CI у команді мобільної розробки

Для цього ми написали простий bash-скрипт premerge.sh:

#!/usr/bin/env bash

set -e

git fetch origin develop

git merge origin/develop

Тут просто підтягуються всі найсвіжіші зміни з develop і вливаються у поточну гілку. Ми додали скрипт premerge.sh першим кроком всіх білдів і почали перевіряти саме те, що ми хочемо, тобто інтеграцію.

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

Додаток розвивався, задач з'являлося все більше, росла команда, і premerge.sh іноді почав нас підводити. У develop проникали конфліктуючі зміни, які ламали складання.

Приклад того, як це відбувається:

Еволюція CI у команді мобільної розробки

Два розробники одночасно починають пиляти фічі A і B. Розробник фічі A виявляє в проекті функцію, що не використовується. answer() і, як добрий бойскаут, видаляє її. При цьому розробник фічі B у гілці додає новий виклик цієї функції.

Розробники закінчують роботу і одночасно відкривають pull request. Запускаються білди, premerge.sh перевіряє обидва pull request щодо свіжого стану develop – всі перевірки зелені. Після цього мерщій pull request фічі A, мерзнеться pull request фічі B… Бум! Develop ламається, тому що в коді develop є виклик неіснуючої функції.

Еволюція CI у команді мобільної розробки

Коли не збирається develop, це локальна катастрофа. Вся команда нічого не може зібрати та віддати на тестування.

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

Еволюція CI у команді мобільної розробки

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

Як не ламати develop

Перший варіант: перезбирати всі pull request при оновленні develop. Якщо в нашому прикладі pull request з фічею A перший потрапить у develop, pull request фічі B перезбереться, і, відповідно, перевірки не пройдуть через помилку компіляції.

Щоб зрозуміти, скільки часу на це піде, розглянемо приклад із двома PR. Відкриваємо два PR: два білди, два запуски перевірок. Після того, як перший PR влитий в develop, другий треба перезбирати. На два PR йде три запуску перевірок: 2 + 1 = 3.

В принципі нормально. Але ми переглянули статистику, і типовою ситуацією в нашій команді було 10 відкритих PR, а тоді кількість перевірок — це сума прогресії: 10 + 9 +… + 1 = 55. Тобто, щоб прийняти 10 PR, треба перезбирати 55 разів. І це в ідеальній ситуації, коли всі перевірки відбуваються з першого разу, коли ніхто не відкриває додатковий pull request, доки обробляється цей десяток.

Уявіть себе розробником, якому потрібно встигнути натиснути на кнопку «merge» першим, тому що якщо це зробить сусід, то доведеться чекати, поки всі зборки пройдуть заново.

Другий можливий спосіб: збирати pull request після code review. Тобто відкриваєте pull request, збираєте потрібну кількість акрів від колег, виправляєте що потрібно, після цього запускаєте білди. Якщо вони успішні, pull request зливається з розробкою. У цьому випадку додаткових перезапусків немає, але зворотний зв'язок сильно сповільнюється. Я як розробник, відкриваючи pull request, відразу хочу бачити, чи збирається він. Наприклад, якщо впав якийсь тест, потрібно його швидко відремонтувати. У разі відкладеного складання уповільнюється зворотний зв'язок, а отже, і вся розробка. Нас це теж не влаштовувало.

У результаті залишився лише третій варіант. велосипедити. Весь наш код, всі наші вихідні записи зберігаються в репозиторії в Bitbucket-сервері. Відповідно нам довелося розробити плагін для Bitbucket.

Еволюція CI у команді мобільної розробки

Цей плагін перевизначає механізм злиття pull request'ів. Початок стандартний: відкривається PR, запускаються всі зборки, проходить code review. Але після того, як code review пройдено, і розробник вирішує натиснути на "merge", плагін перевіряє, щодо якого стану develop запускалися перевірки. Якщо після білдів develop встиг оновитися, плагін не дозволить влити такий pull request в основну гілку. Він просто перезапустить білди щодо нового develop.

Еволюція CI у команді мобільної розробки

У нашому прикладі з змінами, що конфліктують, такі білди не пройдуть через помилку компіляції. Відповідно, розробнику фічі B доведеться виправити код, перезапустити перевірки, тоді плагін автоматично застосує pull request.

До впровадження цього плагіна ми в середньому було 2,7 запуску перевірки на один pull request. Із плагіном стало 3,6 запуску. Нас це влаштувало.

Варто зазначити, що цей плагін має недолік: він перезапускає білд лише один раз. Тобто все одно залишається маленьке віконце, через яке до develop можуть потрапити конфліктуючі зміни. Але ймовірність цього невисока, і ми пішли на цей компроміс між кількістю запусків та ймовірністю поломки. За два роки вистрілило лише один раз, тож, напевно, не дарма.

На написання першої версії плагіна для Bitbucket ми пішли два тижні.

Нові перевірки

Тим часом наша команда продовжувала зростати. Додавали нові перевірки.

Ми подумали: навіщо робити помилки, якщо їх можна запобігати? І тому впровадили статичний аналіз коду. Почали з lint, який входить до Android SDK. Але він на той час зовсім не вмів працювати з Kotlin-кодом, а в нас вже 75% програми було написано на Kotlin. Тому до lint додалися інтегровані Android Studio checks.

Для цього довелося сильно перекрутитися: взяти Android Studio, запакувати її в Docker і запускати на CI з віртуальним монітором, щоб вона думала, що запущена на реальному ноутбуці. Але це працювало.

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

Але інструментальні тести та скріншотні тести потрібно запускати на пристроях: на емуляторах або на реальних девайсах. З огляду на те, що тестів багато і вони ганяються часто, потрібна ціла ферма. Заводити свою ферму дуже важко, тому ми знайшли готовий варіант - Firebase Test Lab.

Firebase Test Lab

Був обраний, тому що Firebase - продукт Google, тобто має бути надійним і навряд чи колись помре. Ціни демократичні: 5 $ за годину роботи реального пристрою, 1 $ за годину роботи емулятора.

На впровадження Firebase Test Lab у наш CI пішло приблизно три тижні.

Але команда продовжувала зростати, і Firebase нас, на жаль, почав підбивати. На той момент він не мав ніякого SLA. Іноді Firebase змушував чекати, поки звільниться потрібна кількість девайсів для тестів, а не починав їх виконувати одразу, як ми цього хотіли. Очікування у черзі займало до півгодини, а це дуже довго. Instrumentation тести ганялися на кожному PR, затримки дуже сповільнювали розробку, а потім ще прийшов рахунок за місяць із круглою сумою. Загалом, вирішено було відмовитися від Firebase і пиляти in-house, якщо вже команда досить зросла.

Docker + Python + bash

Взяли docker, запхали в нього емулятори, написали просту програмку на Python, яка в потрібний момент піднімає необхідну кількість емуляторів в потрібній версії, а коли їх зупиняє. І, звичайно, кілька bash-скриптів — куди ж без них?

На створення власного тестового середовища пішло п'ять тижнів.

В результаті на кожний pull request припадав великий, що блокує злиття, перелік перевірок:

  • Складання АРК;
  • Junit-тести;
  • Lint;
  • Android Studio checks;
  • Instrumentation тести;
  • Screenshot тести.

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

Занадто довго – це скільки? Ми вивантажили дані з Bitbucket та TeamCity в систему аналізу та зрозуміли, що середній час очікування 45 хвилин. Тобто розробник, відкриваючи pull request у середньому чекає на результати білдів 45 хвилин. На мою думку, це дуже багато, і так працювати не можна.

Звичайно, ми вирішили прискорити всі наші білди.

Прискорюємось

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

Забираємо занадто довгі перевірки

Наш Continuous Integration міг відловити такі типи помилок та проблем.

  • Не збирається. CI може зловити помилку компіляції, коли через конфліктні зміни щось не збирається. Як я вже казав, тоді ніхто нічого не може зібрати, розробка встає, і всі нервуються.
  • Баг у поведінці. Наприклад, коли програма збирається, але при натисканні на кнопку падає, або кнопка взагалі не натискається. Це погано, тому що такий баг може дістатися користувача.
  • Баг у верстці. Наприклад, кнопка натискається, але з'їхала на 10 пікселів вліво.
  • Збільшення техборгу.

Подивившись на цей список, ми зрозуміли, що критичними є лише перші два пункти. Такі проблеми ми хочемо відловлювати насамперед. Баги у верстці виявляються на етапі design-review і тоді легко виправляються. Робота з техборгом потребує окремого процесу та планування, тому ми вирішили не перевіряти його на pull request.

Виходячи з цієї класифікації, ми перетрусили весь перелік перевірок. Викреслили Lint і перенесли його запуск на ніч: просто щоб він видавав звіт, скільки проблем у проекті. З техборгом ми домовилися працювати окремо, а від Android Studio checks відмовилися зовсім. Android Studio у Docker для запуску інспекцій звучить цікаво, але завдає багато неприємностей у підтримці. Будь-яке оновлення версій Android Studio – це боротьба з незрозумілими багами. Так само складно було підтримувати скріншотні тести, тому що бібліотека працювала не дуже стабільно, були помилкові спрацьовування. Скріншотні тести прибрали зі списку перевірок.

Зрештою у нас залишилися:

  • Складання АРК;
  • Junit-тести;
  • Instrumentation tests.

Gradle remote cache

Без важких перевірок стало краще. Але немає межі досконалості!

Наш додаток вже було розбито приблизно на 150 gradle модулів. Зазвичай у такому випадку добре працює Gradle remote cache, і ми вирішили спробувати.

Gradle remote cache – це сервіс, який може кешувати артефакти складання окремих завдань в окремих модулях. Gradle, замість того щоб реально компілювати код, по HTTP стукає в remote cache і запитує, чи хтось вже виконував цю таску. Якщо так, просто скачує результат.

Запустити Gradle remote cache легко, тому що Gradle надає Docker-образ. Нам удалося це зробити за три години.

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

Нижче графік cache misses.

Еволюція CI у команді мобільної розробки

На самому початку відсоток промахів повз кеш був близько 65. Через три тижні вдалося довести це значення до 20%. Виявилося, що таски, які збирає Android додаток, мають дивні транзитивні залежності, через які Gradle промахувався повз кеш.

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

Імпакт аналіз

На pull request ми збираємо git diff та знаходимо змінені Gradle модулі.

Еволюція CI у команді мобільної розробки

Має сенс запускати тільки ті instrumentation тести, які перевіряють змінені модулі та всі модулі, які від них залежать. Тести для сусідніх модулів запускати сенс немає: там не змінився код, і нічого не може зламатися.

З instrumentation тестами не все так просто, тому що вони повинні перебувати в верхньому модулі Application. Ми застосували евристику з аналізом байт-коду, щоб зрозуміти, до якого модуля належить кожен тест.

Модернізація роботи інструментальних тестів, щоб вони перевіряли лише задіяні модулі, зайняла близько восьми тижнів.

Заходи щодо прискорення перевірок успішно спрацювали. З 45 хвилин ми дійшли приблизно до 15. Чверть години чекати на білд вже нормально.

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

Еволюція CI у команді мобільної розробки

Проблеми зі зворотним зв'язком уповільнюють розробку, тому ми постаралися забезпечити максимально зрозумілу та докладну інформацію про кожен PR та білд. Почали з коментарів у Bitbucket до PR із зазначенням, який білд упав і чому, писали адресні повідомлення у Slack. Зрештою зробили для сторінки PR dashboard зі списком усіх білдів, які зараз запускаються та їх станом: у черзі, запускається, упав чи завершився. Можна клікнути на білд і потрапити на його балку.

Еволюція CI у команді мобільної розробки

На докладний зворотний зв'язок було витрачено шість тижнів.

Плани

Переходимо до новітньої історії. Вирішивши питання зворотного зв'язку, ми вийшли на новий рівень – вирішили збудувати свою ферму емуляторів. Коли тестів та емуляторів багато, ними складно керувати. У результаті всі наші емулятори переїхали в k8s-кластер із гнучким управлінням ресурсів.

Крім того, є інші плани.

  • Повернути Lint (та інший статичний аналіз). Ми вже працюємо у цьому напрямі.
  • Запускати на PR блокер все end-to-end тести на всіх версіях SDK.

Отже, ми простежили історію розвитку Continuous Integration у Авіто. Тепер хочу дати кілька порад з погляду досвідченого.

Поради

Якби я міг дати тільки одну пораду, це була б ця:

Будь ласка, будьте обережнішими з shell-скриптами!

Bash – дуже гнучкий та потужний інструмент, на ньому дуже зручно та швидко писати скрипти. Але з ним можна потрапити у пастку, і ми, на жаль, у неї потрапили.

Починалося все із простих скриптів, які запускалися на наших білд-машинах:

#!/usr/bin/env bash
./gradlew assembleDebug

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

Еволюція CI у команді мобільної розробки

Можете уявити трудомісткі на розвиток таких скриптів. Раджу не потрапляти до цієї пастки.

Чим можна замінити?

  • Будь-якою скриптовою мовою. Писати на Python або Kotlin Script зручніше, бо це програмування, а чи не скрипти.
  • Або описати всю логіку білдів у вигляді Custom gradle tasks для вашого проекту.

Ми вирішили вибрати другий варіант, і зараз планомірно видаляємо всі bash-скрипти та пишемо багато кастомних gradle-тасок.

Порада №2: зберігати інфраструктуру у коді.

Зручно, коли налаштування Continuous Integration зберігається не в UI-інтерфейсі Jenkins або TeamCity і т.п., а як текстові файли прямо в репозиторії проекту. Це дає версію. Не важко буде відкотитися або зібрати код на іншій гілці.

Скрипти можна зберігати у проекті. А що робити з оточенням?

Порада №3: ​​із оточенням може допомогти Docker.

Android-розробникам він точно допоможе, iOS поки що немає, на жаль.

Це приклад простого docker-файлу, який містить у собі jdk та android-sdk:

FROM openjdk:8

ENV SDK_URL="https://dl.google.com/android/repository/sdk-tools-linux-3859397.zip" 
    ANDROID_HOME="/usr/local/android-sdk" 
    ANDROID_VERSION=26 
    ANDROID_BUILD_TOOLS_VERSION=26.0.2

# Download Android SDK
RUN mkdir "$ANDROID_HOME" .android 
    && cd "$ANDROID_HOME" 
    && curl -o sdk.zip $SDK_URL 
    && unzip sdk.zip 
    && rm sdk.zip 
    && yes | $ANDROID_HOME/tools/bin/sdkmanager --licenses

# Install Android Build Tool and Libraries
RUN $ANDROID_HOME/tools/bin/sdkmanager --update
RUN $ANDROID_HOME/tools/bin/sdkmanager "build-tools;${ANDROID_BUILD_TOOLS_VERSION}" 
    "platforms;android-${ANDROID_VERSION}" 
    "platform-tools"

RUN mkdir /application
WORKDIR /application

Написавши цей docker-файл (скажу по секрету, його можна не писати, а стягнути готовий з GitHub) і зібравши образ, ви отримуєте віртуальну машину, на якій зможете збирати програму і запускати Junit-тести.

Два головні аргументи, чому це має сенс: масштабованість і повторюваність. З використанням docker можна швидко підняти десяток білд-агентів, які будуть мати таке ж оточення, як і колишній. Це полегшує життя CI-інженерів. Запхати android-sdk в docker дуже просто, з емуляторами трохи складніше: доведеться трохи піднапружитися (ну, або знову з GitHub завантажити готове).

Порада №4: пам'ятати, що перевірки робляться не заради перевірок, а для людей.

Розробникам дуже важливий швидкий і, найголовніше, зрозумілий зворотний зв'язок: що у них зламалося, який тест упав, де білдлог подивитися.

Порада №5: будьте прагматичні при розвитку Continuous Integration.

Чітко розумійте, які типи помилок хочете запобігти скільки готові витратити ресурсів, часу, машинного часу. Занадто довгі перевірки можна, наприклад, перенести на ніч. А від тих, які ловлять не дуже важливі помилки, зовсім відмовитися.

Порада №6: використовуйте готові інструменти.

Наразі є багато компаній, які надають хмарний CI.

Еволюція CI у команді мобільної розробки

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

Порада №7: у великій команді вигідніше in-house рішення.

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

Економіка описує все наше життя, зокрема Continuous Integration. Я побудував графік трудовитрат на кожен етап розвитку нашої Continuous Integration.

Еволюція CI у команді мобільної розробки

Видно, що будь-яке поліпшення дається дедалі важче. Дивлячись на цей графік, можна зрозуміти, що розвивати Continuous Integration потрібно відповідно до зростання розміру команди. Для команди з двох осіб витрачати 50 днів на розробку внутрішньої ферми емуляторів — така собі ідея. Але при цьому для великої команди зовсім не займатися Continuous Integration — теж погана ідея, тому що на проблеми інтеграції, ремонт комунікації тощо. піде ще більше часу.

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

  • Автоматизувати недешево. Згадайте графік трудовитрат.
  • За автоматизації люди помиляються.
  • Автоматизувати іноді дуже ліньки, бо й так усе працює. Навіщо ще щось покращувати, навіщо весь цей Continuous Integration?

Але я маю статистику: у 20% збірок ловляться помилки. І це не тому, що наші розробники погано пишуть код. Це тому, що розробники впевнені, що якщо вони припустяться якоїсь помилки, вона не потрапить у develop, її зловлять автоматизовані перевірки. Відповідно, розробники можуть витрачати більше часу на написання коду та цікаві штуки, а не локально щось ганяти та перевіряти.

Займайтеся Continuous Integration. Але в міру.

До речі, Микола Нестеров не лише сам робить класні доповіді, а ще входить до програмного комітету AppsConf і допомагає іншим готувати вам змістовні виступи. Повноту та корисність програми найближчої конференції можна оцінити за темами розкладі. А за подробицями приходьте 22-23 квітня до Інфопростору.

Джерело: habr.com

Додати коментар або відгук