Linux ve macOS'ta C ve C++ dilleri için PVS-Studio analizöründe, 7.04 sürümünden itibaren, belirtilen dosyaların listesini kontrol etmek için bir test seçeneği ortaya çıktı. Yeni modu kullanarak analizörü taahhütleri ve çekme isteklerini kontrol edecek şekilde yapılandırabilirsiniz. Bu makale, Travis CI, Buddy ve AppVeyor gibi popüler CI (Sürekli Entegrasyon) sistemlerinde bir GitHub projesinin değişen dosyalarının listesini kontrol etmeyi nasıl ayarlayacağınızı anlatacaktır.
Dosya listesi kontrol modu
Linux ve macOS için PVS-Studio 7.04 sürümünde, kaynak dosyaların listesini kontrol etmek için bir mod ortaya çıktı. Bu, derleme sistemi bir dosya oluşturmanıza izin veren projeler için işe yarar.
Ayrıca dosya listesi kontrol modu, derleyici başlatmalarının strace izleme günlüğü (pvs-studio-analyzer trace) ile birlikte kullanılabilir. Bunu yapmak için öncelikle projenin tam yapısını gerçekleştirmeniz ve analizcinin kontrol edilen tüm dosyaların derleme parametreleri hakkında eksiksiz bilgi toplaması için onu izlemeniz gerekir.
Bununla birlikte, bu seçeneğin önemli bir dezavantajı vardır - ya projeyi her çalıştırdığınızda tüm projenin tam yapı takibini yapmanız gerekecektir; bu da başlı başına bir taahhüdü hızlı bir şekilde kontrol etme fikriyle çelişir. Veya izleme sonucunun kendisini önbelleğe alırsanız, kaynak dosyaların bağımlılık yapısı izlemeden sonra değişirse (örneğin, kaynak dosyalardan birine yeni bir #include eklenirse) çözümleyicinin sonraki çalıştırmaları eksik olabilir.
Bu nedenle, taahhütleri veya çekme isteklerini kontrol etmek için izleme günlüğüyle birlikte dosya listesi kontrol modunun kullanılmasını önermiyoruz. Bir taahhüdü kontrol ederken artımlı bir derleme yapabilmeniz durumunda, modu kullanmayı düşünün
Analiz için kaynak dosyaların listesi bir metin dosyasına kaydedilir ve parametre kullanılarak analizciye iletilir -S:
pvs-studio-analyzer analyze ... -f build/compile_commands.json -S check-list.txt
Bu dosya, dosyalara giden göreceli veya mutlak yolları belirtir ve her yeni dosya, yeni bir satırda olmalıdır. Analiz için yalnızca dosya adlarının değil aynı zamanda çeşitli metinlerin de belirtilmesi kabul edilebilir. Analizci bunun bir dosya olmadığını görecek ve satırı görmezden gelecektir. Dosyalar manuel olarak belirtilirse, yorum yapmak için bu yararlı olabilir. Ancak genellikle CI'da analiz sırasında bir dosya listesi oluşturulur; örneğin bunlar bir taahhüt veya çekme isteğinden gelen dosyalar olabilir.
Artık bu modu kullanarak yeni kodu ana geliştirme dalına girmeden önce hızlı bir şekilde kontrol edebilirsiniz. Tarama sisteminin analizör uyarılarına yanıt vermesini sağlamak için yardımcı program plog-dönüştürücü bayrak eklendi --uyarıları belirtin:
plog-converter ... --indicate-warnings ... -o /path/to/report.tasks ...
Bu bayrakla, analizör raporunda uyarılar varsa dönüştürücü sıfırdan farklı bir kod döndürecektir. Dönüş kodunu kullanarak bir ön taahhüt kancasını, onaylamayı veya çekme isteğini engelleyebilirsiniz ve oluşturulan analizör raporu görüntülenebilir, paylaşılabilir veya e-postayla gönderilebilir.
Not. Bir dosya listesini ilk kez analiz etmeye başladığınızda, tüm proje analiz edilecektir çünkü analizcinin başlık dosyalarındaki proje kaynak dosyalarının bağımlılıklarını içeren bir dosya oluşturması gerekir. Bu, C ve C++ dosyalarını analiz etmenin bir özelliğidir. Gelecekte bağımlılık dosyası önbelleğe alınabilir ve analizör tarafından otomatik olarak güncellenecektir. Artımlı analiz modunu kullanmaya göre dosya listesi kontrol modunu kullanırken taahhütleri kontrol etmenin avantajı, nesne dosyalarını değil, yalnızca o dosyayı önbelleğe almanız gerekmesidir.
Çekme isteği analizinin genel ilkeleri
Projenin tamamını analiz etmek çok zaman alır, bu nedenle yalnızca belirli bir kısmını kontrol etmek mantıklıdır. Sorun, yeni dosyaları proje dosyalarının geri kalanından ayırmanız gerekmesidir.
İki dallı bir taahhüt ağacı örneğine bakalım:
Bu işlemin gerçekleştiğini hayal edelim A1 zaten test edilmiş oldukça büyük miktarda kod içerir. Biraz önce taahhütten bir dal oluşturduk A1 ve bazı dosyaları değiştirdim.
Tabii bunu sonradan fark ettiniz A1 iki taahhüt daha gerçekleşti, ancak bunlar aynı zamanda diğer şubelerin birleşmeleriydi çünkü taahhütte bulunmuyoruz usta. Ve şimdi zamanı geldi düzeltme hazır. Bu nedenle birleşme için bir çekme talebi ortaya çıktı B3 и A3.
Elbette birleşmelerinin tüm sonucunu kontrol etmek mümkün olurdu, ancak yalnızca birkaç dosya değiştirildiği için bu çok zaman alıcı ve haksız olurdu. Bu nedenle sadece değişenleri analiz etmek daha verimli olur.
Bunu yapmak için, master ile birleştirmek istediğimiz dalın HEAD'inde bulunan dallar arasındaki farkı elde ederiz:
git diff --name-only HEAD origin/$MERGE_BASE > .pvs-pr.list
$MERGE_BASE buna daha sonra ayrıntılı olarak bakacağız. Gerçek şu ki, her CI hizmeti veri tabanı hakkında birleştirme için gerekli bilgileri sağlamaz, bu nedenle her seferinde bu verileri elde etmek için yeni yollar bulmanız gerekir. Bu, aşağıda açıklanan web hizmetlerinin her birinde ayrıntılı olarak açıklanacaktır.
Böylece dallar arasındaki farkı veya daha doğrusu değiştirilen dosya adlarının bir listesini elde ettik. Şimdi dosyayı vermemiz gerekiyor .pvs-pr.list (yukarıdaki çıktıyı ona yönlendirdik) analizöre:
pvs-studio-analyzer analyze -j8
-o PVS-Studio.log
-S .pvs-pr.list
Analizden sonra günlük dosyasını (PVS-Studio.log) okunması kolay bir formata dönüştürmemiz gerekiyor:
plog-converter -t errorfile PVS-Studio.log --cerr -w
Bu komut içindeki hataları listeleyecektir.
Ancak şimdi yalnızca hataları görüntülemekle kalmayıp, aynı zamanda montaj ve test için servisimizi sorunların varlığı konusunda bilgilendirmemiz gerekiyor. Bu amaçla dönüştürücüye bir bayrak eklendi -W (--uyarıları belirtin). En az bir analizör uyarısı varsa yardımcı program dönüş kodu plog-dönüştürücü 2 olarak değişecek ve bu da CI hizmetine çekme isteği dosyalarındaki olası hataların varlığı hakkında bilgi verecektir.
Travis C.I.
Yapılandırma dosya olarak yapılır .travis.yml. Kolaylık sağlamak için, her şeyi dosyadan çağrılacak işlevlerle birlikte ayrı bir bash betiğine koymanızı tavsiye ederim. .travis.yml (bash betiği_adı.sh işlev_adı).
Gerekli kodu script'e ekleyeceğiz. darbeBu şekilde daha fazla işlevsellik elde edeceğiz. Kısımda kurmak şunu yazalım:
install:
- bash .travis.sh travis_install
Herhangi bir talimatınız varsa, bunları kısa çizgileri kaldırarak betiğe aktarabilirsiniz.
Dosyayı açalım .travis.sh ve analizör ayarını fonksiyona ekleyin 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
}
Şimdi bölüme ekleyelim senaryo analiz çalıştırın:
script:
- bash .travis.sh travis_script
Ve bash betiğinde:
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
}
Bu kodun projeyi derledikten sonra çalıştırılması gerekir; örneğin CMake üzerinde bir yapınız varsa:
travis_script() {
CMAKE_ARGS="-DCMAKE_EXPORT_COMPILE_COMMANDS=On ${CMAKE_ARGS}"
cmake $CMAKE_ARGS CMakeLists.txt
make -j8
}
Bu şekilde ortaya çıkacak:
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
}
Muhtemelen bu ortam değişkenlerini zaten fark etmişsinizdir $TRAVIS_PULL_REQUEST и $TRAVIS_BRANCH. Travis CI bunları bağımsız olarak beyan ediyor:
- $TRAVIS_PULL_REQUEST çekme isteği numarasını saklar veya yanlış, eğer bu normal bir şube ise;
- $TRAVIS_REPO_SLUG proje deposunun adını saklar.
Bu işlevin algoritması:
Travis CI dönüş kodlarına yanıt verir, dolayısıyla uyarıların varlığı hizmete taahhüdü hata içeriyor olarak işaretlemesini söyleyecektir.
Şimdi bu kod satırına daha yakından bakalım:
git diff --name-only origin/HEAD > .pvs-pr.list
Gerçek şu ki Travis CI, bir çekme isteğini analiz ederken şubeleri otomatik olarak birleştiriyor:
Bu nedenle analiz ediyoruz A4Ve B3->A3. Bu özelliğinden dolayı farkı hesaplamamız gerekiyor. A3, tam olarak şubenin tepesi olan köken.
Geriye önemli bir ayrıntı kaldı; başlık dosyalarının derlenmiş çeviri birimlerindeki (*.c, *.cc, *.cpp, vb.) bağımlılıklarını önbelleğe almak. Analizör, bir dosya listesini kontrol etme modunda ilk kez başlatıldığında bu bağımlılıkları hesaplar ve ardından bunları .PVS-Studio dizinine kaydeder. Travis CI klasörleri önbelleğe almanıza olanak tanır, böylece dizin verilerini kaydedeceğiz .PVS-Stüdyo/:
cache:
directories:
- .PVS-Studio/
Bu kodun dosyaya eklenmesi gerekiyor .travis.yml. Bu dizin, analizden sonra toplanan çeşitli verileri saklar; bu, sonraki dosya listesi analizi veya artımlı analiz çalıştırmalarını önemli ölçüde hızlandırır. Bu yapılmazsa, analizci aslında her seferinde tüm dosyaları analiz edecektir.
Buddy
Travis CI gibi,
Öncelikle montaj hattına yeni bir aksiyon eklememiz gerekiyor:
Projeyi oluşturmak için kullanılan derleyiciyi belirtelim. Bu eylemde yüklü olan liman işçisi konteynerine dikkat edin. Örneğin GCC için özel bir konteyner var:
Şimdi PVS-Studio'yu ve gerekli yardımcı programları yükleyelim:
Editöre aşağıdaki satırları ekleyelim:
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
Şimdi Çalıştır sekmesine (ilk simge) gidelim ve ilgili düzenleyici alanına aşağıdaki kodu ekleyelim:
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
Travs-CI ile ilgili bölümü okursanız bu kod size zaten tanıdık geliyor ancak artık yeni bir aşama var:
Gerçek şu ki, artık birleştirmenin sonucunu değil, çekme isteğinin yapıldığı şubenin HEAD'ini analiz ediyoruz:
Yani koşullu bir taahhütteyiz B3 ve farkı almamız gerekiyor 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
Belirlemek için A3 GitHub API'sini kullanalım:
https://api.github.com/repos/${USERNAME}/${REPO}/pulls/${PULL_REQUEST_ID}
Buddy'nin sağladığı aşağıdaki değişkenleri kullandık:
- $BUDDY_EXECUTION_PULL_REQEUST_NO — çekme isteği numarası;
- $BUDDY_REPO_SLUG — kullanıcı adı ve havuzun birleşimi (örneğin max/test).
Şimdi aşağıdaki butonu kullanarak değişiklikleri kaydedelim ve çekme isteğinin analizini etkinleştirelim:
Travis CI'dan farklı olarak belirtmemize gerek yok .pvs-studio Buddy sonraki başlatmalar için tüm dosyaları otomatik olarak önbelleğe aldığından önbellekleme için. Bu nedenle geriye kalan son şey, PVS-Studio kullanıcı adını ve şifresini Buddy'ye kaydetmektir. Değişiklikleri kaydettikten sonra Pipeline'a geri döneceğiz. Değişkenleri ayarlamaya ve PVS-Studio için kullanıcı adı ve anahtar eklemeye geçmemiz gerekiyor:
Bundan sonra yeni bir çekme isteğinin veya taahhüdün ortaya çıkması incelemeyi tetikleyecektir. Bir taahhütte hatalar varsa Buddy bunu çekme isteği sayfasında gösterecektir.
AppVeyor
AppVeyor'un kurulumu Buddy'ye benzer, çünkü her şey web arayüzünde gerçekleşir ve proje havuzuna bir *.yml dosyası eklemenize gerek yoktur.
Projeye genel bakışta Ayarlar sekmesine gidelim:
Bu sayfayı aşağı kaydıralım ve çekme isteklerini toplamak için önbellek tasarrufunu etkinleştirelim:
Şimdi montaj için görüntüyü ve gerekli ortam değişkenlerini belirttiğimiz Ortam sekmesine gidelim:
Önceki bölümleri okuduysanız, bu iki değişkene oldukça aşinasınızdır – PVS_KEY и PVS_USERNAME. Değilse, PVS-Studio analizörünün lisansını doğrulamanın gerekli olduğunu hatırlatmama izin verin. Bunları gelecekte Bash betiklerinde tekrar göreceğiz.
Aşağıdaki aynı sayfada önbelleğe alma klasörünü belirtiyoruz:
Bunu yapmazsak bir çift dosya yerine tüm projeyi analiz edeceğiz ancak çıktıyı belirtilen dosyalardan alacağız. Bu nedenle doğru dizin adının girilmesi önemlidir.
Şimdi betiğin test etme zamanı geldi. Testler sekmesini açın ve Komut Dosyası'nı seçin:
Bu forma aşağıdaki kodu yapıştırmanız gerekmektedir:
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
Kodun şu kısmına dikkat edelim:
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
pwd komutunun değerinin, bu varsayılan değeri saklaması gereken bir değişkene oldukça spesifik bir şekilde atanması ilk bakışta tuhaf görünebilir, ancak şimdi her şeyi açıklayacağım.
Analizörü AppVeyor'da kurarken analizörün son derece garip davranışıyla karşılaştım. Bir yandan her şey doğru çalıştı ama analiz başlamadı. /home/appveyor/projects/testcalc/ dizininde olduğumuzu fark etmek için çok zaman harcadım ve analizci /opt/appveyor/build-agent/ dizininde olduğumuzdan emin. Sonra $PWD değişkeninin biraz yalan söylediğini fark ettim. Bu nedenle analize başlamadan önce değerini manuel olarak güncelledim.
Ve sonra her şey eskisi gibi:
Şimdi aşağıdaki parçayı düşünün:
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"`
İçinde çekme talebinin bildirildiği dallar arasındaki farkı görüyoruz. Bunu yapmak için aşağıdaki ortam değişkenlerine ihtiyacımız var:
- $APPVEYOR_PULL_REQUEST_NUMBER — çekme isteği numarası;
- $APPVEYOR_REPO_NAME - kullanıcı adı ve proje deposu.
Sonuç
Elbette olası tüm sürekli entegrasyon hizmetlerini dikkate almadık, ancak hepsinin birbirine son derece benzer çalışma özellikleri var. Önbelleğe alma dışında her hizmet kendi "bisikletini" oluşturur, dolayısıyla her şey her zaman farklıdır.
Travis-CI'da olduğu gibi bir yerlerde birkaç satır kod ve önbelleğe alma kusursuz bir şekilde çalışıyor; AppVeyor'da olduğu gibi bir yerde, ayarlarda klasörü belirtmeniz yeterlidir; ancak bir yerde benzersiz anahtarlar oluşturmanız ve sistemi, önbelleğe alınmış parçanın üzerine yazma fırsatı vermesi için ikna etmeye çalışmanız gerekir. Bu nedenle yukarıda ele alınmayan bir sürekli entegrasyon hizmeti üzerinde çekme isteklerinin analizini kurmak istiyorsanız öncelikle önbellekleme konusunda sorun yaşamayacağınızdan emin olun.
İlginiz için teşekkür ederiz. Bir şeyler yolunda gitmezse, bize yazmaktan çekinmeyin.
Bu makaleyi İngilizce konuşan bir kitleyle paylaşmak istiyorsanız lütfen çeviri bağlantısını kullanın: Maxim Zvyagintsev.
Kaynak: habr.com