Hoʻohui ʻia ʻo VueJS+TS me SonarQube

Hoʻohana ikaika mākou i ka paepae i kā mākou hana kaniQube e mālama i ka maikaʻi code ma kahi kiʻekiʻe. I ka hoʻohui ʻana i kekahi o nā papahana i kākau ʻia ma VueJs+Typescript, ua ala mai na pilikia. No laila, makemake wau e haʻi aku iā ʻoe i nā kikoʻī hou aku pehea mākou i hoʻoponopono ai iā lākou.

Hoʻohui ʻia ʻo VueJS+TS me SonarQube

Ma kēia ʻatikala e kamaʻilio mākou, e like me kaʻu i kākau ai ma luna, e pili ana i ke kahua SonarQube. ʻO kahi manaʻo liʻiliʻi - he aha ia ma ka laulā, no ka poʻe e lohe nei no ka manawa mua:

kaniQube (mua Sonar) he kahua kumu hāmama no ka nānā mau ʻana a me ke ana ʻana i ka maikaʻi code.
Kākoʻo i ka nānā ʻana i nā code a me ka ʻike hewa e like me nā lula o ka MISRA C, MISRA C++, MITER/CWE a me CERT Secure Coding Standards. Hiki iā ia ke ʻike i nā hewa mai ka OWASP Top 10 a me CWE/SANS Top 25 papa inoa hewa papahana.
ʻOiai ka hoʻohana ʻana o ka paepae i nā mea hana like ʻole i hoʻomākaukau ʻia, hoʻemi ʻo SonarQube i nā hopena i kahi dashboard hoʻokahi, e mālama ana i ka mōʻaukala o nā holo a laila e ʻae iā ʻoe e ʻike i ke ʻano maʻamau o nā loli i ka maikaʻi o ka polokalamu i ka wā o ka hoʻomohala ʻana.

Hiki ke loaʻa nā kikoʻī hou aku ma kahua pūnaewele

Kākoʻo ʻia ka nui o nā ʻōlelo papahana. Ke noʻonoʻo ʻia e ka ʻike mai ka loulou ma luna, ʻoi aku kēia ma mua o 25 mau ʻōlelo. No ke kākoʻo ʻana i kahi ʻōlelo kikoʻī, pono ʻoe e hoʻokomo i ka plugin kūpono. Aia ka mana kaiaulu i kahi plugin no ka hana pū me pio ka (me nā typeсript), ʻoiai ke ʻōlelo nei ka wiki i ka ʻokoʻa. Mahope pio ka pane plugin SonarJS, no Typescript SonarTS ʻo kēlā me kēia.

Hoʻohana ʻia ka mea kūʻai kūhelu e hoʻouna i ka ʻike uhi sonarqube-scanner, ka mea, e hoʻohana ana i nā hoʻonohonoho mai hoʻonohonoho-file, hoʻouna i kēia ʻikepili i ke kikowaena kaniQube no ka hoʻohui hou a me ka hōʻuluʻulu.

no ka mea, pio ka ka mea npm wahī. No laila, e hoʻomaka kākou i ka hoʻokō ʻanuʻu kaniQube в ʻIke-hoʻohana papahana Palapalaʻano.

No ka hoʻolālā ʻana i ke kikowaena kaniQube e hoohana kakou pā · pili.

sonar.yaml:

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

Hoʻomaka:

docker-compose -f sonar.yml up

Ma hope o kēia kaniQube e loaʻa ma: http://localhost:9001 .

Hoʻohui ʻia ʻo VueJS+TS me SonarQube
ʻAʻohe papahana i loko i kēia manawa a ua kūpono kēlā. E hoʻoponopono mākou i kēia kūlana. Ua lawe au i ka papahana laʻana kūhelu no VueJS+TS+Jest. E kulou kakou ia kakou iho:

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

Pono mua mākou e hoʻokomo i ka mea kūʻai aku kaniQube, i kapaia sonar-scannerno npm aia kahi ʻōwili:

yarn add sonarqube-scanner

A hoʻohui koke i ke kauoha i Hō'olālā e hana me ia.

package.json:

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

A laila, no ka hana ʻana o ka scanner, pono ʻoe e hoʻonohonoho i nā hoʻonohonoho papahana i kahi faila kūikawā. E hoʻomaka kākou me nā kumu.

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 - helu wahi Sonar'A;
  • sonar.projectKey - mea hoʻomaopopo papahana kūikawā ma ke kikowaena Sonar'A;
  • sonar.projectName - kona inoa, hiki ke hoʻololi i kēlā me kēia manawa, no ka mea, ʻike ʻia ka papahana e projectKey;
  • sonar.sources - waihona me nā kumu, maʻamau kēia src, akā hiki i kekahi mea. Hoʻonohonoho ʻia kēia waihona e pili ana i ka waihona kumu, ʻo ia ka waihona kahi i hoʻokuʻu ʻia ai ka scanner;
  • sonar.hōʻoia - kahi ʻāpana e hele like me ka mea ma mua. ʻO kēia ka waihona kahi i loaʻa ai nā hoʻokolohua. Ma kēia papahana, ʻaʻohe waihona like, a aia ka hoʻāʻo ma ka ʻaoʻao o ka mea i hoʻāʻo ʻia ma ka waihona 'hōʻike', no laila e haʻalele mākou iā ia i kēia manawa a hoʻohana i ka ʻāpana aʻe;
  • sonar.test.inclusions - ala no nā hoʻāʻo e hoʻohana ana i kahi mask, aia kekahi mau mea i hoʻokaʻawale ʻia e nā koma;
  • sonar.sourceEncoding - hoʻopili no nā faila kumu.

No ka hoʻomaka mua ʻana o ka scanner, ua mākaukau nā mea a pau, koe wale nō ka hana nui ma mua: ka hoʻokuʻu ʻana i ka mīkini hoʻāʻo ponoʻī, i hiki iā ia ke hoʻopuka i ka ʻike e pili ana i ka uhi, e hoʻohana ai ka scanner ma hope.

Akā no ka hana ʻana i kēia, pono ʻoe e hoʻonohonoho i ka mīkini hoʻāʻo e hana i kēia ʻike. Ma kēia papahana, ʻo ka mīkini hoʻāʻo ʻO Jest. A aia kona mau hoʻonohonoho ma ka ʻāpana pili o ka faila pakete.json.

E hoʻohui i kēia mau hoʻonohonoho:

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

ʻO ia, hoʻonoho mākou i ka hae ponoʻī no ka pono e helu i ka uhi a me ke kumu (me nā ʻokoʻa) ma ke kumu e hoʻokumu ʻia ai.

I kēia manawa, e holo kāua i ka hoʻāʻo:

yarn test

E ʻike mākou i kēia mau mea:

Hoʻohui ʻia ʻo VueJS+TS me SonarQube

ʻO ke kumu ʻaʻohe code i loko o ka ʻāpana ponoʻī. E hoʻoponopono kākou i kēia.

HelloWorld.vue:

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

E lawa kēia no ka helu ʻana i ka uhi.

Ma hope o ka hoʻomaka hou ʻana i ka hoʻāʻo, e hōʻoia mākou i kēia:

Hoʻohui ʻia ʻo VueJS+TS me SonarQube

Ma ka ʻaoʻao e ʻike mākou i ka ʻike e pili ana i ka uhi, a e hana ʻia kahi waihona ma ka waihona papahana ʻaoʻao pale me ka ʻike hoʻopaʻa hoʻāʻo ma kahi ʻano āpau LCOV (LTP GCOV hoʻonui).

ʻO Gcov he mea hoʻohana manuahi no ka nānā ʻana i ka uhi code. Hoʻopuka ʻo Gcov i ka helu pololei o nā hoʻokō no kēlā me kēia ʻōlelo i loko o kahi papahana a hiki iā ʻoe ke hoʻohui i nā hōʻike i ke code kumu. Hele mai ʻo Gcov ma ke ʻano he hana maʻamau ma ke ʻano he ʻāpana o ka pūʻolo GCC.
Lcov - kiʻi paʻi kiʻi no gcov. Hoʻākoakoa ʻo ia i nā faila gcov no nā faila kumu he nui a hana i kahi pūʻulu o nā ʻaoʻao HTML me ka ʻike code a me ka uhi. Hoʻokumu ʻia nā ʻaoʻao i mea e maʻalahi ai ka hoʻokele. Kākoʻo ʻo Lcov i ka uhi ʻana o nā kaula, nā hana, a me nā lālā.

Ma hope o ka pau ʻana o nā hoʻāʻo, e loaʻa ka ʻike uhi i loko uhi/lcov.info.
Pono mākou e ʻōlelo SonarMai hea mai iaʻu? No laila, e hoʻohui i kēia mau laina i kāna faila hoʻonohonoho. Akā aia hoʻokahi wahi: hiki i nā papahana ke ʻōlelo he nui, ʻo ia hoʻi, i loko o ka waihona src aia nā code kumu no nā ʻōlelo papahana a me ka pili ʻana me kekahi a i ʻole, a ma ka huli ʻana, hoʻoholo ʻia ka hoʻohana ʻana i kahi plugin e kona hoʻonui. A hiki ke mālama ʻia ka ʻike uhi ma nā wahi like ʻole no nā ʻōlelo papahana like ʻole, no laila aia kēlā me kēia ʻōlelo i kāna ʻāpana ponoʻī no ka hoʻonohonoho ʻana i kēia. Hoʻohana kā mākou papahana Palapalaʻano, no laila pono mākou i kahi ʻāpana hoʻonohonoho no ia wale nō:

sonar-project.properties:

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

Ua mākaukau nā mea a pau no ka hoʻomaka mua ʻana o ka scanner. Makemake au e hoʻomaopopo ʻo ia ka papahana Sonar'E hana 'akomi 'ia i ka manawa mua e holo ai 'oe i ka scanner no kekahi papahana. I nā manawa aʻe, e hōʻiliʻili ʻia ka ʻike i mea e ʻike ai i ka dynamics o nā hoʻololi i nā ʻāpana papahana i ka manawa.

No laila, e hoʻohana kākou i ke kauoha i hana ʻia ma mua pakete.json:

yarn run sonar 

'Ōlelo Aʻo: Hiki iā ʻoe ke hoʻohana i ka ʻāpana -X no ka hoʻopaʻa inoa kikoʻī.

Inā hoʻomaka ka scanner no ka manawa mua, a laila e hoʻoiho mua ʻia ka binary o ka scanner ponoʻī. Ma hope o kēlā, hoʻomaka a hoʻomaka i ka nānā ʻana i ke kikowaena Sonar'a no nā plugins i hoʻokomo ʻia, no laila e helu ana i ka ʻōlelo i kākoʻo ʻia. Hoʻouka ʻia nā ʻāpana ʻē aʻe no kāna hana: nā ʻaoʻao kiʻekiʻe, nā lula hana, ka waihona metric, nā lula kikowaena.

Hoʻohui ʻia ʻo VueJS+TS me SonarQube

Hoʻohui ʻia ʻo VueJS+TS me SonarQube

'Ōlelo Aʻo: ʻAʻole mākou e kamaʻilio kikoʻī iā lākou i loko o ke ʻano o kēia ʻatikala, akā hiki iā ʻoe ke hoʻopili mau i nā kumu kumu.

A laila, hoʻomaka ka ʻikepili waihona src no ka loaʻa ʻana o nā faila kumu no nā mea a pau (inā ʻaʻole i kuhikuhi ʻia kahi kikoʻī) i kākoʻo ʻia i ka ʻōlelo, me kā lākou papa kuhikuhi hope.

Hoʻohui ʻia ʻo VueJS+TS me SonarQube

E hele mai ana nā ʻano loiloi ʻē aʻe, ʻaʻole mākou e noʻonoʻo i kēia ʻatikala (no ka laʻana, e like me ka linting, ka ʻike ʻana i ke kope kope, etc.).

I ka pau ʻana o ka hana a ka scanner, ʻohi ʻia nā ʻike a pau i hōʻiliʻili ʻia, mālama ʻia a hoʻouna ʻia i ke kikowaena.

Ma hope o kēia, hiki iā mākou ke ʻike i ka mea i hana ʻia ma ka ʻaoʻao pūnaewele:

Hoʻohui ʻia ʻo VueJS+TS me SonarQube

E like me kā mākou e ʻike ai, ua hana kekahi mea, a hōʻike pū i kekahi ʻano uhi, akā ʻaʻole like ia me kā mākou ʻO Jest-hōʻike.

E noʻonoʻo kākou. E nānā i ka papahana i nā kikoʻī hou aku, e kaomi i ka waiwai uhi, a "e hāʻule" i loko o kahi hōʻike kikoʻī kikoʻī:

Hoʻohui ʻia ʻo VueJS+TS me SonarQube

Maanei mākou e ʻike ai, ma waho aʻe o ka faila nui i nānā ʻia HelloWorld.vue, aia kekahi waihona main.ts, e hoʻopōʻino i ke kiʻi holoʻokoʻa o ka uhi. Akā, pehea mākou i kāpae ʻia mai ka helu ʻana o ka uhi. ʻAe, pololei nā mea a pau, akā aia ma ka pae ʻO Jest, akā ua kuhikuhi ʻia e ka scanner, no laila ua pau i kāna helu ʻana.

E hoʻoponopono kākou i kēia:

sonar-project.properties:

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

Makemake au e wehewehe: ma kahi o nā waihona i kuhikuhi ʻia i kēia ʻāpana, ua hoʻohui pū ʻia nā waihona āpau i helu ʻia ma ka ʻāpana. sonar.test.inclusions.

Ma hope o ka hoʻomaka ʻana i ka scanner, ʻike mākou i ka ʻike pololei:

Hoʻohui ʻia ʻo VueJS+TS me SonarQube

Hoʻohui ʻia ʻo VueJS+TS me SonarQube

E nānā kākou i ka helu aʻe - Nā moʻolelo maikaʻi. Ua kamaʻilio wau ma luna e pili ana i ke kākoʻo Sonaro kekahi mau 'ōlelo i ka manawa like. ʻO kēia ka mea a mākou e ʻike nei. Akā ʻike mākou ua kākau ʻia kā mākou papahana TS, no laila, no ke aha e hoʻopaʻa ai i ka scanner me nā manipulations pono ʻole a me nā loiloi. E hoʻonoho mākou i ka ʻōlelo no ka nānā ʻana ma ka hoʻohui ʻana i hoʻokahi ʻāpana i ka faila hoʻonohonoho Sonar'A:

sonar-project.properties:

...
sonar.language=ts
...

E holo hou i ka scanner a ʻike i ka hopena:

Hoʻohui ʻia ʻo VueJS+TS me SonarQube

Ua pau loa ka uhi ana.

Inā mākou e nānā i ka log scanner, hiki iā mākou ke ʻike i kēia laina:

Hoʻohui ʻia ʻo VueJS+TS me SonarQube

ʻO ia hoʻi, ʻaʻole i kuhikuhi ʻia kā mākou mau faila papahana.

Penei ke kūlana: kākoʻo kūhelu VueJs aia i loko o ka plugin SonarJSka mea nona ke kuleana pio ka.

Hoʻohui ʻia ʻo VueJS+TS me SonarQube

Akā ʻaʻole kēia kākoʻo i ka plugin SonarTS no ka mea, TS, kahi i wehe ʻia ai kahi tikiki kūhelu ma ka tracker bug Sonar'A:

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

Eia kekahi mau pane mai kekahi o nā ʻelele mai nā mea hoʻomohala SonarQube, e hōʻoia ana i kēia ʻoiaʻiʻo.

Hoʻohui ʻia ʻo VueJS+TS me SonarQube

Hoʻohui ʻia ʻo VueJS+TS me SonarQube

Akā ua hana nā mea a pau iā mākou, ke kūʻē nei ʻoe. ʻAe, e hoʻāʻo iki kāua “hack”.
Inā he kākoʻo .vue- nā waihona Sonar'Auē, a laila e ho'āʻo kākou e haʻi iā ia e noʻonoʻo iā lākou Palapalaʻano.

E hoʻohui i kahi ʻāpana:

sonar-project.properties:

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

E hoʻomaka kākou i ka scanner:

Hoʻohui ʻia ʻo VueJS+TS me SonarQube

A, voila, ua hoʻi nā mea a pau i ka mea maʻamau, a me hoʻokahi profile wale nō no Palapalaʻano. ʻO ia hoʻi, hiki iā mākou ke hoʻoponopono i ka pilikia ma ke kākoʻo VueJs+TS no ka mea, kaniQube.

E hoʻāʻo kākou e hele hou a hoʻomaikaʻi iki i ka ʻike uhi.

He aha kā mākou i hana ai i kēia manawa:

  • hoʻohui ʻia i ka papahana Sonar-mea nānā;
  • hoʻonoho ʻO Jest e hoʻopuka i ka ʻike pili;
  • hoʻonohonoho ʻia Sonar-mea nānā;
  • hoʻoponopono i ka pilikia kākoʻo .vue- nā waihona + Palapalaʻano.

Ma waho aʻe o ka uhi hoʻāʻo ʻana, aia kekahi mau ʻōlelo aʻoaʻo hoihoi no ka maikaʻi o ka code, no ka laʻana, ka hoʻololi code a me ka helu o nā laina (i komo i ka helu ʻana i nā coefficients pili i ka paʻakikī code) o ka papahana.

I ka hoʻokō o kēia manawa o ka plugin no ka hana ʻana me TS (SonarTS) ʻaʻole e hana CPD (Ka mea nānā i ka kope kope) a me ka helu ʻana i nā laina code .vue- nā waihona.

No ka hana ʻana i kahi kūlana synthetic o ka hoʻopili code, e kope wale i ka faila me kahi inoa ʻē aʻe a hoʻohui pū i ke code. main.ts he hana dummy a hoʻopālua iā ia me kahi inoa ʻē aʻe. No ka nānā ʻana i ka hana kope ʻana e like me .vue, a iloko .ts - nā waihona.

main.ts:

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

No ka hana ʻana i kēia, pono ʻoe e ʻōlelo i ka laina hoʻonohonoho no ka manawa pōkole:

sonar-project.properties:

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

E hoʻomaka hou i ka scanner me ka hoʻāʻo:

yarn test && yarn run sonar

ʻOiaʻiʻo, e hāʻule kā mākou uhi, akā i kēia manawa ʻaʻole mākou hoihoi i kēlā.

Ma ke ʻano o ke kope ʻana i nā laina code, e ʻike mākou:

Hoʻohui ʻia ʻo VueJS+TS me SonarQube

No ka nānā ʻana e hoʻohana mākou CPD-mea hoʻohana – jscpd:

npx jscpd src

Hoʻohui ʻia ʻo VueJS+TS me SonarQube

No nā laina code:

Hoʻohui ʻia ʻo VueJS+TS me SonarQube

E hoʻoholo ʻia paha kēia i nā mana plugin e hiki mai ana SonarJS(TS). Makemake wau e hoʻomaopopo e hoʻomaka mālie lākou e hoʻohui i kēia mau plugins ʻelua i hoʻokahi SonarJS, a'u i manao ai he pololei.

I kēia manawa makemake wau e noʻonoʻo i ke koho o ka hoʻomaikaʻi ʻana i ka ʻike uhi.

I kēia manawa hiki iā mākou ke ʻike i ka uhi hoʻāʻo ma nā ʻōlelo pākēneka no ka papahana holoʻokoʻa, a no nā faila. Akā hiki ke hoʻonui i kēia hōʻailona me ka ʻike e pili ana i ka nui Ho'okahi- nā ho'āʻo no ka papahana, a me ka pōʻaiapili o nā faila.

Aia kahi waihona e hiki ai ʻO Jest-e hoʻololi i ka hōʻike i ke ʻano no Sonar'A:
ʻikepili hoʻāʻo maʻamau - https://docs.sonarqube.org/display/SONAR/Generic+Test+Data.

E hoʻokomo i kēia waihona i kā mākou papahana:

yarn add jest-sonar-reporter

A hoʻohui i ka hoʻonohonoho ʻO Jest:

package.json:

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

I kēia manawa, e holo kāua i ka hoʻāʻo:

yarn test

A laila e hana ʻia kahi faila ma ke kumu o ka papahana hōʻike hōʻike.xml.

E hoʻohana kākou i ka hoʻonohonoho Sonar'A:

sonar-project.properties:

…
sonar.testExecutionReportPaths=test-report.xml
…

A hoʻomaka hou i ka scanner:

yarn run sonar

E ʻike kākou i ka mea i hoʻololi ʻia ma ka interface Sonar'A:

Hoʻohui ʻia ʻo VueJS+TS me SonarQube

ʻAʻohe mea i loli. ʻO ka ʻoiaʻiʻo ʻaʻole i noʻonoʻo ʻo Sonar i nā faila i wehewehe ʻia ma ka hōʻike Jest e like me nā faila Ho'okahi- nā ho'āʻo. No ka hoʻoponopono ʻana i kēia kūlana, hoʻohana mākou i ka hoʻonohonoho hoʻonohonoho Sonar sonar.hōʻoia, kahi e hōʻike maopopo ai mākou i nā waihona me nā hoʻāʻo (hoʻokahi wale nō mākou i kēia manawa):

sonar-project.properties:

…
sonar.tests=src/components/__tests__
…

E hoʻomaka hou i ka scanner:

yarn run sonar

E ʻike kākou i ka mea i hoʻololi ʻia ma ka interface:

Hoʻohui ʻia ʻo VueJS+TS me SonarQube

I kēia manawa ua ʻike mākou i ka helu o kā mākou Ho'okahi-tests a, i ka pau ʻole ʻana ma ke kaomi ʻana i loko, hiki iā mākou ke ʻike i ka hāʻawi ʻana o kēia helu ma waena o nā faila papahana:

Hoʻohui ʻia ʻo VueJS+TS me SonarQube

hopena

No laila, ua nānā mākou i kahi mea hana no ka nānā mau ʻana kaniQube. Ua hoʻohui maikaʻi mākou i kahi papahana i kākau ʻia i loko VueJs+TS. Hoʻoponopono i kekahi mau pilikia pili. Ua hoʻonui mākou i ka ʻike ʻike o ka hōʻailona uhi hōʻike. Ma kēia ʻatikala ua nānā mākou i hoʻokahi wale nō o nā pae hoʻohālike code code (ʻo ia paha kekahi o nā mea nui), akā kaniQube kākoʻo i nā pae hoʻohālikelike ʻē aʻe, me ka hoʻāʻo palekana. Akā ʻaʻole i loaʻa piha kēia mau hiʻohiʻona i loko kaiaulu-mau mana. ʻO kekahi o nā hiʻohiʻona hoihoi a pono hoʻi ka hoʻohui kaniQube me nā ʻōnaehana hoʻokele waihona code like ʻole, e like me GitLab a me BitBucket. E pale aku hui huki(merge) noi'a i ka lālā nui o ka waihona ke hoʻohaʻahaʻa ʻia ka uhi. Akā, he moʻolelo kēia no kahi ʻatikala ʻokoʻa loa.

PS: Loaʻa nā mea a pau i wehewehe ʻia ma ka ʻatikala ma ke ʻano code koʻu ʻōpuʻu.

Hiki i nā mea hoʻohana i hoʻopaʻa inoa ʻia ke komo i ka noiʻi. Eʻe, e 'oluʻolu.

Ke hoʻohana nei ʻoe i ke kahua SonarQube:

  • 26,3%ʻAe5

  • 15,8%ʻAʻole3

  • 15,8%Ua lohe au e pili ana i kēia kahua a makemake wau e hoʻohana i3

  • 10,5%Ua lohe au e pili ana i kēia kahua a ʻaʻole makemake e hoʻohana2

  • 0,0%Ke hoʻohana nei au i kahi paepae ʻokoʻa0

  • 31,6%ʻAkahi aʻu i lohe e pili ana iā ia6

19 mea hoʻohana i koho. Ua hōʻole nā ​​mea hoʻohana 3.

Source: www.habr.com

Pākuʻi i ka manaʻo hoʻopuka