
Ama o GitLab e não gosta de erros? Quer aumentar a qualidade do código fonte? Então você veio ao lugar certo. Hoje vamos explicar como configurar o analisador C# PVS-Studio para verificar merge requests. Desejamos a todos uma ótima leitura!
— é uma ferramenta para identificar erros e vulnerabilidades potenciais no código fonte de programas escritos nas linguagens C, C++, C# e Java. Funciona em sistemas de 64 bits no Windows, Linux e macOS. Pode analisar código destinado a plataformas ARM de 32 bits, 64 bits e embarcadas.
A propósito, lançamos o PVS-Studio 7.08, onde fizemos muitas melhorias . Por exemplo:
- analisador C# para Linux e macOS;
- plugin para Rider;
- novo modo de verificação de lista de arquivos.
Modo de verificação da lista de arquivos
Anteriormente, para verificar arquivos específicos, era necessário passar um .xml para o analisador com a lista de arquivos. Porém, como isso não era muito conveniente, adicionamos a possibilidade de passar um .txt, o que facilita bastante a vida.
Para verificar arquivos específicos, é necessário especificar a flag —sourceFiles (--follow) e passar um .txt com a lista de arquivos. Isso fica assim:
pvs-studio-dotnet -t path/to/solution.sln -f fileList.txt -o project.jsonSe você está interessado em configurar a verificação de commits ou pull requests, você também pode fazê-lo usando este modo. A diferença estará na obtenção da lista de arquivos para análise e dependerá de quais sistemas você está utilizando.
Princípio da verificação de merge request
A essência da verificação é que os problemas encontrados pelo analisador não sejam incluídos no master branch. Também não queremos analisar o projeto inteiro a cada vez. Além disso, ao mesclar branches, temos uma lista de arquivos alterados. Portanto, sugiro adicionar a verificação de merge requests.
Veja como é um merge request antes da implementação do analisador estático:

Ou seja, todos os erros que estavam na branch mudanças, irão para a branch master. Como não gostaríamos que isso acontecesse, adicionamos a análise, e agora o esquema fica assim:

Analisamos changes2 e, se não houver erros, aceitamos o merge request, caso contrário, rejeitamos.
Aliás, se você estiver interessado na análise de commits e pull requests para C/C++, pode ler sobre isso .
GitLab
— uma ferramenta de ciclo de vida DevOps de código aberto que representa um sistema de gerenciamento de repositórios de código para Git, com uma wiki própria, sistema de rastreamento de bugs, pipeline CI/CD e outras funcionalidades.
Antes de começar a implementar a análise de merge requests, é necessário se registrar e subir seu projeto. Se você não souber como fazer isso, sugiro meu colega.
Nota. O método descrito a seguir para configurar o ambiente é apenas uma das possibilidades. O objetivo é mostrar os passos para configurar o ambiente necessário para a análise e iniciar o analisador. Pode ser que, no seu caso, seja mais otimizado dividir as etapas de preparação do ambiente (adição de repositórios, instalação do analisador) e análise: por exemplo, preparando imagens Docker com o ambiente necessário e seu uso ou algum outro método.
Para entender melhor o que acontecerá em seguida, proponho dar uma olhada no seguinte esquema:

Para o funcionamento, o analisador requer .NET Core SDK 3, portanto, antes de instalar o analisador, você precisa adicionar os repositórios da Microsoft, de onde serão instaladas as dependências necessárias para o analisador. A adição de repositórios da Microsoft para diferentes distribuições Linux .
Para instalar o PVS-Studio através do gerenciador de pacotes, também será necessário adicionar os repositórios do PVS-Studio. A adição de repositórios para diferentes distribuições é descrita mais detalhadamente em .
Para o funcionamento, o analisador necessita de uma chave de licença. Você pode obter uma licença de avaliação na .
Nota. Note que para o modo de operação descrito (análise de merge requests) é necessária uma licença Enterprise. Portanto, se você deseja experimentar esse modo de operação, não se esqueça de indicar no campo "Mensagem" que precisa especificamente da licença Enterprise.
Se ocorrer um merge request, precisaremos analisar apenas a lista de arquivos alterados; caso contrário, analisamos todos os arquivos. Após a análise, é preciso converter os logs para o formato que precisamos.
Agora, tendo em mente o algoritmo de trabalho, podemos passar para a escrita do script. Para isso, é necessário alterar o arquivo .gitlab-ci.yml ou, se não existir, criá-lo. Para criar, pressione o nome do seu projeto -> Configurar CI/CD.

Agora estamos prontos para escrever o script. Vamos primeiro escrever o código que instalará o analisador e inserirá a licença:
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.slnUma vez que a instalação e a ativação devem ocorrer antes de todos os outros scripts, usamos um marcador especial before_script. Vou explicar um pouco esse trecho.
Preparação para a instalação do analisador:
- 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 updateAdicionando os repositórios do PVS-Studio e do analisador:
- 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-dotnetAtivação da licença:
- pvs-studio-analyzer credentials $PVS_NAME $PVS_KEY$PVS_NAME — nome de usuário.
$PVS_KEY — chave do produto.
Restauração das dependências do projeto, onde $CI_PROJECT_DIR – caminho completo para o diretório do projeto:
- dotnet restore "$CI_PROJECT_DIR"/Path/To/Solution.slnPara uma análise correta, o projeto deve ser compilado com sucesso e suas dependências devem ser restauradas (por exemplo, os pacotes NuGet necessários devem ser baixados).
As variáveis de ambiente que contêm informações da licença podem ser definidas clicando em Setting, e depois em CI / CD.

Na janela que se abre, encontramos a opção Variáveis, na direita clicamos no botão Expand e adicionamos as variáveis. O resultado deve ser o seguinte:

Agora podemos prosseguir para a análise. Primeiro, adicionaremos um script para análise completa. No flag -t passamos o caminho até a solução, no flag -o escrevemos o caminho para o arquivo onde os resultados da análise serão gravados. Também estamos interessados no código de retorno. Nesse caso, é importante que o processamento seja interrompido quando o código de retorno indicar que alertas foram gerados durante a análise. Veja como fica esse trecho:
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; fiOs códigos de retorno funcionam com base em uma máscara de bits. Por exemplo, se durante a análise foram emitidos avisos, o código de retorno será 8. Se a licença expirar dentro de um mês, o código de retorno será 4. Se erros forem detectados na análise e a licença estiver prestes a expirar, os dois valores serão gravados no código de retorno: somamos os números e obtemos o código de retorno final — 8+4=12. Assim, ao verificar os bits relevantes, podemos obter informações sobre diferentes estados durante a análise. Códigos de retorno são descritos em detalhes na seção "Códigos de Retorno pvs-studio-dotnet (Linux / macOS)" do documento.".
Neste caso, estamos interessados em todos os códigos de retorno que incluem 8.
- exit_code=$((($exit_code & 8)/8))Receberemos 1 quando o código de retorno contiver o bit que nos interessa, caso contrário, receberemos 0.
Chegou a hora de adicionar a análise do merge request. Antes de fazer isso, vamos preparar o espaço para o script. Precisamos que ele execute apenas quando um merge request ocorrer. Assim:
merge:
script:
only:
- merge_requestsVamos para o script em si. Enfrentei o problema de que a máquina virtual não sabe nada sobre origin/master. Portanto, vamos ajudar um pouco:
- git fetch originAgora vamos obter a diferença entre os branches e salvar o resultado em txt arquivo:
- git diff --name-only origin/master $CI_COMMIT_SHA > pvs-fl.txtOnde $CI_COMMIT_SHA – o hash do último commit.
Em seguida, iniciamos a análise da lista de arquivos, usando a flag --follow. Passamos o arquivo .txt obtido anteriormente. E, semelhante à análise completa, verificamos os códigos de retorno:
- 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; fiO script completo para verificar o merge request será assim:
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_requestsSó resta adicionar a conversão do log depois que todos os scripts foram executados. Usaremos a etiqueta after_script e a utilidade plog-converter:
after_script:
- plog-converter -t html -o eLog ./PVS-Studio.jsonUtilitário — é um projeto open source que é usado para converter relatórios de erros do analisador em várias formas, como HTML. Uma descrição mais detalhada da ferramenta pode ser encontrada na subseção "Utilitário Plog Converter" .
Aliás, se você quiser trabalhar com o relatório .json localmente a partir da IDE, sugiro o nosso para IDE Rider. O uso dele é descrito em mais detalhes no .
Para conveniência, aqui está .gitlab-ci.yml na íntegra:
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.jsonAssim que adicionarmos tudo ao arquivo, clicamos em Commit changes. Para verificar se tudo está correto, acessamos CI/CD -> Pipelines -> Em execução. Isso abrirá uma janela da máquina virtual, no final da qual deve estar o seguinte:

Vimos Job succeeded – sucesso, tudo perfeito. Agora podemos testar o que foi feito.
Exemplos de operação
Para o exemplo, criaremos um projeto simples (em master) que terá alguns arquivos. Depois disso, em outro branch, mudaremos apenas um arquivo e tentaremos fazer um merge request.
Vamos considerar dois casos: quando o arquivo modificado contém um erro e quando não contém. Primeiro, um exemplo com erro.
Suponha que no branch master há um arquivo Program.cs, que não contém erros, e em outro branch o desenvolvedor adicionou um código com erro e deseja fazer um merge request. Que erro ele cometeu exatamente – não importa tanto, o importante é que ele exista. Por exemplo, esqueceu o operador throw (sim, ):
void MyAwesomeMethod(String name)
{
if (name == null)
new ArgumentNullException(....);
// fazer algo
....
}Vamos ver o resultado da análise do exemplo com erro. Também, para garantir que apenas um arquivo foi analisado, adicionei a flag -r na linha de comando do pvs-studio-dotnet:

Vemos que o analisador encontrou um erro e não permitiu a fusão dos branches.
Vamos verificar o exemplo sem erro. Corrigimos o código:
void MyAwesomeMethod(String name)
{
if (name == null)
throw new ArgumentNullException(....);
// fazer algo
....
}Resultados da análise do merge request:

Como vemos, não foram encontrados erros, e a execução da tarefa foi concluída com sucesso, que era o que queríamos verificar.
Conclusão
Filtrar código ruim antes da fusão dos branches é muito conveniente e agradável. Portanto, se você utiliza CI/CD, tente integrar um analisador estático para verificação. Além disso, isso é feito de forma bastante simples.
Obrigado pela atenção.
Se você quiser compartilhar este artigo com uma audiência de língua inglesa, por favor, use o link para a tradução: Nikolay Mironov. .
Fonte: habr.com
