
En av de mest nødvendige funksjonene som mangler i gratisversjonen av GitLab, er muligheten til å stemme mot nullstilling av repositoriet for å kontrollere Merge request (MR) ved hjelp av obligatorisk kodegjennomgang.
Vi lager et minimum av funksjonalitet selv – vi forbyr Merge, så lenge flere utviklere ikke gir "tommel opp" til MR.
Hvorfor er dette i det hele tatt?
Vår organisasjon kan absolutt unne seg å kjøpe en lisens for GitLab. Men siden utviklingen foregår i et lukket miljø uten tilgang til internett, og det er streng budsjettering, kan innkjøp av self-managed lisenser med nødvendig funksjonalitet ta mange måneder, mens arbeidet må gjøres nå.
Resultatet blir at vi må:
- enten helt forby Merge i beskyttede grener for en del utviklere, men da får utviklerne som har rett til Merge konflikter når de slår sammen andres MR som en bonus;
- eller gi mulighet til å utføre ukontrollerte sammenslåinger med din mastergren uten kodegjennomgang, selv om det er en juniorutvikler som begynte i går.
Det første jeg gjorde var å begynne å søke på Google, og trodde helt klart noen allerede hadde gjort noe lignende (uten kodeendringer), men det viste seg at en slik implementering i community-versjonen enda ikke hadde vært.
Den generelle arbeidsflyten
Som et eksempel vil vi konfigurere Merge request godkjenninger på et test-repositorium :
- Vi oppretter en token for tilgang til GitLab API (gjennom den vil vi hente informasjon om antall stemmer "for" og "imot")
- Vi legger til token i GitLab-variabler
- Vi forbyr Merge ved feil i pipelinen (hvis antallet "for" stemmer er utilstrekkelig)
- Vi konfigurerer stemmesjekk som en del av CI/CD-pipelinen
- Vi forbyr å gjøre commits i beskyttede grener, alle endringer gjøres kun gjennom MR
- Vi sjekker hva vi har oppnådd
1. Vi oppretter en token for API-tilgang
Vi går til Innstillinger for bruker → Tilgangstokener og noterer tokens:

Kontoen for å motta token
API-tilgang gjør det mulig å gjøre nesten alt med repositoriene dine, så jeg anbefaler å opprette en egen GitLab-konto, gi den minimale rettigheter på dine repositorier (for eksempel Reporter) og få token for denne kontoen.
2. Legger til token i GitLab-variabler
For eksempel, på det forrige trinnet fikk vi token QmN2Y0NOUFlfeXhvd21ZS01aQzgK
Vi åpner Innstillinger → CI/CD → Variabler → Legg til variabel → GITLAB_TOKEN_FOR_CI

Vi får til slutt:

Dette kan gjøres enten på et enkelt repo eller på flere repositorier.
3. Sett forbud mot Merge hvis ikke kollegers godkjenning er innhentet etter en gjennomgang av koden.
I vårt tilfelle vil et forbud mot Merge innebære at byggesystemet returnerer en feil ved utilstrekkelig antall stemmer.
Gå til Innstillinger → Generelt → Forespørsel om sammenslåing → Kontroller for sammenslåing og aktiver alternativet "Byggekøene må fullføres med hell."

4. Konfigurer pipelinen
Hvis du ikke allerede har laget en CI/CD pipeline for applikasjonen din
Opprett en fil i roten av repositoriet .gitlab-ci.yml med det enkleste innholdet:
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"
Separat repo for CI/CD konfigurasjon
Jeg vil anbefale å lage et eget repo der du må opprette en fil myapp.gitlab-ci.yml for å konfigurere pipelinen. På den måten kan du bedre kontrollere tilgangen til deltakere som kan endre byggpipen og få tilgangstoken.
Plasseringen av den nye pipeline-filen må du spesifisere ved å gå inn på myapp-repoet — Innstillinger — CI/CD — Byggkøer — Brukerdefinert CI-konfigurasjonsvei — angi ny fil, for eksempel myapp.gitlab-ci.yml@gitlab-ce-mr-approvals/Ci
Tips: bruk en linter for å gjøre endringer i GitLab CI-filer
Selv om du jobber alene, kan det være nyttig å jobbe gjennom MR og kjøre alle endringene dine i pipeline-filene gjennom en linter. Hvis du gjør en feil i YAML-filsyntaksen, vil det ikke ødelegge den fungerende pipelinen, men bare blokkere Merge.
Eksempler på containere med linters du kan integrere i pipelinen din:
Og et eksempel på sjekkstadiet:
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;
Det gjenstår å legge til noen parametere i pipelinen din for at alt skal fungere:
faser:
- test
variables:
NEED_VOTES: 1
include:
- remote: "https://gitlab.com/gitlab-ce-mr-approvals/ci/-/raw/master/check-approve.gitlab-ci.yml"
Variabelen NEED_VOTES definerer hvor mange "tomler opp" som må være på MR for at Merge skal være tilgjengelig. En verdi på én betyr at du selv kan godkjenne din MR ved å "like" den.
include inkluderer teststadiet, som sjekker antall "likes".
Det enkleste pipeline-eksempelet med myapp.gitlab-ci.yml
faser:
- bygg
- 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
Innholdet i 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\/${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\/.*$\/'
Mer om hva som skjer under gjennomgangen:
- det er satt en begrensning som sier at gjennomgangen bare skjer ved opprettelse av MR til master- eller release/-grener
- ved å bruke GitLab API får vi antall 'likes' og 'dislikes'
- vi regner ut forskjellen mellom positive og negative tilbakemeldinger
- hvis forskjellen er mindre enn det vi har satt i NEED_VOTES, blokkerer vi muligheten for å gjøre en sammenslåing
5. Forby commits i beskyttede grener
Vi definerer de grenene vi skal utføre kodegjennomgang for, og spesifiserer at vi kun kan jobbe med dem via MR.
For å gjøre dette går vi til Innstillinger → Repository → Protected Branches:

6. Sjekker
Vi setter NEED_VOTES: 0
Vi lager en MR og setter 'dislike'.

I byggeloggen:

Nå setter vi 'like' og kjører en ny sjekk:

Kilde: habr.com
