Anàlisi de commits i sol·licituds d'extracció a Travis CI, Buddy i AppVeyor mitjançant PVS-Studio

Anàlisi de commits i sol·licituds d'extracció a Travis CI, Buddy i AppVeyor mitjançant PVS-Studio
A l'analitzador PVS-Studio per a llenguatges C i C++ a Linux i macOS, a partir de la versió 7.04, ha aparegut una opció de prova per comprovar la llista de fitxers especificats. Mitjançant el nou mode, podeu configurar l'analitzador per comprovar les confirmacions i les sol·licituds d'extracció. Aquest article us explicarà com configurar la comprovació de la llista de fitxers modificats d'un projecte GitHub en sistemes CI (integració contínua) tan populars com Travis CI, Buddy i AppVeyor.

Mode de comprovació de la llista de fitxers

Estudi PVS és una eina per identificar errors i vulnerabilitats potencials en el codi font dels programes escrits en C, C++, C# i Java. Funciona en sistemes de 64 bits a Windows, Linux i macOS.

A la versió PVS-Studio 7.04 per a Linux i macOS, ha aparegut un mode per comprovar la llista de fitxers font. Això funciona per a projectes el sistema de compilació dels quals us permet generar un fitxer compile_commands.json. És necessari que l'analitzador extreu informació sobre la compilació dels fitxers especificats. Si el vostre sistema de compilació no admet la generació del fitxer compile_commands.json, podeu provar de generar aquest fitxer mitjançant la utilitat Tingui.

A més, el mode de comprovació de la llista de fitxers es pot utilitzar juntament amb el registre de traça de traça dels llançaments del compilador (traça pvs-studio-analyzer). Per fer-ho, primer haureu de realitzar una compilació completa del projecte i fer-ne un seguiment perquè l'analitzador reculli informació completa sobre els paràmetres de compilació de tots els fitxers que s'estan comprovant.

Tanmateix, aquesta opció té un inconvenient important: haureu de realitzar un seguiment complet de la compilació de tot el projecte cada vegada que l'executeu, cosa que en si mateix contradiu la idea de comprovar ràpidament una confirmació. O, si emmagatzemeu el resultat de la traça a la memòria cau, les execucions posteriors de l'analitzador poden estar incompletes si l'estructura de dependència dels fitxers font canvia després de la traça (per exemple, s'afegeix un nou #include a un dels fitxers font).

Per tant, no recomanem utilitzar el mode de comprovació de la llista de fitxers amb el registre de traça per comprovar les confirmacions o les sol·licituds d'extracció. En cas que pugueu fer una compilació incremental quan comproveu una confirmació, considereu utilitzar el mode anàlisi incremental.

La llista de fitxers font per a l'anàlisi es desa en un fitxer de text i es passa a l'analitzador mitjançant el paràmetre -S:

pvs-studio-analyzer analyze ... -f build/compile_commands.json -S check-list.txt

Aquest fitxer especifica camins relatius o absoluts als fitxers, i cada fitxer nou ha d'estar en una línia nova. És acceptable especificar no només els noms dels fitxers per a l'anàlisi, sinó també diversos textos. L'analitzador veurà que això no és un fitxer i ignorarà la línia. Això pot ser útil per comentar si els fitxers s'especifiquen manualment. Tanmateix, sovint es generarà una llista de fitxers durant l'anàlisi en CI, per exemple, aquests poden ser fitxers d'una sol·licitud de confirmació o d'extracció.

Ara, utilitzant aquest mode, podeu comprovar ràpidament el codi nou abans que entri a la branca principal de desenvolupament. Per garantir que el sistema d'escaneig respon als avisos de l'analitzador, la utilitat Plog-conversor bandera afegida --indicar-advertències:

plog-converter ... --indicate-warnings ... -o /path/to/report.tasks ...

Amb aquesta bandera, el convertidor retornarà un codi diferent de zero si hi ha avisos a l'informe de l'analitzador. Mitjançant el codi de retorn, podeu bloquejar una sol·licitud de precommit hook, commit o pull, i l'informe de l'analitzador generat es pot mostrar, compartir o enviar per correu electrònic.

Nota. Quan comenceu a analitzar una llista de fitxers, s'analitzarà tot el projecte, perquè l'analitzador ha de generar un fitxer de dependències dels fitxers font del projecte als fitxers de capçalera. Aquesta és una característica de l'anàlisi de fitxers C i C++. En el futur, el fitxer de dependència es pot guardar a la memòria cau i l'analitzador l'actualitzarà automàticament. L'avantatge de comprovar les confirmacions quan s'utilitza el mode de comprovació de la llista de fitxers en lloc d'utilitzar el mode d'anàlisi incremental és que només cal emmagatzemar a la memòria cau aquest fitxer i no els fitxers objecte.

Principis generals de l'anàlisi de la sol·licitud d'extracció

L'anàlisi de tot el projecte requereix molt de temps, de manera que té sentit comprovar-ne només una part determinada. El problema és que heu de separar els fitxers nous de la resta de fitxers del projecte.

Vegem un exemple d'arbre de commit amb dues branques:

Anàlisi de commits i sol·licituds d'extracció a Travis CI, Buddy i AppVeyor mitjançant PVS-Studio

Imaginem-nos aquest compromís A1 conté una quantitat força gran de codi que ja s'ha provat. Una mica abans vam fer una branca del commit A1 i ha canviat alguns fitxers.

Per descomptat, ho vas adonar després A1 es van produir dos commits més, però també van ser fusions d'altres branques, perquè no ens comprometem mestre. I ara ha arribat el moment en què hotfix llest. Per això va aparèixer una sol·licitud d'extracció per a la fusió B3 и A3.

Per descomptat, seria possible comprovar tot el resultat de la seva fusió, però això seria massa llarg i injustificat, ja que només es van canviar alguns fitxers. Per tant, és més eficient analitzar només els canviats.

Per fer-ho, obtenim la diferència entre les branques, en estar al CAP de la branca des de la qual volem fusionar-nos en mestre:

git diff --name-only HEAD origin/$MERGE_BASE > .pvs-pr.list

$MERGE_BASE ho veurem amb detall més endavant. El fet és que no tots els serveis de CI ofereixen la informació necessària sobre la base de dades per a la fusió, de manera que cada vegada heu de trobar noves maneres d'obtenir aquestes dades. Això es descriurà detalladament a continuació en cadascun dels serveis web descrits.

Així doncs, tenim la diferència entre les branques, o millor dit, una llista de noms de fitxers que es van canviar. Ara hem de donar el fitxer .pvs-pr.list (hi hem redirigit la sortida anterior) a l'analitzador:

pvs-studio-analyzer analyze -j8 
                            -o PVS-Studio.log 
                            -S .pvs-pr.list

Després de l'anàlisi, hem de convertir el fitxer de registre (PVS-Studio.log) a un format fàcil de llegir:

plog-converter -t errorfile PVS-Studio.log --cerr -w

Aquesta ordre enumerarà els errors a stderr (sortida de missatge d'error estàndard).

Només ara no només hem de mostrar errors, sinó també informar el nostre servei de muntatge i prova sobre la presència de problemes. Amb aquest propòsit, es va afegir una bandera al convertidor -W (--indicar-advertències). Si hi ha almenys un avís de l'analitzador, el codi de retorn de la utilitat Plog-conversor canviarà a 2, que al seu torn informarà el servei CI sobre la presència d'errors potencials als fitxers de sol·licitud d'extracció.

Travis C.I.

La configuració es fa com un fitxer .travis.yml. Per comoditat, us aconsello que ho poseu tot en un script bash independent amb funcions que es cridaran des del fitxer .travis.yml (bash nom_script.sh nom_funció).

Afegirem el codi necessari a l'script a colpejar, d'aquesta manera obtindrem més funcionalitats. A la secció instal · lar escrivim el següent:

install:
  - bash .travis.sh travis_install

Si teníeu instruccions, podeu transferir-les a l'script, eliminant els guions.

Obrim el fitxer .travis.sh i afegiu la configuració de l'analitzador a la funció 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 
}

Ara afegim a la secció script executa l'anàlisi:

script:
  - bash .travis.sh travis_script

I a l'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
}

Aquest codi s'ha d'executar després de crear el projecte, per exemple, si teníeu una compilació a CMake:

travis_script() {
  CMAKE_ARGS="-DCMAKE_EXPORT_COMPILE_COMMANDS=On ${CMAKE_ARGS}"
  cmake $CMAKE_ARGS CMakeLists.txt
  make -j8
}

Sortirà així:

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
}

Probablement ja heu notat aquestes variables d'entorn $TRAVIS_PULL_REQUEST и $TRAVIS_BRANCH. Travis CI els declara independentment:

  • $TRAVIS_PULL_REQUEST emmagatzema el número de sol·licitud d'extracció o false, si es tracta d'una branca regular;
  • $TRAVIS_REPO_SLUG emmagatzema el nom del repositori del projecte.

L'algorisme d'aquesta funció:

Anàlisi de commits i sol·licituds d'extracció a Travis CI, Buddy i AppVeyor mitjançant PVS-Studio
Travis CI respon als codis de retorn, de manera que la presència d'advertiments dirà al servei que marqui la confirmació com a que conté errors.

Ara mirem més de prop aquesta línia de codi:

git diff --name-only origin/HEAD > .pvs-pr.list

El fet és que Travis CI fusiona automàticament les branques mentre analitza una sol·licitud d'extracció:

Anàlisi de commits i sol·licituds d'extracció a Travis CI, Buddy i AppVeyor mitjançant PVS-Studio
Per això analitzem A4I no B3->A3. A causa d'aquesta característica, hem de calcular la diferència amb A3, que és precisament la part superior de la branca de origen.

Queda un detall important: la memòria cau de les dependències dels fitxers de capçalera en unitats de traducció compilades (*.c, *.cc, *.cpp, etc.). L'analitzador calcula aquestes dependències quan s'inicia per primera vegada en el mode de comprovació d'una llista de fitxers i després els desa al directori .PVS-Studio. Travis CI us permet emmagatzemar carpetes a la memòria cau, de manera que desarem les dades del directori .PVS-Studio/:

cache:
  directories:
    - .PVS-Studio/

Aquest codi s'ha d'afegir al fitxer .travis.yml. Aquest directori emmagatzema diverses dades recollides després de l'anàlisi, cosa que accelerarà significativament les execucions posteriors de l'anàlisi de la llista de fitxers o l'anàlisi incremental. Si això no es fa, l'analitzador analitzarà tots els fitxers cada vegada.

Amic

Com Travis CI, Amic ofereix la possibilitat de crear i provar automàticament projectes emmagatzemats a GitHub. A diferència de Travis CI, es configura a la interfície web (hi ha suport bash disponible), de manera que no cal emmagatzemar fitxers de configuració al projecte.

En primer lloc, hem d'afegir una nova acció a la línia de muntatge:

Anàlisi de commits i sol·licituds d'extracció a Travis CI, Buddy i AppVeyor mitjançant PVS-Studio
Indiquem el compilador que s'ha utilitzat per construir el projecte. Observeu el contenidor docker que està instal·lat en aquesta acció. Per exemple, hi ha un contenidor especial per a GCC:

Anàlisi de commits i sol·licituds d'extracció a Travis CI, Buddy i AppVeyor mitjançant PVS-Studio
Ara instal·lem PVS-Studio i les utilitats necessàries:

Anàlisi de commits i sol·licituds d'extracció a Travis CI, Buddy i AppVeyor mitjançant PVS-Studio
Afegim les següents línies a l'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

Ara anem a la pestanya Executar (primera icona) i afegim el codi següent al camp de l'editor corresponent:

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

Si llegiu la secció sobre Travs-CI, aquest codi ja us és familiar, però ara hi ha una nova etapa:

Anàlisi de commits i sol·licituds d'extracció a Travis CI, Buddy i AppVeyor mitjançant PVS-Studio
El cas és que ara analitzem no el resultat de la fusió, sinó el CAP de la branca des de la qual es fa la sol·licitud d'extracció:

Anàlisi de commits i sol·licituds d'extracció a Travis CI, Buddy i AppVeyor mitjançant PVS-Studio
Per tant, estem en un compromís condicional B3 i hem d'aconseguir la diferència 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

Per determinar A3 Utilitzem l'API de GitHub:

https://api.github.com/repos/${USERNAME}/${REPO}/pulls/${PULL_REQUEST_ID}

Hem utilitzat les variables següents que ens proporciona Buddy:

  • $BUDDY_EXECUTION_PULL_REQEUST_NO - número de sol·licitud d'extracció;
  • $BUDDY_REPO_SLUG — una combinació de nom d'usuari i repositori (per exemple max/test).

Ara desem els canvis amb el botó següent i activem l'anàlisi de la sol·licitud d'extracció:

Anàlisi de commits i sol·licituds d'extracció a Travis CI, Buddy i AppVeyor mitjançant PVS-Studio
A diferència de Travis CI, no cal que ho especifiquem .pvs-studio per a la memòria cau, ja que Buddy guarda automàticament tots els fitxers a la memòria cau per a llançaments posteriors. Per tant, l'últim que queda és desar l'inici de sessió i la contrasenya de PVS-Studio a Buddy. Després de desar els canvis, tornarem a Pipeline. Hem de passar a configurar variables i afegir un inici de sessió i una clau per a PVS-Studio:

Anàlisi de commits i sol·licituds d'extracció a Travis CI, Buddy i AppVeyor mitjançant PVS-Studio
Després d'això, l'aparició d'una nova sol·licitud d'extracció o confirmació activarà la revisió. Si una confirmació conté errors, Buddy ho indicarà a la pàgina de sol·licitud d'extracció.

AppVeyor

Configurar AppVeyor és similar a Buddy, ja que tot passa a la interfície web i no cal afegir un fitxer *.yml al repositori del projecte.

Anem a la pestanya Configuració a la visió general del projecte:

Anàlisi de commits i sol·licituds d'extracció a Travis CI, Buddy i AppVeyor mitjançant PVS-Studio
Desplacem-nos cap avall per aquesta pàgina i activem l'emmagatzematge de la memòria cau per recollir sol·licituds d'extracció:

Anàlisi de commits i sol·licituds d'extracció a Travis CI, Buddy i AppVeyor mitjançant PVS-Studio
Ara anem a la pestanya Entorn, on especifiquem la imatge per al muntatge i les variables d'entorn necessàries:

Anàlisi de commits i sol·licituds d'extracció a Travis CI, Buddy i AppVeyor mitjançant PVS-Studio
Si has llegit les seccions anteriors, estàs molt familiaritzat amb aquestes dues variables − PVS_KEY и PVS_USERNAME. Si no, permeteu-me recordar-vos que són necessaris per verificar la llicència de l'analitzador PVS-Studio. Els tornarem a veure als scripts de Bash en el futur.

A la mateixa pàgina a continuació indiquem la carpeta per a la memòria cau:

Anàlisi de commits i sol·licituds d'extracció a Travis CI, Buddy i AppVeyor mitjançant PVS-Studio
Si no ho fem, analitzarem tot el projecte en lloc d'un parell de fitxers, però obtindrem la sortida dels fitxers especificats. Per tant, és important introduir el nom de directori correcte.

Ara és el moment de provar el guió. Obriu la pestanya Proves i seleccioneu Script:

Anàlisi de commits i sol·licituds d'extracció a Travis CI, Buddy i AppVeyor mitjançant PVS-Studio
Heu d'enganxar el codi següent en aquest formulari:

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

Fixem-nos en la següent part del codi:

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

L'assignació força específica del valor de l'ordre pwd a una variable que hauria d'emmagatzemar aquest valor per defecte sembla estranya a primera vista, però ara ho explicaré tot.

Mentre configurava l'analitzador a AppVeyor, em vaig trobar amb un comportament extremadament estrany de l'analitzador. D'una banda, tot va funcionar correctament, però l'anàlisi no va començar. Vaig passar molt de temps observant que estem al directori /home/appveyor/projects/testcalc/ i l'analitzador està segur que estem a /opt/appveyor/build-agent/. Llavors em vaig adonar que la variable $PWD estava una mica mentida. Per aquest motiu, he actualitzat manualment el seu valor abans de començar l'anàlisi.

I després tot és com abans:

Anàlisi de commits i sol·licituds d'extracció a Travis CI, Buddy i AppVeyor mitjançant PVS-Studio
Considereu ara el fragment següent:

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"`

En ell obtenim la diferència entre les branques sobre les quals es declara la sol·licitud d'extracció. Per fer-ho necessitem les següents variables d'entorn:

  • $APPVEYOR_PULL_REQUEST_NUMBER — número de sol·licitud d'extracció;
  • $APPVEYOR_REPO_NAME - nom d'usuari i repositori del projecte.

Conclusió

Per descomptat, no hem considerat tots els possibles serveis d'integració contínua, però tots tenen unes especificitats operatives molt similars entre si. Amb l'excepció de la memòria cau, cada servei fa la seva pròpia "bicicleta", de manera que tot és sempre diferent.

En algun lloc, com a Travis-CI, un parell de línies de codi i la memòria cau funcionen perfectament; en algun lloc, com a AppVeyor, només cal que especifiqueu la carpeta a la configuració; però en algun lloc cal crear claus úniques i intentar convèncer el sistema perquè us doni l'oportunitat de sobreescriure el fragment de la memòria cau. Per tant, si voleu configurar l'anàlisi de les sol·licituds d'extracció en un servei d'integració contínua que no s'ha comentat anteriorment, primer assegureu-vos que no tindreu problemes amb la memòria cau.

Gràcies per la vostra atenció. Si alguna cosa no funciona, no dubteu a escriure'ns a suport. Aconsellarem i ajudarem.

Anàlisi de commits i sol·licituds d'extracció a Travis CI, Buddy i AppVeyor mitjançant PVS-Studio

Si voleu compartir aquest article amb un públic de parla anglesa, utilitzeu l'enllaç de traducció: Maxim Zvyagintsev. Anàlisi de commits i sol·licituds d'extracció a Travis CI, Buddy i AppVeyor mitjançant PVS-Studio.

Font: www.habr.com

Afegeix comentari