Релізний менеджмент — це з тих речей, які непомітні, коли все працює добре, і нестерпні, коли ні. Роками користувачі Linear обходили відсутність нормального release-примітиву — версійні лейбли, групи, кастомні статуси, саморобні скрипти. Це працювало. І тихо ламалося: лейбл не перейменували в одній з команд, issue застрягло в "Awaiting Release" на три спринти, а стейкхолдер питає "то що насправді зараз у проді?" — і ніхто впевнено не відповідає.
Тоді Linear випустили Linear Release — повноцінну сутність із pipelines, stages, версіями та CI-інтеграцією. Це огляд фічі з нотатками про міграцію реального маркетплейс-проєкту з лейбл-схеми.
Як було раніше
Без об'єкту релізу кожна команда вигадує свій протокол. У мене він був такий. Кожне issue, яке йшло в реліз, отримувало версійний лейбл — next_v1.5.0_marketplace — який жив у label-групі Versions. Group exclusivity не давав одному issue нести два версійних лейбли водночас. Після деплою next_* перейменовувався в current_*, а попередній current_* — в old_*. Окреме issue "Release vX.Y.Z" тримало QA-чеклист для задеплоєного білда.
Кастомна CI-частина закривала прогалини: dispatch-тригернутий GitHub Actions workflow аналізував коміти, визначав чи це major/minor/patch, генерував CHANGELOG, відкривав release PR у main. Кастомний скіл проходив по лейблах, створював milestone, готував QA issue, публікував project update — це pre-deploy. Після merge той самий скіл перейменовував лейбли, переводив issues в In Prod, оновлював releases-документ, постив post-deploy update.
Воно працювало. Мінус очевидний: кожна частина — це обхідний шлях. Система несла сенс, якого платформа не бачила. Новачкам потрібен був written runbook, щоб зрозуміти що означає next_ vs current_ vs old_. І єдине місце, де сам деплой відбивався в Linear, — це ручний статус-апдейт, який хтось мав не забути написати.
Що таке Linear Release
Linear Release вводить три примітиви, які стара лейбл-схема апроксимувала вручну:
- Pipeline — один незалежний стрім релізів. Веб-апп, який шипиться на merge, — один pipeline; iOS-апп на 2-тижневому потязі — інший; нічний dogfood білд — третій. Кожен має власну історію версій і власний access key.
- Stage — фаза всередині одного релізу на pipeline'і: code freeze, in QA, RC soak. Стейджі — це гейти на тому самому білді, а не окремі стріми.
- Версія — те, що реально продукує деплой. Її створює CI, а не людина, що вводить значення в лейбл.
Pipeline'и бувають двох типів: continuous (кожен деплой завершає реліз — типово для веб-аппів, що шипляться на merge) і scheduled (релізи збирають зміни, проходять через стейджі, потім шипляться — типово для версіонованого mobile та on-prem). Вибір між ними важливий: неправильний робить модель незручною, правильний — змушує її зникнути.
Сама інтеграція — невеликий action у workflow:
- uses: linear/linear-release-action@v0
with:
access-key: ${{ secrets.LINEAR_ACCESS_KEY }}
command: sync
Все. Action читає коміти, мапить їх на Linear issues, оновлює активний реліз на pipeline'і. Жодних webhook-вигадок, MCP-скриптів і перейменування лейблів.
Кілька слів про Jira
У Jira є fixVersion уже два десятиліття. Те, що Linear доганяє лише зараз, — справедлива критика: трекінг релізів — це release-management 101. Але як саме Linear до цього дійшов — відрізняється так, що це важливо.
Релізний об'єкт у Jira — це запис у каталозі: ти створюєш його заздалегідь, чіпляєш issues, шипиш. Система не знає твого CI. Зв'язок Jira-CI — це той плагін, що ти прикручуєш (Bitbucket, Jenkins, GitLab — вибери свій інтеграційний податок).
Реліз у Linear — це CI-артефакт: action запускається на кожному деплої, версія — те, що каже твоя гілка чи тег, а зв'язок з issues обчислюється з комітів. Каталог тут нижче за течією від деплою, а не вище. Для команд, які реально деплоять кілька разів на тиждень, ця інверсія і робить різницю.
Зворотний бік чесний: якщо твій реліз-процес нерегулярний і керується вручну — модель Jira з каталогом досі відчувається природніше. Linear Release хоче, щоб ти деплоїв з CI.
Як я це налаштовую у себе
У моєму маркетплейс-проєкті це виглядає так. Dispatch-тригернутий release-prepare workflow досі робить version bump + changelog + release PR — це pre-deploy механіка, ортогональна Linear. Що змінилось — те, що відбувається після merge у main.
Vercel auto-deploy досі біжить. Auto-tag і GitHub Release досі створюються. Але тепер другий job у тому ж workflow ще й кличе Linear Release Action. Pipeline — continuous (шипимось на merge), версія береться з package.json, action робить решту: знаходить коміти з останнього релізу, резолвить їх issue keys і завершає реліз на відповідному pipeline'і.
Що залишилось — і це важливо — це шар business update. Linear дає тобі релізи; він не дає тобі stakeholder-зрозумілого опису того, що задеплоїлось. Це досі моя відповідальність — генерувати, але вже зі структурованого release-об'єкта, а не з лейблів.
Ручних операцій з лейблами на реліз
Cross-team sync-кроків
Додано CI-рядків
Розмір кастомного скіла
Що це дає
Нудна відповідь — видимість. Цікавіша — видимість для людей, які не сидять у Linear щодня.
Нетехнічні стейкхолдери ставлять три питання: що зашипилось, коли і що далі. До Linear Release ці відповіді жили у трьох різних місцях — лейбли, статус-апдейти, project-документ. Тепер вони на самому релізі: версія, час деплою, issues, стейдж. У кожного релізу є стабільний URL, який можна вкинути куди завгодно.
Для розробки більший виграш — автоматичний зв'язок деплоїв з issues. Якщо хоч раз доводилось вручну переводити 14 issues з "Awaiting Release" у "In Prod" тому що хтось зашипив під час твоєї обідньої перерви — ти знаєш ціну старого підходу. Тепер це робить CI.
Чого ще не вистачає
Дві прогалини помітні.
Перша — Slack-доставка. У Linear є інтеграція зі Slack загалом, але release-сповіщення досі вимагають Zap/workflow, щоб запостити в канал гарне "v1.5.0 щойно вийшов — ось що в ньому". Для фічі, чий весь сенс — нетехнічна видимість, це дивне упущення.
Друга — генерація business update. Release-об'єкт знає список issues, але перетворити це на stakeholder-summary — згрупувати subtasks по parent-фічах, прибрати внутрішні tech-debt items, виділити feature-flagged роботу — це досі кастомна логіка. Тримаю її в скілі. Було б непогано, якби Linear дав template-хук тут.
Третя дрібна претензія — генерація changelog. Action знає коміти, GitHub Release має changelog, але деталь релізу в Linear не показує сам текст changelog прямо. Можна перейти за лінком, але це зайвий клік.
Підсумок
Епоха лейблів-і-груп у релізах Linear була довгим обхідним шляхом до відсутнього примітиву. Кастомний CI і скіли, які я навколо нього збудував, — не дарма: вони кодували знання, які тепер платформа виражає нативно. Але це різниця між тим, щоб пояснювати runbook кожному новому інженеру, і тим, щоб показати пальцем на URL.
Linear Release — не найамбітніша фіча, яку випустили Linear, але та, яку я найменше помічаю. А для релізного менеджменту — це найвищий комплімент, який можна зробити.