Итак, вы - лид в команде из, скажем, 5-6 разработчиков и 2-3 тестировщика, возникает проблема - как тестировать задачи, запускать тесты по веткам, желательно не толкаясь локтями на одном стенде и не потратив недели на настройку и поддержку инфраструктуры. Сегодня расскажу о подходе, к которому сам пришел, оказавшись в такой ситуации.

Первым делом рассмотрим опции:

  1. Использование заранее созданных веток для разных целей, скажем, master, dev и test. Этот подход самый простой в реализации, но его минус - он плохо масштабируется. Тестировщикам придется делить один стенд для работы, кроме того, вливать больше одной ветки для тестирования в dev - чревато конфликтами и беспорядком в git. Создавать же еще больше технических веток - еще больший хаос в гите.

  2. Собирать каждую ветку в свой полноценный стенд, qa-xxx.dev.xxx.com . Это самый зрелый и удобный для использования вариант, вот только для маленьких команд он непосильно сложен, особенно если среди вас нет девопса. Вам нужно будет разобраться с автоматизацией выдачи SSL сертификатов, настройкой DNS, nginx, подчисткой старых веток и так далее.

  3. Компромиссный вариант. Собирать каждую ветку по отдельности, но по запросу и на заранее созданные инстансы, 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, позволяет полноценно тестировать в независимых окружениях и не накладывает ограничений на разработку.

Комментарии (5)


  1. Ares_ekb
    04.07.2022 17:25
    +1

    У нас как-то проще настроено. Для каждой задачи ветка. Задачи в основном достаточно короткие - до недели. Для веток создаются merge request. Для всех коммитов в ветки, для которых уже создан merge request, запускается сборка через GitLab CI/CD. При слиянии ветки в master запускается сборка + деплой на тестовый стенд. На тестовом стенде можно проверить функциональность. Не возникает потребности тестировать отдельные ветки.


  1. cccco
    04.07.2022 18:45
    +1

    А по тегам разворачивать пробовали?
    Соотносите каждый стенд с тегом определённого формата. Например, тег формата stage-* запускает разворачивание на стейдж-стенде с коммита, на который этот тег был повешен.


  1. AlexGluck
    04.07.2022 21:28

    А почему бы не нанять фриланс-девопса, чтобы он под вас написал код?


    1. ivymike
      05.07.2022 09:13

      Б - безопасность


  1. AlexGluck
    05.07.2022 10:02
    +1

    Что безопасность? Заключить те же соглашения что и со штатным сотрудником нельзя?