SonarQube and GitLab Setup
Tags: gitlab, sonarqube, docker, devops
Published: 2020-06-07 22:39:37

[SonarQube](https://www.sonarqube.org/) is a great tool for code quality and security checks. It is one of the tools we use to ensure quality of our products is measured and improved over time.

We also use [GitLab](https://gitlab.com) – code management and CI/CD tool on some of our projects. SonarQube code analysis is integrated as a step in our GitLab CI pipelines.

For a long time I had a custom-built docker image for those purposes, automatically built and published to GitLab Container Registry.

Although quite automated, this custom-build docker image was adding to maintenance of the pipelines. I was happy to see that SonarSource has recently published [official SonarScanner CLI docker image](https://github.com/SonarSource/sonar-scanner-cli-docker), and [announced a support for GitLab integration in v8](https://www.sonarqube.org/sonarqube-8-0/)

{% github SonarSource/sonar-scanner-cli-docker no-readme %}

The docker image expects code being mounted on [`$PWD`](https://github.com/SonarSource/sonar-scanner-cli-docker/blob/f210c44a7b9af1cc74939335f2f9101550592f94/4/bin/entrypoint.sh#L13), which is set to [`/usr/src`](https://github.com/SonarSource/sonar-scanner-cli-docker/blob/f210c44a7b9af1cc74939335f2f9101550592f94/4/Dockerfile#L34). This is different to where GitLab is mounting sources directory by default.

To make it all work the following environment variable needs to be set:

```yaml
sonar:
  image: sonarsource/sonar-scanner-cli
  script:
    - sonar-scanner -Dsonar.qualitygate.wait=true
  allow_failure: true
  variables:
    SONAR_PROJECT_BASE_DIR: "${CI_PROJECT_DIR}"
```

Environment variable `SONAR_PROJECT_BASE_DIR` [overrides default behavior](https://github.com/SonarSource/sonar-scanner-cli-docker/blob/f210c44a7b9af1cc74939335f2f9101550592f94/4/bin/entrypoint.sh#L15). Predefined GitLab environment variable [`CI_PROJECT_DIR`](https://docs.gitlab.com/ee/ci/variables/predefined_variables.html) refers to the location where GitLab is mounting project source code.

Without this variable set the following misleading error will appear in GitLab log:

```
ERROR: Error during SonarScanner execution
java.lang.IllegalStateException: Unable to create user cache: /usr/src/.sonar/cache
	at org.sonarsource.scanner.api.internal.cache.FileCache.createDir(FileCache.java:147)
	at org.sonarsource.scanner.api.internal.cache.FileCache.<init>(FileCache.java:46)
	at org.sonarsource.scanner.api.internal.cache.FileCache.create(FileCache.java:52)
	at org.sonarsource.scanner.api.internal.cache.FileCacheBuilder.build(FileCacheBuilder.java:48)
	at org.sonarsource.scanner.api.internal.JarDownloaderFactory.create(JarDownloaderFactory.java:42)
	at org.sonarsource.scanner.api.internal.IsolatedLauncherFactory.createLauncher(IsolatedLauncherFactory.java:68)
	at org.sonarsource.scanner.api.EmbeddedScanner.doStart(EmbeddedScanner.java:185)
	at org.sonarsource.scanner.api.EmbeddedScanner.start(EmbeddedScanner.java:123)
	at org.sonarsource.scanner.cli.Main.execute(Main.java:73)
	at org.sonarsource.scanner.cli.Main.main(Main.java:61)
Caused by: java.nio.file.AccessDeniedException: /usr/src/.sonar
	at java.base/sun.nio.fs.UnixException.translateToIOException(Unknown Source)
	at java.base/sun.nio.fs.UnixException.rethrowAsIOException(Unknown Source)
	at java.base/sun.nio.fs.UnixException.rethrowAsIOException(Unknown Source)
	at java.base/sun.nio.fs.UnixFileSystemProvider.createDirectory(Unknown Source)
	at java.base/java.nio.file.Files.createDirectory(Unknown Source)
	at java.base/java.nio.file.Files.createAndCheckIsDirectory(Unknown Source)
	at java.base/java.nio.file.Files.createDirectories(Unknown Source)
	at org.sonarsource.scanner.api.internal.cache.FileCache.createDir(FileCache.java:145)
	... 9 more
ERROR: 
ERROR: Re-run SonarScanner using the -X switch to enable full debug logging.
```

## Improvements

It might be a good idea to cache Sonar Scanner directories to be re-used in future pipeline runs:

```yaml
sonar:
  image: sonarsource/sonar-scanner-cli
  script:
    - sonar-scanner -Dsonar.qualitygate.wait=true
  allow_failure: true
  variables:
    SONAR_PROJECT_BASE_DIR: "${CI_PROJECT_DIR}"
  cache:
    key: "sonar-${CI_PROJECT_ID}"
    paths:
      - ".scannerwork"
      - ".sonar"
```

In my particular case, SonarQube analysis was not dependent on any other steps in the pipeline, so I've used [`needs`](https://docs.gitlab.com/ee/ci/yaml/#needs) and [`dependencies`](https://docs.gitlab.com/ee/ci/yaml/#dependencies) properties to make it run ahead of time and skip downloading artifacts of other steps.

```yaml
sonar:
  image: sonarsource/sonar-scanner-cli
  needs: []
  dependencies: []
  script:
    - sonar-scanner -Dsonar.qualitygate.wait=true
  allow_failure: true
  variables:
    SONAR_PROJECT_BASE_DIR: "${CI_PROJECT_DIR}"
    GIT_DEPTH: 0
  cache:
    key: "sonar-${CI_PROJECT_ID}"
    paths:
      - ".scannerwork"
      - ".sonar"
```

Finally, I've used `GIT_DEPTH` environment variable to enforce [Shallow Clone](https://docs.gitlab.com/ee/ci/large_repositories/) of our fairly large repository.