Інтеграція PVS Studio в CI процес

Здравствуйте, шановні читачі.
Мене звати Стас, я інженер команди DevOps Tooling в компанії Align Technology.
У цій статті я спробую коротко розповісти про те, як у нашій компанії впровадили статичний аналіз коду на основі PVS-Studio.
Введення
Приблизно рік тому ми задумалися про те, щоб запровадити в нашій компанії статичний аналіз.
Ми і раніше використовували для цього різні засоби, в тому числі і для C/C + + проектів. Тому було цікаво спробувати новий інструмент для відомої задачі.
Інструмент, більш досконалий, ніж вбудований кошти VS, cpp-check, інтегрований в Sonar.
Як таке завжди відбувається, спочатку виникла ініціативна група розробників (з одного розробника, а його менеджер ідею в цілому підтримав).
Він прийшов до нашої команди і сказали, що хоче спробувати.
Ми зв'язалися з розробниками PVS студії, вони запропонували скористатися безкоштовної пробної версії.
Розробник перевірив код свого проекту і влаштував для колег-розробників презентацію, показавши, які помилки допомагає виявити PVS-Studio.
Причому на презентації було показано, що і у відносно новому коді зустрічаються серйозні помилки.
Презентація була дуже успішною, розробники сміялися над кодом колег і над своїм кодом.
Ряди этузиастов поповнилися, причому, що цінне, в тому числі і менеджерами.
Після цього менеджери (сумісний з этузиастами-розробниками) порахували ROI для впровадження цього продукту.
Як вони ROI вважали — на цей рахунок, можливо, буде окрема стаття.
Загалом, купили ми PVS-Studio.
І перед нашою командою поставити завдання впровадити статичний аналіз та виправлення помилок в процес розробки продукту.
Ось як ми цю задачу вирішили:
Процес
Процес усунення виявлених попереджень рухається ривками, в основному за рахунок ентузіастів.
Час від часу, коли хтось з ініціативних розробників знаходить час, він усуває якийсь один вид попереджень.
Це зручніше, тому що як правило, попередження легко усунути без зміни логіки коду, і тому підозрілі
ділянки коду можуть бути легко отрефакторены. Крім того, багато попередження усуваються за допомогою одного або декількох
більш або менш стандартних прийомів, так що усунення одного типу попереджень у всьому проекті продуктивніше,
ніж, наприклад, усунення всього розмаїття попереджень в окремому файлі.
Технічна реалізація
Для полегшення життя розробникам-этузиастам нами була проведена інтеграція PVS-аналізу в процес CI.
CI-сервером у нас служить Atlassian Bamboo, тому я буду використовувати його терміни при описі.
Нами були створені спеціальні складальні плани, автоматично запускаються за розкладом. За одним планом на кожен проект.
Цей план запускає через командний рядок standalone-перевірку головного проекту для актуальної версії коду.
Аналіз триває досить довго (2-4 години), тому таку перевірку ми виробляємо не частіше одного разу на день.
Після перевірки PVS-аналізатор генерує plog-файл — по суті xml з переліком знайдених попереджень.
Після цей файл трохи обробляється (замінюються абсолютні шляхи на відносні), а потім, за допомогою xslt-перетворення,
перетворюється в xUnit-звіт, який вміє розуміти і визуализовывать Bamboo.
Ми перетворюємо кожен тип попередження в один юніт-тест, з переліком всіх файлів, в яких це попередження знайдено.
Після першого запуску всі попередження відправляються в карантин (тобто білди будуть вважатися успішними у разі провалених тестів).
В той момент, коли розробник фиксит якийсь конкретний тип попередження, він випускає відповідний тест з карантину.
Таким чином, якщо раптом попередження, яке ми вважаємо виправленим у всьому проекті, раптом з'являється знову, ми отримуємо звалився білд
і вживаємо заходів.
Виглядає свежеобнаруженное попередження так:
Warning converted to test
Стандартно xUnit містить трирівневу ієрархію: TestSuite як об'єднання TestCase-ів. У TestCase міститься від 0 (якщо тест пройшов) до безлічі Failures. Ми транслюємо результати перевірки наступним чином.
  • Testsuite — це аналізатори в PVS-студії, наприклад «Problems related to code analyzer». Цей рівень не використовується на практиці для якихось цілей, можна було б звалити все TestCase в один TestSuite. Але ми припускаємо, що для деяких проектів частина перевірок не буде розглядатися, і цей рівень поділу стане в нагоді.
  • Testcase — це конкретні попередження, наприклад «Implicit type conversion N argument of function 'foo' to 32-bit type». Власне, це і є один тест з точки зору Bamboo. TestCase для будь-якого попередження є завжди, незалежно, виникає це попередження в нашому коді чи ні. Коли попередження в нашому коді не зустрічається — тест стає зеленим.
  • Failure — це файл і номер рядка, де конкретне попередження виявлено. Можна подивитися, де конкретно зустрічається і чи варто братися за виправлення цього типу ввечері в суботу. :-)
Складності
При інтеграції PVS-аналізатора в наш CI виникло кілька труднощів.
По-перше, труднощі з ліцензією. Нами була куплена site-ліцензія на 30 користувачів. Згідно з ліцензійною політикою, одна установка на конкретний екземпляр ОС «з'їдає» одну ліцензію.
Оскільки збірок і проектів у нас багато, то і складальних агентів теж пристойно — ми підходимо вже до ліміту в 100 агентів (зараз їх ~90). Звичайно, не всі з них використовуються для складання C++-коду, однак і таких машин у нас достатньо. Поставити на них на всіх PVS-студію ми не могли, довелося зробити кілька виділених під це агентів. У результаті, якщо в момент запуску аналізу ці виділені агенти зайняті, аналіз їх чекає звільнення і в результаті займає їх на тривалий час в першій половині робочого дня. З-за цього у нас health-check білди, стартуемые після кожного коміта, відчувають нестачу агентів. Крім того, може автоматичне розгортання агентів (доводиться весь час перераховувати використовувані ліцензії, що непросто в відсутність ліцензійної сервера).
По-друге, труднощі з отриманням довідника попереджень. Єдине місце, звідки їх можна отримати — це сайт розробників PVS-студії, розділ технічної документації. Однак зробити автоматичний аналізатор цієї сторінки нам поки не вдалося — верстка сторінки занадто незручна для правильного розбору і кожен раз трохи змінюється. Так і є деяка складність автоматичного централізованого оновлення версій PVS-студії на всіх агентів і довідника (це, звичайно, можна вирішити, але поки не дійшли руки). Так що оновлюємо поки руками.
Результат
Ось кілька прикладів знайдених помилок, тобто коли процес спрацював в новому коді.
  • V544. It is odd that the value 'X' of HRESULT type is compared with 'Y'
    • Minor issue: в цьому місці проблема стилю
      static HRESULT findSomething(const X& x);
      // later in the code
      if (findSomething(x) == -1)

  • V501: There are identical sub-expressions to the left and to the right of the 'foo' operator
    • Minor issue: невірний assert — no production impact
      assert(leftPoints.size() == leftPoints.size());

    • Major issue: баг
      if (upper && upper)
      return something;

    • Major issue: баг
      template < class T>
      void operator () ( const char* name, const T& t1, const T& t2 )
      { 
      if( t1 != t1 )
      {
      diff = true;
      }
      }

  • V674: The expression contains a suspicious mix of integer and real types.
    • Major issue: баг
      double precision = getSettingInt("Model", "Precision", 1e-6);

      · V655: The strings were concatenated but are not utilized. Consider inspecting the expression.
      switch (someEnum)
      {
      case someCondition:
      err + " is null ";
      break;

    V596: The object was created but it is not being used. The 'throw' keyword could be missing.
    • Minor issue: баг, який проявиться з невеликою ймовірністю
      if (open(...))
      {
      std::runtime_error("Can not open database");
      }


    V557: Array overrun is possible.
    • Major issue: баг
      float Jx[3];
      ...
      for (int i=0; i < 4; i++){
      for (int j=i; j < 4; j++){
      value += Jx[i]*Jx[j];
      }
      }




Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.