Análise de solicitações de mesclagem no GitLab usando PVS-Studio para C #

image1.png


Você adora o GitLab e não gosta de bugs? Quer melhorar a qualidade do seu código-fonte? Então você veio ao lugar certo. Hoje vamos falar sobre como configurar o analisador PVS-Studio C # para verificar as solicitações de mesclagem. Todo o humor de unicórnio e uma leitura agradável.



PVS-Studio é uma ferramenta para detectar erros e vulnerabilidades potenciais no código-fonte de programas escritos em C, C ++, C # e Java. Funciona em sistemas de 64 bits no Windows, Linux e macOS. Pode analisar código para plataformas ARM de 32 bits, 64 bits e incorporadas.



A propósito, lançamos o PVS-Studio 7.08, no qual fizemos muitas coisas interessantes . Por exemplo:



  • Analisador C # para Linux e macOS;
  • plugin para Rider;
  • novo modo para verificar a lista de arquivos.


Modo de verificação da lista de arquivos



Anteriormente, para verificar determinados arquivos, era necessário passar um .xml com uma lista de arquivos para o analisador. Mas como não é muito conveniente, adicionamos a capacidade de transferir .txt, o que torna a vida muito fácil.



Para verificar arquivos específicos, você precisa especificar o sinalizador --sourceFiles ( -f ) e passar .txt com uma lista de arquivos. Se parece com isso:



pvs-studio-dotnet -t path/to/solution.sln -f fileList.txt -o project.json


Se você estiver interessado em configurar a verificação para commits ou solicitações pull, você também pode fazer isso usando este modo. A diferença estará em obter uma lista de arquivos para análise e dependerá de quais sistemas você está usando.



Princípio de verificação de solicitação de mesclagem



O ponto principal da verificação é que os problemas detectados pelo analisador não vão parar no branch master durante a fusão . Além disso, não queremos analisar todo o projeto todas as vezes. Além disso, ao mesclar ramos, temos uma lista de arquivos alterados. Portanto, sugiro adicionar uma verificação para a solicitação de mesclagem.



Esta é a aparência da solicitação de mesclagem antes de implementar o analisador estático:



image2.png


Ou seja, todos os erros que estavam no branch de alterações irão para o branch master. Como não gostaríamos disso, adicionamos análise e agora o diagrama se parece com este:



image3.png


Analisamos as alterações2 e, se não houver erros, aceitamos o pedido de fusão, caso contrário, rejeitamos.



A propósito, se você estiver interessado em analisar commits e solicitações pull para C / C ++, você pode ler sobre isso aqui .



Gitlab



GitLab é uma ferramenta de ciclo de vida DevOps baseada na web de código aberto que fornece um sistema de gerenciamento de repositório de código para Git com seu próprio wiki, rastreador de bug, pipeline de CI / CD e muito mais.



Antes de começar a implementar a análise de solicitações de mesclagem, você precisa se registrar e fazer upload de seu projeto. Se você não sabe fazer isso, sugiro um artigo do meu colega.



Nota... O método de configuração de ambiente descrito abaixo é um dos possíveis. O objetivo é mostrar as etapas de configuração do ambiente necessário para análise e execução do analisador. Talvez, no seu caso, seja mais ideal separar as etapas de preparação do ambiente (adicionar repositórios, instalar o analisador) e análise: por exemplo, preparar imagens Docker com o ambiente necessário e usá-las, ou algum outro método.



Para entender melhor o que vai acontecer agora, sugiro dar uma olhada no seguinte diagrama:



image4.png


O analisador requer o .NET Core SDK 3 para funcionar, portanto, antes de instalar o analisador, você precisa adicionar os repositórios da Microsoft, a partir dos quais as dependências necessárias para o analisador serão instaladas. A adição de repositórios Microsoft para várias distribuições Linux é descrita no documento correspondente .



Para instalar o PVS-Studio por meio do gerenciador de pacotes, você também precisará adicionar repositórios PVS-Studio. Adicionar repositórios para distribuições diferentes é descrito com mais detalhes na seção correspondente da documentação .



O analisador requer uma chave de licença para operar. Você pode obter uma licença de teste na página de download do analisador .



Nota... Observe que o modo de operação descrito (análise de solicitações de mesclagem) requer uma licença Enterprise. Portanto, se você deseja experimentar este modo de operação, não se esqueça de indicar no campo "Mensagem" que você precisa da licença Enterprise.



Se ocorrer uma solicitação de mesclagem, precisamos analisar apenas a lista de arquivos alterados, caso contrário, analisamos todos os arquivos. Após a análise, precisamos converter os logs para o formato que precisamos.



Agora, tendo diante de seus olhos o algoritmo de trabalho, você pode começar a escrever um roteiro. Para fazer isso, você precisa modificar o arquivo .gitlab-ci.yml ou, se não, criá-lo. Para criá-lo, você precisa clicar no nome do seu projeto -> Configurar CI / CD .



image5.png


Agora estamos prontos para escrever o script. Vamos primeiro escrever o código que irá 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.sln


Como a instalação e a ativação devem ocorrer antes de todos os outros scripts, usamos uma tag before_script especial . Vou explicar um pouco esse fragmento.



Preparando para instalar o 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 update


Adicionando repositórios e analisador PVS-Studio:



  - 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


Ativação da licença:



  - pvs-studio-analyzer credentials $PVS_NAME $PVS_KEY


$ PVS_NAME - nome de usuário.



$ PVS_KEY - chave do produto.



Restaurando as dependências do projeto, em que $ CI_PROJECT_DIR é o caminho completo para o diretório do projeto:



  - dotnet restore "$CI_PROJECT_DIR"/Path/To/Solution.sln


Para uma análise correta, o projeto deve ser construído com sucesso e suas dependências devem ser restauradas (por exemplo, os pacotes NuGet necessários devem ser carregados).



Você pode definir variáveis ​​de ambiente contendo informações de licença clicando em Configuração e, a seguir, em CI / CD .



image6.png


Na janela que se abre, encontre o item Variáveis , à direita, clique no botão Expandir e adicione variáveis. O resultado deve ser assim:



image7.png


Agora você pode prosseguir para a análise. Primeiro, vamos adicionar um script para análise completa. Passamos o caminho da solução para o sinalizador -t e, para o sinalizador -o , gravamos o caminho para o arquivo no qual os resultados da análise serão gravados. Também estamos interessados ​​no código de retorno. Nesse caso, interessa-nos que a operação seja encerrada quando o código de retorno contiver informações de que foram emitidos avisos durante a análise. Esta é a aparência deste snippet:



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


Os códigos de retorno funcionam como uma máscara de bits. Por exemplo, se, como resultado da análise, foram emitidos avisos, o código de retorno será 8. Se a licença expirar em um mês, o código de retorno será 4. Se forem encontrados erros durante a análise, e a licença expirar em um mês, no código retornar, ambos os valores serão escritos: some os números e obtenha o código de retorno final - 8 + 4 = 12. Assim, ao verificar os bits correspondentes, informações sobre vários estados podem ser obtidas durante a análise. Os códigos de retorno são descritos com mais detalhes na seção "códigos de retorno pvs-studio-dotnet (Linux / macOS)" do documento " Verificando projetos do Visual Studio / MSBuild / .NET Core na linha de comando usando PVS-Studio ".



Nesse caso, estamos interessados ​​em todos os códigos de retorno,onde 8 aparece.



  - exit_code=$((($exit_code & 8)/8))


Obteremos 1 quando o código de retorno contiver a parte do número no qual estamos interessados, caso contrário, obteremos 0.



É hora de adicionar a análise de solicitação de mesclagem. Antes de fazer isso, vamos preparar um local para o script. Só precisamos que ele seja executado quando ocorrer uma solicitação de mesclagem. Se parece com isso:



merge:
  script:
  only:
  - merge_requests


Vamos passar para o próprio script. Descobri que a máquina virtual não sabe nada sobre origem / mestre . Portanto, a ajudamos um pouco:



  - git fetch origin


Agora vamos obter a diferença entre os ramos e salvar o resultado em um arquivo txt :



  - git diff --name-only origin/master $CI_COMMIT_SHA > pvs-fl.txt


Onde $ CI_COMMIT_SHA é o hash do último commit.



Em seguida, executamos a análise da lista de arquivos usando o sinalizador -f . Transferimos para ele o arquivo .txt anterior recebido. Bem, por analogia com a análise completa, olhamos para 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; fi


O script completo para verificar a solicitação de mesclagem terá a seguinte aparência:



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


Resta apenas adicionar a conversão do log depois que todos os scripts forem executados. Usamos o rótulo after_script e o utilitário plog-converter :



after_script:
  - plog-converter -t html -o eLog ./PVS-Studio.json


O utilitário plog-converter é um projeto de código aberto usado para converter o relatório de erro do analisador em vários formatos, como HTML. Uma descrição mais detalhada do utilitário é fornecida na subseção "Utilitário Plog Converter" da seção correspondente da documentação .



A propósito, se você deseja trabalhar convenientemente com o relatório .json localmente do IDE, sugiro nosso plugin para o IDE Rider. Seu uso é descrito com mais detalhes no documento correspondente .



Por conveniência, aqui está todo o .gitlab-ci.yml :



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.json


Assim que tudo tiver sido adicionado ao arquivo, clique em Confirmar alterações . Para ver se tudo está correto, acesse CI / CD -> Pipelines -> Executando . Uma janela de máquina virtual será aberta, no final da qual deve ser a seguinte:



image8.png


Vimos Jó ter sucesso - sucesso, está tudo bem. Agora você pode testar o que fez.



Exemplos de trabalho



Como exemplo de trabalho, vamos criar um projeto simples (em master ) no qual haverá vários arquivos. Depois disso, em outro branch, vamos alterar apenas um arquivo e tentar fazer uma solicitação de mesclagem.



Considere dois casos: quando o arquivo modificado contém um erro e quando não contém. Primeiro, um exemplo com um erro.



Digamos que haja um arquivo Program.cs no branch master , que não contém erros, e em outro branch, o desenvolvedor adicionou código incorreto e deseja fazer uma solicitação de mesclagem. Que tipo de erro ele cometeu não é tão importante, o principal é que existe. Por exemplo, esqueci o operador de lançamento (sim, eles estão tão errados ):



void MyAwesomeMethod(String name)
{
  if (name == null)
    new ArgumentNullException(....);
  // do something
  ....
}


Vejamos o resultado da análise de um exemplo com erro. Além disso, para garantir que apenas um arquivo foi analisado, adicionei o sinalizador -r à linha de inicialização pvs-studio-dotnet:



image9.png


Vemos que o analisador encontrou um erro e não permitiu a fusão de ramos.



Verificando o exemplo sem erro. Consertando o código:



void MyAwesomeMethod(String name)
{
  if (name == null)
    throw new ArgumentNullException(....);
  // do something
  ....
}


Resultados da análise de solicitação de mesclagem:



image10.png


Como podemos ver, não foram encontrados erros e a execução da tarefa foi bem-sucedida, o que queríamos verificar.



Conclusão



Filtrar código inválido antes de mesclar branches é muito conveniente e agradável. Portanto, se você estiver usando CI / CD, tente construir um analisador estático para teste. Além disso, isso é feito de forma bastante simples.



Obrigado pela atenção.





Se você deseja compartilhar este artigo com um público falante de inglês, use o link de tradução: Nikolay Mironov. Análise de solicitações de mesclagem no GitLab usando PVS-Studio para C # .



All Articles