Prontoを実行するGithub Actionを作った


Ruby でコードを書くときに Rubocop などでコードチェックするのは品質向上に役立つと思う。
Pronto を使って Rubocop を実行すると Github のプルリクエストにコメントとしてエラーを指摘してくれる。
あんまりいい例でないけどこんな感じ。

チーム開発するときには「不要な改行は取ってください」とかレビューでコメントしなくて良くなるし、1人で開発するときにもうっかりミスを防げて良い(私は1人でも実装中のメモを残すためにプルリクエストを作ったりする)。

自動で実行されないと結局使わなくなっていくので、CIサービスなどで実行していたのだけど、Github Workflow で実行できればそれが一番手軽なのでやってみた。

最初は Pronto の README に記載されているGitHub Actions Integration を見ながらワークフローを定義して使っていたのだけど、pronto 等の gem インストールだけで1分以上かかっていた。
予め、 pronto 関連 gem をインストールしたDockerイメージを利用すれば時間短縮できるのでは? と思い立ち、 Github Actionを作った1。結果としてイメージのPullにかかる時間は10秒少々なので時間短縮できた。

作ったものは次で公開している。

以下、公開している Pronto Action について紹介する。

サポートしている Pronto runners

次のPronto Runnerを使えるようにしている。

Runnerはもっとたくさんあるが、Ruby(Rails)でなにか作るときにこれくらいが使えればさしあたって私には事足りると思う。

サポートしている Rubocop extentions

Rubocop は徐々にチェック内容ごとにExtentionとして分割されているが、こちらはできる限り含めるようにした。

上記以外に cookstyleもあるのだけど、インストールでエラーが起ったので除外した2

設定項目

ワークフローを定義するときに Pronto Action に設定できる項目は次の通り。

name reqire default
github_token true --
commit false origin/master
runner false rubocop
formatters false github_status github_pr
path false '.'

基本的に Pronto の Usageに記載されているOptionと同じ3

設定例

ワークフローの設定例を紹介する。

Rubocop を実行する

シンプルに Rubocop を実行するワークフローの定義は次の通り。

The followoing yaml is a simplest workflow difinition of using pronto-action.

.github/workflows/pronto-rubocop.yaml
name: Pronto
on:
  pull_request:
    types: [opened, synchronize]
jobs:
  pronto:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v1
      - uses: HeRoMo/[email protected]
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}

指摘をコメントする場所が必要なので ワークフローをトリガーするイベントはpull_requestにしておくのがポイント。
あと、Pronto の実行には git の履歴が必要なので actions/checkout@v1 でチェックアウトする4

ESLintを実行する

Actionで利用するDockerイメージには ESLint は含めていないのでセットアップしてから実行する必要がある5
それらを含めたワークフローの設定例は次の通り。

.github/workflows/pronto-eslint_npm.yaml
name: Pronto
on:
  pull_request:
    types: [opened, synchronize]
jobs:
  eslint_npm:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v1
      - name: Setup Node.js
        uses: actions/setup-node@v1
        with:
          node-version: '12.18.x'
      - name: yarn install
        run: yarn install
      - name: pronto run
        uses: HeRoMo/[email protected]
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          runner: eslint_npm

多分、これだけだと 「eslint が見つからない」とかエラーが出ると思う。
そうなったら。.pronto_eslint_npm.ymlというファイルを作って、eslint_npm を設定する6

その設定例は次の通り。

.pronto_eslint_npm.yml
eslint_executable: './node_modules/.bin/eslint'
files_to_lint: '(\.js|\.ts)$'  # TypeScriptをチェックしたいときには指定しておく
cmd_line_opts: './src/**/* ./__tests__/**/*' # eslint のコマンドラインオプション

まとめ

  • Github workflow で Pronto を実行するための Github Action を公開した。
  • 時間的なオーバヘッド少なくPronto実行を自動化できる。
  • リポジトリのソースにProntoを含めなくても(Gemfileに記述しなくても)、Prontoを実行できる。

  1. Pronto RubyというActionも公開されているが、いろいろと依存関係が解決できてなくて特定のプロジェクトには合うだろうけど、汎用的に使えそうになかったので自作することにした。 

  2. 個人的に今後、Chefを使うことはないと思うので、調べる気にもならなかった。 

  3. プルリクエストに対して実行するので、コミット前の変更をチェックするためのオプションである --staged--unstagedは不要と思い、除外した。 

  4. actions/checkout@v2 がリリースされているがこれはデフォルト fetch-depth:1 でチェックアウトするので、prontoが動けない。動くようにしようとすると設定項目が増えてちょっと面倒。 

  5. Dockerイメージに含めることもできるのだけど、ESLint周りはアップデートが速すぎて、Actionとして最新を保つのが大変だし、ワークフローで利用する側としてもそれに追随するのは辛いと思うのでプロジェクトの package.json からインストールして利用するようにした。 

  6. https://github.com/doits/pronto-eslint_npm#configuration-of-eslintnpm