Jedną z najbardziej potrzebnych funkcji, której nie ma w darmowej wersji GitLaba, jest możliwość głosowania przeciwko unieważnieniu repozytorium oraz kontrola żądania łączenia (MR), za pomocą obowiązkowego przeglądu kodu.
Sami zajmijmy się minimalną funkcjonalnością - zabronimy scalania, dopóki kilku programistów nie pochwali MR.
Dlaczego tak jest w ogóle?
Naszą organizację z łatwością stać na zakup licencji GitLab. Ponieważ jednak rozwój odbywa się w zamkniętej pętli bez dostępu do Internetu i istnieje ścisłe planowanie budżetu, zakup licencji samozarządzających z niezbędną funkcjonalnością może ciągnąć się przez wiele miesięcy, ale prace należy wykonać już teraz.
W rezultacie musisz:
- lub całkowicie zabraniaj łączenia w chronionych gałęziach niektórym programistom, ale wtedy programiści, którzy mają prawo do łączenia, będą otrzymywać konflikty podczas łączenia MR innych osób jako bonus;
- lub daj możliwość niekontrolowanego połączenia z gałęzią główną bez przeglądu kodu, nawet jeśli jest to Junior, który został zatrudniony zaledwie wczoraj.
Pierwsze co zrobiłem to Google wierząc, że ktoś na pewno już coś podobnego zrobił (bez modyfikacji kodu), ale okazało się, że w wersji społecznościowej nie ma jeszcze takiej implementacji.
Ogólny schemat pracy
Jako przykład skonfigurujmy zatwierdzanie żądań scalania w repozytorium testowym
- Stwórzmy token dostępu do API GitLab (za jego pośrednictwem otrzymamy informację o liczbie głosów „za” i „przeciw”)
- Dodajmy token do zmiennych GitLab
- Wyłączmy scalanie w przypadku błędów w potoku (jeśli nie ma wystarczającej liczby głosów pozytywnych)
- Skonfigurujmy weryfikację głosów w ramach potoku CI/CD
- Zabraniamy dokonywania zmian w chronionych gałęziach; wszelkie zmiany wprowadzane są wyłącznie za pośrednictwem MR
- Sprawdźmy co się ostatecznie stało
1. Utwórz token, aby uzyskać dostęp do API
Przejdź do Ustawienia użytkownika → Tokeny dostępu i zapisz token:
Konto, aby otrzymać token
Dostęp API pozwala na zrobienie niemal wszystkiego ze swoimi repozytoriami, dlatego polecam założyć osobne konto Gitlab, nadać mu minimalne uprawnienia do swoich repozytoriów (np. Reporter) i zdobyć token do tego konta.
2. Dodaj token do zmiennych Gitlab
Przykładowo w poprzednim kroku otrzymaliśmy token QmN2Y0NOUFlfeXhvd21ZS01aQzgK
Otwórz Ustawienia → CI/CD → Zmienne → Dodaj zmienną → GITLAB_TOKEN_FOR_CI
W rezultacie otrzymujemy:
Można to zrobić albo w jednym repozytorium, albo w grupie repozytoriów.
3. Zakazujemy scalania, jeśli po sprawdzeniu kodu nie otrzymamy zgody współpracowników.
W naszym przypadku zakaz scalania będzie polegał na tym, że potok montażowy zwróci błąd, jeśli nie będzie wystarczającej liczby głosów.
Przejdź do Ustawienia → Ogólne → Żądania połączenia → Kontrole scalania i włącz opcję Linie montażowe muszą zakończyć się pomyślnie.
4. Ustawianie rurociągu
Jeśli nie utworzono jeszcze potoku CI/CD dla swojej aplikacji
Utwórz plik w katalogu głównym repozytorium .gitlab-ci.yml z najprostszą treścią:
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"
Oddzielne repozytorium do konfiguracji CI/CD
Polecam utworzenie osobnego repozytorium, w którym należy utworzyć plik myapp.gitlab-ci.yml w celu skonfigurowania potoku. W ten sposób możesz lepiej kontrolować dostęp uczestników, którzy mogą zmienić potok kompilacji i otrzymać token dostępu.
Należy określić lokalizację nowego pliku potoku, przechodząc do repozytorium myapp - Ustawienia - CI/CD - Linie montażowe - Niestandardowa ścieżka konfiguracji CI - określ nowy plik, np. myapp.gitlab-ci.yml@gitlab-ce-mr-approvals/Ci
Wskazówka: użyj lintera, aby wprowadzić zmiany w plikach GitLab CI
Nawet jeśli pracujesz sam, praca za pomocą MR będzie dobrą pomocą, uruchamiając wszystkie zmiany w plikach potokowych za pośrednictwem lintera. Jeśli popełnisz błąd w składni pliku YAML, nie spowoduje to przerwania procesu produkcyjnego, ale po prostu zablokuje scalanie.
Przykład kontenerów z lintersami, które możesz wbudować w swój rurociąg:
I przykładowy etap weryfikacji:
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;
Pozostaje dodać kilka parametrów do potoku, aby działał:
stages:
- test
variables:
NEED_VOTES: 1
include:
- remote: "https://gitlab.com/gitlab-ce-mr-approvals/ci/-/raw/master/check-approve.gitlab-ci.yml"
Zmienna NEED_VOTES określa, ile „kciuków w górę” musi mieć MR, aby połączenie było dostępne. Wartość równa jeden oznacza, że sam możesz zatwierdzić swoje MR poprzez „polubienie” go.
include obejmuje etap testowy, podczas którego sprawdzana jest ilość „lajków”.
Najprostszy potok na przykładzie myapp.gitlab-ci.yml
stages:
- build
- test
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
script:
- echo CI_MERGE_REQUEST_TARGET_BRANCH_NAME $CI_MERGE_REQUEST_TARGET_BRANCH_NAME
- java HelloWorld.java
Zawartość sprawdź-approve.gitlab-ci.yml
ci-mr:
stage: test
script:
- 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})" ];
then
echo "MR OK";
else
echo "MR ERROR Need more votes";
exit 1;
fi
image: laptevss/gitlab-api-util
rules:
- if: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "master" || $CI_MERGE_REQUEST_TARGET_BRANCH_NAME =~ /^release/.*$/'
Więcej informacji o tym, co dzieje się podczas weryfikacji:
- istnieje ograniczenie, że sprawdzenie zostanie przeprowadzone tylko podczas tworzenia MR w gałęzi głównej lub release/*
- korzystając z GitLab API otrzymujemy liczbę „polubień” i „nielubień”
- oblicz różnicę między odpowiedziami pozytywnymi i negatywnymi
- jeśli różnica jest mniejsza niż wartość, którą ustawiliśmy w NEED_VOTES, wówczas blokujemy możliwość łączenia
5. Zabroń zatwierdzenia chronionych gałęzi
Definiujemy gałęzie, dla których musimy przeprowadzić przeglądy kodu i wskazujemy, że można z nimi pracować wyłącznie za pośrednictwem MR.
Aby to zrobić, przejdź do Ustawienia → Repozytorium → Chronione gałęzie:
6. Sprawdź
Ustaw NEED_VOTES: 0
Robimy MR i wpisujemy „nie lubię”.
W dziennikach kompilacji:
Teraz wstaw „lubię to” i zacznij sprawdzać ponownie:
Źródło: www.habr.com