
Ena od najpomembnejših funkcij, ki je na voljo le v plačljivi različici GitLab, je možnost glasovanja proti ponastavitvi repozitorija za nadzor Merge request (MR) z obveznim pregledom kode.
Minimalno funkcionalnost bomo naredili sami — onemogočili bomo Merge, dokler ne bo več razvijalcev potrdilo MR z 'palcem navzgor'.
Zakaj to sploh potrebujemo?
Naša organizacija si lahko privošči nakup licence za GitLab. Vendar pa se razvoj izvaja v zaprtem okolju brez dostopa do interneta, in ker imamo strogo načrtovanje proračuna, lahko nakup licenc self-managed s potrebno funkcionalnostjo traja mesece, čeprav moramo delati takoj.
Na koncu se moramo odločiti:
- bodisi povsem prepovemo Merge v zaščitene veje za nekatere razvijalce, vendar takrat razvijalci, ki imajo pravico do Merganja, prejmejo konflikte pri združevanju tujih MR kot bonus;
- ali pa omogočimo neomejeno združevanje z vašo glavno vejo brez pregleda kode, tudi če gre za Juniorja, ki je včeraj začel.
Kot prvotno sem se odpravil na google, domnevajoč, da je zagotovo nekdo že to naredil (brez prilagoditve kode), vendar se je izkazalo, da take izvedbe v različici community še ni bilo.
Splošna shema dela
Kot primer bomo nastavili odobritve Merge requestov na testnem repozitoriju. :
- Ustvarili bomo token za dostop do API GitLab (prek njega bomo pridobili informacije o številu glasov 'za' in 'proti').
- Dodali bomo token v spremenljivke GitLab.
- Onemogočili bomo Merge ob napakah v pipeline-u (če glasov 'za' ni dovolj).
- Nastavili bomo preverjanje glasov kot del CI/CD pipeline-a.
- Onemogočili bomo izvajanje commitov v zaščitene veje, vse spremembe se izvajajo samo prek MR.
- Preverimo, kaj smo na koncu dosegli.
1. Ustvarimo token za dostop do API.
Pojdite v Nastavitve uporabnika → Dostope in shranite token:

Račun za pridobitev tokena.
Dostop do API-ja omogoča praktično vse vaše repozitorije, zato priporočam, da ustvarite poseben račun GitLab, mu dodelite minimalne pravice do vaših repozitorijev (na primer, Reporter) in pridobite token za ta račun.
2. Dodamo token v spremenljivke GitLab.
Na prejšnjem koraku smo pridobili token. QmN2Y0NOUFlfeXhvd21ZS01aQzgK
Odprite Nastavitve → CI/CD → Spremenljivke → Dodaj spremenljivko → GITLAB_TOKEN_FOR_CI

Na koncu bomo dobili:

To do this, you can use either a single repository or a group of repositories.
3. Set a restriction on Merge if approvals from colleagues have not been received after the code review.
In our case, the restriction on Merge will be that the build pipeline will return an error if there are not enough votes.
Go to Settings → General → Merge Requests → Merge Checks and enable the option The build lines must complete successfully.

4. Configure the pipeline
If you haven't set up a CI/CD pipeline for your application yet,
Create a file in the root of the repository .gitlab-ci.yml with the simplest content:
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"
A separate repository for CI/CD configuration
I would recommend creating a separate repository where you need to create a myapp.gitlab-ci.yml file to configure the pipeline. This way, you can better control access for participants who can modify the build pipeline and obtain access tokens.
The location of the new pipeline file must be specified by navigating to the myapp repository — Settings — CI/CD — Build Lines — Custom CI configuration path — specify the new file, for example, myapp.gitlab-ci.yml@gitlab-ce-mr-approvals/Ci
Tip: use a linter for making changes to GitLab CI files.
Even if you are working alone, using MR will be a good helper, passing all your changes to the pipeline files through a linter. If you make a syntax error in the YAML file, it will not break your working pipeline but simply block the Merge.
Examples of containers with linters that you can integrate into your pipeline:
And an example of a check stage:
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;
You just need to add a few parameters to your pipeline to make everything work:
etape:
- test
variables:
NEED_VOTES: 1
include:
- remote: "https://gitlab.com/gitlab-ce-mr-approvals/ci/-/raw/master/check-approve.gitlab-ci.yml"
The NEED_VOTES variable defines how many "thumbs up" must be on the MR for a Merge to be available. A value of one means you can approve your own MR by "liking" it.
include connects the test stage, which checks the number of "likes".
Najenostavnejši pipeline na primeru myapp.gitlab-ci.yml
etape:
- zgraditi
- 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
Vsebina 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\/.*$/
Več o tem, kaj se dogaja med preverjanjem:
- nastavljena omejitev, da bo preverjanje potekalo samo pri ustvarjanju MR v vejah master ali release/*
- z uporabo API GitLab pridobimo število 'všečkov' in 'ne-všečkov'
- izračunamo razliko med pozitivnimi in negativnimi odzivi
- če je razlika manjša od vrednosti, ki jo določimo pri NEED_VOTES, blokiramo možnost združitve
5. Prepovemo commit-e v zaščitene veje
Določimo veje, za katere moramo izvesti code review in navedemo, da je mogoče delati z njimi samo preko MR.
Zato gremo v Nastavitve → Repozitorij → Zaščitene veje:

6. Preverjamo
Določimo NEED_VOTES: 0
Ustvarimo MR in damo 'ne-všeček'.

V logih gradnje:

Zdaj damo 'všeček' in zaženemo ponovno preverjanje:

Izvor: habr.com
