Everyday Rails

Automatic code review with Pronto and GitHub Actions

By Aaron Sumner, May 29, 2021. File under: , , .

Using Ruby style and formatting tools like Standard or rufo on legacy application is tricky. You make a small change to an existing file, run the linter to check your work, and–dang. So many style pre-existing style violations! Such noisy ensuing git commits! That’s why I really like Pronto–it only checks your specific changes, not the whole file, so you can keep changes in scope.

I’ve written in the past about automating code review locally with Pronto, and the mindset I like to adopt around code review (both as a reviewer and reviewee). In this article, I’ll take it one step further, and show how to elevate automated code review by integrating Pronto with a CI pipeline–specifically, GitHub Actions!

The setup shown here is specific to GitHub Actions, but Pronto can also be integrated with GitLab or Bitbucket. Refer to Pronto's README file for details.

How to set up Pronto with GitHub Actions

I’m assuming your project is already on GitHub. I recommend doing this work in a new branch, rather than pushing it up straight to your project’s default branch, so you can test the integration with some intentionally bad code.

Add a configuration file to tell GitHub Actions to scan code on each pull request. This is almost verbatim from the example provided in the Pronto README, but I’ve modified it to share the runners I use most, along with comments to help explain a few steps.

Put the file in the .github/workflows directory. You can name the file whatever you want, as long as it ends in .yml.

name: Code quality
# Run this workflow when a pull request is created.
on: [pull_request]

jobs:
  pronto:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v2
      # Pronto docs suggest limiting the depth of the clone
      # to speed things up.
      - run: |
          git fetch --no-tags --prune --depth=10 origin +refs/heads/*:refs/remotes/origin/*

      # If your project only specifies its Ruby version in its
      # Gemfile, you'll need to specify a version for the
      # action to use. See documentation for the
      # ruby/setup-ruby action for details.
      - name: Setup Ruby
        uses: ruby/setup-ruby@v1

      # Install the runners you'd like Pronto to use on each
      # scan. This setup includes the Standard Ruby style
      # guide, and Brakeman security analyzer
      - name: Set up Pronto
        run: gem install pronto pronto-standardrb pronto-brakeman

      # Perform a scan on the diff between your branch and
      # your PR's target branch (e.g, staging, main ...)
      - name: Run Pronto
        run: pronto run -f github_status github_pr -c origin/$
        env:
          PRONTO_PULL_REQUEST_ID: $
          PRONTO_GITHUB_ACCESS_TOKEN: "$"
I've historically kept my Pronto setup outside of an application's Gemfile in order to limit crossover with the app's dependencies. This example follows suit--it does not use Bundler to install Pronto and its runners. I may revisit this someday.

I like Standard (versus, say, straight-up Rubocop) because it’s an opinionated style guide, and I’m on-board with pretty much all of its opinions. Any style guide that steers you toward cleaner commits is a big winner in my book. I’ve also included Brakeman here because it’s simple to integrate and can find easy-to-miss security holes in your application. I recommend these as starting points regardless of your level of experience with Rails.

Testing it out!

Now for the fun part: Let’s see the setup in action. To test the new GitHub Actions workflow, create a new temporary branch from the feature branch you used to add the workflow. (You can also totally use the same development branch if you’re comfortable using Git to clean up and force-push changes to your feature branch.) If you’re using Standard, intentionally bad indentation (three spaces instead of two, tabs instead of spaces) or using single quotes instead of double quotes are good test cases for this setup.

Push your branch up to GitHub, open a pull request, and give the workflow a few minutes to do its job. You should receive an email notifying you of success or failure, and each runner (in this case, Standard and Brakeman) will pass or fail the PR. But here’s my favorite part: Pronto reports each found violation as an in-line comment in your PR’s code!

From there, you can fix the violations (ideally using fixup commits that you can autosquash before merging), or use GitHub’s collaboration tools to discuss reported violations with teammates. Unfortunately, the github-actions bot isn’t yet smart enough to have a conversation with you.

Conclusion/next steps

With one file, this GitHub Actions and Pronto integration adds a nice safety net to any Rails application, to help protect against future bad code violations. Violations are reported in a way that’s just obtrusive enough for a developer to notice. Think of the integration as your super-detail-oriented robot teammate who’ll find those little style issues, so you can get them fixed before turning the review over to your human teammates.

There are many more Pronto runners you may wish to check out and add to your own setup. Thanks for reading!

Discussion

Follow along on on Mastodon, Facebook, or Bluesky to keep up-to-date with my latest posts. Better yet, subscribe to my newsletter for updates from Everyday Rails, book picks, and other thoughts and ideas that didn't quite fit here.
Buy Me A Coffee

Test with confidence!

If you liked my series on practical advice for adding reliable tests to your Rails apps, check out the expanded ebook version. Lots of additional, exclusive content and a complete sample Rails application.

Newsletter

Ruby on Rails news and tips, and other ideas and surprises from Aaron at Everyday Rails. Delivered to your inbox on no particular set schedule.