Статьи

3 шага для анализа Gradle-проекта с помощью SonarQube с помощью Docker

Насколько сложно начать работу с проектом Gradle и проанализировать его с помощью SonarQube на местном уровне?

Ингредиенты:

SonarQube (ранее Sonar) — это платформа с открытым исходным кодом для непрерывного контроля качества кода.

Gradle — это система автоматизации сборки с открытым исходным кодом.

Docker позволяет упаковать приложение со всеми его зависимостями в стандартизированный модуль для разработки программного обеспечения.

«Насколько это легко?» был вопрос, который у меня возник после того, как я решил переформатировать свою компанию HP EliteBook с Windows в полноценный Linux Mint .

Итак, я уже поиграл с Docker, и IMHO, это работает намного приятнее в Linux, поэтому я подумал, что пришло время поиграть с ним еще немного и, возможно, получится проанализировать проект с помощью SonarQube без особых хлопот .

Итак, насколько это легко?

sonarqube_logo_720 Gradle Домашняя страница-докер-логотип

Шаг 1 — Получение SonarQube с Docker

Первое, что я отправился на поиски, был образ Docker, в котором уже есть SonarQube. Это будущее IMHO: запуск любых компонентов, которые вам нужны, внутри контейнера.

По крайней мере, для целей разработки и тестирования это большой выигрыш: не важно, какая ОС или личная рабочая среда, образ такой, какой он есть, и пока вы можете запускать Docker, вы будете «точно» знать, что будет работать.

Сейчас нет времени на создание образа, просто пригласите кого- нибудь, кто уже поделился им в собственной компании или на DockerHub.

Docker Hub — это каноническая платформа для публикации и использования образов контейнеров Docker.

Просто искал «сонар».

dockerhub-поиск-для-сонар

243 хранилища на данный момент. Были 2, которые привлекли мое внимание:

  • sonarqube — который является официальным. Имеет 165 звезд и 243 тысячи тяг .
  • orangesignal/sonar который имеет 2 звезды и 378 тяг
  • tpires/sonar-server который имеет 18 звезд и 94 тысячи тяг.

Хотя номера №1 и №3, кажется, имеют более высокую комбинацию звезд / orangesignal/sonar , я orangesignal/sonar потому что он использовал Docker Compose .

Docker Compose

На странице DockerHub orangesignal / sonar есть ссылка на репозиторий GitHub. Клонировал это:

1
git clone https://github.com/orangesignal/docker-sonarqube.git

Макет каталога:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
tvinke@picard ~ $ cd docker-sonarqube/
tvinke@picard ~/docker-sonarqube $ tree
.
├── 3.6
│   ├── docker-entrypoint.sh
│   └── Dockerfile
├── 3.7
│   ├── docker-entrypoint.sh
│   └── Dockerfile
├── 4.0
│   ├── docker-entrypoint.sh
│   └── Dockerfile
├── 4.1
│   ├── docker-entrypoint.sh
│   └── Dockerfile
├── 4.2
│   ├── docker-entrypoint.sh
│   └── Dockerfile
├── 4.3
│   ├── docker-entrypoint.sh
│   └── Dockerfile
├── 4.4
│   ├── docker-entrypoint.sh
│   └── Dockerfile
├── 4.5
│   ├── docker-entrypoint.sh
│   └── Dockerfile
├── 5.0
│   ├── docker-entrypoint.sh
│   └── Dockerfile
├── 5.1
│   ├── docker-entrypoint.sh
│   └── Dockerfile
├── docker-build.bash
├── docker-compose.yml
├── example
│   ├── docker-compose.yml
│   ├── docker-entrypoint.sh
│   ├── Dockerfile
│   └── nginx-conf.d
│       └── default.conf
├── LICENSE
├── README.md
├── remove_all_stopped_containers.bash
└── remove_all_untagged_images.bash
 
12 directories, 30 files

Различные версии SonarQube (на самом деле Dockerfiles ) и интересный docker-compose.yml содержащий «композицию».

docker-compose.yml

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
db:
  image: postgres:9
  hostname: pgsql-01
  ports:
    - 5432:5432
  environment:
    - POSTGRES_DB=sonar
    - POSTGRES_USER=sonar
    - POSTGRES_PASSWORD=sonar
 
sonar:
  image: orangesignal/sonar:latest
  hostname: sonar-01
  links:
    - db
  ports:
    - 9000:9000
  environment:
    - SONAR_JDBC_URL=jdbc:postgresql://pgsql-01:5432/sonar
    - SONAR_JDBC_USERNAME=sonar
    - SONAR_JDBC_PASSWORD=sonar

Вместо H2 или MySQL говорится, что нужно использовать базу данных Postgres, используя образ Docker postgres:9 и запускать ее под определенным именем хоста и портом. За ним следует часть, где последняя опубликованная версия изображения orangesignal/sonar упоминается и связана с базой данных Postgres.

У меня уже был установлен Docker, но мне еще нужно было установить Docker Compose, чтобы иметь возможность работать

1
tvinke@picard ~/docker-sonarqube $ docker-compose up

Это начинает весь Шебанг.

01
02
03
04
05
06
07
08
09
10
11
...
sonar_1 | 2016.02.26 10:24:35 INFO  web[o.s.s.s.IndexSynchronizer] Index source lines
sonar_1 | 2016.02.26 10:24:35 INFO  web[o.s.s.s.IndexSynchronizer] Index users
sonar_1 | 2016.02.26 10:24:35 INFO  web[o.s.s.s.IndexSynchronizer] Index views
sonar_1 | 2016.02.26 10:24:35 INFO  web[jruby.rack] jruby 1.7.9 (ruby-1.8.7p370) 2013-12-06 87b108a on Java HotSpot(TM) 64-Bit Server VM 1.8.0_66-b17 [linux-amd64]
sonar_1 | 2016.02.26 10:24:35 INFO  web[jruby.rack] using a shared (threadsafe!) runtime
sonar_1 | 2016.02.26 10:24:41 INFO  web[jruby.rack] keeping custom (config.logger) Rails logger instance
sonar_1 | 2016.02.26 10:24:41 INFO  web[o.a.c.h.Http11NioProtocol] Starting ProtocolHandler ["http-nio-0.0.0.0-9000"]
sonar_1 | 2016.02.26 10:24:41 INFO  web[o.s.s.a.TomcatAccessLog] Web server is started
sonar_1 | 2016.02.26 10:24:41 INFO  web[o.s.s.a.EmbeddedTomcat] HTTP connector enabled on port 9000
sonar_1 | 2016.02.26 10:24:42 INFO  app[o.s.p.m.Monitor] Process[web] is up

Доступ к панели инструментов SonarQube

На http: // localhost: 9000 сейчас SonarQube обслуживает:

sonarqube-панель

Проекты еще не проанализированы.

Шаг 2 — Получение примера Gradle Project

Мне нужен был пример проекта Gradle.

Я мог бы выбрать создание чистого, основанного на Java проекта Gradle с нуля, но добавление некоторых источников и тестов для анализа заставило бы меня преодолеть 5-минутный срок, который я установил для себя.

Лучший вариант — просто использовать проект из собственного репозитория GitHub с примерами SonarQube:

1
tvinke@picard ~/workspace $ git clone https://github.com/SonarSource/sonar-examples.git

Каталог /projects содержит примеры проектов для:

  • различные анализаторы (SonarQube Runner, Maven, Ant)
  • разные языки (Java, Cobol, .Net и т. д.)
  • различные способы выполнения модульных тестов и получения данных покрытия кода

Примеры используют Sonar Runner, который больше не поддерживается. К счастью, проект java-gradle-simple был именно тем, что мне было нужно.

Вывод tree (еще один красивый инструмент Linux):

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
tvinke@picard ~/workspace/sonar-examples/projects/languages/java/gradle/java-gradle-simple $ tree
.
├── build.gradle
├── README.md
└── src
    ├── main
    │   └── java
    │       └── example
    │           └── Greeting.java
    └── test
        └── java
            └── example
                ├── FailingTest.java
                └── GreetingTest.java
 
7 directories, 5 files

Некоторые вещи, на которые я надеялся, что SonarQube может что-то сообщить. То, что я искал, было примером правильного build.gradle с использованием плагина Sonar Gradle.

build.gradle

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
apply plugin: 'java'
apply plugin: 'org.sonarqube'
apply plugin: 'jacoco'
 
allprojects { 
  ext.baseVersion = "0.1"
  ext.snapshotVersion = true
   
  group = "org.sonarqube"
  version = "$baseVersion" + (snapshotVersion ? "-SNAPSHOT" : "")
}
 
sonarqube {
    properties {
        property "sonar.projectName", "Java :: Simple Project :: SonarQube Scanner for Gradle"
        property "sonar.projectKey", "org.sonarqube:java-gradle-simple"
        property "sonar.jacoco.reportPath", "${project.buildDir}/jacoco/test.exec"
    }
}
 
buildscript {
    repositories {
      maven {
        url "http://repo1.maven.org/maven2/"
      }
      maven {
        url "https://plugins.gradle.org/m2/"
      }
      mavenLocal()
    }
    dependencies {
      classpath 'org.ajoberstar:gradle-jacoco:0.1.0'
      classpath 'org.sonarqube.gradle:gradle-sonarqube-plugin:1.0'
    }
}
 
test {
  ignoreFailures = true
}
 
repositories {
  repositories {
    maven {
    }
  }
}
 
dependencies {
    testCompile 'junit:junit:4.12'
}

Как видите, есть несколько плагинов:

1
2
3
apply plugin: 'java'
apply plugin: 'org.sonarqube'
apply plugin: 'jacoco'

Помимо плагина Java, есть также плагин SonarQube и плагин JaCoCo. Последний предоставляет метрики покрытия кода Java с помощью библиотеки JaCoCo («Покрытие кода Java»), созданной командой EclEmma.

Кроме того, настроены некоторые другие вещи, такие как свойства сонара:

1
2
3
4
5
6
7
sonarqube {
    properties {
        property "sonar.projectName", "Java :: Simple Project :: SonarQube Scanner for Gradle"
        property "sonar.projectKey", "org.sonarqube:java-gradle-simple"
        property "sonar.jacoco.reportPath", "${project.buildDir}/jacoco/test.exec"
    }
}

Часть предназначена для идентификации проекта внутри SonarQube, если вы используете его для нескольких проектов.

Я оставил все как есть, потому что я могу просто начать …

Шаг 3 — Анализ с использованием Gradle Sonar Plugin

Плагин Gradle Sonar использует все виды значений по умолчанию и использует большую часть информации из сборки Gradle для анализа проекта.

Поэтому я надеялся, что Things Just Worked (что является ловушкой, если все идет гладко с минимальной конфигурацией), так что просто посмотрите, что произойдет, если мы сделаем так:

1
gradle sonarqube

С настройками SonarQube по умолчанию это сработало бы, и была бы найдена локальная база данных H2.

Где на самом деле SonarQube?

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
INFO: Work directory: /home/tvinke/workspace/sonar-examples/projects/languages/java/gradle/java-gradle-simple/build/sonar
INFO: SonarQube Server 5.1.2
11:38:15.164 INFO  - Load global repositories
11:38:15.281 INFO  - Load global repositories (done) | time=119ms
11:38:15.283 INFO  - Server id: 20160226102431
11:38:15.285 INFO  - User cache: /home/tvinke/.sonar/cache
11:38:15.292 INFO  - Install plugins
11:38:15.329 INFO  - Install JDBC driver
11:38:15.335 INFO  - Create JDBC datasource for jdbc:h2:tcp://localhost/sonar
:sonarqube FAILED
 
FAILURE: Build failed with an exception.
 
* What went wrong:
Execution failed for task ':sonarqube'.
> Unable to execute Sonar
 
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
 
BUILD FAILED
 
Total time: 2.41 secs

К сожалению, наш docker-compose.yml говорит иначе — вместо этого мы используем базу данных Postgres с другими настройками JDBC, а не базу данных H2 в jdbc:h2:tcp://localhost/sonar .

Мы можем либо переопределить значения по умолчанию, установив некоторые глобальные свойства в ~/.gradle/gradle.properties например

1
2
3
4
systemProp.sonar.host.url=http://localhost:9000
systemProp.sonar.jdbc.url=jdbc:postgresql://localhost/sonar
systemProp.sonar.jdbc.username=sonar
systemProp.sonar.jdbc.password=sonar

Или передайте его в командной строке (сохраняя значения по умолчанию):

1
2
3
gradle sonarqube
 -Dsonar.jdbc.url=jdbc:postgresql://localhost:5432/sonar
 -Dsonar.verbose=true

SonarQube начинает и заканчивает быстро анализировать этот небольшой проект:

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
tvinke@picard ~/workspace/sonar-examples/projects/languages/java/gradle/java-gradle-simple $ gradle sonarqube -Dsonar.jdbc.url=jdbc:postgresql://localhost:5432/
sonar
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:compileTestJava UP-TO-DATE
:processTestResources UP-TO-DATE
:testClasses UP-TO-DATE
:test UP-TO-DATE
:sonarqube
INFO: Default locale: "en_US", source code encoding: "UTF-8" (analysis is platform dependent)
INFO: Work directory: /home/tvinke/workspace/sonar-examples/projects/languages/java/gradle/java-gradle-simple/build/sonar
INFO: SonarQube Server 5.1.2
12:00:29.104 INFO  - Load global repositories
12:00:29.184 INFO  - Load global repositories (done) | time=81ms
12:00:29.185 INFO  - Server id: 20160226102431
12:00:29.186 INFO  - User cache: /home/tvinke/.sonar/cache
12:00:29.192 INFO  - Install plugins
12:00:29.219 INFO  - Install JDBC driver
12:00:29.223 INFO  - Create JDBC datasource for jdbc:postgresql://localhost:5432/sonar
12:00:29.758 INFO  - Initializing Hibernate
12:00:30.421 INFO  - Load project repositories
12:00:30.574 INFO  - Load project repositories (done) | time=153ms
12:00:30.574 INFO  - Load project settings
12:00:30.786 INFO  - Load technical debt model
12:00:30.801 INFO  - Apply project exclusions
12:00:30.939 WARN  - 'sonar.dynamicAnalysis' is deprecated since version 4.3 and should no longer be used.
12:00:30.954 WARN  - SCM provider autodetection failed. No SCM provider claims to support this project. Please use sonar.scm.provider to define SCM of your project.
12:00:30.955 INFO  - -------------  Scan Java :: Simple Project :: SonarQube Scanner for Gradle
12:00:30.959 INFO  - Load module settings
12:00:31.025 INFO  - Load rules
12:00:31.231 INFO  - Base dir: /home/tvinke/workspace/sonar-examples/projects/languages/java/gradle/java-gradle-simple
12:00:31.231 INFO  - Working dir: /home/tvinke/workspace/sonar-examples/projects/languages/java/gradle/java-gradle-simple/build/sonar
12:00:31.232 INFO  - Source paths: src/main/java
12:00:31.232 INFO  - Test paths: src/test/java
12:00:31.233 INFO  - Binary dirs: build/classes/main
12:00:31.233 INFO  - Source encoding: UTF-8, default locale: en_US
12:00:31.233 INFO  - Index files
12:00:31.241 INFO  - 3 files indexed
12:00:31.314 INFO  - Quality profile for java: Sonar way
12:00:31.326 INFO  - Sensor JavaSquidSensor
12:00:31.513 INFO  - Configured Java source version: 7
12:00:31.746 INFO  - Java Main Files AST scan...
12:00:31.748 INFO  - 1 source files to be analyzed
12:00:31.950 INFO  - Java Main Files AST scan done: 204 ms
12:00:31.950 INFO  - 1/1 source files have been analyzed
12:00:31.951 INFO  - Java bytecode scan...
12:00:31.964 INFO  - Java bytecode scan done: 13 ms
12:00:31.964 INFO  - Java Test Files AST scan...
12:00:31.964 INFO  - 2 source files to be analyzed
12:00:32.011 INFO  - Java Test Files AST scan done: 47 ms
12:00:32.011 INFO  - 2/2 source files have been analyzed
12:00:32.013 INFO  - Package design analysis...
12:00:32.015 INFO  - Package design analysis done: 2 ms
12:00:32.016 INFO  - Sensor JavaSquidSensor (done) | time=690ms
12:00:32.016 INFO  - Sensor Lines Sensor
12:00:32.017 INFO  - Sensor Lines Sensor (done) | time=1ms
12:00:32.018 INFO  - Sensor QProfileSensor
12:00:32.021 INFO  - Sensor QProfileSensor (done) | time=4ms
12:00:32.021 INFO  - Sensor InitialOpenIssuesSensor
12:00:32.032 INFO  - Sensor InitialOpenIssuesSensor (done) | time=11ms
12:00:32.032 INFO  - Sensor ProjectLinksSensor
12:00:32.039 INFO  - Sensor ProjectLinksSensor (done) | time=7ms
12:00:32.039 INFO  - Sensor VersionEventsSensor
12:00:32.057 INFO  - Sensor VersionEventsSensor (done) | time=18ms
12:00:32.057 INFO  - Sensor SurefireSensor
12:00:32.057 INFO  - parsing /home/tvinke/workspace/sonar-examples/projects/languages/java/gradle/java-gradle-simple/build/test-results
12:00:32.100 INFO  - Sensor SurefireSensor (done) | time=43ms
12:00:32.100 INFO  - Sensor JaCoCoOverallSensor
12:00:32.105 WARN  - You are not using the latest JaCoCo binary format version, please consider upgrading to latest JaCoCo version.
12:00:32.106 INFO  - Analysing /home/tvinke/workspace/sonar-examples/projects/languages/java/gradle/java-gradle-simple/build/jacoco/test.exec
12:00:32.117 WARN  - You are not using the latest JaCoCo binary format version, please consider upgrading to latest JaCoCo version.
12:00:32.117 INFO  - Analysing /home/tvinke/workspace/sonar-examples/projects/languages/java/gradle/java-gradle-simple/build/sonar/jacoco-overall.exec
12:00:32.151 INFO  - No information about coverage per test.
12:00:32.152 INFO  - Sensor JaCoCoOverallSensor (done) | time=52ms
12:00:32.152 INFO  - Sensor SCM Sensor
12:00:32.152 INFO  - No SCM system was detected. You can use the 'sonar.scm.provider' property to explicitly specify it.
12:00:32.152 INFO  - Sensor SCM Sensor (done) | time=0ms
12:00:32.152 INFO  - Sensor JaCoCoSensor
12:00:32.152 WARN  - You are not using the latest JaCoCo binary format version, please consider upgrading to latest JaCoCo version.
12:00:32.153 INFO  - Analysing /home/tvinke/workspace/sonar-examples/projects/languages/java/gradle/java-gradle-simple/build/jacoco/test.exec
12:00:32.155 INFO  - No information about coverage per test.
12:00:32.155 INFO  - Sensor JaCoCoSensor (done) | time=3ms
12:00:32.155 INFO  - Sensor CPD Sensor
12:00:32.155 INFO  - JavaCpdEngine is used for java
12:00:32.155 INFO  - Cross-project analysis disabled
12:00:32.169 INFO  - Sensor CPD Sensor (done) | time=14ms
12:00:32.170 INFO  - No quality gate is configured.
12:00:32.195 INFO  - Compare to previous analysis (2016-02-26)
12:00:32.197 INFO  - Compare over 30 days (2016-01-27, analysis of Fri Feb 26 09:54:19 CET 2016)
12:00:32.501 INFO  - Execute decorators...
12:00:33.012 INFO  - Store results in database
12:00:33.177 INFO  - Analysis reports generated in 13ms, dir size=1002 bytes
12:00:33.181 INFO  - Analysis reports compressed in 4ms, zip size=2 KB
12:00:33.211 INFO  - Analysis reports sent to server in 29ms
12:00:33.211 INFO  - ANALYSIS SUCCESSFUL, you can browse http://localhost:9000/dashboard/index/org.sonarqube:java-gradle-simple
12:00:33.211 INFO  - Note that you will be able to access the updated dashboard once the server has processed the submitted analysis report.
 
BUILD SUCCESSFUL
 
Total time: 5.274 secs

Результат:

АНАЛИЗ УСПЕШНЫЙ

На панели инструментов SonarQube приведен список нашего простого Java-проекта. Обзор проекта теперь показывает много информации о состоянии текущей кодовой базы.

sonarqube-проект анализировались

У собственного примера проекта SonarQube есть 2 (преднамеренные) проблемы:

sonarqube-простодушные Java-проект-вопросы

Обзор проблем говорит о том, что на самом деле происходит:

sonarqube-простодушные Java-проект-вопросы-обзор

sonarqube-простой Java-проект-эмиссионные детали

sonarqube-простой Java-проект-эмиссионные более подробно,

Так что ответьте на мой первоначальный вопрос: не так сложно проанализировать проект Gradle с помощью локальной установки SonarQube.

Поскольку у меня уже были установлены Docker и Docker Compose, нам понадобилось «5 минут», чтобы добраться сюда, но вам потребуется еще 10 минут, чтобы погасить технический долг.

Теперь, чего вы ждете — иди исправим! 🙂

Дальнейшее чтение