Github Rubocop Workflow

It took me a while to figure out the correct collection of magical incantations required to make RuboCop run in a GitHub workflow, but ONLY on the files that were changed within the PR. This is a useful configuration if you have a codebase that has not yet been modified to satisfy all your “Cops”. I’ve also included a version of the same file that you can use when you’re ready to have RuboCop run on all non-excluded files.

The result is that rubocop will only block your PR if some of the files touched in the PR don’t conform to your new standards. Once your codebase is

The on: [pull_request] means that it will run when you make the pull request and any time you push to it (with or without force).


# A GitHub workflow to run rubocop, but ONLY on changed files
# honors any exclusions specified in your .rubocop.yml
#
# store this file in .github/workflows/rubocop.yml
# note: the Checkout Branches step is required
# because by default what's checked out is the branch
# that represents the future merging of the PRs branch
# with the target branch.

name: RuboCop

on: [pull_request]
jobs:
  rubocop:
    runs-on: ubuntu-22.04
    steps:
      - uses: actions/checkout@v2
      - uses: ruby/setup-ruby@v1
        with:
          ruby-version: .ruby-version
          bundler-cache: true
      - name: Install gems
        run: |
          bundle config path vendor/bundle
          bundle config set without 'test tools functional'
          bundle install --jobs 4 --retry 3          
      - name: Checkout Branches
        run: |
          git fetch origin ${{ github.head_ref }}
          git fetch origin ${{ github.base_ref }}          
      - name: Run RuboCop
        run: bundle exec rubocop --parallel --force-exclusion $( git diff --name-only --ignore-submodules=all --diff-filter=ACMR origin/${{ github.base_ref }}..origin/${{ github.head_ref }} )

Once your codebase has finally been cleaned up to a point that RuboCop is happy with it you can change it to the following. This is strongly recommend because it will catch when code made it through to the target branch without getting checked (merged directly, or a PR that was merged despite failing checks). The time difference is not noteworthy. Spinning up the container and checking out the gems takes much longer than the actual RuboCop run.

# store this file in .github/workflows/rubocop.yml
# this will run rubocop on ALL the files in your repo
# that have not been excluded in your main .rubocop.yml
# rubocop configuration file.

name: RuboCop

on: [pull_request]
jobs:
  rubocop:
    runs-on: ubuntu-22.04
    steps:
      - uses: actions/checkout@v2
      - uses: ruby/setup-ruby@v1
        with:
          ruby-version: .ruby-version
          bundler-cache: true
      - name: Install gems
        run: |
          bundle config path vendor/bundle
          bundle config set without 'test tools functional'
          bundle install --jobs 4 --retry 3          
      - name: Run RuboCop
        run: bundle exec rubocop --parallel --force-exclusion