A partir da versão 7.04, o analisador PVS-Studio para linguagens C e C ++ no Linux e macOS possui uma capacidade de teste para verificar a lista de arquivos especificados. Usando o novo modo, você pode configurar o analisador para verificar confirmações e solicitações. Este artigo mostra como configurar a verificação da lista de arquivos de projeto GitHub modificados em sistemas populares de CI (integração contínua) como Travis CI, Buddy e AppVeyor.
Modo de verificação da lista de arquivos
O PVS-Studio é uma ferramenta para detectar erros e possíveis vulnerabilidades no código fonte de programas escritos em C, C ++, C # e Java. Funciona em sistemas de 64 bits no Windows, Linux e macOS.
No PVS-Studio versão 7.04 para Linux e macOS, o modo de verificar a lista de arquivos de origem apareceu. Isso funciona para projetos cujo sistema de construção permite que o arquivo
compile_commands.json seja gerado. É necessário para o analisador extrair informações sobre a compilação dos arquivos especificados. Se o seu sistema de construção não suportar a geração do arquivo compile_commands.json, você poderá tentar gerar esse arquivo usando o utilitário
Bear .
Além disso, o modo de verificação da lista de arquivos pode ser usado junto com o log de rastreamento de strace das partidas do compilador (rastreamento do pvs-studio-analyzer). Para fazer isso, primeiro você precisará realizar uma montagem completa do projeto e acompanhá-lo, para que o analisador colete informações completas sobre os parâmetros de compilação de todos os arquivos testados.
No entanto, essa opção tem uma desvantagem significativa - você precisará fazer um rastreamento completo de toda a montagem do projeto a cada início, o que por si só contradiz a idéia de uma verificação rápida da confirmação. Ou, se o próprio resultado do rastreamento estiver armazenado em cache, o início subsequente do analisador poderá não ser concluído se a estrutura de dependência dos arquivos de origem for alterada após o rastreamento (por exemplo, um novo #include é adicionado a um dos arquivos de origem).
Portanto, não recomendamos o uso do modo de verificação da lista de arquivos com o log de rastreamento para verificar confirmações ou solicitações de recebimento. Caso você possa fazer uma montagem incremental ao verificar uma confirmação, considere usar o modo de
análise incremental .
A lista de arquivos de origem para análise é salva em um arquivo de texto e transferida para o analisador usando o parâmetro
-S :
pvs-studio-analyzer analyze ... -f build/compile_commands.json -S check-list.txt
Nesse arquivo, os caminhos relativos ou absolutos para os arquivos são indicados e cada novo arquivo deve estar em uma nova linha. É permitido especificar não apenas os nomes dos arquivos para análise, mas também vários textos. O analisador verá que este não é um arquivo e ignorará a linha. Isso pode ser útil para comentar se os arquivos forem especificados manualmente. No entanto, muitas vezes uma lista de arquivos será gerada durante a análise no IC, por exemplo, esses podem ser arquivos de uma solicitação de confirmação ou recebimento.
Agora, usando esse modo, você pode verificar rapidamente o novo código antes que ele entre no ramo de desenvolvimento principal. Para que o sistema de verificação responda aos avisos do analisador, o sinalizador
--indicate- warnings foi adicionado ao
utilitário plog-converter :
plog-converter ... --indicate-warnings ... -o /path/to/report.tasks ...
Com esse sinalizador, o conversor retornará um código diferente de zero se houver avisos no relatório do analisador. Usando o código de retorno, você pode bloquear o gancho de pré-confirmação, a solicitação de confirmação ou recebimento e exibir o relatório do analisador gerado na tela, compartilhar ou enviar por correio.
Nota Na primeira vez em que você executa a análise da lista de arquivos, todo o projeto será analisado, porque o analisador precisa gerar um arquivo de dependências dos arquivos de origem do projeto a partir dos arquivos de cabeçalho. Esse é um recurso da análise de arquivos C e C ++. No futuro, o arquivo de dependência poderá ser armazenado em cache e será atualizado automaticamente pelo analisador. A vantagem de verificar confirmações ao usar o modo de verificação da lista de arquivos sobre o modo de análise incremental é que você só precisa armazenar em cache esse arquivo, não os arquivos de objeto.Princípios gerais da análise de solicitação pull
A análise de todo o projeto leva muito tempo; portanto, faz sentido verificar apenas uma parte dele. O problema é que você precisa separar os novos arquivos do restante dos arquivos do projeto.
Considere um exemplo de uma árvore de confirmação com dois ramos:
Vamos imaginar que o commit
A1 contém uma quantidade bastante grande de código que já foi testado. Um pouco antes, fizemos uma ramificação a partir do commit
A1 e alteramos alguns arquivos.
Obviamente, você notou que, depois da
A1, havia mais duas confirmações, mas também eram fusões de outras filiais, porque não nos comprometemos no
mestre . E agora chegou a hora em que o
hotfix está pronto. Portanto, um pedido pull para a fusão de
B3 e
A3 apareceu .
Obviamente, era possível verificar todo o resultado da fusão, mas isso seria muito longo e injustificado, pois apenas alguns arquivos foram alterados. Portanto, é mais eficiente analisar apenas as alterações.
Para fazer isso, obtemos a diferença entre os galhos, estando na cabeça do galho do qual queremos mesclar no master:
git diff --name-only HEAD origin/$MERGE_BASE > .pvs-pr.list
$ MERGE_BASE , consideraremos com mais detalhes posteriormente. O fato é que nem todo serviço de IC fornece as informações necessárias sobre a base da mesclagem; portanto, toda vez que você precisar criar novas maneiras de obter esses dados. Isso será detalhado abaixo em cada um dos serviços da web descritos.
Portanto, temos a diferença entre os ramos, ou melhor, uma lista de nomes de arquivos que foram alterados. Agora, precisamos fornecer o
arquivo .pvs-pr.list (redirecionamos a saída para ele acima) para o analisador:
pvs-studio-analyzer analyze -j8 \ -o PVS-Studio.log \ -S .pvs-pr.list
Após a análise, precisamos converter o arquivo de log (PVS-Studio.log) em um formato fácil de ler:
plog-converter -t errorfile PVS-Studio.log --cerr -w
Este comando listará erros no
stderr (fluxo de saída da mensagem de erro padrão).
Só agora precisamos não apenas exibir erros, mas também informar nosso serviço para montagem e teste de problemas. Para fazer isso, o sinalizador
-W (
--indicate-warnings ) foi adicionado ao conversor. Se houver pelo menos um aviso do analisador, o código de retorno do utilitário
plog-converter será alterado para 2, que, por sua vez, informará o serviço de IC sobre a presença de possíveis erros nos arquivos de solicitação de recebimento.
Travis ci
A configuração é feita como um arquivo
.travis.yml . Por conveniência, recomendo que você coloque tudo em um script bash separado com funções que serão chamadas no arquivo
.travis.yml (
bash script_name.sh function_name ).
Adicionaremos o código necessário ao script
bash , para obter mais funcionalidade. Na seção de
instalação , escreva o seguinte:
install: - bash .travis.sh travis_install
Se você teve alguma instrução, pode transferi-la para o script removendo hífens.
Abra o arquivo
.travis.sh e adicione a instalação do analisador à função
travis_install () :
travis_install() { wget -q -O - https://files.viva64.com/etc/pubkey.txt \ | sudo apt-key add - sudo wget -O /etc/apt/sources.list.d/viva64.list \ https://files.viva64.com/etc/viva64.list sudo apt-get update -qq sudo apt-get install -qq pvs-studio }
Agora adicione a execução da análise à seção de
script :
script: - bash .travis.sh travis_script
E no script bash:
travis_script() { pvs-studio-analyzer credentials $PVS_USERNAME $PVS_KEY if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then git diff --name-only origin/HEAD > .pvs-pr.list pvs-studio-analyzer analyze -j8 \ -o PVS-Studio.log \ -S .pvs-pr.list \ --disableLicenseExpirationCheck else pvs-studio-analyzer analyze -j8 \ -o PVS-Studio.log \ --disableLicenseExpirationCheck fi plog-converter -t errorfile PVS-Studio.log --cerr -w }
Esse código precisa ser executado após a criação do projeto, por exemplo, se você construiu o CMake:
travis_script() { CMAKE_ARGS="-DCMAKE_EXPORT_COMPILE_COMMANDS=On ${CMAKE_ARGS}" cmake $CMAKE_ARGS CMakeLists.txt make -j8 }
Acontecerá assim:
travis_script() { CMAKE_ARGS="-DCMAKE_EXPORT_COMPILE_COMMANDS=On ${CMAKE_ARGS}" cmake $CMAKE_ARGS CMakeLists.txt make -j8 pvs-studio-analyzer credentials $PVS_USERNAME $PVS_KEY if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then git diff --name-only origin/HEAD > .pvs-pr.list pvs-studio-analyzer analyze -j8 \ -o PVS-Studio.log \ -S .pvs-pr.list \ --disableLicenseExpirationCheck else pvs-studio-analyzer analyze -j8 \ -o PVS-Studio.log \ --disableLicenseExpirationCheck fi plog-converter -t errorfile PVS-Studio.log --cerr -w }
Você provavelmente já percebeu as variáveis de ambiente especificadas
$ TRAVIS_PULL_REQUEST e
$ TRAVIS_BRANCH . O Travis CI os anuncia por conta própria:
- $ TRAVIS_PULL_REQUEST armazena o número da solicitação de recebimento ou false, se for uma ramificação regular;
- $ TRAVIS_REPO_SLUG armazena o nome do repositório do projeto.
O algoritmo desta função:
O Travis CI responde aos códigos de retorno; portanto, a presença de avisos informará o serviço para marcar o commit como contendo erros.
Agora, vamos dar uma olhada mais de perto nesta linha de código:
git diff --name-only origin/HEAD > .pvs-pr.list
O fato é que o Travis CI mescla ramificações automaticamente durante a análise de solicitação de recebimento:
Portanto, analisamos
A4 , não
B3-> A3 . Devido a esse recurso, precisamos calcular a diferença com
A3 , que é precisamente o topo da ramificação desde a
origem .
Um detalhe importante permaneceu - as dependências de armazenamento em cache dos arquivos de cabeçalho nas unidades de conversão compiladas (* .c, * .cc, * .cpp, etc.). O analisador calcula essas dependências na primeira inicialização no modo de verificação da lista de arquivos e, em seguida, salva no diretório .PVS-Studio. O Travis CI permite que você
armazene em cache as pastas, portanto salvaremos os dados do
diretório .PVS-Studio / :
cache: directories: - .PVS-Studio/
Esse código precisa ser adicionado ao arquivo
.travis.yml . Esse diretório armazena vários dados coletados após a análise, o que acelerará significativamente os lançamentos subsequentes da análise de lista de arquivos ou análise incremental. Se isso não for feito, o analisador analisará todos os arquivos todas as vezes.
Amigo
Como o Travis CI, o
Buddy oferece a capacidade de criar e testar automaticamente projetos armazenados no GitHub. Ao contrário do Travis CI, ele é configurado na interface da Web (o suporte ao bash está disponível), portanto não há necessidade de armazenar arquivos de configuração no projeto.
Primeiro de tudo, precisamos adicionar uma nova ação à linha de montagem:
Indicamos o compilador usado para construir o projeto. Preste atenção ao contêiner de docker instalado nesta ação. Por exemplo, há um contêiner especial para o GCC:
Agora instale o PVS-Studio e os utilitários necessários:
Adicione as seguintes linhas ao editor:
apt-get update && apt-get -y install wget gnupg jq 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
Agora vá para a guia Executar (primeiro ícone) e adicione o seguinte código ao campo apropriado do editor:
pvs-studio-analyzer credentials $PVS_USERNAME $PVS_KEY if [ "$BUDDY_EXECUTION_PULL_REQUEST_NO" != '' ]; then PULL_REQUEST_ID="pulls/$BUDDY_EXECUTION_PULL_REQUEST_NO" MERGE_BASE=`wget -qO - \ https://api.github.com/repos/${BUDDY_REPO_SLUG}/${PULL_REQUEST_ID} \ | jq -r ".base.ref"` git diff --name-only HEAD origin/$MERGE_BASE > .pvs-pr.list pvs-studio-analyzer analyze -j8 \ -o PVS-Studio.log \ --disableLicenseExpirationCheck \ -S .pvs-pr.list else pvs-studio-analyzer analyze -j8 \ -o PVS-Studio.log \ --disableLicenseExpirationCheck fi plog-converter -t errorfile PVS-Studio.log --cerr -w
Se você leu a seção Travs-CI, esse código já é familiar para você, no entanto, agora um novo estágio apareceu:
O fato é que agora estamos analisando não o resultado da fusão, mas o HEAD da filial da qual a solicitação de recebimento é feita:
Portanto, estamos no commit condicional
B3 e precisamos obter a diferença com
A3 :
PULL_REQUEST_ID="pulls/$BUDDY_EXECUTION_PULL_REQUEST_NO" MERGE_BASE=`wget -qO - \ https://api.github.com/repos/${BUDDY_REPO_SLUG}/${PULL_REQUEST_ID} \ | jq -r ".base.ref"` git diff --name-only HEAD origin/$MERGE_BASE > .pvs-pr.list
Para determinar
A3, use a API do GitHub:
https://api.github.com/repos/${USERNAME}/${REPO}/pulls/${PULL_REQUEST_ID}
Usamos as seguintes variáveis que o Buddy fornece:
- $ BUDDY_EXECUTION_PULL_REQEUST_NO - puxa o número da solicitação ;
- $ BUDDY_REPO_SLUG - combinação de nome de usuário e repositório (por exemplo, max / test).
Agora salve as alterações usando o botão abaixo e ative a análise de solicitação de recebimento:
Diferentemente do Travis CI, não precisamos especificar
.pvs-studio para armazenamento em cache, pois o Buddy armazena em cache automaticamente todos os arquivos para lançamentos subsequentes. Portanto, a última coisa que resta é salvar o login e a senha do PVS-Studio no Buddy. Depois de salvar as alterações, voltaremos ao Pipeline. Precisamos continuar configurando as variáveis e adicionar o login e a chave do PVS-Studio:
Depois disso, a aparência de uma nova solicitação ou confirmação de recebimento acionará uma verificação. Se a confirmação contiver erros, o Buddy indicará isso na página de solicitação de recebimento.
Appveyor
A configuração do AppVeyor é semelhante ao Buddy, pois tudo acontece na interface da web e não é necessário adicionar um arquivo * .yml ao repositório do projeto.
Vá para a guia Configurações na visão geral do projeto:
Role esta página para baixo e ative o salvamento de cache para criar solicitações pull:
Agora vá para a guia Ambiente, onde especificamos a imagem para a montagem e as variáveis de ambiente necessárias:
Se você ler as seções anteriores, estará familiarizado com essas duas variáveis -
PVS_KEY e
PVS_USERNAME . Caso contrário, lembro que eles são necessários para verificar a licença do analisador PVS-Studio. No futuro, nós os encontraremos novamente nos scripts do Bash.
Na mesma página abaixo, indicamos a pasta para armazenamento em cache:
Caso contrário, analisaremos o projeto inteiro em vez de um par de arquivos, mas obteremos a saída dos arquivos especificados. Portanto, é importante inserir o nome do diretório correto.
Agora é hora do script verificar. Abra a guia Testes e selecione Script:
Insira o seguinte código neste formulário:
sudo apt-get update && sudo apt-get -y install jq wget -q -O - https://files.viva64.com/etc/pubkey.txt \ | sudo apt-key add - sudo wget -O /etc/apt/sources.list.d/viva64.list \ https://files.viva64.com/etc/viva64.list sudo apt-get update && sudo apt-get -y install pvs-studio pvs-studio-analyzer credentials $PVS_USERNAME $PVS_KEY PWD=$(pwd -L) if [ "$APPVEYOR_PULL_REQUEST_NUMBER" != '' ]; then PULL_REQUEST_ID="pulls/$APPVEYOR_PULL_REQUEST_NUMBER" MERGE_BASE=`wget -qO - \ https://api.github.com/repos/${APPVEYOR_REPO_NAME}/${PULL_REQUEST_ID} \ | jq -r ".base.ref"` git diff --name-only HEAD origin/$MERGE_BASE > .pvs-pr.list pvs-studio-analyzer analyze -j8 \ -o PVS-Studio.log \ --disableLicenseExpirationCheck \ --dump-files --dump-log pvs-dump.log \ -S .pvs-pr.list else pvs-studio-analyzer analyze -j8 \ -o PVS-Studio.log \ --disableLicenseExpirationCheck fi plog-converter -t errorfile PVS-Studio.log --cerr -w
Preste atenção à seguinte parte do código:
PWD=$(pwd -L) if [ "$APPVEYOR_PULL_REQUEST_NUMBER" != '' ]; then PULL_REQUEST_ID="pulls/$APPVEYOR_PULL_REQUEST_NUMBER" MERGE_BASE=`wget -qO - \ https://api.github.com/repos/${APPVEYOR_REPO_NAME}/${PULL_REQUEST_ID} \ | jq -r ".base.ref"` git diff --name-only HEAD origin/$MERGE_BASE > .pvs-pr.list pvs-studio-analyzer analyze -j8 \ -o PVS-Studio.log \ --disableLicenseExpirationCheck \ --dump-files --dump-log pvs-dump.log \ -S .pvs-pr.list else pvs-studio-analyzer analyze -j8 \ -o PVS-Studio.log \ --disableLicenseExpirationCheck fi
A atribuição bastante específica do valor do comando pwd à variável que deve armazenar esse valor padrão parece estranha à primeira vista, no entanto, explicarei tudo agora.
Ao configurar o analisador no AppVeyor, encontrei um comportamento extremamente estranho do analisador. Por um lado, tudo funcionou corretamente, mas a análise não foi iniciada. Passei muito tempo percebendo que estamos no diretório / home / appveyor / projects / testcalc /, e o analisador tem certeza de que está em / opt / appveyor / build-agent /. Então percebi que a variável $ PWD está mentindo um pouco. Por esse motivo, atualizei seu valor manualmente antes de iniciar a análise.
E então tudo, como antes:
Agora considere o seguinte trecho:
PULL_REQUEST_ID="pulls/$APPVEYOR_PULL_REQUEST_NUMBER" MERGE_BASE=`wget -qO - \ https://api.github.com/repos/${APPVEYOR_REPO_NAME}/${PULL_REQUEST_ID} \ | jq -r ".base.ref"`
Nele, obtemos a diferença entre os ramos sobre os quais a solicitação de recebimento é declarada. Para fazer isso, precisamos das seguintes variáveis de ambiente:
- $ APPVEYOR_PULL_REQUEST_NUMBER - número de solicitação de recebimento;
- $ APPVEYOR_REPO_NAME - nome de usuário e repositório do projeto.
Conclusão
Obviamente, não consideramos todos os serviços possíveis de integração contínua, no entanto, todos eles têm características muito semelhantes entre si. Com exceção do armazenamento em cache, cada serviço faz sua própria “bicicleta”, então tudo é sempre diferente.
Em algum lugar, como no Travis-CI, algumas linhas de código e cache funcionam perfeitamente; em algum lugar, como no AppVeyor, você só precisa especificar a pasta nas configurações; mas em algum lugar você precisa criar chaves exclusivas e tentar convencer o sistema a dar a oportunidade de substituir o fragmento em cache. Portanto, se você deseja configurar a análise de solicitações pull no serviço de integração contínua, que não foi discutido acima, primeiro verifique se você não terá problemas com o cache.
Obrigado pela atenção. Se algo não der certo, sinta-se à vontade para nos escrever em
suporte . Vamos pedir e ajudar.

Se você deseja compartilhar este artigo com um público que fala inglês, use o link para a tradução: Maxim Zvyagintsev.
Análise de confirmações e solicitações pull no Travis CI, Buddy e AppVeyor usando PVS-Studio .