SonarQubeの検証結果をGitHubPullRequestのstatusに連携する方法
SonarQubeという静的コード解析ツールがありますが、
解析結果をGitHubのPullRequestステータスに連携すると、
開発フローのプロセスに、コードの品質チェックを組み込むことができます。
SonarQube
https://www.sonarqube.org/
このエントリでは、SonarQubeとGitHubのAPIを利用して、
SonarQubeの解析結果を、GitHubのPullRequestのステータスに反映する手順を説明します。
前提とする環境:
SonarQube 7.0
※ブランチ毎にSonarQube ScannerでSonarQubeに解析結果を連携済みのこと。
※GitHubでPullRequstによるレビューを運用していること。
SonarQubeとGitHub連携には、
SonarQubeでの指摘をPullRequestにコメントする方法もありますが。
このエントリでは、
品質基準を満たしていないPullRequestのステータスをfailureにして
masterブランチへ、mergeさせ無いように連携させることにします。
以下の流れで連携させていきます。
- SonarQubeの解析結果の取得
- GitHub PullRequestへのステータス設定
ここでは、以下のいずれかの条件に合致する場合はstatusを失敗にします。
- QualityGateでERRORが存在する
- BLOCKER, CRITICALレベルのIssueが1件でも存在する
SonarQubeの解析結果の取得
まず、SonarQubeAPIを使って解析結果を取得します。
QualityGateの結果、Issueの件数を順に取得していきます。
SonarQubeAPIの呼び出し方
SonarQubeAPIの呼び出し方は、以下のURLの通りです。
Web API | Doc SonarQube
https://docs.sonarqube.org/display/DEV/Web+API
ログインIDとパスワードを使う場合:
※$SONARQUBE_HOST/MY_LOGIN/MY_PASSWORDは自分の環境のものに置き換えます。
curl -u MY_LOGIN:MY_PASSWORD https://$SONARQUBE_HOST/api/user_tokens/search
tokenを使う場合:
※$SONARQUBE_HOST/SONARQUBE_TOKENは自分の環境のものに置き換えます。
curl -u SONARQUBE_TOKEN https://$SONARQUBE_HOST/api/user_tokens/search
APIによるQualityGate結果の取得
SonarQubeには、QualityGateという
コード品質のプラクティスを遵守させるためのQualityGateという仕組みがあります。
※具体的には、新規追加コードのテストカバレージ・コピー&ペーストしたコードの量などの基準が指定できます。
SonarQubeAPIで、この解析結果を取得することにします。
以下のようにするとQualityGateの結果を取得できます。
※$SONARQUBE_HOST/$PROJECT_KEY/SONARQUBE_TOKENは自分の環境のものに置き換えます。
curl -u $SONARQUBE_TOKEN https://$SONARQUBE_HOST/api/qualitygates/project_status?projectKey=$PROJECT_KEY
ここでは、OK/ERRORのステータスだけあれば十分なので、以下のようにjqで加工します。
curl -u $SONARQUBE_TOKEN https://$SONARQUBE_HOST/api/qualitygates/project_status?projectKey=$PROJECT_KEY | jq -r '.projectStatus.status'
後で使いやすいように、シェルの関数にまとめておきます。
#!/bin/bash
get_sonarqube_qualitygate_status() {
SONARQUBE_HOST=$1
SONARQUBE_TOKEN=$2
PROJECT_KEY=$3
REQUEST_URL="https://$SONARQUBE_HOST/api/qualitygates/project_status?projectKey=$PROJECT_KEY"
STATUS=$(curl -u $SONARQUBE_TOKEN -s $REQUEST_URL | jq -r '.projectStatus.status')
echo $STATUS
}
get_sonarqube_qualitygate_status $SONARQUBE_HOST $SONARQUBE_TOKEN $PROJECT_KEY
マニュアルからは、このAPIの記述が見つけられなかったのですが、
以下のissueに使用例が書かれていました。
api/resources is deprecated since SonarQube 5.6 | GitHub
https://github.com/andnyb/sonarqube-slack-pusher/issues/20
APIによるIssue結果の取得
次にIssue(SonarQubeによる指摘事項)の件数を、取得することにします。
以下のようにするとIssueの一覧を取得できます。
※$SONARQUBE_HOST/$PROJECT_KEY/$SONARQUBE_TOKENは自分の環境のものに置き換えます。
curl -u $SONARQUBE_TOKEN -s "https://$SONARQUBE_HOST/api/issues/search?componentRoots=$PROJECT_KEY&severities=BLOCKER,CRITICAL&statuses=OPEN,REOPENED"
jqで加工し、Issueの件数を数えます。
curl -u $SONARQUBE_TOKEN -s "https://$SONARQUBE_HOST/api/issues/search?componentRoots=$PROJECT_KEY&severities=BLOCKER,CRITICAL&statuses=OPEN,REOPENED" | jq '.issues[].key' | wc -l
こちらも、後で使いやすいようにシェルの関数にまとめておきます。
#!/bin/bash
count_sonarqube_issues() {
SONARQUBE_HOST=$1
SONARQUBE_TOKEN=$2
PROJECT_KEY=$3
SEVERITIES=$4
REQUEST_URL="https://$SONARQUBE_HOST/api/issues/search?componentRoots=$PROJECT_KEY&severities=$SEVERITIES&statuses=OPEN,REOPENED"
COUNT=$(curl -u $SONARQUBE_TOKEN -s $REQUEST_URL | jq '.issues[].key' | wc -l)
echo $COUNT
}
count_sonarqube_issues $SONARQUBE_HOST $SONARQUBE_TOKEN $PROJECT_KEY BLOCKER,CRITICAL
このAPIの使い方は以下を参照してください。
Web Service /api/issues | Doc SonarQube
https://docs.sonarqube.org/pages/viewpage.action?pageId=2392181
GitHub PullRequestへのステータス設定
次に、取得した解析結果をGitHubのステータスに反映します。
GitHubAPIによるStatusの設定方法
GitHubAPIによるStatusの設定方法は、以下のURLの通りです。
REST API v3 | GitHub Developer
https://developer.github.com/v3/
Statuses | GitHub REST API v3
https://developer.github.com/v3/repos/statuses/
具体的には、以下のように呼び出します。
curl -u $GH_ACCESS_TOKEN \
-X POST \
--data "{\"state\":\"${GH_STATE}\", \"target_url\":\"${GH_TARGET_URL}\", \"description\":\"${GH_DESCRIPTION}\", \"context\":\"${GH_CONTEXT}\"}" \
https://api.github.com/repos/$GH_PROJECT_USERNAME/$GH_PROJECT_REPONAME/statuses/${GIT_SHA1}
変数は、それぞれ以下のように置き換えます。
- $GH_ACCESS_TOKENは、GitHubの設定からpersonal access tokenを取得したものに置き換え。
- $GH_STATEは、success/failureのいずれか
- $GH_TARGET_URLは、statusにつけるリンク先(SonarQubeのDashboardなど)
- $GH_DESCRIPTIONは、ステータスの説明(BLOCKER/CRITICALのissue数など)
- $GH_CONTEXTは、ステータスを識別する名称(「sonarqube-status」などを指定)
- $GH_PROJECT_USERNAME,$GH_PROJECT_REPONAMEは、GitHubリポジトリの名称
- $GIT_SHA1は、GitのコミットのSHA1
これもシェルの関数にしておきます。
#!/bin/bash
gh_status_post() {
GH_ACCESS_TOKEN=$1
GH_PROJECT_USERNAME=$2
GH_PROJECT_REPONAME=$3
GIT_SHA1=$4
GH_STATE=$5
GH_TARGET_URL=$6
GH_DESCRIPTION=$7
GH_CONTEXT=$8
POST_URL=https://api.github.com/repos/${$GH_PROJECT_USERNAME}/${GH_PROJECT_REPONAME}/statuses/${GIT_SHA1}
curl -u $GH_ACCESS_TOKEN \
-X POST \
--data "{\"state\":\"${GH_STATE}\", \"target_url\":\"${GH_TARGET_URL}\", \"description\":\"${GH_DESCRIPTION}\", \"context\":\"${GH_CONTEXT}\"}" \
$POST_URL
}
gh_status_post $GH_ACCESS_TOKEN $GH_PROJECT_USERNAME $GH_PROJECT_REPONAME $GIT_SHA1 $GH_STATE $GH_TARGET_URL $GH_DESCRIPTION $GH_CONTEXT
SonarQube解析結果をステータスに反映
ここまでの内容をまとめると、
SonarQubeの解析結果をGitHubのステータスに反映できます。
#!/bin/bash
get_sonarqube_qualitygate_status() {
※同じなので省略
}
count_sonarqube_issues() {
※同じなので省略
}
gh_status_post() {
※同じなので省略
}
SONARQUBE_HOST=<SonarQubeホスト名を指定>
SONARQUBE_TOKEN=<SonarQubeトークンを指定>
PROJECT_KEY=<SonarQubeのキー名を指定>
GH_ACCESS_TOKEN=<GitHubのトークンを指定>
GH_PROJECT_USERNAME=<GitHubリポジトリのUser/Organization名を指定>
GH_PROJECT_REPONAME=<GitHubリポジトリ名を指定>
GIT_SHA1=<GitのCommitのSHA1を指定>
GH_CONTEXT=<GitHubステータスの識別名を指定>
QG_STATUS=$(get_sonarqube_qualitygate_status $SONARQUBE_HOST $SONARQUBE_TOKEN $PROJECT_KEY)
CRITICAL_CNT=$(count_sonarqube_issues $SONARQUBE_HOST $SONARQUBE_TOKEN $PROJECT_KEY BLOCKER,CRITICAL)
GH_STATE=success
if [ "$QG_STATUS" = "ERROR" ]; then
GH_STATE=failure
GH_DESCRIPTION="Quality Gate Failed, $CRITICAL_CNT Critical Issues"
else
GH_DESCRIPTION="Quality Gate Passed, $CRITICAL_CNT Critical Issues"
fi
if [ $CRITICAL_CNT -gt 0 ]; then
GH_STATE=failure
fi
GH_TARGET_URL=https://$SONARQUBE_HOST/dashboard?id=$PROJECT_KEY
gh_status_post $GH_ACCESS_TOKEN $GH_PROJECT_USERNAME $GH_PROJECT_REPONAME $GIT_SHA1 $GH_STATE $GH_TARGET_URL "$GH_DESCRIPTION" $GH_CONTEXT
このスクリプトをCIツールに組み込み、
SonarQube Scannerを実行した後で呼び出せばステータスが反映されるようになります。
※リポジトリ名やブランチ名は利用しているCIツールの仕様に合わせて取得してください。
仕上げにGitHubのProtectedBranch機能で、
ここで作成したステータスを必須にすれば、
開発フローでSonarQubeの品質チェックを遵守させることが出来るようになります。
Enabling required status checks | GitHub Help
https://help.github.com/articles/enabling-required-status-checks/