Revisione del codice in Gitlab CE: se non ci sono approvazioni della richiesta di unione, ma lo voglio davvero

Revisione del codice in Gitlab CE: se non ci sono approvazioni della richiesta di unione, ma lo voglio davvero

Una delle funzioni più necessarie, che non è presente nella versione gratuita di GitLab, è la possibilità di votare contro l'annullamento del repository e controllare la richiesta di Merge (MR), utilizzando la revisione obbligatoria del codice.

Eseguiamo noi stessi la funzionalità minima: proibiremo l'unione fino a quando diversi sviluppatori non daranno il pollice in su a MR.

Perché è necessario?

La nostra organizzazione può facilmente permettersi di acquistare una licenza GitLab. Ma poiché lo sviluppo viene effettuato in un circuito chiuso senza accesso a Internet e esiste una rigorosa pianificazione del budget, l'acquisto di licenze autogestite con le funzionalità necessarie può richiedere molti mesi, ma è necessario lavorare ora.

Di conseguenza devi:

  • o vietare completamente l'unione in rami protetti per alcuni sviluppatori, ma gli sviluppatori che hanno il diritto all'unione ricevono conflitti quando uniscono i MR di altre persone come bonus;
  • oppure dare la possibilità di effettuare fusioni incontrollate con il proprio ramo master senza revisione del codice, anche se si tratta di Junior, assunto proprio ieri.

La prima cosa che ho fatto è stata andare su Google, credendo che qualcuno avesse sicuramente già fatto qualcosa di simile (senza modificare il codice), ma si è scoperto che non esisteva ancora tale implementazione nella versione community.

Schema generale di lavoro

Ad esempio, configuriamo le approvazioni delle richieste di unione su un repository di test la mia app:

  1. Creiamo un token per l'accesso all'API GitLab (attraverso di esso riceveremo informazioni sul numero di voti "a favore" e "contro")
  2. Aggiungiamo il token alle variabili GitLab
  3. Disabilitiamo Unisci in caso di errori nella pipeline (se non ci sono abbastanza voti positivi)
  4. Impostiamo la verifica del voto come parte della pipeline CI/CD
  5. Vietiamo di effettuare commit su rami protetti; tutte le modifiche vengono apportate solo tramite MR
  6. Controlliamo cosa è successo alla fine

1. Crea un token per accedere all'API

Vai su Impostazioni utente → Token di accesso e annota il token:

Revisione del codice in Gitlab CE: se non ci sono approvazioni della richiesta di unione, ma lo voglio davvero

Account per ricevere un token
L'accesso API ti consente di fare quasi tutto con i tuoi repository, quindi ti consiglio di creare un account Gitlab separato, concedendogli diritti minimi sui tuoi repository (ad esempio Reporter) e ottenendo un token per quell'account.

2. Aggiungi il token alle variabili Gitlab

Ad esempio, nel passaggio precedente abbiamo ricevuto un token QmN2Y0NOUFlfeXhvd21ZS01aQzgK

Aprire Impostazioni → CI/CD → Variabili → Aggiungi variabile → GITLAB_TOKEN_FOR_CI

Revisione del codice in Gitlab CE: se non ci sono approvazioni della richiesta di unione, ma lo voglio davvero

Di conseguenza otteniamo:

Revisione del codice in Gitlab CE: se non ci sono approvazioni della richiesta di unione, ma lo voglio davvero

Questa operazione può essere eseguita su un repository o su un gruppo di repository.

3. Mettiamo al bando la fusione se non viene ricevuta l'approvazione dei colleghi dopo la revisione del codice.

Nel nostro caso, il divieto di Merge sarà che la pipeline di assemblaggio restituirà un errore se non ci sono abbastanza voti.

Vai su Impostazioni → Generale → Richieste di unione → Verifiche di unione e abilita l'opzione Le linee di assemblaggio devono essere completate correttamente.

Revisione del codice in Gitlab CE: se non ci sono approvazioni della richiesta di unione, ma lo voglio davvero

4. Impostazione della pipeline

Se non hai ancora creato una pipeline CI/CD per la tua applicazione
Crea un file nella radice del repository .gitlab-ci.yml con il contenuto più semplice:

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"

Repository separato per la configurazione CI/CD
Consiglierei di creare un repository separato in cui è necessario creare un file myapp.gitlab-ci.yml per configurare la pipeline. In questo modo puoi controllare meglio l'accesso dei partecipanti che possono modificare la pipeline di compilazione e ricevere un token di accesso.

La posizione del nuovo file della pipeline dovrà essere specificata accedendo al repository myapp - Impostazioni - CI/CD - Linee di assemblaggio - Percorso di configurazione CI personalizzato - specifica il nuovo file, ad es. myapp.gitlab-ci.yml@gitlab-ce-mr-approvals/Ci

Suggerimento: utilizzare un linter per apportare modifiche ai file CI GitLab
Anche se lavori da solo, lavorare con MR sarà di grande aiuto, eseguendo tutte le modifiche ai file della pipeline attraverso un linter. Se commetti un errore nella sintassi del file YAML, ciò non interromperà la pipeline di produzione, ma bloccherà semplicemente Merge.

Un esempio di contenitori con linter che puoi integrare nella tua pipeline:

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

E un esempio della fase di verifica:

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;

Resta da aggiungere alcuni parametri alla tua pipeline per farla funzionare:

stages:
- test

variables:
NEED_VOTES: 1

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

La variabile NEED_VOTES determina quanti "pollici in su" devono avere MR affinché Merge sia disponibile. Un valore pari a uno significa che tu stesso puoi approvare il tuo MR mettendo “mi piace”.

include include la fase di test, che verifica il numero di “Mi piace”.

La pipeline più semplice utilizzando l'esempio di 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

Contenuto 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/.*$/'

Maggiori informazioni su cosa succede durante la verifica:

  • esiste una limitazione secondo cui il controllo verrà eseguito solo durante la creazione di MR nei rami master o release/*
  • utilizzando l'API GitLab, otteniamo il numero di "Mi piace" e "Non mi piace"
  • calcolare la differenza tra risposte positive e negative
  • se la differenza è inferiore al valore impostato in NEED_VOTES, blocchiamo la possibilità di unire

5. Proibire commit su rami protetti

Definiamo i rami per i quali dobbiamo condurre revisioni del codice e indichiamo che possono essere gestiti solo tramite MR.

Per fare ciò, vai su Impostazioni → Repository → Rami protetti:

Revisione del codice in Gitlab CE: se non ci sono approvazioni della richiesta di unione, ma lo voglio davvero

6. Controlla

Imposta NEED_VOTES: 0

Facciamo una MR e mettiamo un “non mi piace”.

Revisione del codice in Gitlab CE: se non ci sono approvazioni della richiesta di unione, ma lo voglio davvero

Nei registri di compilazione:

Revisione del codice in Gitlab CE: se non ci sono approvazioni della richiesta di unione, ma lo voglio davvero

Adesso metti “mi piace” e ricomincia a controllare:

Revisione del codice in Gitlab CE: se non ci sono approvazioni della richiesta di unione, ma lo voglio davvero

Fonte: habr.com

Aggiungi un commento