7. SonarQube

7.1. Sonar Family

  • SonarQube

  • SonarCloud

  • SonarLint

  • SonarScanner

7.2. Install

docker run -d --name sonarqube -p 9000:9000 -p 9092:9092 sonarqube

7.3. SonarScanner

7.3.1. Set-up

cd PROJECT_DIRECTORY
docker run --rm -d --name sonarqube -p 9000:9000 -v $(pwd):/src sonarqube
docker exec -u 0 -it sonarqube bash

    curl -sL https://deb.nodesource.com/setup_8.x -o /opt/node.sh
    bash /opt/node.sh
    apt install -y nodejs pylint python-coverage python-nose
    wget https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-3.3.0.1492.zip -O /opt/sonar-scanner.zip
    unzip -d /opt/ /opt/sonar-scanner.zip
    ln -s /opt/sonar-scanner-*/bin/sonar-scanner /usr/bin/sonar-scanner

7.3.2. Running

VERSION=$(git log -1 --format='%H')
nosetests --with-coverage --cover-erase --cover-xml --cover-inclusive --with-xunit --xunit-file=xunit.xml --cover-xml-file=coverage.xml
sonar-scanner -Dsonar.projectVersion=$VERSION -Dproject.settings=/src/sonar-python.properties

7.3.3. Python

## Sonar Server
sonar.host.url=http://localhost:9000/
sonar.login=admin
sonar.password=admin

## About Project
sonar.projectKey=python
sonar.projectName=Python
sonar.projectDescription=
sonar.links.homepage=
sonar.links.scm=
sonar.links.issue=
sonar.links.ci=

## Analysis
sonar.language=py
sonar.projectBaseDir=/src/
sonar.sources=.
sonar.sourceEncoding=UTF-8
#sonar.scm.provider=hg

## Output
sonar.verbose=false
sonar.log.level=INFO
sonar.showProfiling=false
#sonar.scanner.dumpToFile=/tmp/sonar-python.properties

## Python
sonar.inclusions=**/*.py
sonar.exclusions=**/migrations/**,**/*.pyc,**/__pycache__/**
sonar.python.pylint=/usr/bin/pylint
sonar.python.pylint_config=.pylintrc
sonar.python.xunit.skipDetails=false
sonar.python.xunit.reportPath=xunit.xml
sonar.python.coverage.reportPath=coverage.xml
sonar.core.codeCoveragePlugin=cobertura

## Turn off these rules
## python:s100: "Method names should comply with a naming convention"
## gives many false positives when overriding
## TestCase methods (such as setUp and tearDown) in test files
sonar.issue.ignore.multicriteria=e1,e2
sonar.issue.ignore.multicriteria.e1.ruleKey=python:S100
sonar.issue.ignore.multicriteria.e1.resourceKey=**/tests.py
sonar.issue.ignore.multicriteria.e2.ruleKey=python:S100
sonar.issue.ignore.multicriteria.e2.resourceKey=**/tests.py

7.3.4. JavaScript

## Sonar Server
sonar.host.url=http://localhost:9000/
sonar.login=admin
sonar.password=admin

## About Project
sonar.projectKey=javascript
sonar.projectName=JavaScript
sonar.projectDescription=
sonar.links.homepage=
sonar.links.scm=
sonar.links.issue=
sonar.links.ci=

## Analysis
sonar.language=js
sonar.projectBaseDir=/src/
sonar.sources=.
sonar.sourceEncoding=UTF-8
sonar.scm.provider=git

## Output
sonar.verbose=false
sonar.log.level=INFO
sonar.showProfiling=false
#sonar.scanner.dumpToFile=/tmp/sonar-javascript.properties

## JavaScript
sonar.inclusions=**/*.js,**/*.jsx,**/*.vue
sonar.exclusions=**/tinymce.**,**/jquery.*
sonar.javascript.jQueryObjectAliases=$,jQuery
sonar.javascript.environments=amd,applescript,atomtest,browser,commonjs,couch,embertest,greasemonkey,jasmine,jest,jquery,meteor,mocha,mongo,nashorn,node,phantomjs,prototypejs,protractor,qunit,rhino,serviceworker,shared-node-browser,shelljs,webextensions,worker,wsh,yui
sonar.javascript.globals=angular,goog,google,OpenLayers,d3,dojo,dojox,dijit,Backbone,moment,casper
sonar.javascript.exclusions=**/node_modules/**,**/bower_components/**
sonar.nodejs.executable=/usr/bin/node

7.3.5. CSS

## Sonar Server
sonar.host.url=http://localhost:9000/
sonar.login=admin
sonar.password=admin

## About Project
sonar.projectKey=css
sonar.projectName=CSS
sonar.projectDescription=
sonar.links.homepage=
sonar.links.scm=
sonar.links.issue=
sonar.links.ci=

## Analysis
sonar.language=css
sonar.projectBaseDir=/src/
sonar.sources=.
sonar.sourceEncoding=UTF-8
sonar.scm.provider=git

## Output
sonar.verbose=false
sonar.log.level=INFO
sonar.showProfiling=false
#sonar.scanner.dumpToFile=/tmp/sonar-css.properties

## CSS
sonar.inclusions=**/*.css,**/*.less,**/*.scss
sonar.exclusions=**/tinymce.**,**/jquery.*
sonar.css.node=/usr/bin/node
sonar.css.file.suffixes=.css,.less,.scss

7.3.6. HTML

## Sonar Server
sonar.host.url=http://localhost:9000/
sonar.login=admin
sonar.password=admin

## About Project
sonar.projectKey=html
sonar.projectName=HTML
sonar.projectDescription=
sonar.links.homepage=
sonar.links.scm=
sonar.links.issue=
sonar.links.ci=

## Analysis
sonar.language=html
sonar.projectBaseDir=/src/
sonar.sources=.
sonar.sourceEncoding=UTF-8
sonar.scm.provider=git

## Output
sonar.verbose=false
sonar.log.level=INFO
sonar.showProfiling=false
#sonar.scanner.dumpToFile=/tmp/sonar-html.properties

## HTML
sonar.inclusions=**/*.html,**/*.xhtml,**/*.jspf,**/*.jspx,**/*.cshtml,**/*.vbhtml,**/*.aspx,**/*.ascx,**/*.rhtml,**/*.erb,**/*.shtm,**/*.shtml
sonar.exclusions=

7.3.7. Multi-language

## Sonar Server
sonar.host.url=http://localhost:9000/
sonar.login=admin
sonar.password=admin

## About Project
sonar.projectKey=multilanguage
sonar.projectName=Multi-language
sonar.projectDescription=
sonar.links.homepage=
sonar.links.scm=
sonar.links.issue=
sonar.links.ci=

## Analysis
#sonar.language=
sonar.projectBaseDir=/src/
sonar.sources=.
sonar.sourceEncoding=UTF-8
sonar.scm.provider=git

## Output
sonar.verbose=false
sonar.log.level=INFO
sonar.showProfiling=false
#sonar.scanner.dumpToFile=/tmp/sonar-multilanguage.properties

sonar.inclusions=**/*.css,**/*.less,**/*.scss,**/*.html,**/*.xhtml,**/*.jspf,**/*.jspx,**/*.cshtml,**/*.vbhtml,**/*.aspx,**/*.ascx,**/*.rhtml,**/*.erb,**/*.shtm,**/*.shtml,**/*.js,**/*.jsx,**/*.vue,**/*.py
sonar.exclusions=**/tinymce.**,**/jquery.*,**/sitemap.xml,**/migrations/**,**/*.pyc,**/__pycache__/**

## CSS
sonar.css.node=/usr/bin/node
sonar.css.file.suffixes=.css,.less,.scss

## JavaScript
sonar.javascript.jQueryObjectAliases=$,jQuery
sonar.javascript.environments=amd,applescript,atomtest,browser,commonjs,couch,embertest,greasemonkey,jasmine,jest,jquery,meteor,mocha,mongo,nashorn,node,phantomjs,prototypejs,protractor,qunit,rhino,serviceworker,shared-node-browser,shelljs,webextensions,worker,wsh,yui
sonar.javascript.globals=angular,goog,google,OpenLayers,d3,dojo,dojox,dijit,Backbone,moment,casper
sonar.javascript.exclusions=**/node_modules/**,**/bower_components/**
sonar.nodejs.executable=/usr/bin/node

## Python
sonar.python.pylint=/usr/bin/pylint
sonar.python.pylint_config=.pylintrc
sonar.python.xunit.skipDetails=false
sonar.python.xunit.reportPath=xunit.xml
sonar.python.coverage.reportPath=coverage.xml
sonar.core.codeCoveragePlugin=cobertura

## Turn off these rules
## python:s100: "Method names should comply with a naming convention"
## gives many false positives when overriding
## TestCase methods (such as setUp and tearDown) in test files
sonar.issue.ignore.multicriteria=e1,e2
sonar.issue.ignore.multicriteria.e1.ruleKey=python:S100
sonar.issue.ignore.multicriteria.e1.resourceKey=**/tests.py
sonar.issue.ignore.multicriteria.e2.ruleKey=python:S100
sonar.issue.ignore.multicriteria.e2.resourceKey=**/tests.py

7.4. Budowanie Pull Request

sonar.pullrequest.base=master
sonar.pullrequest.branch=feature/my-new-feature
sonar.pullrequest.key=5
sonar.pullrequest.provider=GitHub
sonar.pullrequest.github.repository=my-company/my-repo https://blog.sonarsource.com/sonarcloud-loves-your-build-pipeline

7.5. Analiza kodu za pomocą mvn

7.5.1. pom.xml

<settings>
    <pluginGroups>
        <pluginGroup>org.sonarsource.scanner.maven</pluginGroup>
    </pluginGroups>
    <profiles>
        <profile>
            <id>sonar</id>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            <properties>
                <!-- Optional URL to server. Default value is http://localhost:9000 -->
                <sonar.host.url>
                  http://myserver:9000
                </sonar.host.url>
            </properties>
        </profile>
     </profiles>
</settings>

7.5.2. Używnianie

mvn sonar:sonar

7.7. Zadania

7.7.1. Instalacja

  • Zainstaluj SonarQube

Tip

User admin, Hasło admin

7.7.2. Wrzucanie wyników statycznej analizy kodu

  • Czy wcześniej zainstalowałeś Bitbucket Server?

  • Skonfiguruj aby statyczna analiza kodu uruchamiała z Jenkins

  • Skonfiguruj tak, by w każdym Pull Request jako komentarz do linii kodu wyświetlały się uwagi z SonarQube

  • Dostosuj poziom komentarzy, aby nie zalać programisty ich zbyt dużą ilością, np. wyświetlaj tylko Blocker i Critical