5
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

reviewdog🐶を飼ってGitLab-CI上で静的解析しませんか?

Last updated at Posted at 2023-04-02

はじめに

レビュワーの工数削減とヒューマンエラーを防ぎコードの品質をさらに向上させていく取り組みの一環として、自動コードレビュー(静的解析) を検討しました。

そこで、reviewdogというツールを用いて実装しようとしたのですが、
reviewdogはgithub-actionsベースで開発がされているため、gitlabでの使用に関しては、ほとんど事例・記事はありませんでした。

導入まで少しだけ苦労したので、この記事がgitlab上でreviewdogの使用を想定している人に向けて参考になれば幸いです。

reviewdogとは?

Go言語で記述されたOSS。
各種 linter 解析の検出結果を MR(またはPull Request) にコメントする形で指摘してくれるツール

以下のreviewdog開発者の記事を読むと概要が掴めると思います。

Reviewdog を飼ってコードレビューや開発を改善しませんか

スクリーンショット 2023-04-02 8.23.40.png

導入までの全体感

  1. reivewdog開発用ブランチ(feature/reviewdog)を作成
  2. feature/reviewdogdevelopブランチへのMRを作成する
  3. .gitlab-ci.ymlにreviewdog導入のスクリプトを書く
  4. 変更をpushしてGitlab CI(パイプライン)を走らせ、Gitlab CIコンソールベースで確認しデバッグを行う
  5. 3,4を、エラーがなくなりreviewdogが正常に機能するまで繰り返す
  6. developブランチにマージする

▼ 準備(テスト用リポジトリを使用する場合)

reviewdog導入テスト用のリポジトリを使用する場合はこちらから開始。
※通常は、既存リポジトリに対してreviewdog用のブランチを切って作業する方法で良い

  1. テスト用新規リポジトリ作成(例:reviewdog-testなど)

  2. .gitlab-ci.ymlの修正

  3. 試しにpushするとパイプラインが実行されない。どうやらgitlab runnerが登録されていないよう

    this job is stuck because you don't have any active runners that can run this job.
    
  4. gitlab runnerの登録

    【gitlab runnerとは?】
    GitLabのCI/CDパイプラインはリポジトリのルートにある .gitlab-ci.yml というyamlファイルによって構成されます。
    Runnerは .gitlab-ci.yml ファイル に記載された処理を実行するアプリケーション

    # gitlabインスタンスで実行
    # 新規リポジトリでのrunnerの登録
    $ gitlab-runner register
    ~
    ~
    => Runner registered successfully. Feel free to start it, but if its running already the config should be automatically reloaded!
    # gitlab-runnerの起動
    $ gitlab-runner run
    

    任意のタグでgitlab runnerが登録されていることを確認

    reviewdog0.png

    パイプラインを走らすと無事実行された!

▼ reviewdog導入

gitlabにreviewdogユーザーの作成

MRにコメントを追加するAPIトークンを取得するため、管理者メニューからユーザー追加でreviewdog用のユーザーを作成

reviewdog1.png

reviewdogユーザーでgitlabにログインしAPIアクセストークンの取得を選択

適切な権限をつけてAPIアクセストークンを発行

reviewdog2.png

※注意点
プロジェクト単位でアクセストークンを発行することもできますが、その場合アイコンを設定できないためレビューがややたんぱくになってしまう

gitlab-runnerにタグを追加

パイプラインを実行するときのstageを既存の処理と分けたいので、新しいタグ(reviewdog)を追加する
reviewdog3.png

開発用ブランチ作成

ブランチ戦略はGit Flowを採用

developブランチからfeature/reviewdogブランチを作成。

以降の作業はfeature/reviewdogブランチで行うこと。

.gitlab-ci.ymlに追記

reviewdogの導入は基本的には.gitlab-ci.yml上で行う

.gitlab-ci.ymlにjobを作成し、job内でreviewdogのコマンドを叩くことで実行される

ここでは、例として、以下3つのlinterの設定を行う

  • textlint
    • README.mdの校正
  • ESlint
    • フロントエンド(Vue.js)用のlinter
  • rubocop
    • バックエンド(ruby)用のlinter

共通部分に追記

  • variablesに先ほど取得したreviesdogユーザーのAPIトークンキーを追加する

  • ESlint用のパス設定用の環境変数を設定

  • stagesにreviewdogを追加する(パイプライン実行時にstageをtestとは分けたかったため)

    .gitlab-ci.yml
    variables:
      # reviewdogユーザーから発行したAPIトークンを設定.これがないとreviewdogがコメントできない。
      REVIEWDOG_GITLAB_API_TOKEN: 発行したアクセスキー
      # eslintのチェック対象とするdir/fileパスを指定。指定したパスに変更があったときのみreviewdog-eslintを実行する。
      ESLINT_TARGET_PATH: app/javascript/packs/
    
    stages:
      - test
      - reviewdog
    
    

textlint

  • textlintインストール
$ npm init -y  # package.jsonがすでに存在すればスキップ。だいたいすでに存在しているはず。
$ npm install --save-dev textlint # --save-devをつけることで開発環境だけに適用
$ npx textlint -v
=> v11.6.3

# textlint のルールは、本体とは別に Node パッケージとして提供されているので、ルールごとに次のようにインストール

# 「ら」抜き言葉を検出するルール
$ npm install --save-dev textlint-rule-no-dropping-the-ra
# 「〜である。〜ます。」の混在を検出するルール
$ npm install --save-dev textlint-rule-no-mix-dearu-desumasu
.gitlab-ci.yml
reviewdog-textlint:
  stage: reviewdog
  variables:
    # 「reviewdog: fail to get diff: failed to get merge-base commit: exit status 1」エラーへの対処
    GIT_STRATEGY: clone
    GIT_DEPTH: 0
  tags:
    - reviewdog
  allow_failure: true # CIに失敗してもMRをマージ可能にする設定
  rules:
    # ソースブランチがfeature/XXX かつ ターゲットブランチがdevelopブランチのときのみパイプラインに追加
    - if: '$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME =~ /^feature/ && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop"'
    # ソースブランチがhotfix/XXX かつ ターゲットブランチがmasterブランチのときのみパイプラインに追加
    - if: '$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME =~ /^hotfix/ && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "master"'
  script:
    - echo "############ reviewdog-textlint start.....############"
    - echo "source_branch:$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME"
    - echo "target_branch:$CI_MERGE_REQUEST_TARGET_BRANCH_NAME"
    # nvmのinstall
    - curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.34.0/install.sh | bash
    # nvm: command not foundへの対応
    - source ~/.nvm/nvm.sh
    # nvm install --lts 版だとエラーになるので、v16を使用。
    - nvm install 16.16.0
    # installの確認
    - node -v
    - npm -v
    # このリポジトリにあるpackage.jsonに記載された内容を元にnode moduleの読み込み
    - npm install
    # reviewdogのinstall.  bin/ 配下に実行ファイルがインストールされる
    - wget -O - -q https://raw.githubusercontent.com/reviewdog/reviewdog/master/install.sh | sh -s
    # *.md ファイルを対象にtextlintを実行
    - npx textlint -f checkstyle ./ | bin/reviewdog -f=checkstyle -name="textlint" -reporter=gitlab-mr-discussion

eslint

.gitlab-ci.yml
reviewdog-eslint:
  stage: reviewdog
  variables:
    # 「reviewdog: fail to get diff: failed to get merge-base commit: exit status 1」エラーへの対処
    GIT_STRATEGY: clone
    GIT_DEPTH: 0
  tags:
    - reviewdog
  allow_failure: true # CIに失敗してもMRをマージ可能にする設定
  rules:
    # ソースブランチがfeature/XXX かつ ターゲットブランチがdevelopブランチのときのみパイプラインに追加
    - if: '$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME =~ /^feature/ && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop"'
      changes:
        - $ESLINT_TARGET_PATH
    # ソースブランチがhotfix/XXX かつ ターゲットブランチがmasterブランチのときのみパイプラインに追加
    - if: '$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME =~ /^hotfix/ && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "master"'
      changes:
        - $ESLINT_TARGET_PATH
  script:
    - echo "############ reviewdog-eslint start.....############"
    - echo "source_branch:$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME"
    - echo "target_branch:$CI_MERGE_REQUEST_TARGET_BRANCH_NAME"
    # nvmのinstall
    - curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.34.0/install.sh | bash
    # nvm: command not foundへの対応
    - source ~/.nvm/nvm.sh
    # nvm install --lts 版だとエラーになるので、v16を使用。
    - nvm install 16.16.0
    # installの確認
    - node -v
    - npm -v
    # このリポジトリにあるpackage.jsonに記載された内容を元にnode moduleの読み込み
    - npm install
    # reviewdogのinstall.  bin/ 配下に実行ファイルがインストールされます
    - wget -O - -q https://raw.githubusercontent.com/reviewdog/reviewdog/master/install.sh | sh -s
    # -f checkstyle 対象とするdir/fileパス指定
    # 例:app/javascript/packs/**/**/*.{ts,js,vue} → ts,js,vueファイル限定
    # 例:app/javascript/packs/**/**/*.{ts,js,vue}, app/javascript/packs/**/*.{ts,js}  → 複数指定可能。但し、指定した拡張子のファイルがパスに存在していないといけない。
    # 例:app/javascript/packs/ → packs配下の全てのファイル
    - npx eslint -f checkstyle $ESLINT_TARGET_PATH | bin/reviewdog -f=checkstyle -name="eslint" -reporter=gitlab-mr-discussion

rubocop

.gitlab-ci.yml
rspec:
  image: ruby:2.7.2
  stage: test
  tags:
    - testing
    - reviewdog
  before_script:
    - hogehoge
  script:
    - hogehoge
  after_script:
    # reviewdog ✖︎ rubocopとの連携を実行
    - echo "############ reviewdog-rubocop start.....############"
    - wget -O - -q https://raw.githubusercontent.com/reviewdog/reviewdog/master/install.sh | sh -s
    - bundle exec rubocop | bin/reviewdog -f=rubocop -reporter=gitlab-mr-discussion
  artifacts:
    paths:
      - coverage/
    expire_in: 10 days

▼ 動作確認

MergeRequestを作成し、literが警告を出した箇所を確認すると、reviewdogがコメントをしてくれます。
ここまで確認できたら成功です。

アイコンが愛くるしいですね🐶

  • textlint
    reviewdog5.png

  • eslint
    reviewdog6.png

  • rubocop
    reviewdog7.png

▼ChatGPTの活用

余談ですが、ChatGPTを使用するとある程度のヒントをくれます。

細かい修正はご自身の環境でデバッグしながら行う必要があります。

以下に、質問の例を示しておきます。プロンプトエンジニアリングの観点から、「段階的かつ論理的に」という言葉を入れると良いです。

あなたは優秀なソフトウェアエンジニアです。
gitlab上にreviewdogを用いて静的解析を行いたいです。
.gitlab-ci.ymlにreviewdog導入のスクリプトを記述してたいです。
例を示して、段階的かつ論理的に教えてください。

▼参考記事

reviewdog / linter

gitlab ci

5
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?