Каталог решений - Как Gitlab-CI и OneScript могут отсортировать массив (Часть 2)

Как Gitlab-CI и OneScript могут отсортировать массив (Часть 2)

Как Gitlab-CI и OneScript могут отсортировать массив (Часть 2)

В наличии

Продолжение сквозного примера настройки Gitlab-CI — вывод результатов теста, условия запуска и таймауты.

Категория:

Описание

Часть 1

Часть 2 (вы здесь)

 

В прошлой части мы написали сборку нашего приложения, но приложение без тестов — плохое приложение. Давайте же их напишем! Но сначала я вам скажу, что закидывать все изменения в main – плохая идея. Обычно есть промежуточная ветка release, а иногда и develop, от которых создают уже ветки для решения конкретных задач: feature/001, feature/002. Давайте же создадим ветку с тестами. Сделать это можно в VS Code. Нажимаем внизу на имя ветки "main", в открывшемся наверху списке выбираем "+ Create new branch…" и вводим ее имя "feature/001_add-tests", а затем жмем Enter.

 

 

После этого внизу имя текущей ветки должно измениться с "main" на "feature/001_add-tests". Теперь создадим в корне репозитория папку tests, а в ней файл Сортировка.os следующего содержания:

  #Использовать asserts
  #Использовать "../src"
  
  Функция ПолучитьСписокТестов(ЮнитТестирование) Экспорт
      
      ВсеТесты = Новый Массив;
  
      ВсеТесты.Добавить("Тест_СортировкаМассива5");
      // ВсеТесты.Добавить("Тест_СортировкаМассива50");
      
      Возврат ВсеТесты;
  КонецФункции
  
  Процедура Тест_СортировкаМассива5() Экспорт
      ТестируемыйМассив = ПолучитьМассивДляТеста(5);
      РезультатСортировки = Сортировка.Отсортировать(ТестируемыйМассив);
      Ожидаем.Что(РезультатСортировки[2]).МеньшеИлиРавно(РезультатСортировки[4]);
  КонецПроцедуры
  
  Процедура Тест_СортировкаМассива50() Экспорт
      ТестируемыйМассив = ПолучитьМассивДляТеста(50);
      РезультатСортировки = Сортировка.Отсортировать(ТестируемыйМассив);
      Ожидаем.Что(РезультатСортировки[20]).МеньшеИлиРавно(РезультатСортировки[40]);
  КонецПроцедуры
  
  Функция ПолучитьМассивДляТеста(Размер)
      Результат = Новый Массив;
      ГСЧ = Новый ГенераторСлучайныхЧисел(42);
      Пока Результат.Количество() < Размер Цикл
          Результат.Добавить(ГСЧ.СлучайноеЧисло(0, 100));
      КонецЦикла;
      Возврат Результат;
  КонецФункции

Да, это то, о чем вы подумали — Unit-тесты для OneScript. Мы добавили два теста, но подключили пока только первый с массивом на 5 элементов. Осталось только подключить его к скрипту, который запускает CI. Для этого изменим текст файла ./ci/scripts/test.os на:

  СоздатьКаталог("./report");
  ЗапуститьПриложение("1testrunner -runall ./tests xddReportPath ./report", , Истина);
  
  Сообщить("Я протестировался!");

Здесь мы создаем папку для отчета о тестировании, а затем запускаем все тесты в папке ./tests. И чтобы результаты попали в Gitlab, надо изменить Job test в .gitlab-ci.yml на:

  test:
    stage: test
    script: oscript ./ci/scripts/test.os
    artifacts:
      paths:
        - ./report/*.xml
      expire_in: 1 week
      reports:
        junit: ./report/*.xml

Что делает artifacts, мы уже знаем по прошлой статье — сохраняет файлы, соответствующие маске, чтобы потом можно было их использовать. Тут добавлена секция reports – она позволяет сказать gitlab-у, что у нас есть еще и отчеты в формате jUnit и мы хотим увидеть их в Pipeline. Более подробно можно посмотреть в разделе Testing на официальном сайте Gitlab: https://docs.gitlab.com/ee/ci/unit_test_reports.html . Здесь доступны описания форматов файлов с результатами, например, для Code Quality – результатов статического анализа кода, также можно передавать метрики или покрытие кода тестами. Но давайте запустим наш тест. Закоммитим изменения и не забудем сделать push.

 

 

После переходим в список Pipelines и видим, что тест запустился. Откроем же сам Pipeline (клик на колонку Pipeline ID), чтобы увидеть результаты:

 

 

И видим, что в Pipeline появилась вкладка Tests, где мы можем посмотреть результаты с детализацией по конкретным тестам:

 

 

Теперь вернемся в IDE и в файле ./tests/Сортировка.os раскомментируем строку "ВсеТесты.Добавить("Тест_СортировкаМассива50");" Зафиксируем и отправим изменения в удаленный репозиторий. После чего снова откроем список Pipelines в Gitlab. Нам надо подождать завершения тестов:

 

 

Но я сразу скажу, что завершения теста можете не ждать: он будет выполняться 1 час, после чего завершится по таймауту. Если тест у вас завершился успешно за пару секунд, вам явно стоит бежать казино и ставить все на зеро. Но откуда у нас этот таймаут? Да еще и Job build не выполнился из-за того, что в тестах были ошибки. Хорошо бы это исправить.

 

 

Начнем с таймаута. В правой панели можно увидеть Timeout: 1h (from project) – это стандартный таймаут для любой работы проекта. Указать его можно в настройках. Переходим в Settings → CI/CD → разворачиваем "General pipelines" и прокручиваем до секции Timeout – там указан стандартный 1 час:

 

 

Но это таймаут "по умолчанию" и обычно его менять не надо. Нам же надо переопределить его для конкретной работы. Откроем в VS Code .gitlab-ci.yml и допишем в работу test "timeout: 3 hours". Так же здесь добавим поле "allow_failure: true" и тогда при ошибке в Job test пайплайн будет продолжать выполняться, а Job будет отображаться в Pipeline желтым с восклицательным знаком, а не красным с крестом. В результате мы получаем Job вида:

 

 

И все же изменим тесты, чтобы сортировать не 50, а 10 значений — есть "небольшое" подозрение, что наш алгоритм сортировки может иметь некоторые недостатки в определенных условиях:

 

 

Теперь опять делаем "Stage all changes" → "Commit" → "Push". Переходим в Gitlab и открываем последний Pipeline и Job test в нем, чтобы убедиться, что таймаут теперь 3 часа:

 

 

Итак, мы готовы влить эти изменения в основную ветку. Обычно для этого необходимо сделать merge request, ведь ветку main блокируют, чтобы джун случайно не запушил туда нерабочий код. Переходим в "Merge requests" и видим, что Gitlab сам предлагает создать его на последнюю ветку. Жмем "Create merge request":

 

 

В открывшемся окне скролим вниз. Там ставим флаг "Squash commits when merge request is accepted", чтобы в основной ветке был только один коммит, а не россыпь промежуточных с неработающим кодом. После нажимаем синюю кнопку "Create merge request". В открывшимся окне нажимаем кнопку "Merge":

 

 

Если мы перейдем в список Pipelines после этого, то увидим, что у нас запустилась сборка после мержа:

 

 

Обычно нам не нужно, чтобы pipeline запускался на каждый push. Давайте создадим новую ветку, назовем ее "feature/002_rules" и опишем в ней условия запуска. Перед созданием в VS Code новой ветки не забудьте перед этим переключиться на ветку main и получить изменения. Кликните внизу на "feature/001_add-tests" и выбрав в выпавшем списке main:

 

 

После этого на вкладке "Source control" делаем Pull. А как создать новую ветку, было описано в начале данной статьи.

 

 

Далее создаем новую ветку как было описано в начале статьи. Итак, мы готовы прописать условия запуска для конкретных работ. Если посмотреть в документацию по Gitlab-CI, то можно найти два способа для задания этих условий. Первый опирается на использование секций only и except и его описание начинается с:

 

 

Последуем этому совету и посмотрим что же такое rules. В документации данный способ представляет собой массив условий каждому из которых соответствует способ выполнения. Итак в нашем случае предположим, что мы не хотим запускать тесты на ветке main, а в остальных случаях только если хеш коммита содержит d, ведь это счастливое число. Хотя в остальных было бы хорошо иметь возможность запустить его при необходимости вручную. Как это написать? Давайте перепишем работу test следующим образом:

  test:
    stage: test
    rules:
      - if: '$CI_COMMIT_BRANCH == "main"'
        when: never
      - if: '$CI_COMMIT_SHORT_SHA =~ /[d]/'
        when: on_success
      - if: '$CI_COMMIT_BRANCH != "main"'
        when: manual
    script: oscript ./ci/scripts/test.os
    timeout: 3 hours
    allow_failure: true
    artifacts:
      paths:
        - ./report/*.xml
      expire_in: 1 week
      reports:
        junit: ./report/*.xml

В появившейся секции rules мы описываем напротив if условие, а далее напротив when как должна быть запущена работа. Причем в if мы используем предопределенные переменные CI: CI_COMMIT_BRANCH – ветка на которой был запущен pipeline и CI_COMMIT_SHORT_SHA — первые 8 цифр хеша коммита. Таких переменных много, ознакомится с ними можно в документации Gitlab-CI: https://docs.gitlab.com/ee/ci/variables/predefined_variables.html. Причем доступны они не только в условиях, но и при выполнении сприптов как переменные окружения. В секции when мы можем указать следующие значения:

on_success (default): запускается, если работы предыдущего stage выполнены или для них указано allow_failure: true

manual: для запуска надо будет вручную нажать кнопку run у работы

always: всегда

on_failure: если в предыдущих stage были ошибки

delayed: с указанной задержкой (прописывается в .gitlab-ci.yml)

never: никогда

Давайте же закоммитим эти изменения и отправим в удаленный репозиторий. Чтобы посмотреть как влияет разное значение SHA добавим/удалим пробел в любом файле и отправим коммиты:

 

 

Как мы видим, если в хеше коммита нет буквы d для запуска работы надо нажать на кнопку run:

 

 

Теперь давайте сделаем merge request и вольем feature ветку в main. Как и было прописано тесты на main при этом не запустились. Но так же мы увидим, что у нас появился pipeline на merge request (как мы его не заметили раньше?!):

 

 

Merge request – тоже событие CI. Если мы посмотрим переменные CI, то можно найти CI_PIPELINE_SOURCE – источник события. С помощью этого параметра мы можем определить когда pipeline запущен:

  • push – когда отправляем что-то в удаленный репозиторий в том числе и при завершении merge request

  • api – с использованием API Gitlab (https://docs.gitlab.com/ee/api/pipelines.html)

  • merge_request_event — при создании request и при изменении вливаемой ветки

  • schedule — запущенный по расписанию

 

 

Давайте тогда создадим новую ветку (feature/003-mr) и перепишем условия работы на $CI_PIPELINE_SOURCE == "merge_request_event" || $CI_COMMIT_BRANCH == "main" — дадим возможность смотреть результаты тестов тем, кто проводит ревью и после влития в main. Так же добавим условие в build:

  build:
    stage: build
    rules:
      - if: $CI_COMMIT_BRANCH == "main"
    script: oscript ./ci/scripts/build.os
    artifacts:
      paths:
        - ./possum.exe
      expire_in: 1 week

И отправим в удаленный репозиторий. Если перейдем в список pipelines, то мы увидим, что никакой pipeline не сгенерировался — не было ни одной работы, которая подходит под условие. А теперь создадим merge request:

 

 

Как мы можем убедиться, теперь ревьювер может видеть результаты теста. Причем если мы отправим еще один коммит по открытому merge request, то pipeline запустится еще раз. Можем убедиться в этом, закоммитив какие-нибудь изменения:

 

 

Теперь вмержим merge request и убедимся, что еще раз запустились тесты, а после прошла сборка. В итоге мы теперь можем проверять тесты по каждому merge request – очень удобно.

Конец второй части. Состояние репозитория на момент окончания статьи можно посмотреть по команде:

  git clone https://gitlab.com/ffSaschaGff/possum_app.git .
  git checkout e408f587ef5db20fa41d8625e500258c20ec4eea

 

has been added to your cart:
Оформление заказа