Skip to content

Instantly share code, notes, and snippets.

@jclif
Last active September 21, 2016 16:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jclif/5f20f8958cfb224a0099bb263a41ad88 to your computer and use it in GitHub Desktop.
Save jclif/5f20f8958cfb224a0099bb263a41ad88 to your computer and use it in GitHub Desktop.
Styles, Linters, and Dependency Checks

What's this all about, anyway?

Let's make our codebase better. Here's my three step program:

  1. Prevent new bad code from getting in
  2. Make the bad code that already got in, not bad
  3. Feel great because our codebase is great (you look great today)

Some hot/fresh keywords for SEO:

  1. Styles (community-driven standards for writing commit messages, javascript, ruby, scss, etc)
  2. Linters (programs that use static analysis to check your text files for errors and bad code styles)
  3. Dependencies (we have lot's of them; some of them are bad, sometimes; when they fail, we get in trouble)

Why should we care?

When you write to communicate (which you should be doing ALL THE TIME if you are writing code...that will be read potentially many times by potentially many developers, including future you), you should aim to write idiomatically. There are standards and conventions that have been set in place by our wider community of peers (https://github.com/bbatsov/ruby-style-guide). If we apply these standards, some good stuff will happen, not least of which: it will become easier for new developers to understand our code base, and (by regularly enforcing these styles) it will become easier for us to understand other ruby code. Aren't there a lot of standards for styling code? How can I remember them allZOMG? Yes, there are a lot. So what should we do with the these repetitive and exacting menial tasks? MAKE ROBOTS DO THEM!

Rubocop

So yeah, essentially, Rubocop is a gem that uses static analysis (parses the contents of your files without running them) to identify bad code styles. It has a number of sensible defaults that can be configured to our hearts' content by specifying configuration options in a file called 'rubocop.yml'. Here's how you use it in large code repositories that have not historically had a large emphasis on code styles (like ours):

  1. Install rubocop using bundler (bundle install rubocop)
  2. Run Rubocop for the first time (rubocop). This will cause Rubocop to produce a staggering (read: embarassing) number of warnings.
  3. Generate a Rubocop configuration file (.rubocop_todo.yml) to ignore all of these warnings (for now) (rubocop --auto-gen-config). Now when we run Rubocop, there are no warnings! Are we done?! (no)
  4. Whenever we write new code, we can run Rubocop and ensure that no new offenses are checked into our code base.
  5. Whenever we have spare time to refactor, we remove an ignore block form .rubocop_todo.yml and correct the warnings (whilst humming 99 Bottles of Beer on the Wall).
  6. Repeat steps 4 and 5 until the rubocop_todo.yml is empty.
  7. Repeat steps 4 until cosmic heat death.

My brain is already exceeding maximum RAM usage. Please save me from this tooling hellscape.

More tools to the rescue! Don't worry, you can forget about this one (until you commit). Let's use an oft-forgotten git utility: hooks (https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks). Don't mess with native hit hooks. There's a gem for that.

Overcommit

So yeah, essentially, overcommit uses git hooks, but let's you write ruby code to run custom checks on your codebase. Also, unlike other git hook gems, the configuration files live in source (which you check in), so everyone shares the same checks. Here's how you use it:

  1. Forget that it exists
  2. Write your code
  3. Commit your code
  4. If your commit fails due to a failed check, fix it, yo
  5. If your commit is successful, but you see a CommitMsg warning, that means you screwed up the formatting on your commit message. Fix it with git commit --amend, ya goober.
  6. If your commit is successful, and you don't see any warnings, you win! Ship it.

What checks do we run currently?

Overcommit loads a file called '.overcommit.yml' in order to determine what checks to run. At any time, you can check this file at the root directory of our project, but for the sake of explanation, here are the current checks at the time of this documents writing: Preample: most of these checks that care about files will only look at staged files. You would have to run overcommit --run in order to see warnings for the entire codebase.

PreCommit checks:

  • RuboCop: runs rubocop over files that have been staged
  • BundleAudit: checks dependencies for security vulnerabilities
  • BundleCheck: ensures that Gemfile and Gemfile.lock are nSync

CommitMsg checks:

  • SingleLineSubject: commit messages should include a subject line followed by an empty line followed by an optional body with additional details
  • HardTabs: please just don't
  • RussianNovel: for funzies; don't write more than 30 lines

Potentially useful hooks:

  • BundleOutdated: checks for newer gem versions
  • CoffeeLint/HamlLint/EtcLint: runs linters
  • ForbiddenBranches: prevents committing code to protected branches (must be merged)
  • RailsBestPractices: runs files through rails standards checks (https://github.com/railsbp/rails_best_practices)
  • TrailingWhitespace

This is amazing. I need more hooks in my life.

For all of your hook related needs, please see the out-of-the-box checks that overcommit offers (https://github.com/brigade/overcommit/tree/master/lib/overcommit/hook), or be even more awesome, and write your own! (http://www.guoxiang.me/posts/28-how-to-write-a-custom-overcommit-precommit-git-hook-in-4-steps)

THE END

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment