💡

GitLab CI で Qodana の静的検査 (Code Quality もあり)

2023/09/05に公開

GitLab CI で Qodana の静的検査 (Code Quality もあり)

前回 Qodana Cloud を使ってみました。

JetBrains IDE の静的検査エンジンを単独で使えるようにしたのが Qodana (多分) なので、ローカル開発環境で動かしてもあまりうれしくありません。

というわけで、本命の GitLab CI で使ってみます。ついでに GitLab のマージリクエストで検査結果を表示してみます。

目次

GitLab CI

セットアップ

Qodana の公式サイトの GitLab CI/CD に例が書いてああるのでそれを参考にします。しかしちょっと間違ってるような気がします。

とりあえずキャッシュとか考えずにザクッと書いたのがこちらです。

qodana:
  image:
    name: jetbrains/qodana-python-community
    entrypoint: [""]
  variables:
    QODANA_TOKEN: $qodana_token
  script:
    - qodana --save-report --results-dir=$CI_PROJECT_DIR/.qodana
  artifacts:
    paths: [ .qodana/ ]
    when: always
    expose_as: Qodana

qodana:image:name: には利用するリンターの Docker Image を指定します。Qodana Docker イメージから適当に選びます。今回は Python の無償版を利用しました。

variables:QODANA_TOKEN: で Qodana Cloud のプロジェクトのアクセストークンを指定します。GitLab プロジェクトの CI/CD 変数に qodana_token を追加して、アクセストークンを設定してください。なお、Qodana Cloud にレポートをアップロードする必要がなく、コミュニティ版のリンターしか使わない場合は CI/CD 変数の設定は不要です。今回は設定していません。

スキャンした結果は、作業用ディレクトリの .qodana ディレクトリに出力しています。artifacts: でこのレポートを GitLab にアップロードして、Merge Request などからレポートをダウンロードできるようにします。

when: always はスキャンでエラーがあったときに CI ジョブを失敗させることができますが、その場合でもレポートを GitLab にアップロードするために設定しています。この設定を忘れると、CI ジョブが失敗してエラーを見たいのに、レポートがアップロードされていないという悲しい目にあいます。

expose_as: を付けておくと、マージリクエストにレポートディレクトリへのリンクが追加されます。

静的検査を CI で実行する

ブランチを作成し、問題のある新しい Python ファイルを追加します。

main.py
def hello(a):
  pass

これをコミット & プッシュすると qodana ジョブで静的検査が開始されます。マージリクエストを作成すると、静的検査の結果をマージリクエストからアクセスできて便利です。

でもちょっと使い勝手が悪いです。

  • 検査結果を見るためには SARIF ファイルをダウンロードして、JetBrains IDE に食わせなければなりません。面倒です。
  • 静的検査結果の HTML レポートは、GitLab Pages 経由でブラウザー上で表示できます。しかし、エラーで表示できません。

レポートをマージリクエストで見る

せっかく CI で静的検査したのに、レポートを見るのがこんなに面倒なのは本末転倒ですよね。というわけで、マージリクエストなどのページからすぐにレポートにアクセスできるようにします。

GitLab には Code Quality という機能があります。これは静的検査の結果をマージリクエストに表示する機能です。(SARIF 形式は受け付けず、Code Quality 形式出なければなりません)

SARIF ファイルを Code Quality 形式に変換する SARIF Converter を使います。

qodana:
  image:
    name: jetbrains/qodana-python-community
    entrypoint: [""]
  variables:
    QODANA_TOKEN: $qodana_token
  script:
    - qodana --save-report --results-dir=$CI_PROJECT_DIR/.qodana
  after_script:
    - curl -L -o sarif-converter https://gitlab.com/ignis-build/sarif-converter/-/releases/permalink/latest/downloads/bin/sarif-converter-linux
    - chmod +x sarif-converter
    - ./sarif-converter --type codequality .qodana/qodana.sarif.json gl-code-quality-report.json
  artifacts:
    paths: [ .qodana/ ]
    when: always
    expose_as: Qodana
    reports:
      codequality: gl-code-quality-report.json

after_script: で SARIF Converter をダウンロードして、SARIF ファイルを変換しています。

artifacts:reports:codequality: に変換後のレポートファイルを指定して添付します。

一旦これで、メインブランチにコミットしてプッシュしてください。

その後、ブランチを作成して問題がある Python ファイルを作成し、コミットしてプッシュしてマージリクエストを作成します。(作成したマージリクエスト)

なお、Premium 以上を購入していれば、コード差分で問題のあるコードを確認できて便利です。

Qodana Cloud で見る

静的検査のレポートは Qodana Cloud で見た方がいいです。Qodana Cloud のプロジェクトアクセストークンを GitLab CI/CD 変数 qodana_token に設定すれば、レポートは Qodana Cloud にアップロードされ、Qodana Cloud で表示できます。

最後に

これで GitLab CI と Code Quality で静的検査とそのレポートを見ることができるようになりました。

ところで、静的検査は IDE でやった方がいいのでしょうか? それとも CI でやった方がいいのでしょうか?

開発では問題を後回しにすればするほど改修にかかるコストが膨らんでいきます。CI でのコード検査は結果が出るまでに時間がかかるだけでなく、同じような指摘をたくさん食らいます。修正のコストもばかになりません。なので、静的解析は IDE 上でコードを書いている最中に行います。書いたはなから指摘されるので、修正のコストはかなり下がり、修正が苦ではなくなります。

では CI での静的検査が不要かと言われるとそうでもありません。静的検査はソースコードの増大に伴いすごく時間がかかるようになります。IDE はそれを避けるために、今書いているソースコードだけを静的検査にかけることがほとんどです。検査結果を無視する開発者もいます。結果、静的検査をすり抜けることがよくあります。その保険のために CI での静的検査を活用します。

コミット時に全検査すればいいと思われるかもしれませんが、コミットに時間がかかるようになると、開発者はコミットを小まめにやらなくなります。これはこれで問題があるので、IDE での検査と CI での検査の両方を活用するのがおすすめです。

次回は Qodana の設定周りを解説してみます。

Discussion