
Een van de meest noodzakelijke functies die niet in de gratis versie van GitLab zit, is de mogelijkheid om tegen het resetten van de repository te stemmen en het controleren van Merge-requests (MR) met behulp van verplichte code review.
Laten we de minimale functionaliteit zelf maken — we verbieden Merge totdat meerdere ontwikkelaars een 'duim omhoog' geven op de MR.
Waarom eigenlijk?
Onze organisatie kan het zich goed veroorloven om een licentie voor GitLab aan te schaffen. Maar omdat de ontwikkeling plaatsvindt in een afgesloten omgeving zonder toegang tot internet, en er een strikte begroting is, kan het weken duren voordat de aanschaf van self-managed licenties met de benodigde functionaliteit rond is, terwijl we nu al moeten werken.
Uiteindelijk moet men:
- of helemaal Merge in beschermde takken voor sommige ontwikkelaars verbieden, maar dan krijgen ontwikkelaars die recht hebben op Merge als bonus conflicten bij het samenvoegen van andermans MR;
- of de mogelijkheid bieden om ongecontroleerde samenvoegingen met uw master-tak te doen zonder code review, zelfs als dit een Junior betreft die net gisteren is begonnen.
De eerste stap was googelen, in de veronderstelling dat iemand ongetwijfeld zoiets al had gedaan (zonder code-aanpassingen), maar het bleek dat een dergelijke implementatie nog niet bestond in de community-versie.
Algemene werkstructuur
Als voorbeeld configureren we Merge request goedkeuringen in een testrepository :
- Laten we een token genereren voor toegang tot de GitLab API (hiermee verkrijgen we informatie over het aantal stemmen 'voor' en 'tegen')
- Voeg het token toe aan de GitLab-variabelen
- Verbied Merge bij fouten in de pipeline (als het aantal stemmen 'voor' onvoldoende is)
- Stel de stemcontrole in als onderdeel van de CI/CD pipeline
- Verbied commits in beschermde takken, alle wijzigingen worden alleen via MR uitgevoerd
- Laten we controleren wat we uiteindelijk hebben bereikt
1. We creëren een token voor toegang tot de API
Ga naar Gebruikersinstellingen → Toegangstokens en noteer het token:

Account voor het verkrijgen van het token
Toegang tot de API maakt het mogelijk om bijna alles met uw repositories te doen, daarom raad ik aan om een apart GitLab-account te maken, het minimale rechten op uw repositories te geven (bijvoorbeeld Reporter) en het token voor dat account te verkrijgen.
2. Voeg het token toe aan de GitLab-variabelen
Bijvoorbeeld, in de vorige stap hebben we het token gekregen QmN2Y0NOUFlfeXhvd21ZS01aQzgK
Open Instellingen → CI/CD → Variabelen → Voeg variabele toe → GITLAB_TOKEN_FOR_CI

Uiteindelijk krijgen we:

Dit kan zowel op één repository als op een groep repositories worden gedaan.
3. We zetten de merge-blokkade in als er geen goedkeuringen van collega's zijn na de code-review.
In ons geval betekent een blokkade op de merge dat de buildpipeline een fout retourneert bij onvoldoende stemmen.
Ga naar Instellingen → Algemeen → Merge-verzoeken → Merge-controles en schakel de optie in dat de buildlijnen met succes moeten worden uitgevoerd.

4. Configureren van de pipeline
Als je nog geen CI/CD-pipeline voor je applicatie hebt gemaakt,
maak je een bestand aan in de hoofdmap van de repository .gitlab-ci.yml met de eenvoudigste inhoud:
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 "Hallo wereld"
Een aparte repository voor CI/CD-configuratie
Ik zou aanbevelen een aparte repository te maken waarin je het bestand myapp.gitlab-ci.yml voor het configureren van de pipeline aanmaakt. Zo kun je beter de toegang van deelnemers controleren die de buildpipeline kunnen wijzigen en toegangstokens kunnen verkrijgen.
De locatie van het nieuwe pipeline-bestand moet worden aangegeven door naar de repository myapp — Instellingen — CI/CD — Buildlijnen — Aangepast pad voor CI-configuratie — het nieuwe bestand op te geven, bijvoorbeeld myapp.gitlab-ci.yml@gitlab-ce-mr-approvals/Ci
Tip: gebruik een linter voor het aanbrengen van wijzigingen in GitLab CI-bestanden
Zelfs als je alleen werkt, is het een goede hulp om via MR te werken, waardoor al je wijzigingen in de pipeline-bestanden door de linter worden gehaald. Als je een syntaxisfout maakt in het YAML-bestand, voorkomt dit dat je de werkende pipeline breekt en blokkeert gewoon de merge.
Voorbeeld van containers met liners die je kunt integreren in je pipeline:
En een voorbeeld van een controlefase:
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;
Het is nog nodig om enkele parameters aan je pipeline toe te voegen, zodat alles werkt:
fasen:
- test
variables:
NEED_VOTES: 1
include:
- remote: "https://gitlab.com/gitlab-ce-mr-approvals/ci/-/raw/master/check-approve.gitlab-ci.yml"
De variabele NEED_VOTES bepaalt hoeveel "duimen omhoog" er nodig zijn voor de MR om te kunnen worden samengevoegd. Een waarde van één betekent dat je je eigen MR kunt goedkeuren door deze "te liken".
include voegt de testfase toe die het aantal "likes" controleert.
Eenvoudige pipeline aan de hand van myapp.gitlab-ci.yml
fasen:
- bouwen
- 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
Inhoud check-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\/{$client_name}\/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\/{$client_name}\/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\/{$client_name}\/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\/{$client_name}\/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\/{$client_name}\/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\/.*$ /'
Meer informatie over wat er gebeurt tijdens de controle:
- er is een beperking ingesteld dat de controle alleen zal plaatsvinden bij het aanmaken van een MR in de takken master of release/*
- door gebruik te maken van de GitLab API, halen we het aantal 'likes' en 'dislikes' op
- we berekenen het verschil tussen positieve en negatieve reacties
- als het verschil kleiner is dan de door ons ingestelde waarde in NEED_VOTES, blokkeren we de mogelijkheid om samen te voegen
5. Verbied commits naar beschermde takken
We bepalen de takken waarvoor we code review moeten uitvoeren en geven aan dat we er alleen via MR mee kunnen werken.
Daarvoor gaan we naar Instellingen → Repository → Beschermde Takken:

6. We controleren
We stellen NEED_VOTES in op: 0
We maken een MR en geven een 'dislike'.

In de bouwlogs:

Nu geven we een 'like' en starten we de hercontrole:

Bron: habr.com
