J. A. R. V. I. S. — невидимий помічник Leo

Рано чи пізно IT-проекти стикаються з труднощами підтримки високої якості коду та/або збільшується часом доставки змін до production. Lingualeo випробувала на собі всі проблеми зростання і готова поділитися своєю історією підвищення ефективності розробки. Про те, як це відбувалося, розповів teamlead інфраструктурою команди Lingualeo Михайло Кабищев.
image

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

  • Початок розробки продукту. Розробка і налагодження відбувається на одному-єдиному сервері, на якому запущено все, що потрібно проектом. Помилки бувають часто, але це не страшно, тому що це лише прототип, і живих користувачів там ще немає.
  • Поява перших користувачів. Компанія починає відчувати ціну помилок і проблем на продакшені. Вже не можна правити все на продакшені, приходить розуміння того, що треба мислити релізами. Розробники впроваджують workflow для роботи з кодової базою, з'являється щось на кшталт stage-сервера, на якому тестуються релізи.
  • Зростання проекту і команди. У розробці одночасно перебуває велика кількість завдань. Вимоги до процесу і якості коду сильно зростають. За всім дуже важко стежити: хтось забуває запустити юніт-тести, хтось не знає, куди і як потрібно задеплоить чергову завдання для тестування.
У підсумку рутинні операції починають забирати дуже багато часу, і компанія думає, як автоматизувати ці процеси.

Інтуїтивно команда Lingualeo досить швидко розуміла, що пора переходити на наступний етап. Іноді перехід відбувався в правильному руслі, а іноді не дуже. У якийсь момент в компанії сформувалися кілька команд розробки, які працювали в одній загальній системі. У кожної команди був свій проект в jira, власна CI-система (система Continuous Integration), вміє запускати юніт-тести, розгортати майданчики для тестування, збирати і деплоить релізи.

Звучить начебто непогано, так?

Але все одно в цьому підході були моменти, які нам не дуже подобалися:

Велику кількість проектів в jira. Спочатку всі використовували один workflow. Але потім одна команда додала додаткове поле, інша — проміжний статус і так далі. З-за цього постійно доводилося вносити зміни у CI-систему, і іноді ці зміни конфліктували один з одним.

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

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

На черговому ретро ми зрозуміли, що далі так жити не можна, і висунули кілька тез:

  • Вся розробка повинна «переїхати» в єдиний проект в jira з єдиним для всіх workflow
  • Можна використовувати готовий build-сервер замість самопісного
  • Система деплоя повинна бути універсальною, щоб деплоить різні програми

Єдиний проект в Jira

Враховуючи свій попередній досвід при проектуванні нового workflow, вирішили розділити всі можливі типи задач на дві групи:

Task
Це завдання, які не вимагають написання коду і мають найпростіший flow:

image

  1. Task. Просто завдання. Це може бути research, додавання нового репозиторію, написання документації і т. д.
  2. Migration. Всі міграції бази даних ми виконуємо вручну. Вручну не означає, що ми робимо це прямо в sql-консолі, для цього є ряд інструментів, але їх запуск відбувається вручну.


CI-unit
image

Жовтим кольором на схемі вказані кроки, які необхідно виконувати вручну, а синім ті, які потрібно автоматизувати


Такі завдання потребують написання коду в одному з репозиторіїв. В якості фреймворку для роботи з кодом ми використовуємо gitflow, тому поділ наступне:
  1. feature
  2. bug
  3. hotfix
Призначення типів можна прочитати у будь-якому описі про gitflow. Ми розділили feature і bug на окремі типи, так Lingualeo зручніше розставляти пріоритети для задач і вести аналітику. Раніше кожна команда мала свою власну agile-дошку зі своїми завданнями, це було дуже зручно, і потрібно було придумати спосіб поділу завдань по командам.

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

  • Team. Ім'я команди, що володіє завданням.
  • Component. В нашому випадку component однозначно вказує на репозиторій. Хоча jira і дозволяє вказувати кілька значень у полі component, з цим проблем у нас не виникало.
  • FixVersion. Номер релізу, в який потрапить(попала) завдання.
  • Reporter. Людина, який створив завдання.
  • Customer. Це замовник завдання. За замовчуванням він дорівнює reporter'у, але може бути змінений. Саме він виробляє приймання завдання.
  • Developer. Розробник, відповідальний за завдання. У завдання можуть підзадачі, які будуть робити різні люди, але саме developer відповідає за задачу цілком.
  • QA Engineer. За аналогією c developer'ом, ця людина відповідає за тестування завдання цілком.
  • Code reviewer. Всі завдання (ну добре, майже всі) у нас проходять code-review, і це та людина, яка цим займається.


Build-сервер

Точно так само, як і всі, команда Lingualeo дивилася на трьох основних гравців на цьому ринку: Jenkins, Teamcity, Bamboo. Потестували всі три, але найбільше сподобався Teamcity: безкоштовний, є зручний REST API і приємний інтерфейс.

Так хто такий J. A. R. V. I. S.?

Отже, ми отримали наступну конфігурацію: jira — для ведення завдань, teamcity -для прогону тестів, складання релізів і т. д і github — для зберігання коду. Нам потрібно було подружити всі ці системи разом.

Для кожної пари існує кілька плагінів, але всі вони здалися нам або не дуже зручними, або не надавали потрібного функціоналу. Тому ми вирішили написати невелике ядро, яке буде керувати всіма системами.

image

При проектуванні ми врахували вимога «безболісно і мінімальними зусиллями замінити будь-який компонент системи». Наприклад, для заміни build-сервера нам доведеться всього лише написати новий адаптер, а не шукати купу плагінів.

Ми хотіли, щоб J. A. R. V. I. S. вмів робити за нас наступні операції:

  • перевіряти код на відповідність стандартам
  • запускати unit-тести
  • створювати і мерджить pull request'и в github'e
  • створювати тестові стенди для тестування завдань
  • створювати релизные і хотфиксные гілки
  • виробляти деплой
Крім цього ми хотіли якомога рідше вносити зміни у вихідний код системи, вона повинна надавати нам блоки (дії), з яких ми будемо збирати наші процеси, а сама послідовність дій і умови, при яких їх виконувати, ми вирішили описувати у вигляді yaml-файлів. Ось приклад конфігурації, в якому описані правила для запуску перевірки коду:

start inspection:
search:
jql: 'project="DEV" AND status="Ready for Inspection"'
action:
type: 'run-build'
params:
buildTypeId: 'CodeInspection_%component%'
success:
transition: 'start inspection'
fail:
transition: 'fail inspection'
complete inspection:
search:
jql: 'project="DEV" and status="On inspection"'
action:
type: 'check-build'
params:
buildTypeId: 'CodeInspection_%component%'
success:
transition: 'complete inspection'
fail:
transition: 'fail inspection'


Перше правило знаходить всі тікети зі статусом Ready for Inspection і запускає відповідну конфігурація в teamcity, яка перевіряє код на відповідність стандартам, а також проганяє всі unit-тести. Якщо запуск конфігурації вдався, то до тікети застосовується перехід start inspection, і він переходить у статус On Inspection. Друге правило перевіряє всі запущені конфігурації. Якщо вона успішно завершилася, то тікет переходить далі. Якщо під час складання сталися помилки, то тікет через перехід Fail Inspection повертається назад до виробника.

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

Сам J. A. R. V. I. S. розробляється і теж збирається за допомогою J. A. R. V. I. S.'a :)

Завдяки уніфікації процесу розробки в компанії і створення J. A. R. V. I. S.'a ми змогли підвищити якість що випускається нами коду і зменшити час доставки змін до production, зменшили час розробників, що витрачався на рутинні операції.

Джерело: Хабрахабр

0 коментарів

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