Привет, Хабр! Меня зовут Женя, я SDET в «Островке». Каждый день я помогаю командам внедрять автотесты — от сетапа проекта до код-ревью. Сегодня хочу рассказать, как мы бились над кросспроектными джобами и что из этого вышло.
Спойлер: финальное решение оказалось элегантным, но давайте по порядку.
Нативный тригер - просто, но не гибко
Для начала обратимся к нативному тригеру gitlab, который выглядит довольно просто:
trigger_autotests:
stage: autotests
trigger:
project: $PROJECT_RELATIVE_URL
branch: $AUTOTESTS_BRANCH
variables:
BASE_HOST: https://$CI_COMMIT_REF_SLUG-$CI_PROJECT_NAME.p.ostrovok.ru # любая значимая переменная
Скорее всего при запуске пайплайна с такой джобой вы увидите ошибку 403 Forbidden, причем причина падения видна только при наведении курсора тк в джобу провалиться нельзя

Чтобы решить проблему, необходимо добавить каждого разработчика в Members целевого проекта с ролью Developer, но если команда большая, это превращается в рутину. Групповые права не работают — CI_JOB_TOKEN привязан к конкретному пользователю. Прокинуть системный токен тоже не получится — этот функционал пока в обсуждении (ссылка).
Api-тригер - обходим ограничения
Более гибкий вариант:
Берём токен из Settings → CI/CD → Pipeline triggers в проекте с тестами
Сохраняем его в переменные основного проекта как DOWNSTREAM_TOKEN
Используем в джобе:
trigger_autotests:
stage: autotests
tags:
- runner-type:shell
script:
- >
curl -X POST
-F token=$DOWNSTREAM_TOKEN
-F ref=$AUTOTESTS_BRANCH
-F "variables[BASE_HOST]=https://$CI_COMMIT_REF_SLUG-$CI_PROJECT_NAME.p.ostrovok.ru" # любая значимая переменная
"https://gitlab.ostrovok.ru/api/v4/projects/$DOWNSTREAM_PROJECT_ID/trigger/pipeline"
Запускаем и радуемся, что джоба не упала из-за отсутствия прав. Но такая джоба не упадет, даже если упадут тесты, ведь для GitLab главное — что POST-запрос отработал. Никакой визуализации дочернего пайплайна не будет, так что тестировщикам приходится вручную отслеживать результаты.
Вот и получается дилемма: либо раздавать права, либо мириться с невидимыми тестами. Либо...
Наше решение - тесты в Docker-образе
autotests:
stage: autotests
image: $AUTOTESTS_IMAGE
tags:
- runner-type:qa-selenium-docker
script:
- cd /opt
- pytest ... # любая ваша команда с тестами
Казалось бы, решение идеальное — но и здесь есть два подводных камня, о которых лучше знать заранее:
1) GitLab по умолчанию монтирует проект в /builds/<namespace>/<project>, полностью игнорируя WORKDIR из Dockerfile. Если не сделать cd в нужную директорию (у нас это /opt/tests), pytest просто не найдёт тесты, и вы получите загадочное "No tests found".
2) Права доступа — снова они! Стандартный раннер отказывался удалять pycache после тестов, поэтому все новые джобы падали с ошибками. Решили переключением на qa-runner, который работает в привилегированном режиме (privileged: true) — это даёт ему права на удаление системных файлов вроде pycache.
Выводы: какой способ выбрать
Нативный триггер — если команды маленькие и права не проблема
API-триггер — когда важно обойти ограничения, а мониторить тесты вручную — норма
Docker-образ — универсальное решение, которое подходит почти для всех случаев
Всем зеленых пайплайнов!