Code review в Gitlab CE: ако нямате одобрение за Merge request, но имате голямо желание.

Code review в Gitlab CE: ако нямате одобрение за Merge request, но имате голямо желание.

Една от най-необходимите функции, която липсва в безплатната версия на GitLab, е възможността за гласуване срещу нулиране на репозитория, контролирайки Merge request (MR) чрез задължителен code review.

Нека създадем минималния функционал сами - ще забраним Merge, докато няколко разработчици не поставят «палец нагоре» на MR.

Защо изобщо?

Нашата организация напълно може да си позволи да закупи лиценз за GitLab. Но, тъй като разработката се извършва в затворен контур без достъп до интернет и имаме строги бюджетни планове, закупуването на лицензи self-managed с нужната функционалност може да отнеме много месеци, а работата трябва да започне веднага.

В крайна сметка ни се налага:

  • или напълно да забраним Merge в защитените клонове за част от разработчиците, но тогава разработчиците, които имат право на Merge, получават конфликти при сливане на чужди MR като бонус;
  • или да предоставим възможност за неконтролирани слиwania с вашата основна клон без code review, дори ако това е Junior, който току-що е започнал.

Първото нещо, което направих, беше да гугля, вярвайки, че със сигурност някой вече е направил нещо подобно (без модификация на кода), но се оказа, че такава реализация в community версията все още не е имало.

Обща схема на работа

Като пример ще настроим одобрения за Merge request на тестово хранилище myapp:

  1. Създаваме токен за достъп до API на GitLab (чрез него ще получаваме информация за броя на гласовете «за» и «против»)
  2. Добавяме токена в променливите на GitLab
  3. Забраняваме Merge при грешки в пайплайна (ако гласовете «за» са недостатъчни)
  4. Настройваме проверка на гласовете като част от пайплайна CI/CD
  5. Забраняваме извършването на комити в защитените клонове, всички промени се извършват само чрез MR
  6. Ще проверим какво сме постигнали в крайна сметка

1. Създаваме токен за достъп до API

Влизаме в Настройки на потребителя → Токени за достъп и записваме токена:

Code review в Gitlab CE: ако нямате одобрение за Merge request, но имате голямо желание.

Профил за получаване на токен
Достъпът до API позволява да правите практически всичко с вашите репозитории, затова препоръчвам да създадете отделен профил за GitLab, да му предоставите минимални права върху вашите репозитории (например, Reporter) и да получите токен за този профил.

2. Добавяме токена в променливите на GitLab

Например, на предишната стъпка получихме токена QmN2Y0NOUFlfeXhvd21ZS01aQzgK

Отваряме Настройки → CI/CD → Променливи → Добавяне на променлива → GITLAB_TOKEN_FOR_CI

Code review в Gitlab CE: ако нямате одобрение за Merge request, но имате голямо желание.

В крайна сметка ще получим:

Code review в Gitlab CE: ако нямате одобрение за Merge request, но имате голямо желание.

Можете да направите това както на едно хранилище, така и на група хранилища.

3. Налагаме забрана за Merge, ако не получим одобрение от колеги след проведен код преглед.

В нашия случай забраната за Merge ще бъде, че сборният конвейер ще върне грешка при недостатъчен брой гласове.

Влизаме в Настройки → Основни → Запитвания за сливане → Проверки при сливане и активираме опцията Сборните линии трябва да завършват успешно.

Code review в Gitlab CE: ако нямате одобрение за Merge request, но имате голямо желание.

4. Настройваме пайплайна

Ако все още не сте направили CI/CD конвейер за вашето приложение
Създайте в корена на хранилището файл .gitlab-ci.yml с най-простото съдържание:

stages:
  - build
  - test

variables:
  NEED_VOTES: 1

include:
  - remote: "https://gitlab.com/gitlab-ce-mr-approvals/ci/-/raw/master/check-approve.gitlab-ci.yml"

run-myapp:
  stage: build
  script: echo "Hello world"

Отделно хранилище за конфигурация на CI/CD
Препоръчвам да направите отделно хранилище, в което трябва да създадете файл myapp.gitlab-ci.yml за настройка на конвейера. По този начин ще можете по-добре да контролирате достъпа на участниците, които могат да променят сборния конвейер и да получат токен за достъп.

Местоположението на новия файлов конвейер трябва да бъде указано, като влезете в хранилището myapp — Настройки — CI/CD — Сборни линии — Потребителски маршрут за конфигурация на CI — указвате новия файл, например myapp.gitlab-ci.yml@gitlab-ce-mr-approvals/Ci

Съвет: използвайте линтер за въвеждане на промени в файловете на GitLab CI
Дори ако работите сами, добър помощник е работата чрез MR, проверявайки всички ваши промени в файловете на пайплайна през линтер. Ако допуснете грешка в синтаксиса на YAML файла, това няма да ви позволи да счупите работния конвейер, а просто ще блокира Merge.

Пример за контейнери с линтери, които можете да вградите в вашия пайплайн:

hub.docker.com/r/gableroux/gitlab-ci-lint
hub.docker.com/r/sebiwi/gitlab-ci-validate

И пример за етапа на проверка:

stages:
  - lint

lint:
  stage: lint
  image: sebiwi/gitlab-ci-validate:1.3.0
  variables:
    GITLAB_HOST: https://gitlab.com
  script:
    - CI_FILES=(./*.yml)
    - for f in "${CI_FILES[@]}"; do
        gitlab-ci-validate $f;
      done;

Остава да добавите няколко параметъра в вашия пайплайн, за да заработи всичко:

етапи:
- тест

variables:
NEED_VOTES: 1

include:
- remote: "https://gitlab.com/gitlab-ce-mr-approvals/ci/-/raw/master/check-approve.gitlab-ci.yml"

Променливата NEED_VOTES определя колко "палци нагоре" трябва да има MR, за да бъде разрешен Merge. Стойността, равна на един, означава, че самият вие можете да одобрите своя MR, като му дадете "лайк".

include вклучва етапа test, който проверява броя "лайкове".

Най-простият пайплайн на примера myapp.gitlab-ci.yml
етапи:
- изграждане
- тест

variables:
NEED_VOTES: 0

include:
- remote: "https://gitlab.com/gitlab-ce-mr-approvals/ci/-/raw/master/check-approve.gitlab-ci.yml"

run-myapp:
stage: build
image: openjdk
скрипт:
- echo CI_MERGE_REQUEST_TARGET_BRANCH_NAME $CI_MERGE_REQUEST_TARGET_BRANCH_NAME
- java HelloWorld.java

Съдържание check-approve.gitlab-ci.yml
ci-mr:
етап: тест
скрипт:
- echo ${CI_API_V4_URL}
- echo "CI_PROJECT_ID ${CI_PROJECT_ID}"
- echo "CI_COMMIT_SHA ${CI_COMMIT_SHA}"
- "export MR_ID=$(curl --silent --request GET --header "PRIVATE-TOKEN: $GITLAB_TOKEN_FOR_CI" ${CI_API_V4_URL}\/projects\/${CI_PROJECT_ID}\/merge_requests | jq ".[] | if .sha == \"${CI_COMMIT_SHA}\" then .id else {} end" | grep --invert-match {})"
- "export MR_TITLE=$(curl --silent --request GET --header "PRIVATE-TOKEN: $GITLAB_TOKEN_FOR_CI" ${CI_API_V4_URL}\/projects\/${CI_PROJECT_ID}\/merge_requests | jq ".[] | if .sha == \"${CI_COMMIT_SHA}\" then .title else {} end" | grep --invert-match {})"
- "export MR_WIP=$(curl --silent --request GET --header "PRIVATE-TOKEN: $GITLAB_TOKEN_FOR_CI" ${CI_API_V4_URL}\/projects\/${CI_PROJECT_ID}\/merge_requests | jq ".[] | if .sha == \"${CI_COMMIT_SHA}\" then .work_in_progress else {} end" | grep --invert-match {})"
- "export MR_UPVOTES=$(curl --silent --request GET --header "PRIVATE-TOKEN: $GITLAB_TOKEN_FOR_CI" ${CI_API_V4_URL}\/projects\/${CI_PROJECT_ID}\/merge_requests | jq ".[] | if .sha == \"${CI_COMMIT_SHA}\" then .upvotes else {} end" | grep --invert-match {})"
- "export MR_DOWNVOTES=$(curl --silent --request GET --header "PRIVATE-TOKEN: $GITLAB_TOKEN_FOR_CI" ${CI_API_V4_URL}\/projects\/${CI_PROJECT_ID}\/merge_requests | jq ".[] | if .sha == \"${CI_COMMIT_SHA}\" then .downvotes else {} end" | grep --invert-match {})"
- MR_VOTES=$(expr ${MR_UPVOTES} - ${MR_DOWNVOTES})
- NEED_VOTES_REAL=${NEED_VOTES:-1}
- echo "MR_ID ${MR_ID} MR_TITLE ${MR_TITLE} MR_WIP ${MR_WIP} MR_UPVOTES ${MR_UPVOTES} MR_DOWNVOTES ${MR_DOWNVOTES}"
- echo "MR_VOTES ${MR_VOTES} Up vote = 1, down vote = -1, MR OK if votes >=${NEED_VOTES_REAL}"
- if [ "${MR_VOTES}" -ge "$(expr ${NEED_VOTES_REAL})" ];
тогава
echo "MR OK";
иначе
echo "MR ERROR Need more votes";
exit 1;
fi
image: laptevss\/gitlab-api-util
правила:
- if: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "master" || $CI_MERGE_REQUEST_TARGET_BRANCH_NAME =~ \/^release\/.*$\/'

Повече информация за това, което се случва при проверка:

  • наложено е ограничение, че проверката ще стане само при създаване на MR в клонове master или release/*
  • използвайки GitLab API, получаваме броя на «лайковете» и «дизлайковете»
  • изчисляваме разликата между положителните и отрицателните отзиви
  • ако разликата е по-малка от зададената от нас стойност в NEED_VOTES, блокираме възможността за извършване на сливане

5. Забраняваме комитите в защитени клони

Определяме клоновете, за които трябва да проведем code review и посочваме, че работата с тях е възможна само чрез MR.

За целта отиваме в Настройки → Репозиторий → Защитени клони:

Code review в Gitlab CE: ако нямате одобрение за Merge request, но имате голямо желание.

6. Проверяваме

Задаваме NEED_VOTES: 0

Правим MR и поставяме «дизлайк».

Code review в Gitlab CE: ако нямате одобрение за Merge request, но имате голямо желание.

В логовете на сборката:

Code review в Gitlab CE: ако нямате одобрение за Merge request, но имате голямо желание.

Сега поставяме «лайк» и стартираме повторна проверка:

Code review в Gitlab CE: ако нямате одобрение за Merge request, но имате голямо желание.

Източник: habr.com

Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри 🔥 Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри | ProHoster