Adding the GitHub Super Linter Action

GitHub recently announced the Super Linter, a Docker container that can be run via GitHub Actions and comes complete with a lot of built in linting tools to help you detect less than ideal code. As someone who uses linters in different contexts, for example shellcheck for bash, rubocop for Ruby and flake8 for Python, I like the idea of having someone else package these up for easier use in my own GitHub repositories. I don’t have many repos running tests under Actions so I decided to move a small one over and see if the Super Linter lived up to its name.

For my experiments I picked the puppet-ip_in_range repo, which provides a small puppet function to determine if an IPv4 address is within a given IPv4 CIDR. I mostly chose it because it has YAML, JSON, Ruby and Markdown in the same code base but also because it’s mostly clean under rubocop. I had three goals for moving the repo:

  • RSpec tests must run under GitHub Actions

  • Super Linter must run but not fail the tests on outputs

  • The addition of Rubocop Linter Action as I like the way it displays the output.

The first of these requirements, running the tests under rspec, was the easiest as I already have it running in another repo and I don’t yet need any test matrices. I’m happy testing under a single version of Puppet and the ruby version it would normally be bundled with. You can see the code that configures the rake spec run in the workflows/ruby.yml configuration.

#... snip ...
  build:
    name: "Run Rspec Tests"
    env:
      PUPPET_GEM_VERSION: "~> 6.16.0"
# ... snip ...
    - name: Build and test with Rake
      run: |
        gem install bundler
        bundle install --jobs 4 --retry 3
        bundle exec rake spec

The highlights of this YAML are that we pass a gem version through to the Gemfile so you can easily run the tests against different versions of Puppet and the multiline run command that installs the gems and runs the specs. If any tests fail the build will also fail. With specs running, and more importantly still passing under Actions, I added the super linter in its own configuration file. You can have multiple steps in the same YAML config but as I’m unsure which parts of the tooling I will keep I’ve kept them separate for now.

The default configuration and example YAML provided are more than enough to get you started with the action. My own Super Lint Configuration is nearly all boilerplate apart from adding the DISABLE_ERRORS: true environment variable to ensure failing lints don’t break the build. And on the very first run I discovered lint warnings where I didn’t expect them.

Text output showing linter name and success or failed for each linter

Initially even my README.md flagged a warning as I had an older style ## header ## buried in the text. After a few small cleanup pull requests to save me some embarrassment, the code base is over 5 years old after all, I had all the unknowns fixed so I could compare the output with the expected linter violations. Most of this repo is ruby code so rubocop, the most common linter on ruby projects, found a number of things it’s not happy with. I’m not a big fan of some of rubocops choices but I’ve never had the time to customise all my local configuration so I was expecting some output, I wasn’t quite expecting some of the things it flagged. For example the GitHub Super Linter raises Style/StringLiterals: Prefer double-quoted strings unless you need single quotes to avoid extra backslashes for escaping while I, and the default rubocop config, prefer single quoted strings to indicate no variables are used in the string. This to me is the important concept to take away from my experiment, the Super Linter action may provide the tooling in a convenient way but it’s customised to a different companies workflow and so you’ll still need to add your own configs to ensure it compares against your style choices.

With the new big gun of the linter world deployed I also added the Rubocop Linter Action. I was expecting this to take a few minutes as i have an example of it running elsewhere but the way the plugin is configured has completely changed (for the better) and I had to do a little rework. I added the Rubocop Linter Action workflow to the repo alongside its new configuration file approach to ensure rubocop issues couldn’t break the build and on the next push i was getting the much prettier than super lint, but much more demanding of screen space, output with syntax highlighting.

Rubocop output showing missing documentation