しおメモ

雑多な技術系ブログです。

iOS(Swift)プロジェクトにSonarCloudを導入する

今回は、静的解析ツールのSonarQubeのクラウド版、 SonarCloudを導入します。

Travis, fastlane導入までは、前回の記事をご参照ください。 scior.hatenablog.com


環境

(追記: 2018/10/8) Xcode 10は❌です。 カバレッジレポートのパスが変わったので現在調査中。
Xcode10⭕️です。

Ruby関連は、

  • ruby 2.5.1p57
  • bundler 1.16.2
  • fastlane 2.104.0

SonarQube

SonarQubeは、静的解析によって、脆弱性やバグ、コードの重複などを診断するサービスです。
他の機能で測定した、Coverage Reportも表示してくれます。
サポートしている言語も多いので、今回Swiftにも導入してみました。

Continuous Inspection | SonarQube

見た目はこのようになっています。
(ほぼ空のプロジェクトなので、クリーンな状態です。)

f:id:scior:20180917223853p:plain

ローカルや自前のサーバーで使うこともできますが、
今回はホスティング版のSonarCloudを利用します。

こちらは、publicリポジトリに対しては無料です。

自前で環境を用意したい方はこちらです。

Downloads | SonarQube

Continuous Inspection

アカウント登録

SonarCloud https://sonarcloud.io/

こちらから、各種ソースホスティングサービス(GitHubなど)と連携して、アカウントを作成します。
登録の際にリポジトリを指定して読み込めますが、後から追加で読み込む際は、
SonarCloudからでは出来ないので、GitHub側から指定します。

GitHubのアカウント設定のApplicationsの画面を開き、

f:id:scior:20180917221523p:plain

Configureからリポジトリを追加します。

f:id:scior:20180917221529p:plain

Select repositoriesで追加したいリポジトリを選びます。

SonarCloudの設定

リポジトリの追加後、この画面に遷移します。

f:id:scior:20180917221535p:plain

適当な名前をつけて、tokenを生成します。

f:id:scior:20180917221538p:plain

上の画像のようにOther, macOSを選択して、sonar-scannerをダウンロードしてPATHを通すと、
一番下のコマンドで、ローカルのソースコードを直接SonarCloudにかけることができます。
(ただし、Swiftの場合、次のsonar-project.propertiesで、
sonar.language=swiftを設定してからでないと、うまく動きません。)

sonar-project.properties

プロジェクトルートにsonar-project.propertiesを作ります。
今回は、MinimumWKWebViewというプロジェクトを例にします。

github.com

# SonarQubeで割り振られるプロジェクトごとのキー
sonar.projectKey=Scior_MinimumWKWebView
sonar.projectName=MinimumWKWebView
sonar.projectVersion=1.0
# 今回はSonarCloudを用いるのでそちらに向ける
sonar.host.url=https://sonarcloud.io

sonar.language=swift
sonar.sources=MinimumWKWebView
# 静的解析の対象を指定する
sonar.inclusions=MinimumWKWebView/**
# カバレッジレポートの場所を指定
sonar.coverageReportPaths=sonarqube-generic-coverage.xml

sonar.projectKeyはSonarCloudに記載されているので、そちらを指定します。

sonar.inclusionsで解析の対象を指定します。
こちらを記述しない場合、fastlaneの.swiftファイルなども解析されてしまい、
ひどい結果になります。

Travis CIとの連携

Using SonarCloud with Travis CI - Travis CI

こちらのTravisのドキュメントを参考に進めていきます。
TravisCUIツールを用いて、先ほど取得したtokenを暗号化します。
(インストール: gem install travis)

travis encrypt [token]

出力された暗号化されたtokenを.travis.ymlに追記します。
organizationはSonarCloudのページに記載されているキーです。

dist: trusty

addons:
  sonarcloud:
    organization: "scior-github"
    token:
      secure: ********

scriptの適切な位置に、sonar-scannerを追加します。

script:
  # -XオプションでDebug出力される
  - sonar-scanner -X

ここまでで、静的解析の結果がSonarCloudに反映されます。

Coverage Reportの反映 (Xcode 9.3+)

xccovの利用

Xcode 9.3からxccovを使って、Coverage測定ができるようになりました。
xcodebuildで生成される.xccovarchivedファイルを、
SonarCloudが解釈できる形にパースして、Travisから渡します。

SonarQubeの解説: Swift Coverage Results Import - Plugins - Doc SonarQube

パースするシェルスクリプトは、下のものを利用します。

github.com

こちらのxccov-to-sonarqube-generic.shを用いて、XMLに変換します。
このシェルスクリプトを、プロジェクトの適当な場所にコピーします。
(今回は./utils/に置きました。)

  • .travis.yml
script:
  - fastlane coverage # 前回のfastlaneの時のスクリプト
  - find . -type d | grep -E  ".xccovarchive$" | xargs -I@ bash utils/xccov-to-sonarqube-generic.sh @ > sonarqube-generic-coverage.xml
  - sonar-scanner -X

fastlaneのビルド結果は、デフォルトではDerivedData云々の、
探しづらい場所に出力されてしまうので、出力先を./Buildに変更します。
(findのところは、-name-execなどお好みでお願いします。)

  • Fastfile
default_platform(:ios)

platform :ios do
  desc "Test"
  lane :test do
    scan(
      derived_data_path: "Build"
    )
  end
end

slatherなど他のコマンドを記述している場合は、そちらにも追記します。

試していないこと

fastlaneにもsonarコマンドがあるのですが、カバレッジの反映まで出来るかどうか、
encryptされたtokenが使えるかどうかなど、不明点が多いので未検証です。

その他参考

SonarQube Integration for Swift – SayTech