Данная статья будет интересна как тестировщикам, так и разработчикам, но рассчитана в большей степени на автоматизаторов, которые столкнулись с проблемой настройки GitLab CI/CD для проведения интеграционного тестирования в условиях недостаточности инфраструктурных ресурсов и/или отсутствия платформы оркестрации контейнеров. Я расскажу, как настроить развертывание тестируемых окружений при помощи docker compose на одном единственном GitLab shell раннере и так, чтобы при развертывании нескольких окружений запускаемые сервисы друг другу не мешали.
Содержание
- Предпосылки
- GitLab Shell Runner
- Подготовка docker-compose.yml
- Подготовка Makefile
- Подготовка .gitlab-ci.yml
- Результат
Предпосылки
В моей практике частенько случалось "лечить" интеграционное тестирование на проектах. И зачастую первой и самой значительной проблемой является CI pipeline, в котором интеграционное тестирование разрабатываемого сервиса(ов) проводится в dev/stage окружении. Это вызывало не мало проблем:
- Из-за дефектов в том или ином сервисе в процессе интеграционного тестирования тестовый контур может быть испорчен битыми данными. Бывали случаи, когда отправка запроса с битым JSON-форматом вешал сервис, что приводило стенд полностью в нерабочее состояние.
- Замедлением работы тестового контура с ростом тестовых данных. Думаю, описывать пример с очисткой/откатом БД не имеет смысла. В своей практике я не встречал проекта, где эта процедура проходила бы гладко.
- Риск нарушить работоспособность тестового контура при тестировании общих настроек системы. Например, user/group/password/application policy.
- Тестовые данные от автотестов мешают жить ручным тестировщикам.
Кто-то скажет, что хорошие автотесты должны чистить данные после себя. У меня есть аргументы против:
- Динамические стенды весьма удобны в использовании.
- Не каждый объект можно удалить из системы через API. Например вызов на удаление объекта не реализован, так как противоречит бизнес логике.
- При создании объекта через API может создаваться огромное количество метаданных, которые удалить проблематично.
- Если тесты имеют зависимость между собой, то процесс очистки данных после выполнения тестов превращается в головную боль.
- Дополнительные (и, на мой взгляд, не оправданные) вызовы к API.
- И главный аргумент: когда тестовые данные начинают чистить прямо из БД. Это превращается в настоящий PK/FK цирк! От разработчиков слышно: «Я только табличку добавил/удалил/переименовал, почему 100500 интеграционных тестов попадало?»
По моему мнению, самое оптимальное решение — это динамическое окружение.
- Много кто использует docker-compose для запуска тестового окружения, но мало кто использует docker-compose при проведении интеграционного тестирования в CI/CD. И тут я не беру в расчет kubernetes, swarm и другие платформы оркестрации контейнеров. Не в каждой компании они есть. Хорошо бы было, если бы docker-compose.yml был универсальный.
- Если даже у нас есть свой QA раннер, как нам сделать так, чтобы сервисы запускаемые через docker-compose не мешали друг-другу?
- Как собирать логи тестируемых сервисов?
- Как чистить раннер?
У меня есть собственный GitLab раннер для своих проектов и с этими вопросами я столкнулся при разработке Java клиента для TestRail. А точнее при запуске интеграционных тестов. Вот далее и будем решать эти вопросы с примерами из данного проекта.
GitLab Shell Runner
Для раннера рекомендую линуксовую виртуалку с 4 vCPU, 4 GB RAM, 50 GB HDD.
На просторах интернета очень много информации по настройке gitlab-runner, поэтому коротко:
- Заходим на машинку по SSH
Если у вас менее 8 GB RAM, то рекомендую сделать swap 10 GB, чтобы не приходил OOM killer и не убивал нам задачи из-за нехватки RAM. Такое может случится, когда запускается одновременно более 5 задач. Задачи будут проходить помедленнее, зато стабильно.
Пример с OOM killerЕсли в логах задачи вы увидите
bash: line 82: 26474 Killed
, то просто выполните на раннереsudo dmesg | grep 26474
[26474] 1002 26474 1061935 123806 339 0 0 java Out of memory: Kill process 26474 (java) score 127 or sacrifice child Killed process 26474 (java) total-vm:4247740kB, anon-rss:495224kB, file-rss:0kB, shmem-rss:0kB
И если картина выглядит примерно так, то или добавляйте swap, или докидывайте RAM.
- Устанавливаем gitlab-runner, docker, docker-compose, make.
- Добавляем пользователя
gitlab-runner
в группуdocker
sudo groupadd docker sudo usermod -aG docker gitlab-runner
- Регистрируем gitlab-runner.
Открываем на редактирование
/etc/gitlab-runner/config.toml
и добавляем
concurrent=20 [[runners]] request_concurrency = 10
Это позволит запускать параллельные задачи на одном раннере. Более подробно читать тут.
Если у вас машинка помощнее, например 8 vCPU, 16 GB RAM, то эти цифры можно сделать как минимум в 2 раза больше. Но все зависит от того, что конкретно будет запускаться на данном раннере и в каком количестве.
Этого достаточно.
Подготовка docker-compose.yml
Основная задача — это docker-compose.yml, который будет использован как локально, так и в CI pipeline.
Для запуска нескольких экземпляров окружения будет использоваться переменная COMPOSE_PROJECT_NAME (см. makefile).
Пример моего docker-compose.yml
version: "3"
# Для корректной работы web (php) и fmt нужно,
# чтобы контейнеры имели общий исполняемый контент.
# В нашем случае, это директория /var/www/testrail
volumes:
static-content:
services:
db:
image: mysql:5.7.22
environment:
MYSQL_HOST: db
MYSQL_DATABASE: mydb
MYSQL_ROOT_PASSWORD: 1234
SKIP_GRANT_TABLES: 1
SKIP_NETWORKING: 1
SERVICE_TAGS: dev
SERVICE_NAME: mysql
migration:
image: registry.gitlab.com/touchbit/image/testrail/migration:latest
links:
- db
depends_on:
- db
fpm:
image: registry.gitlab.com/touchbit/image/testrail/fpm:latest
container_name: "testrail-fpm-${CI_JOB_ID:-local}"
volumes:
- static-content:/var/www/testrail
links:
- db
web:
image: registry.gitlab.com/touchbit/image/testrail/web:latest
# Если переменные TR_HTTP_PORT или TR_HTTPS_PORTS не определены,
# то сервис поднимается на 80 и 443 порту соответственно.
ports:
- ${TR_HTTP_PORT:-80}:80
- ${TR_HTTPS_PORT:-443}:443
volumes:
- static-content:/var/www/testrail
links:
- db
- fpm
Подготовка Makefile
Я использую Makefile, так как это весьма удобно как для локального управления окружением, так и в CI.
Далее комментарии инлайн
# У меня в проектах все вспомогательные вещи лежат в директории `.indirect`,
# в том числе и `docker-compose.yml`
# Использовать bash с опцией pipefail
# pipefail - фейлит выполнение пайпа, если команда выполнилась с ошибкой
SHELL=/bin/bash -o pipefail
# Если переменная CI_JOB_ID не определена
ifeq ($(CI_JOB_ID),)
# присваиваем значение local
CI_JOB_ID := local
endif
# Экспортируем переменную окружения
export COMPOSE_PROJECT_NAME = $(CI_JOB_ID)-testrail
# Останавливаем и удаляем контейнеры, сеть, volumes
docker-down:
docker-compose -f .indirect/docker-compose.yml down
# Предварительно выполняем docker-down (опционально)
docker-up: docker-down
# Забираем последние образы из docker-registry
docker-compose -f .indirect/docker-compose.yml pull
# Запускаем окружение
# force-recreate - принудительное пересоздание контейнеров
# renew-anon-volumes - не использовать volumes предыдущих контейнеров
docker-compose -f .indirect/docker-compose.yml up --force-recreate --renew-anon-volumes -d
# Ну и, на всякий случай, вывести что там у нас в принципе запущено на машинке
docker ps
# Коллектим логи сервисов
docker-logs:
mkdir -p ./logs
docker logs $${COMPOSE_PROJECT_NAME}_web_1 >& logs/testrail-web.log || true
docker logs $${COMPOSE_PROJECT_NAME}_fpm_1 >& logs/testrail-fpm.log || true
docker logs $${COMPOSE_PROJECT_NAME}_migration_1 >& logs/testrail-migration.log || true
docker logs $${COMPOSE_PROJECT_NAME}_db_1 >& logs/testrail-mysql.log || true
# Очистка раннера
docker-clean:
@echo Останавливаем все testrail-контейнеры
docker kill $$(docker ps --filter=name=testrail -q) || true
@echo Очистка докер контейнеров
docker rm -f $$(docker ps -a -f --filter=name=testrail status=exited -q) || true
@echo Очистка dangling образов
docker rmi -f $$(docker images -f "dangling=true" -q) || true
@echo Очистка testrail образов
docker rmi -f $$(docker images --filter=reference='registry.gitlab.com/touchbit/image/testrail/*' -q) || true
@echo Очистка всех неиспользуемых volume
docker volume rm -f $$(docker volume ls -q) || true
@echo Очистка всех testrail сетей
docker network rm $(docker network ls --filter=name=testrail -q) || true
docker ps
$ make docker-up
docker-compose -f .indirect/docker-compose.yml pull
Pulling db ... done
Pulling migration ... done
Pulling fpm ... done
Pulling web ... done
docker-compose -f .indirect/docker-compose.yml up --force-recreate --renew-anon-volumes -d
Creating network "local-testrail_default" with the default driver
Recreating local-testrail_db_1 ... done
Recreating local-testrail_migration_1 ... done
Recreating local-testrail_fpm_1 ... done
Recreating local-testrail_web_1 ... done
docker ps
CONTAINER ID NAMES
3b8f9d4af29c local-testrail_web_1
5622c7d742d5 local-testrail_fpm_1
b580e3392038 local-testrail_migration_1
e467630bd3a5 local-testrail_db_1
$ export CI_JOB_ID=123456789
$ make docker-up
docker-compose -f .indirect/docker-compose.yml pull
Pulling db ... done
Pulling migration ... done
Pulling fpm ... done
Pulling web ... done
docker-compose -f .indirect/docker-compose.yml up --force-recreate --renew-anon-volumes -d
Creating network "123456789-testrail_default" with the default driver
Creating volume "123456789-testrail_static-content" with default driver
Creating 123456789-testrail_db_1 ... done
Creating 123456789-testrail_fpm_1 ... done
Creating 123456789-testrail_migration_1 ... done
Creating 123456789-testrail_web_1 ... done
docker ps
CONTAINER ID NAMES
ccf1ad33d0e8 123456789-testrail_web_1
bc079964f681 123456789-testrail_fpm_1
10dc9d4d8f2a 123456789-testrail_migration_1
fe98d43c380e 123456789-testrail_db_1
$ make docker-logs
mkdir -p ./logs
docker logs ${COMPOSE_PROJECT_NAME}_web_1 >& logs/testrail-web.log || true
docker logs ${COMPOSE_PROJECT_NAME}_fpm_1 >& logs/testrail-fpm.log || true
docker logs ${COMPOSE_PROJECT_NAME}_migration_1 >& logs/testrail-migration.log || true
docker logs ${COMPOSE_PROJECT_NAME}_db_1 >& logs/testrail-mysql.log || true
Подготовка .gitlab-ci.yml
Запуск интеграционных тестов
Integration:
stage: test
tags:
- my-shell-runner
before_script:
# Аутентифицируемся в registry
- docker login -u gitlab-ci-token -p ${CI_JOB_TOKEN} ${CI_REGISTRY}
# Генерируем псевдоуникальные TR_HTTP_PORT и TR_HTTPS_PORT
- export TR_HTTP_PORT=$(shuf -i10000-60000 -n1)
- export TR_HTTPS_PORT=$(shuf -i10000-60000 -n1)
script:
# поднимаем наше окружение
- make docker-up
# запускаем тесты исполняемым jar (у меня так)
- java -jar itest.jar --http-port ${TR_HTTP_PORT} --https-port ${TR_HTTPS_PORT}
# или в контейнере
- docker run --network=testrail-network-${CI_JOB_ID:-local} --rm itest
after_script:
# собираем логи
- make docker-logs
# останавливаем окружение
- make docker-down
artifacts:
# сохраняем логи
when: always
paths:
- logs
expire_in: 30 days
В результате запуска такой задачи в артефактах директория logs будет содержать логи сервисов и тестов. Что очень удобно в случае возникновения ошибок. У меня каждый тест в параллели пишет свой лог, но об этом я расскажу отдельно.
Очистка раннера
Задача будет запускаться только по расписанию.
stages:
- clean
- build
- test
Clean runner:
stage: clean
only:
- schedules
tags:
- my-shell-runner
script:
- make docker-clean
Далее идем в наш GitLab проект -> CI/CD -> Schedules -> New Schedule и добавляем новое расписание
Результат
Запускаем 4 задачи в GitLab CI
В логах последней задачи с интеграционными тестами видим контейнеры от разных задач
CONTAINER ID NAMES
c6b76f9135ed 204645172-testrail-web_1
01d303262d8e 204645172-testrail-fpm_1
2cdab1edbf6a 204645172-testrail-migration_1
826aaf7c0a29 204645172-testrail-mysql_1
6dbb3fae0322 204645084-testrail-web_1
3540f8d448ce 204645084-testrail-fpm_1
70fea72aa10d 204645084-testrail-mysql_1
d8aa24b2892d 204644881-testrail-web_1
6d4ccd910fad 204644881-testrail-fpm_1
685d8023a3ec 204644881-testrail-mysql_1
1cdfc692003a 204644793-testrail-web_1
6f26dfb2683e 204644793-testrail-fpm_1
029e16b26201 204644793-testrail-mysql_1
c10443222ac6 204567103-testrail-web_1
04339229397e 204567103-testrail-fpm_1
6ae0accab28d 204567103-testrail-mysql_1
b66b60d79e43 204553690-testrail-web_1
033b1f46afa9 204553690-testrail-fpm_1
a8879c5ef941 204553690-testrail-mysql_1
069954ba6010 204553539-testrail-web_1
ed6b17d911a5 204553539-testrail-fpm_1
1a1eed057ea0 204553539-testrail-mysql_1
$ docker login -u gitlab-ci-token -p ${CI_JOB_TOKEN} ${CI_REGISTRY}
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
WARNING! Your password will be stored unencrypted in /home/gitlab-runner/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
$ export TR_HTTP_PORT=$(shuf -i10000-60000 -n1)
$ export TR_HTTPS_PORT=$(shuf -i10000-60000 -n1)
$ mkdir ${CI_JOB_ID}
$ cp .indirect/docker-compose.yml ${CI_JOB_ID}/docker-compose.yml
$ make docker-up
docker-compose -f ${CI_JOB_ID:-.indirect}/docker-compose.yml kill
docker network rm testrail-network-${CI_JOB_ID:-local} || true
Error: No such network: testrail-network-204645172
docker network create testrail-network-${CI_JOB_ID:-local}
0a59552b4464b8ab484de6ae5054f3d5752902910bacb0a7b5eca698766d0331
docker-compose -f ${CI_JOB_ID:-.indirect}/docker-compose.yml pull
Pulling web ... done
Pulling fpm ... done
Pulling migration ... done
Pulling db ... done
docker-compose -f ${CI_JOB_ID:-.indirect}/docker-compose.yml up --force-recreate --renew-anon-volumes -d
Creating volume "204645172-testrail_static-content" with default driver
Creating 204645172-testrail-mysql_1 ...
Creating 204645172-testrail-mysql_1 ... done
Creating 204645172-testrail-migration_1 ... done
Creating 204645172-testrail-fpm_1 ... done
Creating 204645172-testrail-web_1 ... done
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c6b76f9135ed registry.gitlab.com/touchbit/image/testrail/web:latest "nginx -g 'daemon of…" 13 seconds ago Up 1 second 0.0.0.0:51148->80/tcp, 0.0.0.0:25426->443/tcp 204645172-testrail-web_1
01d303262d8e registry.gitlab.com/touchbit/image/testrail/fpm:latest "docker-php-entrypoi…" 16 seconds ago Up 13 seconds 9000/tcp 204645172-testrail-fpm_1
2cdab1edbf6a registry.gitlab.com/touchbit/image/testrail/migration:latest "docker-entrypoint.s…" 16 seconds ago Up 13 seconds 3306/tcp, 33060/tcp 204645172-testrail-migration_1
826aaf7c0a29 mysql:5.7.22 "docker-entrypoint.s…" 18 seconds ago Up 16 seconds 3306/tcp 204645172-testrail-mysql_1
6dbb3fae0322 registry.gitlab.com/touchbit/image/testrail/web:latest "nginx -g 'daemon of…" 36 seconds ago Up 22 seconds 0.0.0.0:44202->80/tcp, 0.0.0.0:20151->443/tcp 204645084-testrail-web_1
3540f8d448ce registry.gitlab.com/touchbit/image/testrail/fpm:latest "docker-php-entrypoi…" 38 seconds ago Up 35 seconds 9000/tcp 204645084-testrail-fpm_1
70fea72aa10d mysql:5.7.22 "docker-entrypoint.s…" 40 seconds ago Up 37 seconds 3306/tcp 204645084-testrail-mysql_1
d8aa24b2892d registry.gitlab.com/touchbit/image/testrail/web:latest "nginx -g 'daemon of…" About a minute ago Up 53 seconds 0.0.0.0:31103->80/tcp, 0.0.0.0:43872->443/tcp 204644881-testrail-web_1
6d4ccd910fad registry.gitlab.com/touchbit/image/testrail/fpm:latest "docker-php-entrypoi…" About a minute ago Up About a minute 9000/tcp 204644881-testrail-fpm_1
685d8023a3ec mysql:5.7.22 "docker-entrypoint.s…" About a minute ago Up About a minute 3306/tcp 204644881-testrail-mysql_1
1cdfc692003a registry.gitlab.com/touchbit/image/testrail/web:latest "nginx -g 'daemon of…" About a minute ago Up About a minute 0.0.0.0:44752->80/tcp, 0.0.0.0:23540->443/tcp 204644793-testrail-web_1
6f26dfb2683e registry.gitlab.com/touchbit/image/testrail/fpm:latest "docker-php-entrypoi…" About a minute ago Up About a minute 9000/tcp 204644793-testrail-fpm_1
029e16b26201 mysql:5.7.22 "docker-entrypoint.s…" About a minute ago Up About a minute 3306/tcp 204644793-testrail-mysql_1
c10443222ac6 registry.gitlab.com/touchbit/image/testrail/web:latest "nginx -g 'daemon of…" 5 hours ago Up 5 hours 0.0.0.0:57123->80/tcp, 0.0.0.0:31657->443/tcp 204567103-testrail-web_1
04339229397e registry.gitlab.com/touchbit/image/testrail/fpm:latest "docker-php-entrypoi…" 5 hours ago Up 5 hours 9000/tcp 204567103-testrail-fpm_1
6ae0accab28d mysql:5.7.22 "docker-entrypoint.s…" 5 hours ago Up 5 hours 3306/tcp 204567103-testrail-mysql_1
b66b60d79e43 registry.gitlab.com/touchbit/image/testrail/web:latest "nginx -g 'daemon of…" 5 hours ago Up 5 hours 0.0.0.0:56321->80/tcp, 0.0.0.0:58749->443/tcp 204553690-testrail-web_1
033b1f46afa9 registry.gitlab.com/touchbit/image/testrail/fpm:latest "docker-php-entrypoi…" 5 hours ago Up 5 hours 9000/tcp 204553690-testrail-fpm_1
a8879c5ef941 mysql:5.7.22 "docker-entrypoint.s…" 5 hours ago Up 5 hours 3306/tcp 204553690-testrail-mysql_1
069954ba6010 registry.gitlab.com/touchbit/image/testrail/web:latest "nginx -g 'daemon of…" 5 hours ago Up 5 hours 0.0.0.0:32869->80/tcp, 0.0.0.0:16066->443/tcp 204553539-testrail-web_1
ed6b17d911a5 registry.gitlab.com/touchbit/image/testrail/fpm:latest "docker-php-entrypoi…" 5 hours ago Up 5 hours 9000/tcp 204553539-testrail-fpm_1
1a1eed057ea0 mysql:5.7.22 "docker-entrypoint.s…" 5 hours ago Up 5 hours 3306/tcp 204553539-testrail-mysql_1
Вроде все по красоте, но есть нюанс. Pipeline может быть принудительно отменен во время выполнения интеграционных тестов, и в этом случае запущенные контейнеры не будут остановлены. Время от времени нужно чистить раннер. К сожалению, задача на доработку в GitLab CE все еще в статусе Open
Но у нас добавлен запуск задачи по расписанию, и никто нам не запрещает ее запустить вручную.
Переходим в наш проект -> CI/CD -> Schedules и запускаем задачу Clean runner
Итого:
- У нас один shell runner.
- Конфликтов между задачами и окружением нет.
- У нас параллельный запуск задач с интеграционными тестами.
- Можно запускать интеграционные тесты как локально, так и в контейнере.
- Логи сервисов и тестов собираются и прикрепляются к pipeline-задаче.
- Есть возможность очистки раннера от старых docker-образов.
Время настройки — ~2 часа.
Вот, собственно, и все. Буду рад фидбэку.
P.S.
Особая благодарность freeseacher vvasilenok ivanych. Ваши коментарии оказались очень ценными в контектсе публикации.
Комментарии (13)
gecube
02.05.2019 11:17+1Почему не docker-runner и dind? Это решает проблему чистки раннера, а логи в виде артефактов так же можно сохранять и видеть в панели гитлаба.
Почему docker-compose v3? Вы же наверняка swarm не используете — так и используйте тогда v2.4
leorush
03.05.2019 11:24Действительно, почему не docker-runner и services?
gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/ci/docker/using_docker_images.md#what-is-a-service
Делаем свои образы с центральным логированием на основном, логи в артефактах забираем.
И concurrent на одной машине без изоляции — плохо. Лично сталкивался с этим багом gitlab.com/gitlab-org/gitlab-ee/issues/2588
Лучше сделать несколько раннеров, способных работать с одним инстансом системы.
freeseacher
05.05.2019 22:21+1Спасибо! Весьма полезно. А какую задачу вырешали выводя CI_JOB_ID в имя контейнера?
И знали ли при-p
ключ уdocker-compose
? Что бы можно было делать например так
script: - docker-compose -f .docker/docker-compose.yml -p ${CI_COMMIT_REF_SLUG}-tests build tests - docker-compose -f .docker/docker-compose.yml -p ${CI_COMMIT_REF_SLUG}-tests up --exit-code-from tests tests after_script: - docker-compose -f .docker/docker-compose.yml -p ${CI_COMMIT_REF_SLUG}-tests down -v
vvasilenok
05.05.2019 22:40+1А почему не использовать COMPOSE_PROJECT_NAME=CI_JOB_ID, в этом случае у всех контейнеров и сетей будет уникальное имя?
ivanych
06.05.2019 00:09+1Там выше уже пару комментариев про изоляцию написали, но всё-таки вставлю свои более подробные пять копеек.
В первую очередь мы делаем уникальные названия сервисов для CI. Одной из уникальных переменных в GitLab CI является переменная CI_JOB_ID. Если указать container_name со значением «service-${CI_JOB_ID:-local}»...
Менять название контейнера, добавляя в него номер задания, не нужно. Изоляция одного инстанса от другого делается с помощью опции -p:
docker-compose -p $CI_JOB_ID
С этой опцией все сервисы, указанные в docker-compose.yml, будут запущены в изолированном окружении — инстансе. Каждому контейнеру инстанса будет автоматически добавлен префикс $CI_JOB_ID_ и все контейнеры инстанса будут запущены в автоматически созданной для них сети с таким же префиксом.
Во вторую очередь мы делаем общую сеть для запускаемых сервисов. Это дает нам изоляцию на уровне сети при запуске нескольких тестовых окружений.
Создавать сеть вручную тоже не нужно. Как написал выше — опция -p создаст для инстанса нужную сеть автоматически.
# Останавливаем контейнеры и удаляем сеть
docker-kill:
docker-compose -f $${CI_JOB_ID:-.indirect}/docker-compose.yml kill
Так останавливать инстанс не нужно. Вместо kill используйте down — эта команда удалит после себя мусор (контейнеры, сети и прочее) и дальнейшая очистка раннера будет не в пример проще.
Мне сейчас не хочется поштучно пересматривать Ваши команды очистки, но с большой вероятностью все они (или большая часть) окажутся не нужны.
OlegusTesterovichus Автор
06.05.2019 03:09freeseacher vvasilenok ivanych плюсик вам в карму, добрые люди. Поправил и статью и свой gitlab-ci.
Sovigod
Я возможно не верно понял Makefile, но у вас в остановке контейнеров и их чистке нет фильтрации по CI_JOB_ID. т.е убиваются контейнеры из параллельных пайпов, которые возможно еще работают?
OlegusTesterovichus Автор
Все верно.
Задача по расписанию на очистку раннера настроена на 5 утра. В 5 утра крайне низкая вероятность, что кто-то будет что-то пушить.
Но, если возникла необходимость почистить стенд прямо сейчас, то да. Все запущенные контейнеры будут остановлены и выполняемые задачи с интеграционными тестами упадут. Но предполагается, что запускающий понимает последствия.
Еще момент. Для очистки стенда, фильтрация по CI_JOB_ID и не предполагается. Мы же раннер чистим в принципе, а не от «ошметков» какой-либо конкретной задачи.
Sovigod
Ясно. Пропустил момент что вы чистите по расписанию, а не после сборки. А у вас места хватает тогда? У нас за рабочий день может быть до 100 сборок (тестируем каждый новый пуш коммитов во всех ветках). Если волумы не удалять сразу — за день гигов 100 мусора. И это с ограничением в 4 раннера.
OlegusTesterovichus Автор
Коммитов могло быть много, а пушей в репу вот не сильно много было. Чтоб 100 гигов за день, такого не помню.
В моей практике мы делали максимально удобно для локального запуска окружения/тестов. Разработчики прежде чем пушить гоняли тесты у себя локально. Но тут повторюсь все должно быть максимально удобно. И собрать и тесты прогнать (быстро), и в случае ошибок максимально информативные логи посмотреть. Как оказалось, разработчику проще локально все прогнать и чуть-что логи грепнуть, чем по ссылкам GitLab маневрировать.
411
А почему бы не фильтровать по дате запуска? Ну к примеру чистить только то, что живо более часа?
А с отменой мы вроде с помощью trap справляемся вместо after_script, но надо посмотреть точнее, возможно ошибаюсь.