A partir da versão 7.04, o analisador PVS-Studio para idiomas C e C ++ no Linux e macOS fornece o recurso 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 aborda a configuração da verificação de certos arquivos modificados de um projeto GitHub em sistemas populares de CI (integração contínua), como Travis CI, Buddy e AppVeyor.
Modo de verificar a lista de arquivos
O PVS-Studio é uma ferramenta projetada para detectar erros e possíveis vulnerabilidades no código fonte dos programas, escritos em C, C ++, C # e Java. Funciona em sistemas de 64 bits no Windows, Linux e macOS.
Na versão PVS-Studio 7.04 para Linux e macOS, agora existe o modo de verificar a lista de arquivos. Ele funciona para projetos, cujo sistema de construção permite gerar o arquivo
compile_commands.json . É necessário que o analisador obtenha informações sobre a compilação de determinados arquivos. 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 .
Esse modo de verificar a lista de arquivos também pode ser usado com o log de rastreamento de execução do compilador gerado pelo strace (rastreamento do pvs-studio-analyzer). Para fazer isso, primeiro você precisa concluir uma construção completa do projeto e rastreá-la para que o analisador colete informações completas sobre os parâmetros de compilação de todos os arquivos verificados.
No entanto, essa opção tem uma desvantagem significativa - você precisará executar o rastreamento completo da construção de todo o projeto a cada execução, o que contraria a idéia de uma verificação rápida de confirmação. Ou, se você armazenar em cache o resultado do rastreamento, as execuções subseqüentes do analisador poderão ficar incompletas, caso, após o rastreamento da estrutura das dependências dos arquivos de origem, mude (por exemplo, um novo #include seja adicionado a um dos arquivos de origem).
Portanto, não recomendamos o uso do modo de verificar a lista de arquivos com um log de rastreamento para verificar confirmações ou solicitações de recebimento. Se você pode executar uma construção incremental ao verificar uma confirmação, considere usar o modo de
análise incremental .
A lista de arquivos de origem para a análise é salva no arquivo de texto e passada para o analisador usando o parâmetro
-S :
pvs-studio-analyzer analyze ... -f build/compile_commands.json -S check-list.txt
Este arquivo contém caminhos relativos e absolutos para arquivos em que cada novo arquivo vem em uma nova linha. Você pode especificar os nomes dos arquivos para a análise e o texto diferente. Quanto ao texto, o analisador notará que não é um nome de arquivo e ignorará a linha. Pode ser útil comentar se os arquivos forem especificados manualmente. No entanto, frequentemente a lista de arquivos será gerada durante a análise do IC, por exemplo, pode ser arquivos de uma solicitação de confirmação ou de recebimento.
Agora, usando esse modo, você pode verificar rapidamente o novo código antes que ele entre no ramo de desenvolvimento principal. O sinalizador
--indicate -warnings foi adicionado no utilitário
plog-converter para que o sistema de verificação respondesse à presença de avisos do analisador.
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. Você pode bloquear o pedido de confirmação prévia, confirmação ou solicitação e exibir o relatório do analisador gerado, compartilhar ou enviá-lo por correio.
Nota Durante a primeira análise da lista de arquivos, todo o projeto será verificado, pois o analisador precisará gerar o arquivo com dependências dos arquivos de origem do projeto a partir dos arquivos de cabeçalho. Essa é uma peculiaridade da análise de arquivos C e C ++. No futuro, esse arquivo de dependência poderá ser armazenado em cache e será atualizado automaticamente pelo analisador. A vantagem de verificar confirmações usando o modo de verificar a lista de arquivos no modo de análise incremental é o fato de que você precisa armazenar em cache apenas esse arquivo, não os arquivos de objeto.Princípios gerais da análise de solicitação pull
Toda a análise do projeto leva muito tempo, portanto, faz sentido verificar apenas uma parte dela. O problema é que você precisa separar novos arquivos do restante dos arquivos do projeto.
Vejamos o exemplo de uma árvore de confirmação de dois ramos:
Imagine que o commit
A1 contém uma quantidade bastante grande de código que já foi verificado. Anteriormente, fizemos uma ramificação da confirmação do
A1 e alteramos alguns arquivos.
Obviamente, você notou que após
A1 outros dois commits ocorreram e dois outros branches foram mesclados, pois não confirmamos no
master . Aí chega o momento em que o
hotfix está pronto. É por isso que recebemos uma solicitação de
recebimento para mesclagem
B3 e
A3 .
Poderíamos verificar o resultado da fusão, mas seria muito longo e irracional, pois apenas alguns arquivos foram modificados. Portanto, é mais eficiente analisar apenas os alterados.
Para isso, receberemos a diferença entre as ramificações, estando em HEAD da ramificação, da qual queremos mesclar no mestre:
git diff --name-only HEAD origin/$MERGE_BASE > .pvs-pr.list
Consideraremos
$ MERGE_BASE em detalhes posteriormente. O fato é que nem todo serviço de IC fornece as informações necessárias na base de mesclagem; portanto, toda vez que precisamos pensar em novas maneiras de obter esses dados. Isso será considerado nos detalhes abaixo para cada um dos serviços da web descritos.
Portanto, temos diferença entre os ramos, que é a lista de nomes de arquivos modificados. Agora precisamos alimentar esse arquivo
.pvs-pr.list no analisador. Redirecionamos a saída para ela anteriormente.
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 amigável:
plog-converter -t errorfile PVS-Studio.log --cerr -w
Este comando produzirá a lista de erros no
stderr (fluxo de erros padrão).
O problema é que precisamos não apenas gerar os erros, mas também reportar nosso serviço de compilação e teste sobre os problemas. Para fazer isso, o sinalizador
-W (
--indicate-warnings ) foi adicionado no 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 possíveis erros nos arquivos da solicitação pull.
Travis ci
A configuração é feita no formato do arquivo
.travis.yml . Por conveniência, aconselho a isolar todos os comandos relacionados ao PVS-Studio em um script bash separado com funções que serão chamadas a partir do arquivo
.travis.yml (
bash script_name.sh nome_da_função ).
Ao expandir o script, você obterá mais funcionalidades. Na seção de
instalação , escreva o seguinte:
install: - bash .travis.sh travis_install
Se você recebeu algumas instruções, pode movê-las no script, removendo os hífens.
Abra o arquivo
.travis.sh e adicione a instalação do analisador na 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 vamos adicionar o analisador executado na 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 }
É necessário executar esse código 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 }
Você obterá o seguinte:
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 }
Provavelmente, você já percebeu as variáveis de ambiente
$ TRAVIS_PULL_REQUEST e
$ TRAVIS_BRANCH . O Travis CI os declara:
- $ 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.
Aqui está o algoritmo operacional desta função:
O Travis CI responde aos códigos de retorno; portanto, a presença de avisos informará o serviço para marcar a confirmação 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 ao analisar uma solicitação pull:
É por isso que analisamos
A4 , não
B3-> A3 . Devido a essa peculiaridade, precisamos avaliar a diferença com
A3 , que é o chefe do ramo de
origem .
Um detalhe importante permanece: armazenar em cache as dependências dos arquivos de cabeçalho das unidades de conversão compiladas (* .c, * .cc, * .cpp e outras). O analisador avalia essas dependências durante a primeira execução no modo de verificar a lista de arquivos e as armazena no diretório .PVS-Studio. O Travis CI permite armazenar repositórios em cache, portanto, salvaremos os dados no
diretório .PVS-Studio / :
cache: directories: - .PVS-Studio/
Este código deve ser adicionado ao arquivo
.travis.yml : Este diretório armazena vários dados, coletados após a análise. Esses dados aceleram significativamente as execuções subseqüentes da análise da lista de arquivos ou análise incremental. Caso contrário, o analisador analisará todos os arquivos sempre.
Amigo
Assim como o Travis CI, o
Buddy permite que você crie e teste projetos automaticamente 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, precisamos adicionar uma nova etapa ao pipeline:
Vamos especificar o compilador usado para construir o projeto. Preste atenção ao contêiner do docker, instalado durante esta etapa. Por exemplo, há um contêiner especial para o GCC:
Agora vamos instalar 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
Vamos 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ê ler a seção sobre o Travs-CI, esse código é familiar para você. Mas aqui há um novo passo:
O fato é que agora analisamos não o resultado da mesclagem, mas o HEAD da ramificação com a solicitação pull verificada:
Portanto, estamos em um commit
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 definir
A3, vamos usar a API do GitHub:
https://api.github.com/repos/${USERNAME}/${REPO}/pulls/${PULL_REQUEST_ID}
Usamos as seguintes variáveis, fornecidas pelo Buddy:
- $ BUDDY_EXECUTION_PULL_REQEUST_NO - número de uma solicitação pull;
- $ BUDDY_REPO_SLUG - combinação de um nome de usuário e um repositório (por exemplo, max / test).
Agora vamos salvar as alterações, usando o botão abaixo e ativar a análise de solicitação de recebimento:
Ao contrário do Travis CI, não precisamos especificar
.pvs-studio para armazenamento em cache, pois o Buddy armazena em cache automaticamente todos os arquivos para execuções subseqüentes. Portanto, a última coisa que resta é salvar o login e a senha do PVS-Studio no Buddy. Após salvar as alterações, voltaremos ao Pipeline. Precisamos seguir em frente para configurar as variáveis e inserir o login e a chave do PVS-Studio:
Após isso, uma verificação começará com cada nova solicitação ou confirmação de recebimento. Se um commit contiver erros, o Buddy o indicará 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 o arquivo * .yml no repositório do projeto.
Vamos para a guia Configurações na revisão do projeto:
Role esta página para baixo e ative o salvamento em cache para a criação de solicitação pull:
Agora vamos para a guia Ambiente, onde especificaremos a imagem para a compilação e as variáveis de ambiente necessárias:
Se você leu as seções anteriores, já está familiarizado com essas duas variáveis -
PVS_KEY e
PVS_USERNAME . Caso contrário, lembre-se de 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 na parte inferior, vamos especificar a pasta de cache:
Se não o fizermos, analisaremos o projeto inteiro em vez de alguns arquivos, mas receberemos a saída dos arquivos especificados. Portanto, é importante inserir o nome correto do repositório.
Agora chegou a hora do script de verificação. Abra a guia Testes e escolha Script:
O seguinte código deve ser inserido 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
Vamos prestar 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
É uma atribuição bastante específica do valor de saída do comando pwd para a variável, que deve armazenar esse valor por padrão. No começo parece estranho, mas deixe-me explicar tudo.
Ao configurar o analisador no AppVeyor, me deparei com um comportamento muito estranho do analisador. Por um lado, tudo funcionou corretamente, mas a análise não foi iniciada. Demorou muito tempo para perceber que estávamos no diretório / home / appveyor / projects / testcalc /, enquanto o analisador tinha certeza de que estávamos em / opt / appveyor / build-agent /. Naquele momento, percebi que a variável $ PWD é enganosa. Por esse motivo, renovei manualmente seu valor antes de executar a análise.
A ordem das ações foi a mesma que anteriormente:
Agora dê uma olhada neste fragmento:
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 as ramificações, relacionada à solicitação de extração verificada. Para fazer isso, precisamos das seguintes variáveis de ambiente:
- $ APPVEYOR_PULL_REQUEST_NUMBER - número da solicitação de recebimento;
- $ APPVEYOR_REPO_NAME - nome de usuário e repositório do projeto.
Conclusão
Bem, não consideramos todos os possíveis serviços de integração contínua, no entanto, todos eles têm especificações operacionais semelhantes. Mas, como no cache, cada serviço reinventa sua própria roda, portanto é sempre diferente.
Em alguns casos (como no Travis-CI), são necessárias algumas linhas de código - e o cache funciona perfeitamente. Em outros casos (como no AppVeyor), você apenas precisa especificar o diretório nas configurações. Mas existem alguns serviços em que você precisa criar chaves especiais e tentar convencer o sistema a dar a oportunidade de reescrever um fragmento em cache. Portanto, se você deseja configurar a análise de solicitação de recebimento em um serviço de integração contínua, que não foi considerado acima, primeiro, verifique se você não terá problemas com o cache.
Obrigado pela atenção. Se algo não der certo, você pode escrever com segurança para o nosso
suporte . Vamos dar uma dica e ajuda.