Analizo de komitaĵoj kaj tirpetoj en Travis CI, Buddy kaj AppVeyor uzante PVS-Studio

Analizo de komitaĵoj kaj tirpetoj en Travis CI, Buddy kaj AppVeyor uzante PVS-Studio
En la analizilo PVS-Studio por lingvoj C kaj C++ en Linukso kaj macOS, ekde la versio 7.04, aperis prova okazo por kontroli la liston de specifitaj dosieroj. Uzante la novan reĝimon, vi povas agordi la analizilon por kontroli komitaĵojn kaj tiri petojn. Ĉi tiu artikolo montros al vi kiel agordi projektan liston de dosieroj de GitHub en popularaj CI (Kontinua Integriĝo) sistemoj kiel Travis CI, Buddy kaj AppVeyor.

Dosiera listo kontrola reĝimo

PVS Studio estas ilo por detekti erarojn kaj eblajn vundeblecojn en la fontkodo de programoj skribitaj en C, C++, C# kaj Java. Funkcias sur 64-bitaj sistemoj en Vindozo, Linukso kaj macOS.

La versio de PVS-Studio 7.04 por Linukso kaj macOS havas reĝimon por kontroli la liston de fontdosieroj. Ĉi tio funkcias por projektoj, kies konstrusistemo permesas vin generi dosieron compile_commands.json. Necesas, ke la analizilo ĉerpi informojn pri la kompilo de la specifitaj dosieroj. Se via konstrusistemo ne subtenas generi compile_commands.json-dosieron, vi povas provi generi tian dosieron uzante la ilon. urso.

Ankaŭ, la reĝimo de kontrolado de la listo de dosieroj povas esti uzata kune kun la spuro de kompililoj (pvs-studio-analyzer trace). Por fari tion, vi unue devos plenumi plenan konstruon de la projekto kaj spuri ĝin, por ke la analizilo kolektu kompletajn informojn pri la kompilaj parametroj de ĉiuj kontrolitaj dosieroj.

Tamen, ĉi tiu opcio havas gravan malavantaĝon - vi aŭ devos plenumi plenan konstruspuron de la tuta projekto ĉe ĉiu lanĉo, kio en si mem kontraŭdiras la ideon de rapida kontrolo. Aŭ, se vi konservas la spuran rezulton mem, postaj lanĉoj de la analizilo povas montriĝi nekompletaj se la fontdosiera dependecstrukturo ŝanĝiĝas post spurado (ekzemple, nova #include estas aldonita al unu el la fontdosieroj).

Sekve, ni ne rekomendas uzi la dosierlistan kontrolreĝimon kun spurprotokolo por kontroli komitaĵojn aŭ tiri petojn. Se vi povas fari pliigan konstruon dum kontrolado de kompromiso, konsideru uzi la reĝimon pliiga analizo.

La listo de fontdosieroj por analizo estas konservita al tekstdosiero kaj transdonita al la analizilo uzante la parametron -S:

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

Ĉi tiu dosiero specifas relativajn aŭ absolutajn vojojn al dosieroj, kaj ĉiu nova dosiero devas esti sur nova linio. Estas permesate specifi ne nur la nomojn de dosieroj por analizo, sed ankaŭ diversaj tekstoj. La analizanto vidos, ke ĉi tio ne estas dosiero kaj ignoros la linion. Ĉi tio povas esti utila por komenti se dosieroj estas specifitaj permane. Tamen, ofte la listo de dosieroj estos generita dum CI-analizo, ekzemple dosieroj de kommit aŭ tirpeto.

Nun, uzante ĉi tiun reĝimon, vi povas rapide testi novan kodon antaŭ ol ĝi eniros la ĉefan evolubranĉon. Por ke la konfirmsistemo reagu al analizilo-avertoj, la utileco plog-konvertilo flago aldonita --indiki-avertoj:

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

Kun ĉi tiu flago, la konvertilo resendos ne-nulan kodon se estas avertoj en la analizilo-raporto. Uzante la revenkodon, vi povas bloki antaŭkomigan hokon, fari aŭ tirpeton, kaj montri la generitan analizilan raporton sur la ekrano, dividi ĝin aŭ sendi ĝin per poŝto.

Notu. La unuan fojon, kiam vi komencas analizi la liston de dosieroj, la tuta projekto estos analizita, ĉar la analizilo devas generi dosieron de dependecoj de la fontdosieroj de la projekto sur la kapdosieroj. Ĉi tio estas trajto de analizado de C kaj C++ dosieroj. Estonte, la dependeca dosiero povas esti konservita en kaŝmemoro kaj ĝi estos aŭtomate ĝisdatigita de la analizilo. La avantaĝo de kontrolado de kommits kiam uzanta dosierlistkontrolreĝimon super uzado de pliiga analiza reĝimo estas ke nur tiu dosiero devas esti kaŝmemorigita, ne la objektodosieroj.

Ĝeneralaj principoj de tirpeta analizo

La analizo de la tuta projekto prenas multan tempon, do havas sencon kontroli nur iun parton de ĝi. La problemo estas, ke vi devas apartigi la novajn dosierojn de la ceteraj projektdosieroj.

Konsideru ekzemplon de komita arbo kun du branĉoj:

Analizo de komitaĵoj kaj tirpetoj en Travis CI, Buddy kaj AppVeyor uzante PVS-Studio

Ni ŝajnigu, ke la kompromis A1 enhavas sufiĉe grandan kvanton da kodo, kiu jam estis kontrolita. Iom pli frue ni faris branĉon el la komito A1 kaj ŝanĝis kelkajn dosierojn.

Kompreneble, vi rimarkis tion poste A1 estis du pliaj komitaĵoj, sed ĉi tiuj ankaŭ estis kunfandaĵoj de aliaj branĉoj, ĉar ni ne eniras majstro. Kaj nun venis la tempo, kiam hotfix preta. Tial, tira peto aperis por la kunfando B3 и A3.

Kompreneble, eblus kontroli la tutan rezulton de ilia kunigo, sed tio estus tro longa kaj nepravigebla, ĉar nur kelkaj dosieroj estis ŝanĝitaj. Tial, estas pli efika analizi nur la ŝanĝitajn.

Por fari tion, ni ricevas la diferencon inter la branĉoj, estante en la KASTO de la branĉo de kiu ni volas kunfandi en majstron:

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

$MERGE_BASE ni konsideros detale poste. La fakto estas, ke ne ĉiu CI-servo provizas la necesajn informojn pri la bazo por la kunfando, do ĉiufoje vi devas elpensi novajn manierojn akiri ĉi tiujn datumojn. Ĉi tio estos detala sube en ĉiu el la retservoj priskribitaj.

Do, ni ricevis la diferencon inter la branĉoj, aŭ pli ĝuste, la liston de dosiernomoj kiuj estis ŝanĝitaj. Nun ni devas doni la dosieron .pvs-pr.listo (ni redirektis la eligon supre al ĝi) al la analizilo:

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

Post analizo, ni devas konverti la protokoldosieron (PVS-Studio.log) al legebla formato:

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

Ĉi tiu komando listigos la erarojn en stderr (Norma erara eligofluo).

Nur ĉi tie ni bezonas ne nur montri erarojn, sed ankaŭ informi nian servon por muntado kaj testado pri la ĉeesto de problemoj. Por tio, flago estis aldonita al la konvertilo -W (--indiki-avertoj). Se estas almenaŭ unu averto de analizilo, la revenkodo de la utileco plog-konvertilo ŝanĝos al 2, kiu siavice sciigos la CI-servon, ke ekzistas eblaj eraroj en la tiraj petaj dosieroj.

Travis C.I.

La agordo estas farita en formo de dosiero .travis.yml. Por komforto, mi konsilas al vi meti ĉion en apartan bash-skripton kun funkcioj, kiuj estos nomitaj el la dosiero. .travis.yml (bash scriptname.sh funkcio_nomo).

Ni aldonos la necesan kodon al la skripto sur bash, do ni ricevas pli da funkcieco. En sekcio instali ni skribu la jenon:

install:
  - bash .travis.sh travis_install

Se vi havis iujn instrukciojn, vi povas movi ilin al la skripto forigante la streketojn.

Ni malfermu la dosieron .travis.sh kaj aldonu la analizilon al la funkcio 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 
}

Nun ni aldonu al la sekcio skripto realigu analizon:

script:
  - bash .travis.sh travis_script

Kaj en bash-skripto:

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
}

Ĉi tiu kodo devas esti rulita post kiam la projekto estas konstruita, ekzemple, se vi havis CMake-konstruaĵon:

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

Ĝi rezultos tiel:

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
}

Vi verŝajne jam rimarkis la specifitajn mediovariablojn. $TRAVIS_PULL_REQUEST и $TRAVIS_BRANCH. Travis CI deklaras ilin memstare:

  • $TRAVIS_PULL_REQUEST konservas la tiran peton-numeron, aŭ falsase ĝi estas normala branĉo;
  • $TRAVIS_REPO_SLUG konservas la nomon de la projekta deponejo.

La algoritmo de ĉi tiu funkcio:

Analizo de komitaĵoj kaj tirpetoj en Travis CI, Buddy kaj AppVeyor uzante PVS-Studio
Travis CI respondas al revenkodoj, do la ĉeesto de avertoj diros al la servo marki la kommit kiel bug.

Ni rigardu pli detale ĉi tiun linion de kodo:

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

La fakto estas, ke Travis CI aŭtomate kunfandas branĉojn dum la analizo de tirpeto:

Analizo de komitaĵoj kaj tirpetoj en Travis CI, Buddy kaj AppVeyor uzante PVS-Studio
Tial ni analizas A4kaj ne B3->A3. Pro ĉi tiu funkcio, ni devas kalkuli la diferencon de А3, kiu estas nur la supro de la branĉo de Origino.

Unu grava detalo restas - konservado de la dependecoj de kapdosieroj sur kompilitaj tradukunuoj (*.c, *.cc, *.cpp, ktp.). La analizilo kalkulas ĉi tiujn dependecojn ĉe la unua komenco en la reĝimo de kontrolado de la listo de dosieroj kaj poste konservas ilin en la dosierujo .PVS-Studio. Travis CI permesas vin konservi dosierujojn, do ni konservos dosierujojn .PVS-Studio/:

cache:
  directories:
    - .PVS-Studio/

Ĉi tiu kodo devas esti aldonita al la dosiero .travis.yml. Ĉi tiu dosierujo konservas diversajn datumojn kolektitajn post analizo, kio signife akcelos postajn kurojn de dosierlista analizo aŭ pliiga analizo. Se ĉi tio ne estas farita, tiam la analizilo efektive analizos ĉiujn dosierojn ĉiufoje.

Amiko

Kiel Travis C.I., Amiko provizas la kapablon aŭtomate konstrui kaj testi projektojn, kiuj estas konservitaj en GitHub. Male al Travis CI, ĝi estas agordita en la retinterfaco (bash-subteno disponeblas), do ne necesas stoki agordajn dosierojn en la projekto.

Antaŭ ĉio, ni devas aldoni novan agon al la konstrulinio:

Analizo de komitaĵoj kaj tirpetoj en Travis CI, Buddy kaj AppVeyor uzante PVS-Studio
Indiku la kompililon, kiu estis uzata por konstrui la projekton. Rimarku la docker-ujon instalitan en ĉi tiu agado. Ekzemple, ekzistas speciala ujo por GCC:

Analizo de komitaĵoj kaj tirpetoj en Travis CI, Buddy kaj AppVeyor uzante PVS-Studio
Nun ni instalu PVS-Studio kaj la necesajn ilojn:

Analizo de komitaĵoj kaj tirpetoj en Travis CI, Buddy kaj AppVeyor uzante PVS-Studio
Aldonu la sekvajn liniojn al la redaktilo:

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

Nun ni iru al la langeto Run (la unua ikono) kaj aldonu la sekvan kodon al la responda redaktilo-kampo:

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 vi legis la sekcion pri Travs-CI, tiam ĉi tiu kodo jam estas konata al vi, tamen nun estas nova paŝo:

Analizo de komitaĵoj kaj tirpetoj en Travis CI, Buddy kaj AppVeyor uzante PVS-Studio
La fakto estas, ke nun ni analizas ne la rezulton de la kunfandiĝo, sed la ĈEFON de la branĉo, el kiu oni faras la tiri peton:

Analizo de komitaĵoj kaj tirpetoj en Travis CI, Buddy kaj AppVeyor uzante PVS-Studio
Do ni estas en kondiĉa transdono B3 kaj ni devas akiri la diferencon de 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

Por determini A3 Ni uzu la GitHub API:

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

Ni uzis la sekvajn variablojn provizitajn de Buddy:

  • $BUDDY_EXECUTION_PULL_REQEUST_NO - tiri peton numeron;
  • $BUDDY_REPO_SLUG - kombinaĵo de uzantnomo kaj deponejo (ekzemple max/test).

Nun ni konservu la ŝanĝojn uzante la suban butonon, kaj ebligu tiran peton-analizon:

Analizo de komitaĵoj kaj tirpetoj en Travis CI, Buddy kaj AppVeyor uzante PVS-Studio
Male al Travis CI, ni ne bezonas specifi .pvs-studio por kaŝmemoro, ĉar Buddy aŭtomate konservas ĉiujn dosierojn por postaj lanĉoj. Tial, la lasta afero restas konservi la ensaluton kaj pasvorton por PVS-Studio en Buddy. Post konservado de la ŝanĝoj, ni revenos al la Dukto. Ni devas iri al agordo de variabloj kaj aldoni ensaluton kaj ŝlosilon por PVS-Studio:

Analizo de komitaĵoj kaj tirpetoj en Travis CI, Buddy kaj AppVeyor uzante PVS-Studio
Post tio, la apero de nova tira peto aŭ transdono ekigos kontrolon. Se transdono enhavas erarojn, tiam Buddy montros ĝin sur la retpetopaĝo.

AppVeyor

Agordi AppVeyor similas al Buddy, ĉar ĉio okazas en la retinterfaco kaj ne necesas aldoni *.yml-dosieron al la projekta deponejo.

Ni iru al la langeto Agordoj en la superrigardo de la projekto:

Analizo de komitaĵoj kaj tirpetoj en Travis CI, Buddy kaj AppVeyor uzante PVS-Studio
Ni rulumu malsupren ĉi tiun paĝon kaj ebligu kaŝmemorkonservadon por konstrui tirpetojn:

Analizo de komitaĵoj kaj tirpetoj en Travis CI, Buddy kaj AppVeyor uzante PVS-Studio
Nun ni iru al la langeto Medio, kie ni specifas la bildon por konstrui kaj la necesajn mediajn variablojn:

Analizo de komitaĵoj kaj tirpetoj en Travis CI, Buddy kaj AppVeyor uzante PVS-Studio
Se vi legis la antaŭajn sekciojn, vi tre konas ĉi tiujn du variablojn − PVS_KEY и PVS_USERNAME. Se ne, tiam mi memorigu al vi, ke ili estas necesaj por kontroli la permesilon de la analizilo PVS-Studio. En la estonteco, ni renkontos ilin denove en Bash-skriptoj.

Sur la sama paĝo sube, specifu la dosierujon por kaŝmemoro:

Analizo de komitaĵoj kaj tirpetoj en Travis CI, Buddy kaj AppVeyor uzante PVS-Studio
Se ni ne faros tion, tiam ni analizos la tutan projekton anstataŭ kelkaj dosieroj, sed ni ricevos la eligon bazitan sur la specifitaj dosieroj. Tial gravas enigi la ĝustan dosierujon.

Nun estas tempo por la skripto testi. Malfermu la langeton Testoj kaj elektu Skripton:

Analizo de komitaĵoj kaj tirpetoj en Travis CI, Buddy kaj AppVeyor uzante PVS-Studio
Algluu la sekvan kodon en ĉi tiun formon:

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

Ni rigardu la sekvan parton de la kodo:

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

La sufiĉe specifa atribuo de la valoro de la komando pwd al variablo, kiu devus konservi ĉi tiun defaŭltan valoron, ŝajnas stranga unuavide, tamen mi klarigos ĉion en momento.

Agordante la analizilon en AppVeyor, mi renkontis ekstreme strangan konduton de la analizilo. Unuflanke ĉio funkciis ĝuste, sed la analizo ne komenciĝis. Mi pasigis multe da tempo rimarkante, ke ni estas en la dosierujo /home/appveyor/projects/testcalc/, kaj la analizilo certas, ke ni estas en /opt/appveyor/build-agent/. Tiam mi rimarkis, ke la variablo $PWD estas iom mensoga. Tial mi permane ĝisdatigis ĝian valoron antaŭ ol komenci la analizon.

Kaj poste ĉio, kiel antaŭe:

Analizo de komitaĵoj kaj tirpetoj en Travis CI, Buddy kaj AppVeyor uzante PVS-Studio
Nun konsideru la sekvan fragmenton:

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 ĝi, ni ricevas la diferencon inter la branĉoj sur kiuj la tirpeto estas deklarita. Por tio ni bezonas la sekvajn mediajn variablojn:

  • $APPVEYOR_PULL_REQUEST_NUMBER - tiri peton numeron;
  • $APPVEYOR_REPO_NAME - uzantnomo kaj projekt-deponejo.

konkludo

Kompreneble, ni ne konsideris ĉiujn eblajn kontinuajn integrigajn servojn, tamen ili ĉiuj havas tre similajn laborspecifojn. Krom kaŝmemoro, ĉiu servo faras sian propran "biciklon", do ĉio estas ĉiam malsama.

Ie, kiel en Travis-CI, kelkaj linioj de kodo kaj kaŝmemoro funkcias senmanke; ie, kiel en AppVeyor, vi nur bezonas specifi la dosierujon en la agordoj; sed ie vi devas krei unikajn ŝlosilojn kaj provi konvinki la sistemon doni al vi la ŝancon anstataŭigi la kaŝmemoritan fragmenton. Sekve, se vi volas agordi tiran petan analizon pri kontinua integriga servo, kiu ne estis diskutita supre, tiam unue certigu, ke vi ne havos problemojn kun kaŝmemoro.

Dankon pro via atento. Se io ne funkcias, bonvolu skribi al ni ĉe subteno. Ni konsilos kaj helpos.

Analizo de komitaĵoj kaj tirpetoj en Travis CI, Buddy kaj AppVeyor uzante PVS-Studio

Se vi volas dividi ĉi tiun artikolon kun anglalingva publiko, bonvolu uzi la tradukan ligilon: Maxim Zvyagintsev. Analizo de komitaĵoj kaj tirpetoj en Travis CI, Buddy kaj AppVeyor uzante PVS-Studio.

fonto: www.habr.com

Aldoni komenton