Build faster with automated formatting, linting, and vulnerability scanning
When building software I want to automate everything possible.
Automated code formatting, linting, and vulnerability scanning helps teams I work with write better code, faster.
Critically, these automations make it easier to write, read, and maintain code.
lint-staged
to automatically format and lint code before every commitGood linters and auto-formatters have sane defaults, allow some customization, and integrate with your automated test suite / CI setup.
In your .rubocop.yml
setup, enable NewCops
by default:
#`rubocop` to run normally
#`rubocop --auto-gen-config` to update .rubocop_todo.yml
inherit_from: .rubocop_todo.yml
require:
- rubocop-minitest
- rubocop-performance
- rubocop-rails
- rubocop-rake
- rubocop-thread_safety
AllCops:
TargetRubyVersion: 2.7
TargetRailsVersion: 6.1
Exclude:
- 'db/**/*'
- 'node_modules/**/*'
- 'vendor/bundle/**/*'
NewCops: enable
Rails:
Enabled: true
In your package.json
{
// ...
"eslintConfig": {
// "env": {...}
"extends": ["eslint:recommended", "prettier"],
"parser": "@babel/eslint-parser",
"rules": {
"class-methods-use-this": 2,
"no-console": 2
},
"reportUnusedDisableDirectives": true
},
"prettier": {
"semi": false,
"singleQuote": true,
"trailingComma": "none"
},
"stylelint": {
"extends": ["stylelint-config-standard", "stylelint-config-prettier"],
"plugins": ["stylelint-scss"]
},
"pre-commit": ["lint-staged"]
}
For VS Code .vscode/tasks.json
:
{
"version": "2.0.0",
"tasks": [
{
"label": "rubocop auto-correct file",
"type": "shell",
"command": "bundle exec rubocop -A ${relativeFile}",
"problemMatcher": [],
"presentation": {
"reveal": "always",
"panel": "dedicated"
}
},
{
"label": "erblint auto-correct file",
"type": "shell",
"command": "bundle exec erblint -a ${relativeFile}",
"problemMatcher": [],
"presentation": {
"reveal": "always",
"panel": "dedicated"
}
},
{
"label": "prettier auto-correct file",
"type": "shell",
"command": "yarn prettier --write ${relativeFile}",
"problemMatcher": [],
"presentation": {
"reveal": "always",
"panel": "dedicated"
}
}
]
}
And your VS Code keybindings.json
to set up autocorrect from pressing a combination of keys when looking at a file.
[
{
"key": "ctrl+cmd+shift+r",
"command": "workbench.action.tasks.runTask",
"args": "rubocop auto-correct file"
},
{
"key": "ctrl+cmd+shift+e",
"command": "workbench.action.tasks.runTask",
"args": "erblint auto-correct file"
},
{
"key": "ctrl+cmd+shift+p",
"command": "workbench.action.tasks.runTask",
"args": "prettier auto-correct file"
}
]
And in your package.json
add these "scripts"
:
{
// ...
"scripts": {
"fix": "yarn css:fix; yarn js:fix; yarn md:fix; yarn json:fix",
"lint": "yarn css:lint; yarn js:lint; yarn md:lint; yarn json:lint",
"css:fix": "yarn prettier --write 'app/**/*.scss'; yarn stylelint --fix 'app/**/*.scss'",
"css:lint": "stylelint 'app/**/*.scss'",
"erb:fix": "bundle exec erblint -a --lint-all",
"erb:lint": "bundle exec erblint --lint-all",
"i18n:fix": "i18n-tasks normalize",
"i18n:lint": "i18n-tasks health",
"md:fix": "yarn prettier --write './**/*.md'",
"md:lint": "yarn prettier --check './**/*.md'",
"json:fix": "yarn prettier --write '*.json'; yarn prettier --write 'config/**/*.json'",
"json:lint": "yarn prettier --check '*.json'; yarn prettier --check 'config/**/*.json'",
"js:fix": "yarn prettier --write './**/*.js'; yarn eslint --fix app",
"js:lint": "yarn prettier --check './**/*.js'; yarn eslint app",
"ruby:fix": "bundle exec rubocop -a",
"ruby:lint": "bundle exec rubocop",
"eslint": "eslint",
"prettier": "prettier",
"lint-staged": "$(yarn bin)/lint-staged"
}
}
Install with yarn add -D lint-staged
and add a lint-staged.config.js
file:
// lint-staged.config.js
module.exports = {
'(app|config|lib|test)/**/*.rb': (files) =>
`bundle exec rubocop ${files.join(' ')}`,
'**/*.html.erb': (files) => `bundle exec erblint ${files.join(' ')}`,
'config/locales/**/*.yml': () => 'yarn i18n:fix',
'./**/*.md': ['prettier --write'],
'./**/*.js': ['prettier --write', 'eslint --fix'],
'./**/*.scss': ['stylelint --fix', 'prettier --write']
}
# .circleci/config.yml
#
# Jobs have two parts: the execution environment and a set of steps.
jobs:
setup:
# Install libraries like gems, packages and cache for next steps in parallel
test:
# Run test suite...
lint:
# resource_class: ...
# executor: ...
steps:
- prepare-workspace
- run:
name: Lint JS
command: yarn js:lint
- run:
name: Lint CSS
command: yarn css:lint
- run:
name: Lint Ruby
command: bundle exec rubocop
- run:
name: Lint Rails erb templates
command: bundle exec erblint --lint-all
- run:
name: Scan for Rails code vulnerabilities
command: |
gem install brakeman
brakeman
- run:
name: Scan for bundled Ruby gem vulnerabilities
command: |
gem install bundler-audit
bundle audit check --update
- run:
name: Scan for Ruby and RubyGems system vulnerabilities
command: |
bundle add ruby_audit --group "test"
bundle exec ruby-audit check
#
# Workflows are sequences of jobs. Both lint and test will run in parallel once
# setup completes.
workflows:
build:
jobs:
- setup:
- lint:
requires:
- setup
- test:
requires:
- setup
Update your GitHub repository Settings for Branches to “Require status checks to pass before merging”. Select the check that only passes in the lint job in your CI passes.
This ensures your team writes consistent code, even as the team grows.