Работая с GitLab каждый день, повторяешь кучу одинаковых действий и большинство хотелось бы делать быстрее чем UI позволяет. Каждое действие — это 3-5 кликов и перезагрузка страницы. В какой-то момент надоело и я запилил Chrome-расширение. Расскажу как оно устроено внутри и какие задачи пришлось решать.
Авторизация без токенов
Первый вопрос который встал — как ходить в GitLab API. Стандартный путь: попросить пользователя создать Personal Access Token, сохранить его в storage расширения. Но это неудобно (лишний шаг при установке) и небезопасно (токен с широким scope лежит в сторе, забывается, не отзывается).
Решение оказалось проще. Content script инжектится на страницы GitLab и у него уже есть доступ к session cookies. API-запросы с credentials: 'same-origin' проходят как обычные запросы со страницы. Пользователь залогинен в GitLab — расширение работает. Разлогинился — не работает. Никаких токенов хранить не надо.
Для Jira чуть другая схема. Content script не имеет доступа к cookies другого домена, поэтому запросы делает background service worker через chrome.cookies.getAll(). Достает session cookies Jira, делает fetch напрямую. Пользователь один раз дает разрешение на домен Jira через optional_host_permissions и все.
Наружу ничего не уходит. Все в браузере.
Цепочки действий и background worker
Простые действия типа rebase или retry failed jobs — это один API-вызов из content script. Но появились составные операции. Например «Ship» — это: запустить rebase, подождать пока закончится, сделать bump версии (найти файл, инкрементить, коммитить), подождать новый пайплайн, включить auto-merge.
Проблема: если пользователь уйдет со страницы, content script умрет вместе с цепочкой. Пришлось вынести логику в background service worker. Он живет пока браузер открыт и не зависит от вкладок.
Прогресс выполнения транслируется через chrome.tabs.sendMessage на все открытые вкладки GitLab. На любой странице внизу появляется панель с текущим статусом и кнопкой отмены. Даже если ты ушел с MR страницы, видно что происходит.
Сейчас кнопки: Rebase, Bump версии (patch/minor/major, путь к файлу настраивается), Auto-merge, Ship, Force merge, Retry failed, быстрые комментарии из шаблонов. Все включаются/выключаются, перетаскиваются drag&drop’ом. Можно создать свои кнопки которые запускают нужные джобы.

Борьба с DOM GitLab
Это была головная боль. GitLab активно переписывает фронтенд на Vue, и между версиями 17.6 и 17.11 DOM поменялся несколько раз. Селекторы которые работали в понедельник, ломались в среду после обновления.
Решение — все CSS-селекторы собраны в один объект в начале файла. Каждый селектор содержит несколько фоллбеков через запятую: сначала data-testid (полустабильный API GitLab), потом легаси классы. Когда что-то ломается после апдейта — правишь одну строчку в одном месте.
Вторая проблема — тайминг. Vue рендерит список MR асинхронно, и к моменту запуска расширения DOM может быть пустой. MutationObserver с полингом и таймаутами — если за 3 секунды список не появился, начинаем наблюдать за body и ждем до 10 секунд.
Именно из-за этой хрупкости DOM появились фичи для списка MR. Раз уж я все равно получаю страницу и жду рендер — почему бы не добавить полезные вещи, которых в GitLab нет.
Что добавил на список MR
Размер MR показывается цветным бейджом S/M/L/XL по количеству измененных строк — сразу видно какой MR по размеру. Красный бейдж КОНФЛИКТЫ если ветка конфликтует. Счетчик нерешенных тредов.
Из того что GitLab зачем-то убрал: индикатор своего аппрува. Пришлось вернуть. Фильтр «Ждет моего ревью» показывает только MR на твоем ревью. Копирование ссылки одной кнопкой.
API-запросы за этими данными идут батчами по 5 штук и кешируются на 5 минут.
Jira без переключения контекста
На списке MR расширение парсит ID тикетов из заголовков (регулярка настраивается) и показывает цветные бейджи со статусом — зеленый Done, синий In Progress, желтый In Review.
Но кайф в другом — кликаешь на бейдж и прямо тут, в GitLab, появляется сайдбар с полной инфой по тикету. Описание, приоритет, исполнитель, лейблы, спринт, эпик. Можно менять статус, переназначить исполнителя или сделать свою кнопку которая в один клик поменяет статус и исполнителя.
Технически Jira-запросы идут через background worker (как описал выше — cookies API). Кеш 5 минут. На детальной странице MR бейджи тоже показываются в заголовке.

Cherry-pick: когда одной ветки мало
На странице коммитов рядом с каждым SHA появляется кнопка cherry-pick. Открывается модалка со списком целевых веток, cherry-pick идет по очереди в каждую. Статус в реальном времени — видно что прошло, а где конфликт.
Интересная задача: что делать когда cherry-pick падает из-за конфликта в файле версии? Это частый кейс если бампишь версию в каждом коммите. Расширение воспроизводит коммит через Commits API, исключая файл версии и сохраняя оригинального автора. Версию можно поднять отдельно после или указать чтобы оно поднялось автоматически.
Опционально для каждого cherry-pick создается отдельная ветка и merge request.
Всякое разное
Command Palette. Cmd+K на любой странице GitLab открывает палитру команд. Навигация по проекту, действия с текущим MR, поиск файлов. Контекстная — на MR странице показывает экшены, на остальных только навигацию.
Просмотр упавших джобов. Когда пайплайн падает, обычно надо идти в пайплайн, найти упавший джоб, открыть, скроллить лог… Расширение показывает названия упавших джобов и последние строки ошибки прямо на странице MR. ANSI-цвета рендерятся.
Отчет по активности. Сводка за день: MR создал, замерджил, комментарии, аппрувы. Формируется из GitLab API. Для дейли — скопировал и вставил.
Стек и решения
Manifest V3. Весь код на ES5. Никаких сборщиков и библиотек. Просто JS-файлы. Локализация на 7 языков через стандартный chrome.i18n.
Настройки в chrome.storage.sync, синхронизируются между браузерами. Есть профили по проектам — если в каждом репозитории свой flow, создаешь профиль и расширение подхватывает нужные настройки по URL. Автосохранение с debounce 500мс.

Установка
Chrome Web Store: GitLab MR Actions
Ссылки
Landing: termyanen.github.io/gitlab-actions
Бесплатно, open source. Работает с любым self-hosted GitLab.
Если пользуетесь GitLab и у вас есть рутина которая бесит — пишите в комменты или в issues, добавлю.