初めまして、システムソリューショングループのナオキです。
皆さんは自分が作ったプログラムに不安を感じたことはありませんか? 私は、不安に感じることがあります。完成したと思っていても、ミスがあった。ということはほとんどの方が経験したことがあると思います。
静的解析ツール「SonarQube」は、そういったケアレスミスを無くすために重宝します。
標準化と品質管理への取り組み
現在私は色々な社内開発環境の標準化を進めており、今回はその中の静的解析ツールの一つであるSonarQubeと、CI/CDツールJenkinsでのコード自動検証の紹介をしたいと思います。
SonarQubeとは
SonarQubeとは、オープンソースの品質管理プラットフォームです。
品質管理プラットフォームと言われても、イメージが沸かない方もいらっしゃるかと思います。
噛み砕いて説明すると、様々な言語のソースコードに対し、コード内の「バグ発見」「脆弱性発見」「メンテナンス困難なコード検出」などをサポートする自動コードレビューツールです。また、人の目では見逃してしまいがちな細かい部分までしっかりと解析してくれます。また、CI/CD環境に組み込むことで、定期的に自動チェックを行うことが可能となります。
SonarQubeの解析結果
SonarQubeで解析を行った結果は、このようにブラウザから詳細に確認することができます。
SonarQubeが出力するエラーや警告は非常に詳細で、何がリスクなのか、場合によってはどう解決すべきなのかまでを知らせてくれます。
言語毎の一般的な文法エラーは当然ですが、開発中には気づくことが難しいセキュリティに関する脆弱性なども警告してくれます。
そして、SonarQubeを最新化することで最新のセキュリティ要件にも対応することができます。
SonarQubeの進化
SonarQube V7.4以前は、Rubyのサポートがなく、GitHubから非公式のプラグインを導入し、プラグインのパスやファイルの拡張子を指定する必要がありました。
また、SonarQube V8.5より前は、特定の言語を解析したい時、プラグインのダウンロードや導入など様々な設定が必要でしたが、V8.5(2020/10/09)からは、言語プラグインをインストールする必要がなくなり、最新版のSonarQubeをインストールするだけで、様々な言語を解析してくれるようになりました。
これによって、SonarQubeのアクセシビリティが大幅に向上し、手軽に使えるようになりました。
SonarQube標準対応言語(Community Version 9.1現在)
・C#
・CSS
・Flex
・Go
・Java
・JavaScript/TypeScript
・Kotlin
・PHP
・Python
・Ruby
・Scala
・VB.NET
・HTML
・XML
SonarQubeと他ツールの連携
SonarQube単体では、コマンドを自分で実行して解析にかける必要があり、チェックしたいタイミングで都度実行が必要となります。
解析作業を自動化するためにGitHubと連携し、JenkinsによりSonarQubeを自動で実行します。
流れは、次のようになります。
1.GitHubにファイルをpush
2.Jenkinsがpushイベントを検知
3.自動的にファイルをpull
4.SonarQubeに送り、静的解析
SonarQubeプロジェクト作成
1.「Create Project」→「<> Manually」の順で選択
2.プロジェクト名を入力
「Project key」は自動で入力されます。
「Set Up」をクリックします。
3.「Locally」を選択
4.Generate a token(トークンを生成する)
token名を入力し、「Generate」をクリックします。
5.生成されたトークンを確認
「Continue」を押下。
6.Run analysis on your projectを以下のように選択
What option best describes your build? : 「Other」
What is your OS? : 「Linux」
この後、Execute the Scanner欄のコードをコピーし、JenkinsのPipeline script内にペーストします。
念のためメモを取ってください。
Jenkinsでのパイプライン設定
パイプライン作成
1.「新規ジョブ作成」を選択
2.パイプライン作成
ジョブ名入力:任意の名前
「パイプライン」を選択します。
「OK」をクリック
パイプライン設定
1.ダッシュボードから作成したパイプラインを選択→「設定」
2.GitHub Project
「GitHub project」にチェックを入れます。
Project URL:https://github.xxxxx.com/xxxx/xxxxx (連携するgitHubのURL)
Gitlab Connection:GitHubの接続の際に作成した「Connection name」を入力します。
3.ビルドトリガ
「SCMをポーリング」にチェックを入れます。
TZ=Asia/Tokyo タイムゾーンをTokyoに設定します。
H/15 * * * * 15分間隔で実行するように設定します。
他にも下記のように様々な設定が出来ます。
・H 0,8,16 * * * (毎日0時,8時,16時に実行)
・H 19 * * 1-5 (平日19時に実行)
4.パイプラインスクリプト
定義:Pipeline script
Script:設定に関しては、次の項目に記載してあります。
「保存」を押下
Pipeline script(言語別)
credentialsId(認証情報)は「Jenkinsの管理」→「Manage Credentials」で作成/確認できます。
「Dsonar.projectKey」と「Dsonar.login」は、先ほどSonarQubeで生成したコード内にあります
各環境に合わせ、下記の設定を行う
・「tools」
・「git branch」
・「credentialsId」
・git cloneのURL「url」
・SonarQubeプロジェクトのキー「Dsonar.projectKey」
・SonarQubeプロジェクトのトークン「Dsonar.login」設定後、「保存」を押下
Java
pipeline {
agent any
stages {
stage("Code Checkout from GitHub") {
steps {
//ブランチ名を設定します。
git branch: 'develop',
//認証情報
credentialsId: 'xxxxxxx',
//git cloneのURLを入力します。(https)
url: 'https://github.xxxxx.com/xxxxx/xxxxx.git'
}
}
stage('Code Quality Check via SonarQube') {
steps {
script {
def scannerHome = tool 'sonarqube-scanner';
withSonarQubeEnv("sonarqube-container") {
//sonarQubeのプロジェクトからスキャナーコードをコピーします。
//(別記事:SonarQubeの設定方法を参照)
sh "${tool("sonarqube-scanner")}/bin/sonar-scanner \
-Dsonar.projectKey=xxxxx \
-Dsonar.sources=. \
-Dsonar.host.url=http://sonarqube:9000 \
-Dsonar.login=xxxxxxxxxxxxxxxxxxxxxxx \
-Dsonar.java.binaries=**/*"
//コンパイルされたバイトコードファイルが含まれたディレクトリが存在しない場合は、
//-Dsonar.java.binaries=**/*"を使用し、
//存在する場合は-Dsonar.java.binaries=の後にディレクトリのパスを指定します。
}
}
}
}
}
}
JavaScript/TypeScript(node.jsの設定も入れてあります。)
pipeline {
agent any
//toolsでnode.jsを追加します。
tools{
nodejs 'nodejs16'
}
stages {
stage("Code Checkout from GitHub") {
steps {
//ブランチ名を設定します。
git branch: 'develop',
//認証情報
credentialsId: 'xxxxxxx',
//git cloneのURLを入力します。(https)
url: 'https://github.xxxxx.com/xxxxx/xxxxx.git'
}
}
stage('Code Quality Check via SonarQube') {
steps {
script {
def scannerHome = tool 'sonarqube-scanner';
withSonarQubeEnv("sonarqube-container") {
//sonarQubeのプロジェクトからスキャナーコードをコピーします。
//(別記事:SonarQubeの設定方法を参照)
sh "${tool("sonarqube-scanner")}/bin/sonar-scanner \
-Dsonar.projectKey=xxxxx \
-Dsonar.sources=. \
-Dsonar.host.url=http://sonarqube:9000 \
-Dsonar.login=xxxxxxxxxxxxxxxxxxxxxxx"
}
}
}
}
}
}
Ruby・Go・Python・HTML・CSSなど
pipeline {
agent any
stages {
stage("Code Checkout from GitHub") {
steps {
//ブランチ名を設定します。
git branch: 'develop',
//認証情報
credentialsId: 'xxxxxxx',
//git cloneのURLを入力します。(https)
url: 'https://github.xxxxx.com/xxxxx/xxxxx.git'
}
}
stage('Code Quality Check via SonarQube') {
steps {
script {
def scannerHome = tool 'sonarqube-scanner';
withSonarQubeEnv("sonarqube-container") {
//sonarQubeのプロジェクトからスキャナーコードをコピーします。
//(別記事:SonarQubeの設定方法を参照)
sh "${tool("sonarqube-scanner")}/bin/sonar-scanner \
-Dsonar.projectKey=xxxxx \
-Dsonar.sources=. \
-Dsonar.host.url=http://sonarqube:9000 \
-Dsonar.login=xxxxxxxxxxxxxxxxxxxxxxx"
}
}
}
}
}
}
これでJenkinsとSonarQubeの連携が可能となりました。