Інтэграцыя праекту VueJS+TS з SonarQube

У сваёй працы мы актыўна выкарыстоўваем платформу SonarQube для падтрымання якасці кода на высокім узроўні. Пры інтэграцыі аднаго з праектаў, напісаным на VueJs+Typescript, узніклі праблемы. Таму хацеў бы расказаць падрабязней аб тым, як удалося іх вырашыць.

Інтэграцыя праекту VueJS+TS з SonarQube

У дадзеным артыкуле прамова пайдзе, як пісаў вышэй, аб платформе SonarQube. Трохі тэорыі - што гэта такое наогул, для тых, хто чуе пра яе ўпершыню:

SonarQube (былы сонар) — платформа з адкрытым зыходным кодам для бесперапыннага аналізу (ангел. continuous inspection) і вымярэння якасці кода.
Падтрымлівае аналіз кода і пошук памылак паводле правіл стандартаў праграмавання MISRA C, MISRA C++, MITRE/CWE і CERT Secure Coding Standards. А таксама ўмее распазнаваць памылкі са спісаў OWASP Топ-10 і CWE/SANS Топ-25 памылак праграмавання.
Нягледзячы на ​​тое, што платформа выкарыстоўвае розныя гатовыя прылады, SonarQube зводзіць вынікі да адзінай інфармацыйнай панэлі (ангел. dashboard), вядучы гісторыю прагонаў і дазваляючы тым самым убачыць агульную тэндэнцыю змены якасці праграмнага забеспячэння падчас распрацоўкі.

Больш падрабязна можна даведацца на афіцыйным сайце

Падтрымліваецца вялікая колькасць моў праграмавання. Мяркуючы па інфармацыі са спасылкі вышэй - гэта больш за 25 моў. Для падтрымкі канкрэтнай мовы неабходна ўсталяваць адпаведную ўбудову. У community-версію ўваходзіць убудова для працы з Javascript (у тым ліку typesсript), хаця ў wiki напісана адваротнае. За Javascript адказвае плягін SonarJS, за Typescript SonarTS адпаведна.

Для адпраўкі інфармацыі аб пакрыцці выкарыстоўваецца афіцыйны кліент sonarqube-scanner, які, выкарыстоўваючы налады з конфіг-файла, адпраўляе гэтыя дадзеныя на сервер SonarQube для далейшай кансалідацыі і агрэгавання.

Для Javascript ёсць npm-акрутка. Такім чынам, пачынаем пакрокавае ўкараненне SonarQube в Ую-праект, які выкарыстоўвае Машынапіс.

Для разгортвання сервера SonarQube скарыстаемся докер-Compose.

sonar.yaml:

version: '1'
    services:
        simplesample-sonar:
            image: sonarqube:lts
            ports:
                - 9001:9000
                - 9092:9092
            network_mode: bridge

запуск:

docker-compose -f sonar.yml up

Пасля гэтага SonarQube будзе даступны па адрасе – http://localhost:9001 .

Інтэграцыя праекту VueJS+TS з SonarQube
Пакуль у ім няма праектаў, і гэта справядліва. Будзем выпраўляць дадзеную сітуацыю. За аснову я ўзяў афіцыйны праект-прыклад для VueJS+TS+Jest. Схілюем яго да сябе:

git clone https://github.com/vuejs/vue-test-utils-typescript-example.git

Спачатку нам трэба ўсталяваць кліент SonarQube, які называецца sonar-scanner, для НПМ ёсць абгортка:

yarn add sonarqube-scanner

І адразу ж дадамо каманду ў скрыпты для працы з ім.

package.json:

{
 … 
   scripts: {
      ...
      "sonar": "sonar-scanner"
      ...
   },
 …
}

Далей, для працы сканара, трэба задаць налады праекта ў спецыяльным файле. Пачнём з базавых.

sonar-project.properties:

sonar.host.url=http://localhost:9001

sonar.projectKey=test-project-vuejs-ts
sonar.projectName=Test Application (VueJS+TS)

sonar.sources=src
# sonar.tests=
sonar.test.inclusions=src/**/*tests*/**
sonar.sourceEncoding=UTF-8

  • sonar.host.url - адрас сонар'а;
  • sonar.projectKey - унікальны ідэнтыфікатар праекта на серверы сонар'а;
  • sonar.projectName – яго найменне, яно можа быць зменена ў любы момант, бо ідэнтыфікацыя праекта робіцца па projectKey;
  • sonar.sources – тэчка з зыходнікамі, звычайна гэта SRC, Але можа быць любым. Гэтая тэчка задаецца адносна рутовой тэчкі, якой з'яўляецца тэчка адкуль запушчаны сканер;
  • sonar.tests - Параметр, які ідзе ў пары з папярэднім. Гэта тэчка, дзе знаходзяцца тэсты. У дадзеным праекце, няма такой тэчкі, а тэст знаходзіцца побач з тэстоўваным кампанентам у тэчцы 'тэст', таму мы яго пакуль праігнаруемы і скарыстаемся наступным параметрам;
  • sonar.test.inclusions - шлях для тэстаў з выкарыстаннем маскі, можа быць некалькі элементаў пералічаных праз коску;
  • sonar.sourceEncoding - кадоўка для зыходных файлаў.

Для першага запуску сканара ўсё гатова, акрамя асноўнага папярэдняга дзеяння: запуск самага тэставага рухавічка, для фармавання ім інфармацыі аб пакрыцці, якую і будзе ў наступстве выкарыстаць сканер.

Але для гэтага трэба наладзіць тэставы рухавічок на фармаванне дадзенай інфармацыі. У дадзеным праекце тэставы рухавічок - гэта ёсць. І яго налады знаходзяцца ў адпаведным раздзеле файла package.json.

Дадамо гэтыя наладкі:

"collectCoverage": true,
"collectCoverageFrom": [
      "src/**/*",
      "!src/main.ts",
      "!src/App.vue",
      "!src/**/*.d.*",
      "!src/**/*__tests__*"
],

Гэта значыць задаем сам сцяг неабходнасці вылічэння пакрыцця і крыніца (разам з выключэннямі), на аснове якіх яно будзе фармавацца.

Цяпер запусцім тэст:

yarn test

Убачым наступнае:

Інтэграцыя праекту VueJS+TS з SonarQube

Чыннік у тым, што ў самім кампаненце, як такога, кода няма. Выправім гэта.

HelloWorld.vue:

...
methods: {
    calc(n) {
      return n + 1;
    }
  },
mounted() {
  this.msg1 = this.msg + this.calc(1);
},
...

Гэтага будзе дастаткова для разліку пакрыцця.

Пасля перазапуску цеста пераканаемся ў гэтым:

Інтэграцыя праекту VueJS+TS з SonarQube

На экране мы павінны ўбачыць інфармацыю аб пакрыцці, а ў тэчцы праекта будзе створана тэчка ахоп з інфармацыяй аб пакрыцці тэстамі ва ўніверсальным фармаце LCOV (LTP GCOV extension).

Gcov - вольна распаўсюджваная ўтыліта для даследавання пакрыцця кода. Gcov генеруе дакладную колькасць выкананняў для кожнага аператара ў праграме і дазваляе дадаць анатацыі да зыходнага кода. Gcov пастаўляецца як стандартная ўтыліта ў складзе пакета GCC.
Lcov - графічны інтэрфейс для gcov. Ён збірае файлы gcov для некалькіх файлаў з зыходнікамі і стварае камплект HTML старонак з кодам і звесткамі аб пакрыцці. Таксама генеруюцца старонкі для спрашчэння навігацыі. Lcov падтрымлівае пакрыццё радкоў, функцый, галінаванняў.

Пасля выканання тэстаў інфармацыя аб пакрыцці будзе знаходзіцца ў coverage/lcov.info.
Нам трэба сказаць сонарАдкуль яе ўзяць. Таму дадамо наступныя радкі ў яго файл канфігурацыі. Але ёсць адзін момант: праекты могуць быць мультымоўныя, гэта значыць у тэчцы SRC знаходзяцца зыходнікі для некалькіх моў праграмавання і прыналежнасць да таго ці іншага, і ў сваю чаргу выкарыстанне той ці іншай убудовы, вызначаецца па ім пашырэнню. І інфармацыя аб пакрыцці можа захоўваецца ў розных месцах для розных моў праграмавання, таму для кожнага ЯП ёсць свой раздзел для наладкі гэтага. У нас праект выкарыстоўвае Машынапіс, таму нам неабходны падзел налад менавіта для яго:

sonar-project.properties:

sonar.typescript.coveragePlugin=lcov
sonar.typescript.lcov.reportPaths=coverage/lcov.info

Усё гатова да першага запуску сканара. Жадаю заўважыць, што праект у сонар'е ствараецца аўтаматычна пры першым запуску сканара для дадзенага праекту. У наступныя разы інфармацыя ўжо будзе акумулявацца, каб бачыць дынаміку змены параметраў праекту ў часе.

Такім чынам, скарыстаемся камандай, створанай раней у package.json:

yarn run sonar 

Заўвага: можна таксама скарыстацца параметрам -X для больш дэталёвага лагіравання.

Калі запуск сканара быў упершыню, то спачатку запампуецца бінарнік самога сканара. Пасля гэтага ён запускаецца і пачынае сканаваць сервер сонарТа на прадмет усталяваных убудоў, вылічаючы тым самым падтрымоўваныя ЯП. Таксама загружаюцца іншыя розныя параметры для яго працы: quality profiles, active rules, metrics repository, server rules.

Інтэграцыя праекту VueJS+TS з SonarQube

Інтэграцыя праекту VueJS+TS з SonarQube

Заўвага: падрабязна на іх мы спыняцца не будзем у рамках дадзенага артыкула, але заўсёды можна звярнуцца ў афіцыйныя крыніцы.

Далей пачынаецца аналіз тэчкі SRC на прадмет наяўнасці зыходных файлаў для ўсіх (калі не зададзены відавочна нейкі пэўны) падтрымоўваных ЯП, з наступнай іх індэксацыяй.

Інтэграцыя праекту VueJS+TS з SonarQube

Далей ідуць іншыя розныя аналізы, на якіх мы не завастраем увагу ў дадзеным артыкуле (напрыклад, такія як: лінтынг, вызначэнне дублявання кода і тд).

У самым канцы працы сканара адбываецца агрэгаванне ўсёй сабранай інфармацыі, архіваванне і адпраўка яе на сервер.

Пасля гэтага мы можам ужо паглядзець што атрымалася ў вэб-інтэрфейсе:

Інтэграцыя праекту VueJS+TS з SonarQube

Як бачым, нешта атрымалася, і нават паказвае нейкае пакрыццё, але яно не адпавядае нашаму ёсць-справаздачы.

Давайце разбірацца. Паглядзім на праект больш дэталёва, клікнем па значэнні пакрыцця, і "правалімся" у дэталізаваную справаздачу па файлах:

Інтэграцыя праекту VueJS+TS з SonarQube

Тут мы бачым акрамя асноўнага, доследнага файла HelloWorld.vue, прысутнічае і файл асноўны.ц, Які і псуе ўсю карціну пакрыцця. Але як жа так, мы яго выключалі з разліку пакрыцця. Так, усё правільна, але гэта было на ўзроўні ёсць, Але сканер яго праіндэксаваў, таму ён патрапіў у яго разлікі.

Давайце выправім гэта:

sonar-project.properties:

...
sonar.exclusions=src/main.ts
...

Жадаецца зрабіць удакладненне: апроч тых тэчак, якія зададзены ў дадзеным параметры, таксама дадаюцца ўсе тэчкі, пералічаныя ў параметры sonar.test.inclusions.

Пасля запуску сканара бачым ужо карэктную інфармацыю:

Інтэграцыя праекту VueJS+TS з SonarQube

Інтэграцыя праекту VueJS+TS з SonarQube

Разбярэм наступны момант - Quality profiles. Я казаў вышэй аб падтрымцы сонарТым некалькі ЯП адначасова. Вось гэта якраз мы і назіраем. Але мы ведаем, што праект у нас напісаны на TS, таму навошта напружваць сканер лішнімі маніпуляцыямі і праверкамі. Мова для аналізу зададзім праз даданне яшчэ аднаго параметра ў файл канфігурацыі. сонарТа:

sonar-project.properties:

...
sonar.language=ts
...

Зноў запусцім сканер і паглядзім вынік:

Інтэграцыя праекту VueJS+TS з SonarQube

Пакрыццё знікла зусім.

Калі паглядзім у лог сканара, то можам убачыць наступны радок:

Інтэграцыя праекту VueJS+TS з SonarQube

Гэта значыць, файлы нашага праекта проста не былі праіндэксаваныя.

Сітуацыя наступная: афіцыйна падтрымка VueJs ёсць у плагіне SonarJS, які адказвае за Javascript.

Інтэграцыя праекту VueJS+TS з SonarQube

Але гэтай падтрымкі няма ў плягіне SonarTS для TS, пра што заведзены афіцыйны тыкет у баг-трэкеры сонарТа:

  1. https://jira.sonarsource.com/browse/MMF-1441
  2. https://github.com/SonarSource/SonarJS/issues/1281

Вось некаторыя адказы аднаго з прадстаўнікоў з боку распрацоўшчыкаў SonarQube, які пацвярджае гэты факт.

Інтэграцыя праекту VueJS+TS з SonarQube

Інтэграцыя праекту VueJS+TS з SonarQube

Але ў нас жа ўсё працавала, запярэчыце Вы. Так, так і ёсць, давайце паспрабуем крыху "пахакерыць".
Калі ёсць падтрымка .vue-файлаў сонарТым, то давайце паспрабуем сказаць яму каб ён іх разглядаў як Машынапіс.

Дадамо параметр:

sonar-project.properties:

...
sonar.typescript.file.suffixes=.ts,.tsx,.vue
...

Запусцім сканер:

Інтэграцыя праекту VueJS+TS з SonarQube

І, вуаля, усё вярнулася на кругі свая, і з адным профілем толькі для Машынапіс. Гэта значыць удалося вырашыць праблему ў падтрымцы VueJs+TS для SonarQube.

Паспрабуем пайсці далей і крыху палепшым інфармацыю аб пакрыцці.

Што ж мы зрабілі цяпер:

  • дадалі ў праект сонар-сканер;
  • настроілі ёсць для фарміравання інфармацыі аб пакрыцці;
  • сканфігуравалі сонар-сканер;
  • вырашылі праблему падтрымкі .vue-файлаў + Машынапіс.

Акрамя пакрыцця тэстамі ёсць іншыя цікавыя карысныя крытэры якасці кода, напрыклад, дубліраванне кода і колькасць радкоў (удзельнічае ў разліку каэфіцыентаў, звязаных са складанасцю кода) праекта.

У бягучай рэалізацыі плагіна для працы з TS (SonarTS) не будзе працаваць CPD (Copy Paste Detector) і падлік радкоў кода .vue-файлаў.

Для стварэння сінтэтычнай сітуацыі па дубляванні кода, проста задублюем файл кампанента з іншым імем, таксама дадамо ў код асноўны.ц функцыю-пустышку і задублюем яго з іншым імем. Каб праверыць дубліраванне як у .vue, Так і ў .ts -файлах.

main.ts:

...
function name(params:string): void {
  console.log(params);
}
...

Для гэтага неабходна часова закаментаваць радок канфігурацыі:

sonar-project.properties:

...
sonar.exclusions=src/main.ts
...

Перазапусцім сканер разам з тэставаннем:

yarn test && yarn run sonar

У нас вядома ўпадзе пакрыццё, але зараз нам гэта не цікава.

У разрэзе дублявання радкоў кода ўбачым:

Інтэграцыя праекту VueJS+TS з SonarQube

Для праверкі скарыстаемся CPD-утылітай - jscpd:

npx jscpd src

Інтэграцыя праекту VueJS+TS з SonarQube

Для радкоў кода:

Інтэграцыя праекту VueJS+TS з SonarQube

Магчыма, гэта вырашыцца ў будучых версіях убудоў. SonarJS(TS). Хачу заўважыць, што яны паступова пачынаюць зліваць гэтыя два плагіны ў адзін SonarJS, Што, думаю, правільна.

Цяпер хацелася разгледзець варыянт паляпшэння інфармацыі аб пакрыцці.

Пакуль мы бачым пакрыццё тэстамі ў працэнтных адносінах, па ўсім праекце, і па файлах у прыватнасці. Але ёсць магчымасць пашырыць гэты паказчык інфармацыяй аб колькасці блок-тэстаў па праекце, а таксама ў разрэзе файлаў.

Ёсць бібліятэка, якая ўмее ёсць-рэпарт канвертаваць у фармат для сонарТа:
generic test data - https://docs.sonarqube.org/display/SONAR/Generic+Test+Data.

Усталюем гэтую бібліятэку да сябе ў праект:

yarn add jest-sonar-reporter

І дадамо яго ў канфігурацыю ёсць:

package.json:

…
"testResultsProcessor": "jest-sonar-reporter"
…

Цяпер выканаем тэст:

yarn test

Пасля чаго ў корані праекту будзе створаны файл test-report.xml.

Задзейнічаем яго ў канфігурацыі сонарТа:

sonar-project.properties:

…
sonar.testExecutionReportPaths=test-report.xml
…

І перазапусцім сканер:

yarn run sonar

Паглядзім, што змянілася ў інтэрфейсе сонарТа:

Інтэграцыя праекту VueJS+TS з SonarQube

І нічога не памянялася. Справа ў тым, што Sonar не разглядае файлы, апісаныя ў Jest-рэпарце, як файлы блок-тэстаў. Для таго, каб выправіць гэтую сітуацыю, задзейнічаем параметр канфігурацыі. сонар sonar.tests, у якім відавочна пакажам тэчкі з тэстамі (яна ў нас пакуль адна):

sonar-project.properties:

…
sonar.tests=src/components/__tests__
…

Перазапусцім сканер:

yarn run sonar

Паглядзім, што змянілася ў інтэрфейсе:

Інтэграцыя праекту VueJS+TS з SonarQube

Цяпер мы ўбачылі колькасць нашых блок-тэстаў і, праваліўшыся па кліку ўнутр, можам паглядзець размеркаванне гэтага ліку па файлах праекту:

Інтэграцыя праекту VueJS+TS з SonarQube

Заключэнне

Такім чынам, мы разгледзелі інструмент для бесперапыннага аналізу SonarQube. Паспяхова інтэгравалі ў яго праект, напісаны на VueJs+TS. Вырашылі некаторыя праблемы сумяшчальнасці. Павысілі інфарматыўнасць паказчыка аб пакрыцці тэстамі. У дадзеным артыкуле мы разгледзелі толькі адзін з крытэрыяў якасці кода (магчыма, адзін з асноўных), але SonarQube падтрымлівае і іншыя крытэры якасці, уключаючы тэсціраванне на бяспеку. Але не ўсе гэтыя магчымасці ў поўным аб'ёме даступныя ў супольнасць-версіі. Адна з цікавых і карысных магчымасцяў - гэта інтэграцыі SonarQube з рознымі сістэмамі кіравання рэпазітарамі кода, напрыклад, такія як GitLab і BitBucket. Каб не дапусціць merge pull(merge) requestТая ў асноўную галіну рэпазітара пры дэградацыі пакрыцця. Але гэта гісторыя ўжо зусім іншага артыкула.

PS: Усё, што апісана ў артыкуле ў выглядзе кода даступна ў маім форцы.

Толькі зарэгістраваныя карыстачы могуць удзельнічаць у апытанні. Увайдзіце, Калі ласка.

Ці карыстаецеся Вы платформу SonarQube:

  • 26,3%Так5

  • 15,8%Няма3

  • 15,8%Чуў пра дадзеную платформу і хачу выкарыстоўваць3

  • 10,5%Чуў пра дадзеную платформу і не хачу выкарыстоўваць2

  • 0,0%Выкарыстоўваю іншую платформу0

  • 31,6%Упершыню чую пра яе6

Прагаласавалі 19 карыстальнікаў. Устрымаліся 3 карыстальніка.

Крыніца: habr.com

Дадаць каментар