
Ami GitLab e odi gli errori? Vuoi migliorare la qualità del codice sorgente? Allora sei nel posto giusto. Oggi ti raccontiamo come configurare l'analizzatore C# PVS-Studio per controllare le merge request. A tutti un buon umore da unicorno e buona lettura.
è uno strumento per rilevare errori e potenziali vulnerabilità nel codice sorgente dei programmi scritti in C, C++, C# e Java. Funziona su sistemi a 64 bit su Windows, Linux e macOS. Può analizzare codice destinato a piattaforme a 32 bit, 64 bit e ARM embedded.
A proposito, abbiamo rilasciato PVS-Studio 7.08, in cui abbiamo fatto molte novità . Ad esempio:
- analizzatore C# per Linux e macOS;
- plugin per Rider;
- nuova modalità di controllo della lista dei file.
Modalità di controllo della lista dei file
In passato, per controllare file specifici, era necessario trasmettere all'analizzatore un file .xml contenente l'elenco dei file. Ma poiché non è molto comodo, abbiamo aggiunto la possibilità di trasmettere un .txt, il che semplifica notevolmente la vita.
Per controllare file specifici, è necessario specificare il flag —sourceFiles (-f) e inviare un .txt con l'elenco dei file. Ecco come si presenta:
pvs-studio-dotnet -t path/to/solution.sln -f fileList.txt -o project.jsonSe sei interessato a configurare il controllo dei commit o delle pull request, puoi anche farlo utilizzando questa modalità. La differenza consisterà nel ricevere l'elenco dei file da analizzare e dipenderà dai sistemi che utilizzi.
Principio di controllo della merge request
Il concetto principale del controllo è che i problemi rilevati dall'analizzatore non devono finire nella master branch. Inoltre, non vogliamo analizzare ogni volta l'intero progetto. Tanto più che quando si uniscono i branch abbiamo un elenco di file modificati. Quindi, ti propongo di aggiungere il controllo della merge request.
Ecco come appare una merge request prima dell'implementazione dell'analizzatore statico:

Cioè, tutti gli errori che erano nel branch changes, andranno al branch master. Dato che non ci piacerebbe, aggiungiamo l'analisi, e ora lo schema appare come segue:

Analizziamo changes2 e, se non ci sono errori, accettiamo la merge request, altrimenti la rifiutiamo.
A proposito, se sei interessato all'analisi dei commit e delle pull request per C/C++, puoi leggere di questo .
GitLab
— uno strumento web per il ciclo di vita DevOps open source, che rappresenta un sistema di gestione dei repository di codice per Git con una wiki integrata, un sistema di tracciamento degli errori, un pipeline CI/CD e altre funzionalità.
Prima di iniziare a implementare l'analisi delle merge request, è necessario registrarsi e caricare il proprio progetto. Se non sai come farlo, ti consiglio di un mio collega.
Nota. Il metodo di configurazione dell'ambiente descritto di seguito è uno dei possibili. L'obiettivo è mostrare i passaggi per configurare l'ambiente necessario per l'analisi e avviare l'analizzatore. Potrebbe essere più ottimale nel tuo caso separare le fasi di preparazione dell'ambiente (aggiunta di repository, installazione dell'analizzatore) e analisi: ad esempio, preparare immagini Docker con l'ambiente necessario e utilizzarle o qualche altro metodo.
Per comprendere meglio cosa sta per accadere, ti propongo di dare un'occhiata al seguente schema:

Per lavorare, l'analizzatore richiede il .NET Core SDK 3, quindi prima di installare l'analizzatore è necessario aggiungere i repository Microsoft, dai quali verranno installate le dipendenze necessarie per l'analizzatore. L'aggiunta dei repository Microsoft per diverse distribuzioni Linux .
Per installare PVS-Studio attraverso un gestore di pacchetti sarà anche necessario aggiungere i repository di PVS-Studio. L'aggiunta dei repository per le diverse distribuzioni è descritta più nel dettaglio in .
Per lavorare, l'analizzatore ha bisogno di una chiave di licenza. È possibile ottenere una licenza di prova su .
Nota. Tieni presente che per la modalità di lavoro descritta (analisi delle merge request) è necessaria una licenza Enterprise. Pertanto, se vuoi provare questa modalità di lavoro, non dimenticare di indicare nel campo "Messaggio" che hai bisogno di una licenza Enterprise.
Se avviene una merge request, dovremo analizzare solo l'elenco dei file modificati, altrimenti analizzarli tutti. Dopo l'analisi, sarà necessario convertire i log nel formato desiderato.
Ora, avendo di fronte l'algoritmo di lavoro, possiamo passare alla scrittura dello script. Per farlo, è necessario modificare il file .gitlab-ci.yml o, se non esiste, crearlo. Per crearlo, fai clic sul nome del tuo progetto -> Imposta CI/CD.

Ora siamo pronti per scrivere lo script. Iniziamo a scrivere il codice che installerà l'analizzatore e inserirà la licenza:
before_script:
- apt-get update && apt-get -y install wget gnupg
- apt-get -y install git
- wget https://packages.microsoft.com/config/debian/10/
packages-microsoft-prod.deb -O packages-microsoft-prod.deb
- dpkg -i packages-microsoft-prod.deb
- apt-get update
- apt-get install apt-transport-https
- apt-get update
- wget -q -O - https://files.viva64.com/etc/pubkey.txt | apt-key add -
- wget -O /etc/apt/sources.list.d/viva64.list
https://files.viva64.com/etc/viva64.list
- apt-get update
- apt-get -y install pvs-studio-dotnet
- pvs-studio-analyzer credentials $PVS_NAME $PVS_KEY
- dotnet restore "$CI_PROJECT_DIR"/Test/Test.slnPoiché l'installazione e l'attivazione devono avvenire prima di tutti gli altri script, utilizziamo un'etichetta speciale before_script. Spiego brevemente questo frammento.
Preparazione per l'installazione dell'analizzatore:
- wget https://packages.microsoft.com/config/debian/10/
packages-microsoft-prod.deb -O packages-microsoft-prod.deb
- dpkg -i packages-microsoft-prod.deb
- apt-get update
- apt-get install apt-transport-https
- apt-get updateAggiunta dei repository di PVS-Studio e dell'analizzatore:
- wget -q -O - https://files.viva64.com/etc/pubkey.txt | apt-key add -
- wget -O /etc/apt/sources.list.d/viva64.list
https://files.viva64.com/etc/viva64.list
- apt-get update
- apt-get -y install pvs-studio-dotnetAttivazione della licenza:
- pvs-studio-analyzer credentials $PVS_NAME $PVS_KEY$PVS_NAME — nome utente.
$PVS_KEY — chiave del prodotto.
Ripristino delle dipendenze del progetto, dove $CI_PROJECT_DIR – percorso completo della directory del progetto:
- dotnet restore "$CI_PROJECT_DIR"/Path/To/Solution.slnPer un'analisi corretta, il progetto deve compilarsi correttamente e le sue dipendenze devono essere ripristinate (ad esempio, devono essere scaricati i pacchetti NuGet necessari).
Le variabili ambientali contenenti informazioni sulla licenza possono essere impostate facendo clic su Setting, e poi su CI / CD.

Nella finestra che si apre, troviamo l'opzione Variabili, a destra facciamo clic sul pulsante Expand e aggiungiamo le variabili. Il risultato dovrebbe essere il seguente:

Ora possiamo passare all'analisi. Innanzitutto, aggiungiamo uno script per l'analisi completa. Nel flag -t passiamo il percorso della soluzione, nel flag -o indichiamo il percorso del file in cui verranno scritti i risultati dell'analisi. Inoltre, ci interessa il codice di ritorno. In questo caso, ci interessa che il processo si interrompa quando il codice di ritorno indica che durante l'analisi sono stati emessi avvisi. Ecco come appare questo frammento:
job:
script:
- exit_code=0
- pvs-studio-dotnet -t "$CI_PROJECT_DIR"/Test/Test.sln -o
PVS-Studio.json || exit_code=$?
- exit_code=$((($exit_code & 8)/8))
- if [[ $exit_code == 1 ]]; then exit 1; else exit 0; fiI codici di ritorno funzionano secondo il principio della maschera dei bit. Ad esempio, se durante l'analisi sono stati emessi avvisi, il codice di ritorno sarà 8. Se la licenza scade entro un mese, il codice di ritorno sarà 4. Se durante l'analisi sono stati trovati errori e la licenza scade entro un mese, entrambi i valori saranno registrati nel codice di ritorno: sommiamo i numeri insieme e otteniamo il codice di ritorno finale — 8+4=12. In questo modo, controllando i bit corrispondenti, possiamo ottenere informazioni su diversi stati durante l'analisi. I codici di ritorno sono descritti più dettagliatamente nella sezione "Codici di ritorno pvs-studio-dotnet (Linux / macOS)" del documento.".
In questo caso, ci interessano tutti i codici di ritorno che indicano 8.
- exit_code=$((($exit_code & 8)/8))Otteniamo 1 quando il codice di ritorno contiene il bit numerico che ci interessa, altrimenti otteniamo 0.
È arrivato il momento di aggiungere l'analisi della merge request. Prima di farlo, prepariamo il luogo per lo script. Abbiamo bisogno che venga eseguito solo quando si verifica una merge request. Si presenta in questo modo:
merge:
script:
only:
- merge_requestsPassiamo allo script stesso. Ho trovato che la macchina virtuale non sa nulla di origin/master. Quindi l'aiutiamo un po':
- git fetch originOra otteniamo la differenza tra i rami e salviamo il risultato in txt file:
- git diff --name-only origin/master $CI_COMMIT_SHA > pvs-fl.txtDove $CI_COMMIT_SHA – hash dell'ultimo commit.
Successivamente, eseguiamo l'analisi dell'elenco dei file, utilizzando il flag -f. Passiamo il file .txt ottenuto in precedenza. E, analogamente all'analisi completa, controlliamo i codici di ritorno:
- exit_code=0
- pvs-studio-dotnet -t "$CI_PROJECT_DIR"/Test/Test.sln -f
pvs-fl.txt -o PVS-Studio.json || exit_code=$?
- exit_code=$((($exit_code & 8)/8))
- if [[ $exit_code == 1 ]]; then exit 1; else exit 0; fiLo script completo per controllare la merge request sarà così:
merge:
script:
- git fetch origin
- git diff --name-only origin/master $CI_COMMIT_SHA > pvs-fl.txt
- exit_code=0
- pvs-studio-dotnet -t "$CI_PROJECT_DIR"/Test/Test.sln -f
pvs-fl.txt -o PVS-Studio.json || exit_code=$?
- exit_code=$((($exit_code & 8)/8))
- if [[ $exit_code == 1 ]]; then exit 1; else exit 0; fi
only:
- merge_requestsRimane solo aggiungere la conversione del log dopo che tutti gli script sono stati eseguiti. Utilizziamo l'etichetta after_script e l'utilità plog-converter:
after_script:
- plog-converter -t html -o eLog ./PVS-Studio.jsonUtilità — è un progetto open source che viene utilizzato per convertire il report degli errori dell'analizzatore in varie forme, come HTML. Una descrizione più dettagliata dello strumento è fornita nella sezione "Strumento Plog Converter" .
A proposito, se vuoi lavorare comodamente con il report .json localmente dall'IDE, ti offriamo il nostro per l'IDE Rider. Maggiori dettagli sul suo utilizzo sono descritti nel .
Per comodità ecco .gitlab-ci.yml il file completo:
image: debian
before_script:
- apt-get update && apt-get -y install wget gnupg
- apt-get -y install git
- wget https://packages.microsoft.com/config/debian/10/
packages-microsoft-prod.deb -O packages-microsoft-prod.deb
- dpkg -i packages-microsoft-prod.deb
- apt-get update
- apt-get install apt-transport-https
- apt-get update
- wget -q -O - https://files.viva64.com/etc/pubkey.txt | apt-key add -
- wget -O /etc/apt/sources.list.d/viva64.list
https://files.viva64.com/etc/viva64.list
- apt-get update
- apt-get -y install pvs-studio-dotnet
- pvs-studio-analyzer credentials $PVS_NAME $PVS_KEY
- dotnet restore "$CI_PROJECT_DIR"/Test/Test.sln
merge:
script:
- git fetch origin
- git diff --name-only origin/master $CI_COMMIT_SHA > pvs-fl.txt
- exit_code=0
- pvs-studio-dotnet -t "$CI_PROJECT_DIR"/Test/Test.sln -f
pvs-fl.txt -o PVS-Studio.json || exit_code=$?
- exit_code=$((($exit_code & 8)/8))
- if [[ $exit_code == 1 ]]; then exit 1; else exit 0; fi
only:
- merge_requests
job:
script:
- exit_code=0
- pvs-studio-dotnet -t "$CI_PROJECT_DIR"/Test/Test.sln -o
PVS-Studio.json || exit_code=$?
- exit_code=$((($exit_code & 8)/8))
- if [[ $exit_code == 1 ]]; then exit 1; else exit 0; fi
after_script:
- plog-converter -t html -o eLog ./PVS-Studio.jsonUna volta che hai aggiunto tutto nel file, clicca su Commit changes. Per vedere se è tutto corretto, vai in CI/CD -> Pipelines -> Esecuzione. Si aprirà una finestra della macchina virtuale, alla fine della quale dovrebbe esserci quanto segue:

Abbiamo visto Job succeeded – successo, tutto perfetto. Ora possiamo anche testare quanto fatto.
Esempi di lavoro
Per esempio, creiamo un progetto semplice (in master) in cui ci saranno alcuni file. Dopo di che, in un'altra branch, modificheremo solo un file e proveremo a fare una richiesta di merge.
Consideriamo due casi: quando il file modificato contiene un errore e quando non lo contiene. Iniziamo con l'esempio con l'errore.
Supponiamo che nella branch master ci sia un file Program.cs, che non contiene errori, mentre in un'altra branch lo sviluppatore ha aggiunto codice errato e vuole fare una richiesta di merge. Che errore ha commesso esattamente – non è così importante, l'importante è che ci sia. Ad esempio, ha dimenticato l'operatore throw (sì, ):
void MyAwesomeMethod(String name)
{
if (name == null)
new ArgumentNullException(....);
// fai qualcosa
....
}Guardiamo il risultato dell'analisi dell'esempio con l'errore. Inoltre, per essere sicuri che solo un file sia stato analizzato, ho aggiunto un flag -r alla riga di comando di pvs-studio-dotnet:

Possiamo vedere che l'analizzatore ha trovato un errore e non ha permesso di eseguire la fusione delle branch.
Controlliamo l'esempio senza errore. Correggiamo il codice:
void MyAwesomeMethod(String name)
{
if (name == null)
throw new ArgumentNullException(....);
// fai qualcosa
....
}Risultati dell'analisi della richiesta di merge:

Come possiamo vedere, non sono stati trovati errori, e l'esecuzione del compito è andata a buon fine, che era ciò che volevamo verificare.
Conclusione
Filtrare il codice cattivo prima della fusione delle branch è molto comodo e piacevole. Quindi, se utilizzi CI/CD, prova ad integrare un analizzatore statico per la verifica. Tanto più che è abbastanza semplice da implementare.
Grazie per l'attenzione.
Se desideri condividere questo articolo con un pubblico di lingua inglese, ti chiedo di utilizzare il link alla traduzione: Nikolay Mironov. .
Fonte: habr.com
