Skip to content

Instantly share code, notes, and snippets.

@gyllstromk
Created September 6, 2013 15:41
Show Gist options
  • Save gyllstromk/6465674 to your computer and use it in GitHub Desktop.
Save gyllstromk/6465674 to your computer and use it in GitHub Desktop.
Modularizing your organization's JSHint rules

The typical use of jshint involves including rules in a .jshintrc or Gruntfile.js. This does not scale to multi-repo organizations, as .jshintrc files must be made in each repo, and organization-widge changes to these rules must be copied to each repo's .jshintrc file.

Fortunately, it's easy to formalize and enforce style standards in your organization's Javascript. Here we describe the pattern we use.

The overview:

  1. Formalize your style into JSHint rules (i.e. identify the rules you would place in a .jshintrc file)
  2. Centralize access to jshint rules via a packaging pattern (described below)
  3. Require jshint conformance in unit testing/code reviews/deployments.

Assuming your org's deployment cycle requires unit tests before deployment, this puts you in good shape.

Making jshint rules a package

Using an internally agreed-upon jshint standard, we created a node package in github which we include in all node projects.

This package is pretty simple, but here are the main points:

  1. a jshintrc file contans the jshint rules of our organization
  2. a "bin" script, which executes jshint using this jshintrc file, is installed and available to the including repo. No need to install jshint, however: the module installs its own copy
  3. a custom jshintignore policy, which ignores node_modules and .git.

Other organizations can adopt their own by forking our repo.

Including in packages

All projects in our organization include this in package.json:

"devDependencies": {
    ...
    "jshinthelper": "git+ssh://[email protected]:gyllstromk/jshinthelper.git#0.5.0"
    ...
}

(Note the use of the #0.5.0, which is a tag name. This simply identifies the particular commit I want. More on this below.)

Enforcing conformance involves hooking it into the test scripts in package.json. We use the pretest script: this is executed before the test scripts; if it fails, the tests are not run and npm test fails.

We simply include a jshint step:

  "scripts": {
    "pretest": "./node_modules/.bin/jshint .",
    "test": "./node_modules/.bin/mocha -R spec"

Note that if you aren't using our jshinthelper model, this still works: simply install jshint by itself:

$ npm install jshint --save-dev

This installs jshint to ./node_modules/.bin and runs based on what's in your .jshintrc and .jshintignore files.

Lifecycle

The desired style rules will likely evolve with your project. Versioning via npm/git makes managing this easy.

Versioning

When modifying rules in your jshinthelper fork, a new version has an attendant git version. This can be used directly in the include:

"devDependencies": {
    ...
    "jshinthelper": "git+ssh://[email protected]:gyllstromk/jshinthelper.git#my_commit_version"

This model works for revision number, branch name, and tags.

This way, if a particular package depends on a version of jshinthelper, i.e. the rules in that version, it is unaffected by subsequent updates to the jshinthelper module. Updates to new jshint rules by the package, then, must be explicit: the version of jshinthelper included must be incremented, installed, and tested.

Alteranatively, it may be desired that a package always comply with the latest jshint rules. In this case, ommit version number in the package inclusion:

"devDependencies": {
    ...
    "jshinthelper": "git+ssh://[email protected]:gyllstromk/jshinthelper.git"

In the above, the latest in master branch is always used.

Variants

Say you need different variants of jshint rules, such as one with use_strict. This can be done with git branches, for example:

  1. Make a use_strict variant from within the jshinthelper package:
$ git checkout -b use_strict
  1. Update the .jshintrc file to require use_strict. Commit and push the branch.
  2. In packages where use_strict is required, update the inclusion string in package.json:
"jshinthelper": "git+ssh://[email protected]:gyllstromk/jshinthelper.git#use_strict

vs. grunt

Many use grunt as the location in which jshint rules are placed. I recommend avoiding this in organizations because the logic cannot be centralized; i.e. the jshint rules must be copied to the Gruntfile in each repo, and synchronized on changes.

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