背景
ソースコードをcommit/pushした際の自動レビューと、コード品質の可視化のためにSonarQubeを導入することになった。
既にソースコードはGitLabで管理しており、GitLab-CIを使ってビルドやテスト、デプロイの自動化まで実装済み。
今さら感はあるが、GitLabとSonarQubeの連携方法について調べてみた。
Jenkinsは必要か?
調べていくと、どの事例もJenkinsを間に挟んでGitLabとSonarQubeを連携させている。
図にするとこんな感じ。
正確には、SonarQube側にはsonar-scannerという登場人物もいて、実際の解析を行っているのは彼ですが、ココでは細かいことは割愛。
もともとJenkinsを導入済みのプロジェクトであれば、この構成でも良いと思うが、未導入の場合は無駄な構成のように感じた。
実際、私のプロジェクトもJenkinsは導入していなかった。
SonarQubeに加えてJenkinsが必要なため構築に2倍の労力がかかるし、SonarQubeのためだけにJenkinsを動かしておくのも経済的とは思えない。
一方で、Jenkinsを導入したほうが良いケースもありそう。
Jenkinsのジョブのトリガは、きめ細かに設定することができるので、「日次や週次で定期的に実行させたい」といったケースなどであれば、Jenkinsの導入が有効かもしれない。
ただ、私のプロジェクトでは、GitLabへのコードのPushやマージリクエストのタイミングで実行できれば十分だったので、やはり私のプロジェクトではJenkinsはいらないという結論に至った。
ということで、次の図のような、よりシンプルな構成で導入を試みることにした。
環境
- CentOS 7.5.1804
- GitLab CE 11.11.3
- gitlab-runner v12.6.0
- SonarQube Community Edition Version 7.6 (build 21501)
SonarQubeのインストール
公式が提供しているDockerイメージを使用する。
今回は、簡単に構築するために、公式のdocker-composeサンプルを活用する。
公式のdocker-composeサンプルをダウンロード
mkdir SonarQube
cd ./SonarQube
curl https://raw.githubusercontent.com/SonarSource/docker-sonarqube/master/recipes/docker-compose-postgres-example.yml -o docker-compose.yml
docker-compose.ymlをカスタマイズ
以下のように、docker-compose.ymlをカスタマイズする。
version: "2"
services:
sonarqube:
# コンテナ名を明示的に指定(必須)
container_name: sonarqube-core
# SonarQubeのバージョンを"7.6-community"に指定(必須)
image: sonarqube:7.6-community
ports:
- "9000:9000"
networks:
- sonarnet
environment:
- sonar.jdbc.url=jdbc:postgresql://db:5432/sonar
volumes:
- sonarqube_conf:/opt/sonarqube/conf
- sonarqube_data:/opt/sonarqube/data
- sonarqube_extensions:/opt/sonarqube/extensions
# マシンやdockerデーモンの再起動でコンテナが立ち上がるように(お好みで)
restart: always
db:
# コンテナ名を明示的に指定(推奨)
container_name: sonarqube-postgres
# postgresのバージョンも固定化(お好みで)
image: postgres:12.1
networks:
- sonarnet
environment:
- POSTGRES_USER=sonar
- POSTGRES_PASSWORD=sonar
volumes:
- postgresql:/var/lib/postgresql
# This needs explicit mapping due to https://github.com/docker-library/postgres/blob/4e48e3228a30763913ece952c611e5e9b95c8759/Dockerfile.template#L52
- postgresql_data:/var/lib/postgresql/data
# マシンやdockerデーモンの再起動でコンテナが立ち上がるように(お好みで)
restart: always
networks:
sonarnet:
driver: bridge
volumes:
sonarqube_conf:
sonarqube_data:
sonarqube_extensions:
postgresql:
postgresql_data:
SonarQubeを起動
# 仮想メモリの上限値を変更(省略するとSonarQubeが無限に再起動を繰り返す)
sudo sysctl -w vm.max_map_count=262144
# 起動
docker-compose up
SonarQubeのダッシュボードにアクセス
ブラウザで下記のURLにアクセス。
ユーザ名とパスワードはadminでログインできる。
http://{your_IP_address}:9000/
SonarQubeへのプラグインのインストール
sonar-gitlab-plugin
GitLabと連携するためのプラグイン。
ネット情報では、SonarQubeのGUI上から検索してインストールできるようだったが、私の環境では検索してもヒットせず。
このため、手作業でインストールを実施。
なお、sonar-gitlab-pluginがサポートするSonarQubeのバージョンは7.6まで。
docker-compose.ymlでバージョンを指定したのはこのため。
# GitHubからパッケージをダウンロード
curl https://github.com/gabrie-allaigre/sonar-gitlab-plugin/releases/download/4.1.0-SNAPSHOT/sonar-gitlab-plugin-4.1.0-SNAPSHOT.jar -o sonar-gitlab-plugin-4.1.0-SNAPSHOT.jar
# パッケージをsonarqube-coreコンテナにコピー
# ※あらかじめdocker-compose.ymlでコンテナ名をつけているので、コンテナの指定が楽にできる
docker cp sonar-gitlab-plugin-4.1.0-SNAPSHOT.jar sonarqube-core:/opt/sonarqube/extensions/plugins
SonarQubeのダッシュボードにログインし、Administration > System > Restart Serverで、SonarQubeを再起動する。
再起動後、Administration > Marketplace > Installedで、GitLabが表示されていればOK。
その他のプラグイン
主要な言語用のプラグインなどは、プリインストールされている。
インストール済みのプラグインの確認は、Administration > Marketplace > Installedで確認可能。
もし不足している場合はAllタブで検索して追加する。
SonarQube上で検索してヒットしない場合は、GoogleやGitHubなどで検索し、sonar-gitlab-pluginと同様の手順で手動インストールする。
私のプロジェクトの場合、JavaScriptの静的解析のプロファイルにESLintを使用したかったので、sonar-eslint-pluginを追加でインストール。
こちらも、SonarQubeのGUI上ではインストールできなかったので、手動でインストールした。
SonarQubeの設定
Administration > Configuration > General Settings > GitLab
最低限、以下の項目を設定する。
その他は、必要であれば、個別の環境に合わせて設定する。
| 項目 | 設定値 | 備考 |
|---|---|---|
| GitLab url | {your_GitLab_URL} | |
| GitLab User Token | {your_GitLab_User_Token} | 後述の手順で取得したトークン |
Quality Profiles
各言語の静的解析に使用するプロファイルを選択する。
標準ではSonar wayという、SonarQube推奨のプロファイルが選択されている。
特にこだわりがない場合や、プロジェクトで決まっているものがなければ、デフォルトのままでも問題ない。
もし、ルールを変更する場合は、使いたいプロファイル横の歯車アイコンからSet as Defaultをクリック。
私の場合は、前述の通りJavaScriptのDefaultプロファイルをESLintに変更した。
Projects
右上の+アイコンから、新規プロジェクトを作成し、以下の情報を設定。
| 項目 | 設定値 | 備考 |
|---|---|---|
| Project key | {your_repository_name} | |
| Display name | {your_repository_name} |
Analyze your project画面に遷移するので、Generateをクリック。
表示されるトークンをメモしておく。
さらに、作成されたプロジェクトを開き、Administration > General Settings > GitLab > GitLab Project idに、GitLab上の解析対象プロジェクトのIDを登録しておく。
GitLabの設定
gitlab-runnerのインストール
GitLab-CIを実行するためのgitlab-runnerをインストールする。
既にDocker executorのgitlab-runnerが存在する場合、この手順は省略可。
# docker版の`gitlab-runner`を起動
docker run -d \
--name gitlab-runner-docker \
--restart always \
-v /srv/gitlab-runner-docker/config:/etc/gitlab-runner \
-v /var/run/docker.sock:/var/run/docker.sock \
gitlab/gitlab-runner:v12.6.0
# GitLabにrunnerを登録
docker exec gitlab-runner-docker gitlab-runner register \
--non-interactive \
--url {your_gitlab_url} \
--registration-token {your_gitlab_runner_token} \
--name "gitlab-runner-docker" \
--tag-list "autotest-server,docker" \
--executor "docker" \
--docker-image "alpine:latest"
SonarQubeが使用するBOTアカウントを設定
SonarQubeが、静的解析結果をコミットやマージリクエストに対してコメントするためのアカウントを作成する。
BOTアカウントを作成
| 項目 | 設定値 | 備考 |
|---|---|---|
| Name | SonarQube | 他の名前でも可。投稿に表示されるので、SonarQubeからの投稿であることが分かりやすいように命名する。 |
| Username | SonarQube | 他の名前でも可。 |
| 任意のメールアドレス | ||
| Avatar | SonarQubeのアイコンなどを設定するとわかりやすい |
BOTアカウントに権限を付与
作成したBOTアカウントに、対象プロジェクトへのDeveloper権限を付与する。
BOTアカウントのトークンを取得
作成したBOTアカウントでログインし、Settings > Access Tokensで新規のアクセストークンを発行する。
| 項目 | 設定値 | 備考 |
|---|---|---|
| Name | SonarQube | 任意の名前で可。 |
| Expires at | (空欄) | |
| Scopes | api |
発行したトークンは、SonarQubeの Administration > Configuration > General Settings > GitLab > GitLab User Tokenに登録する。
SonarQubeのトークンをgitlab-runner用の環境変数に登録
解析対象のプロジェクトの、Settings > CI / CD > VariablesにSonarQubeのトークンを追加する。
| 項目 | 設定値 | 備考 |
|---|---|---|
| Type | Variable | |
| Key | SONARQUBE_TOKEN | |
| Value | {your_sonarqube_token} | 前述の手順で取得したトークン |
sonar-project.propertiesの作成
解析対象のプロジェクト直下に、下記のファイルを作成する。
設定値は、各環境に合わせて変更が必要。
# プロジェクト情報(SonarQubeで設定した内容)
sonar.projectKey={your_repository_name}
sonar.projectName={your_repository_name}
# プロジェクトのバージョン(SonarQubeのGUI上で解析結果をバージョンごとに管理可能)
sonar.projectVersion=1.0
# ソースコードのパス
sonar.sources=src
# ソースコードから除外する条件
sonar.exclusions=**/*.spec.js
# テストコードのパス
sonar.tests=src,config
# テストコードに加える条件
sonar.test.inclusions=**/*.spec.js
# 言語を指定しない場合、自動で言語認識をしてくれる。
# 自動認識の場合は、複数言語の認識にも対応。(Javascript + CSSなど)
# sonar.language=js
# カバレッジレポートのパス
sonar.javascript.lcov.reportPaths=coverage/lcov.info
# エンコーディング
sonar.sourceEncoding=UTF-8
.gitlab-ci.ymlの作成
GitLab-CIが実行する処理を定義する。
sonar-scannerという、SonarQubeの解析処理を実行するプログラムが実施されるように定義していく。
なお、sonar-scannerについては公式のDockerイメージを使用する。
インストールして使うこともできるが、不用意に環境を汚したくないし、導入が簡単なDocker版を採用。
公式のDockerイメージは、2020/01/10時点で未だにBeta版だが、今回の用途では何ら問題なく使用することができた。
stages:
- analysis
analysis:
stage: analysis
image:
name: sonarsource/sonar-scanner-cli:4.2
entrypoint: [""]
allow_failure: true
variables:
SONAR_HOST_URL: http://{your_SonarQube_IP}:9000
SONAR_TOKEN: ${SONARQUBE_TOKEN}
SONAR_PROJECT_BASE_DIR: ${CI_PROJECT_DIR}
script:
- |-
sonar-scanner \
-Dsonar.gitlab.project_id=$CI_PROJECT_ID \
-Dsonar.gitlab.ref_name=$CI_COMMIT_REF_NAME \
-Dsonar.gitlab.commit_sha=$CI_COMMIT_SHA
tags:
- docker
公式のDockerイメージは、docker runコマンドで使用されることを前提に作成されており、渡せる環境変数やオプションが限られている。
今回は、GitLabのプロジェクトID、ブランチ名、コミットハッシュを渡したかったため、entrypointを上書きしてコンテナ内でsonar-scannerを直接実行するようにしている。
いよいよ実行
ここまで設定した状態で、GitLabにコードの変更がPushされると、gitlab-runnerでsonar-scannerが実行され、静的解析の結果がSonarQubeに登録されるとともに、GitLabのコミットやマージリクエストに対するコメントとしても投稿される。
各登場人物の仕事を図に表すと、こんな感じ。
もし、静的解析の結果をSonarQubeのダッシュボードに登録したくない場合は、-Dsonar.analysis.mode=previewというオプションを追加すると良い。
その他のTips
SonarQubeBOTの投稿コメントに、SonarQubeダッシュボードへのリンクを追加する
SonarQube標準の設定では、GitLabに投稿されるコメントにSonarQubeダッシュボードへのリンクは含まれない。
しかし、静的解析結果を読んだら、グラフィカルなダッシュボードで詳細を見たくなるはず。
以下の設定をすることで、SonarQubeダッシュボードへのリンクを追加することができる。
Administration > Configuration > General Settings > GitLab > Global template
You can check the details on the [SonarQube dashboard](${sonarUrl}). (Login username and password is `admin`.)
The summary of the analysis results is as follows.
---
<!-- ここに、以下のURLからコピーしたマークダウンを貼り付ける -->
<!-- https://github.com/gabrie-allaigre/sonar-gitlab-plugin/blob/master/templates/global/default.md -->
Administration > Configuration > General Settings > GitLab > Inline template
You can check the details on the [SonarQube dashboard](${sonarUrl}). (Login username and password is `admin`.)
The summary of the analysis results is as follows.
---
<!-- ここに、以下のURLからコピーしたマークダウンを貼り付ける -->
<!-- https://github.com/gabrie-allaigre/sonar-gitlab-plugin/blob/master/templates/inline/default.md -->


