プログラムを中心とした個人的なメモ用のブログです。 タイトルは迷走中。
内容の保証はできませんのであしからずご了承ください。

2017/12/28

[C#] GitLab CI と SonarQube で .NET アプリケーションの CI を行う

event_note2017/12/28 1:37

以前の記事で SonarQube を使って .NET アプリケーションの静的解析を行いました。
今回はこれに GitLab CI を使って継続的インテグレーションを行います。

具体的には Push をトリガーとして自動的にコードを解析を行い、またその解析結果をマージリクエストの画面に表示します。
尚、Jenkins 等の他の CI ツールは必要ありません。

環境

  • GitLab 10.2.0
  • gitlab-runner 10.2.0
  • SonarQube 6.7
  • SonarQube Scanner for MSBuild 4.0
  • .NET Core 2.0

準備

GitLab と SonarQube の環境構築は済んでいる前提です。
Docker を使った環境構築については以下を参考にしてください。

また、GitLab CI を使うためにはタスクランナーとして gitlab-runner が必要です。

以下の記事に書いたように、C# プログラムのコード解析には OpenCover と SonarQube Scanner を使っていますが、これらは Windows 上でしか動作しません。

従って、gitlab-runner は Windows 上にインストールしたものを使う必要があります。
gitlab-runner を Windows にインストールする手順については以下の記事を参照してください。

GitLab に gitlab-runner を登録するところまでも済んでいる前提とします。

GitLab の設定

ユーザーの追加

SonarQube から GitLab に通知するためのユーザーを GitLab に作成します。
後で SonarQube の設定を行うときに作成したユーザーのトークンが必要になります。
トークンは作成したユーザーでログインし、Account のメニューの Private Token で確認できます。
もちろん、別途トークンを作成しても OK です。

Pipeline 失敗時のマージ拒否

Pipeline で失敗している場合にマージリクエストをマージできないようにしたい場合は、該当のプロジェクトで以下を設定します。

[Edit Project] > Only allow merge requests to be merged if the build succeeds を ON にし、Save changes をクリック

SonarQube の設定

管理者アカウントでログインして以下のことを行います。

GitLab Plugin のインストール

[Administration] > [Marketplace] > GitLab で検索し、GitLab をインストールします。

インストールしたら SonarQube を再起動します。

GitLab Plugin の設定

[Administration] > [Configuration] > サイドメニューより GitLab を選択します。

GitLab urlGitLab User Token を設定します。
GitLab User Token には、あらかじめ GitLab に作成しておいたアカウントのトークンを設定します。

詳細は以下を参照してください。

プロジェクトの設定

該当のプロジェクトの画面で以下を設定します。

[Administration] > [General Settings] > サイドメニューより GitLab を選択します。

GitLab Project id を設定します。

.gitlab-ci.yml の作成

GitLab と SonarQube の設定が完了したら、.gitlab-ci.yml を作成します。

SonarQube のコード解析の部分だけのサンプルですが、例えば以下のような感じです。

variables:
  SONARSCANNER: "C:\\SonarQube\\sonar-scanner-msbuild-4.0.0.821\\MSBuild.SonarQube.Runner.exe"
  SONARHOST: "http://localhost:9000"
  SONARKEY: "projectkey"
  REPORT: "coverage.xml"
stages:
  - test
Job1:
  stage: test
  script:
    # GitLab のコンソールログでの文字化け対策
    - chcp 65001
    # SonarQube による解析(環境変数を先頭に置くと yaml パーサーでエラーになるので call をつけている)
    - call %SONARSCANNER% begin /d:sonar.host.url=%SONARHOST% /k:%SONARKEY% /v:"1.0" /d:sonar.analysis.mode=preview /d:sonar.cs.opencover.reportsPaths=%REPORT% /d:sonar.gitlab.commit_sha=%CI_COMMIT_SHA% /d:sonar.gitlab.project_id=%CI_PROJECT_ID% /d:sonar.gitlab.ref_name=%CI_COMMIT_REF_NAME%
    - dotnet build
    - call .\OpenCover.bat %REPORT%
    - call %SONARSCANNER% end
  tags:
    - windows

OpenCover の解析部分はバッチファイルにしていますが、中身については以下の記事を参考にしてください。

SonarQube の解析も、後述するように SonarQube Server と GitLab の通知のために2回行うことを前提にするならば、バッチファイルにして処理を共通化したほうが良いかなと思います。

まぁそれはともかく、とりあえずこれで全て完了です。 これで以下のように動作します。

  • GitLab に Push したタイミングで GitLab CI の機能により、最新コミットのコード解析が行われる
  • SonarQube での解析結果が GitLab に通知される
  • 解析を行ったコミットが含まれるマージリクエストに指摘事項が表示される

マージリクエストの画面にはこんな感じで表示されます。

SonarQube Scanner for MSBuild のパラメータの一覧は以下を参照してください。

.gitlab-ci.yml で使用できる環境変数の一覧は以下を参照してください。

今回使用しているパラメータについては以下に簡単に説明します。

sonar.analysis.mode

デフォルトは publish で、この場合、解析結果が SonarQube Server にアップロードされます。
GitLab に通知したい場合は、preview を指定する必要があります。

SonarQube Server と GitLab の両方に通知したい場合は、面倒ですが sonar.analysis.mode の値を変えて2回解析を実行する必要があります。
尚、publish の場合に後述の GitLab 関連のオプションを設定していると解析に失敗するので注意です。

sonar.host.url

SonarQube Server の URL を指定します。

sonar.cs.opencover.reportsPaths

OpenCover の出力ファイルを指定します。

sonar.gitlab.commit_sha

解析対象の Git のコミットのハッシュ値を指定します。

sonar.gitlab.project_id

GitLab のプロジェクト ID を指定します。
SonarQube のプロジェクト設定で設定済みの場合は不要っぽいです。

sonar.gitlab.ref_name

ブランチ名を指定します。

sonar.gitlab.user_token

GitLab に通知する際のユーザーのトークンを指定します。
SonarQube で設定済みの場合は不要っぽいです。

はまったところ

何度見直しても正しく設定しているはずなのに、解析結果が GitLab に通知されずずっと悩んでいました。

解析ログをよく見ると、以下の警告が表示されていました。

The project does not have a valid "ProjectGuid."

ProjectGuid が何なのかわからないまま調べてみると、どうやら .NET Core の ProjectGuid 変更になったらしく、これを手動で追加すると解析結果が GitLab に通知されるようになりました。
詳細は以下の記事を参照してください。

参考 URL