Итак, вы - лид в команде из, скажем, 5-6 разработчиков и 2-3 тестировщика, возникает проблема - как тестировать задачи, запускать тесты по веткам, желательно не толкаясь локтями на одном стенде и не потратив недели на настройку и поддержку инфраструктуры. Сегодня расскажу о подходе, к которому сам пришел, оказавшись в такой ситуации.
Первым делом рассмотрим опции:
Использование заранее созданных веток для разных целей, скажем, master, dev и test. Этот подход самый простой в реализации, но его минус - он плохо масштабируется. Тестировщикам придется делить один стенд для работы, кроме того, вливать больше одной ветки для тестирования в dev - чревато конфликтами и беспорядком в git. Создавать же еще больше технических веток - еще больший хаос в гите.
Собирать каждую ветку в свой полноценный стенд, qa-xxx.dev.xxx.com . Это самый зрелый и удобный для использования вариант, вот только для маленьких команд он непосильно сложен, особенно если среди вас нет девопса. Вам нужно будет разобраться с автоматизацией выдачи SSL сертификатов, настройкой DNS, nginx, подчисткой старых веток и так далее.
Компромиссный вариант. Собирать каждую ветку по отдельности, но по запросу и на заранее созданные инстансы, test-1, test-2 и так далее. При необходимости масштабирования, создавать новые стенды руками. Кажется, это то, что нужно, вот только как это реализовать? Об этом и пойдет речь ниже.
Для "маршрутизации" веток на инстансы мы используем labels. Выглядит это следующим образом:
Назначение label на ветку автоматически запускает пайплайн с нужными параметрами. Но есть нюанс - оказывается, gitlab не позволяет запускать пайплайны по триггеру на добавление / удаление лейбла. Все, что позволяет gitlab - это выставить ограничение на запуск пайплайна при создании MR, что не совсем подходит - обычно сборка ветки происходит не сразу после его создания.
Хорошая новость в том, что это все-таки возможно - с помощью pipeline triggers и webhooks. Мы просто слушаем события merge request events и триггерим пайплайн в двух случаях: добавление label к ветке и добавление новых коммитов к ветке с нужными label.
Первым делом создаем pipeline trigger token в Settings > CI/CD > Pipeline triggers.
Наш pipeline trigger - по сути микросервис, который принимает вебхуки и по необходимости запускает пайплайны.
Вот его код
const axios = require('axios')
var express = require('express');
var router = express.Router();
router.post('/', async function (req, res) {
const requestBody = req.body
const labelRegex = /^test-\d+$/
let label
// If MR is open
if (!['opened', 'locked'].includes(requestBody.object_attributes.state)) {
res.send({
'message': 'invalid status',
'status': requestBody.object_attributes.state
})
return;
}
if (!requestBody.changes.labels) {
// No changes in labels or new commits
if (!requestBody.changes.updated_at && Object.keys(requestBody.changes).length > 0) {
res.send({
'message': 'The change is empty',
})
return;
}
label = requestBody.labels
.filter(label => label.title.match(labelRegex))
.map(label => label.title)[0]
} else {
// Find a changed label
label = requestBody.changes.labels.current
.filter(label => label.title.match(labelRegex))
.filter(label => !requestBody.changes.labels.previous.find(lbl => lbl.id === label.id))
.map(label => label.title)[0]
}
if (!label) {
res.send({
message: 'label not found'
})
return;
}
await axios.post(`https://gitlab.com/api/v4/projects/${process.env.PROJECT_ID}/trigger/pipeline`, {
token: process.env.ACCESS_TOKEN,
ref: requestBody.object_attributes.source_branch,
variables: {
TEST_INSTANCE: label,
CI_MERGE_REQUEST_LABELS: requestBody.labels?.map(label => label.title).join(',') ?? ''
}
})
res.send({
'message': 'success'
})
});
module.exports = router;
Осталось только добавить вебхук в гитлабе в Settings > Webhooks:
Gitlab предоставляет доступ к логам, так что в случае проблем их можно довольно легко отладить:
Все! Теперь просто присвойте label test-N вашей ветке и вебхук запустит пайплайн. Из приятных бонусов: скрипт также передает все остальные назначенные label-ы через запятую, что позволяет дополнительно задавать на лету переменные окружения, например, вы можете через label управлять, пересоздавать ли БД с нуля или использовать сохраненные данные, и так далее.
Заключение
Конечно, этот способ не идеален и масштабируется лишь ограниченно. Если вам не хватает пяти стендов для тестирования, возможно, вам стоит задуматься о более продвинутой схеме. Однако, для небольших команд подход обеспечивает неплохой development experience, позволяет полноценно тестировать в независимых окружениях и не накладывает ограничений на разработку.