LoginSignup
1
2

More than 3 years have passed since last update.

GitHub ActionsでRun rubocop with reviewdogを使ったCIの構築

Last updated at Posted at 2020-10-25

はじめに

個人開発でRubyを使って開発しています。
静的解析にはもちろんrubocopを使っているのですが、ローカルで実行するのみでした。
この作業をCIでも実行したいと思い、個人で触ったことのなかったGitHub ActionsとRun rubocop with reviewdogを使ってみることにしました。

GitHub Actionsとは

公式からの説明は以下のとおりです。

GitHub Actions は、ソフトウェア開発ライフサイクル内のタスクを自動化するのに役立ちます。 GitHub Actions はイベント駆動型で、指定されたイベントが発生した後に一連のコマンドを実行できます。 たとえば、誰かがリポジトリのプルリクエストを作成するたびに、ソフトウェアテストスクリプトを実行するコマンドを自動的に実行できます。

参照:GitHub Actions入門

ざっとまとめると、GitHubに備わっているIssueやPull Requestなどの機能をトリガーにして、ビルド、テスト、デプロイなどを実行できるツールとなります。

Run rubocop with reviewdog

GitHub Actionsでは、アクションとしてRun rubocop with reviewdogが提供されています。
これは、Pull Requestが作成されたときに以下2つを実行してくれるアクションです。

今回、このアクションを使って静的解析とレビューを行うようにしました。
Run rubocop with reviewdogを使ったGitHub Actionsのyamlは以下のとおりです。

static_analysis.yml
name: Static Analysis

on: pull_request

jobs:
  rubocop:
    name: Run rubocop
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: rubocop
        uses: reviewdog/action-rubocop@v1
        with:
          rubocop_version: 0.93.0
          github_token: ${{ secrets.GITHUB_TOKEN }}
          rubocop_flags: --config backend/.rubocop.yml backend/
          rubocop_extensions: meowcop
          reporter: github-pr-check

Run rubocop with reviewdogにはオプションが指定可能です。
ここで指定したオプションの一部について説明します。
なお、オプション一覧については、Run rubocop with reviewdogのREADMEを確認してください。

  • rubocop_flags
    rubocopを実行する際の引数を指定できます。
    ここでは.rubocop.ymlの指定と、rubocopを実行する場所を指定しています。

  • rubocop_extensions
    rubocopのエクステンションをバージョンの指定と一緒に指定できます。デフォルトではrubocop-railsrubocop-performancerubocop-rspecrubocop-i18nrubocop-rakeの最新バージョンが入るようです。
    ここではもともと指定せずに実行していましたが、後述するact実行時に、meowcopがないと怒られていたので、ここで指定しています。

  • reporter
    reviewdogのオプションであるreporterを使えます。デフォルトではgithub-pr-checkを使用します。

act

yamlを作成していくにあたり動作確認と修正を繰り返す必要があります。
GitHub上で確認する方法は、毎回commit、pushしなければならずフィードバックに時間がかかります。
そのためローカルで実行できるツールはないかと探したところ、actがありました。
actはGitHub Actionsをローカルで実行できるGolangのツールです。

README通り、brewでインストールします。

$ brew install act

実行方法は、プロジェクトの.githubフォルダーがあるディレクトリで、actを実行するだけです。

$ act

actはデフォルトで、pushイベントがあるワークフローを実行します。
特定のイベントを実行したい場合は、引数にそのイベント名をセットすることで実行できます。
例: Pull Requestイベントのワークフローを実行したい場合

$ act pull_request

またローカルでのGitHub Runnerは、ワークフローのruns-onのイメージに対して、act上でイメージが決まっています。
現在はruns-onがubuntu-latestubuntu-18.04の場合はnode:12.6-buster-slimubuntu-16.04の場合はnode:12.6-stretch-slimのイメージが使用されます。(なお、runs-onがwindowsやmacosに対しては、actはサポートしていないようです。)
GitHub Runnerのイメージを指定する場合は、-P runs-onのイメージ名=actでサポートしているイメージ名としてください。

$ act -P ubuntu-latest=nektos/act-environments-ubuntu:18.04

今回は、ワークフローのイメージとactで実行するイメージを合わせたかったので、イベント名(pull_request)とイメージを指定し、実行しました。

$ act pull_request -P ubuntu-latest=nektos/act-environments-ubuntu:18.04

act実行時のエラー

actを実行するとBroken pipe @ io_writev - <STDOUT> といったエラーが出てしまいました。

$ act pull_request -P ubuntu-latest=nektos/act-environments-ubuntu:18.04
[Static Analysis/Run rubocop] 🚀  Start image=nektos/act-environments-ubuntu:18.04
[Static Analysis/Run rubocop]   🐳  docker run image=nektos/act-environments-ubuntu:18.04 entrypoint=["/usr/bin/tail" "-f" "/dev/null"] cmd=[]
[Static Analysis/Run rubocop]   🐳  docker cp src=/Users/masatoyamashita/Data/GitHub/WeatherReport/. dst=/github/workspace
[Static Analysis/Run rubocop] ⭐  Run actions/checkout@v2
[Static Analysis/Run rubocop]   ✅  Success - actions/checkout@v2
[Static Analysis/Run rubocop] ⭐  Run rubocop
[Static Analysis/Run rubocop]   ☁  git clone 'https://github.com/reviewdog/action-rubocop' # ref=v1
[Static Analysis/Run rubocop]   🐳  docker build -t act-reviewdog-action-rubocop-v1:latest /Users/masatoyamashita/.cache/act/reviewdog-action-rubocop@v1
[Static Analysis/Run rubocop]   🐳  docker run image=act-reviewdog-action-rubocop-v1:latest entrypoint=[] cmd=["" "0.93.0" "meowcop" "--config backend/.rubocop.yml backend/" "rubocop" "error" "github-pr-check" "added" "false" "" "."]
| Fetching regexp_parser-1.8.2.gem
| Fetching ast-2.4.1.gem
| Fetching parser-2.7.2.0.gem
| Fetching rainbow-3.0.0.gem
| Fetching rubocop-0.93.0.gem
| Fetching parallel-1.19.2.gem
| Fetching ruby-progressbar-1.10.1.gem
| Fetching unicode-display_width-1.7.0.gem
| Fetching rubocop-ast-0.8.0.gem
| Successfully installed parallel-1.19.2
| Successfully installed ast-2.4.1
| Successfully installed parser-2.7.2.0
| Successfully installed rainbow-3.0.0
| Successfully installed regexp_parser-1.8.2
| Successfully installed rubocop-ast-0.8.0
| Successfully installed ruby-progressbar-1.10.1
| Successfully installed unicode-display_width-1.7.0
| Successfully installed rubocop-0.93.0
| 9 gems installed
| Fetching meowcop-2.15.0.gem
| Successfully installed meowcop-2.15.0
| 1 gem installed
| reviewdog: this is not PullRequest build.
| Broken pipe @ io_writev - <STDOUT>
| /usr/local/bundle/gems/rubocop-0.93.0/lib/rubocop/formatter/clang_style_formatter.rb:47:in `write'
| /usr/local/bundle/gems/rubocop-0.93.0/lib/rubocop/formatter/clang_style_formatter.rb:47:in `puts'
| /usr/local/bundle/gems/rubocop-0.93.0/lib/rubocop/formatter/clang_style_formatter.rb:47:in `report_line'
| /usr/local/bundle/gems/rubocop-0.93.0/lib/rubocop/formatter/clang_style_formatter.rb:30:in `report_offense'
| /usr/local/bundle/gems/rubocop-0.93.0/lib/rubocop/formatter/clang_style_formatter.rb:12:in `block in report_file'
| /usr/local/bundle/gems/rubocop-0.93.0/lib/rubocop/formatter/clang_style_formatter.rb:12:in `each'
| /usr/local/bundle/gems/rubocop-0.93.0/lib/rubocop/formatter/clang_style_formatter.rb:12:in `report_file'
| /usr/local/bundle/gems/rubocop-0.93.0/lib/rubocop/formatter/progress_formatter.rb:42:in `block in finished'
| /usr/local/bundle/gems/rubocop-0.93.0/lib/rubocop/formatter/progress_formatter.rb:41:in `each'
| /usr/local/bundle/gems/rubocop-0.93.0/lib/rubocop/formatter/progress_formatter.rb:41:in `finished'
| /usr/local/bundle/gems/rubocop-0.93.0/lib/rubocop/formatter/formatter_set.rb:33:in `block (3 levels) in <class:FormatterSet>'
| /usr/local/bundle/gems/rubocop-0.93.0/lib/rubocop/formatter/formatter_set.rb:33:in `each'
| /usr/local/bundle/gems/rubocop-0.93.0/lib/rubocop/formatter/formatter_set.rb:33:in `block (2 levels) in <class:FormatterSet>'
| /usr/local/bundle/gems/rubocop-0.93.0/lib/rubocop/runner.rb:95:in `inspect_files'
| /usr/local/bundle/gems/rubocop-0.93.0/lib/rubocop/runner.rb:47:in `run'
| /usr/local/bundle/gems/rubocop-0.93.0/lib/rubocop/cli/command/execute_runner.rb:25:in `execute_runner'
| /usr/local/bundle/gems/rubocop-0.93.0/lib/rubocop/cli/command/execute_runner.rb:17:in `run'
| /usr/local/bundle/gems/rubocop-0.93.0/lib/rubocop/cli/command.rb:11:in `run'
| /usr/local/bundle/gems/rubocop-0.93.0/lib/rubocop/cli/environment.rb:18:in `run'
| /usr/local/bundle/gems/rubocop-0.93.0/lib/rubocop/cli.rb:65:in `run_command'
| /usr/local/bundle/gems/rubocop-0.93.0/lib/rubocop/cli.rb:72:in `execute_runners'
| /usr/local/bundle/gems/rubocop-0.93.0/lib/rubocop/cli.rb:41:in `run'
| /usr/local/bundle/gems/rubocop-0.93.0/exe/rubocop:13:in `block in <top (required)>'
| /usr/local/lib/ruby/2.6.0/benchmark.rb:308:in `realtime'
| /usr/local/bundle/gems/rubocop-0.93.0/exe/rubocop:12:in `<top (required)>'
| /usr/local/bundle/bin/rubocop:23:in `load'
| /usr/local/bundle/bin/rubocop:23:in `<main>'
[Static Analysis/Run rubocop]   ✅  Success - rubocop

Broken pipeについて調べると、長過ぎる出力が問題のようでした。
ログの流れから、rubocopによる指摘が多すぎるからB roken pipe
が起きているのではないかと仮定し、rubocop単体で出力される指摘を1つずつ修正していきました。

再度actを実行したところ、無事成功しました。

$ act pull_request -P ubuntu-latest=nektos/act-environments-ubuntu:18.04
[Static Analysis/Run rubocop] 🚀  Start image=nektos/act-environments-ubuntu:18.04
[Static Analysis/Run rubocop]   🐳  docker run image=nektos/act-environments-ubuntu:18.04 entrypoint=["/usr/bin/tail" "-f" "/dev/null"] cmd=[]
[Static Analysis/Run rubocop]   🐳  docker cp src=/Users/masatoyamashita/Data/GitHub/WeatherReport/. dst=/github/workspace
[Static Analysis/Run rubocop] ⭐  Run actions/checkout@v2
[Static Analysis/Run rubocop]   ✅  Success - actions/checkout@v2
[Static Analysis/Run rubocop] ⭐  Run rubocop
[Static Analysis/Run rubocop]   ☁  git clone 'https://github.com/reviewdog/action-rubocop' # ref=v1
[Static Analysis/Run rubocop]   🐳  docker build -t act-reviewdog-action-rubocop-v1:latest /Users/masatoyamashita/.cache/act/reviewdog-action-rubocop@v1
[Static Analysis/Run rubocop]   🐳  docker run image=act-reviewdog-action-rubocop-v1:latest entrypoint=[] cmd=["" "0.93.0" "meowcop" "--config backend/.rubocop.yml backend/" "rubocop" "error" "github-pr-check" "added" "false" "" "."]
| Fetching parallel-1.19.2.gem
| Fetching ast-2.4.1.gem
| Fetching parser-2.7.2.0.gem
| Fetching rainbow-3.0.0.gem
| Fetching regexp_parser-1.8.2.gem
| Fetching rubocop-ast-0.8.0.gem
| Fetching ruby-progressbar-1.10.1.gem
| Fetching unicode-display_width-1.7.0.gem
| Fetching rubocop-0.93.0.gem
| Successfully installed parallel-1.19.2
| Successfully installed ast-2.4.1
| Successfully installed parser-2.7.2.0
| Successfully installed rainbow-3.0.0
| Successfully installed regexp_parser-1.8.2
| Successfully installed rubocop-ast-0.8.0
| Successfully installed ruby-progressbar-1.10.1
| Successfully installed unicode-display_width-1.7.0
| Successfully installed rubocop-0.93.0
| 9 gems installed
| Fetching meowcop-2.15.0.gem
| Successfully installed meowcop-2.15.0
| 1 gem installed
| reviewdog: this is not PullRequest build.
[Static Analysis/Run rubocop]   ✅  Success - rubocop

GitHub上で確認

actによるローカルの確認が終わったのでpushし、GitHub上でGitHub Actionsを走らせたところ、無事成功しました。
GitHub上の結果

終わりに

GitHub Actions上でreviewdog/action-rubocopを実行しました。
またローカルで実行するためにactを利用しました。
人の手を使わず自動で静的解析を行ってくれてありがたいですね。
こういった自動化はどんどん進めていきたいです。

1
2
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
1
2