Skip to content

Commit

Permalink
Merge pull request #7 from mattlqx/cookstyle
Browse files Browse the repository at this point in the history
add cookstyle hook
  • Loading branch information
mattlqx authored Jan 13, 2020
2 parents 2d182c9 + 550d3f9 commit 70dc069
Show file tree
Hide file tree
Showing 8 changed files with 94 additions and 57 deletions.
8 changes: 8 additions & 0 deletions .pre-commit-hooks.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@
)$
exclude: .*/test/.*\.rb$
verbose: true
- id: cookstyle
name: Enforce Chef style guide with cookstyle
description: Enforce Chef style guide with cookstyle
entry: bin/cookstyle-wrapper.rb
language: script
pass_filenames: true
types: ['file']
verbose: true
- id: chef-cookbook-version
name: Ensure Chef cookbook version bump
description: Ensure Chef cookbook versions are bumped when contents are changed
Expand Down
6 changes: 3 additions & 3 deletions .rubocop.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
AllCops:
TargetRubyVersion: 2.3
TargetRubyVersion: 2.5

Metrics/LineLength:
Severity: refactor
Expand All @@ -20,7 +20,7 @@ Metrics/BlockLength:
Metrics/MethodLength:
Enabled: false

Layout/IndentHeredoc:
Layout/HeredocIndentation:
Enabled: false

Naming/HeredocDelimiterNaming:
Expand All @@ -29,7 +29,7 @@ Naming/HeredocDelimiterNaming:
Style/DateTime:
Enabled: false

Naming/UncommunicativeMethodParamName:
Naming/MethodParameterName:
Enabled: false

Layout/ClosingHeredocIndentation:
Expand Down
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

source 'https://rubygems.org'

gem 'rubocop', '0.57.2'
gem 'rubocop', '0.77.0'
22 changes: 10 additions & 12 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,26 @@ GEM
remote: https://rubygems.org/
specs:
ast (2.4.0)
jaro_winkler (1.5.1)
parallel (1.12.1)
parser (2.5.1.0)
jaro_winkler (1.5.4)
parallel (1.19.1)
parser (2.7.0.2)
ast (~> 2.4.0)
powerpack (0.1.2)
rainbow (3.0.0)
rubocop (0.57.2)
rubocop (0.77.0)
jaro_winkler (~> 1.5.1)
parallel (~> 1.10)
parser (>= 2.5)
powerpack (~> 0.1)
parser (>= 2.6)
rainbow (>= 2.2.2, < 4.0)
ruby-progressbar (~> 1.7)
unicode-display_width (~> 1.0, >= 1.0.1)
ruby-progressbar (1.9.0)
unicode-display_width (1.4.0)
unicode-display_width (>= 1.4.0, < 1.7)
ruby-progressbar (1.10.1)
unicode-display_width (1.6.0)

PLATFORMS
ruby

DEPENDENCIES
rubocop (= 0.57.2)
rubocop (= 0.77.0)

BUNDLED WITH
1.16.2
1.17.2
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,17 @@ Hooks require that `bundle` be already available on your system.

To lint Ruby changes in your repo, use the `rubocop` hook. The root of your repo must have a `Gemfile` that includes the desired version of rubocop. It will be installed via Bundler prior to linting. Rubocop will only be run against changed files for each commit.

To lint Chef changes in your repo, use the `foodcritic` hook. The root of your repo must have a `Gemfile` that includes the desired version of foodcritic. It will be installed via Bundler prior to linting. Foodcritic will only be run against cookbooks with changes to Chef code; this does not include the libraries directory of a cookbook.
To lint Chef changes in your repo, use the `foodcritic` or `cookstyle` hook. The root of your repo must have a `Gemfile` that includes the desired version of foodcritic or cookstyle. It will be installed via Bundler prior to linting. Foodcritic will only be run against cookbooks with changes to Chef code; this does not include the libraries directory of a cookbook. Cookstyle will be run against cookbooks and it's at the tools discretion of what actually gets checked. You may specify `--fix` as an argument for cookstyle for it to auto-fix any issues that it can.

To check Chef cookbook version bumps, use the `chef-cookbook-version` hook. Each changed cookbook will have its `metadata.rb` or `metadata.json` checked to determine if its version has been increased. If not, it will automatically be fixed with the patch-level incremented.

To unit test Ruby changes in your repo, use the `rspec` hook. Each path in your repo with a `spec` directory should have a `Gemfile` that includes your desired version of rspec (or a derivative library). It will be installed via Bundler prior to testing. Rspec will only be run against the closest directory in a changed file's path with a spec dir.

- repo: https://github.com/mattlqx/pre-commit-ruby
rev: v1.2.6
rev: v1.3.0
hooks:
- id: rubocop
- id: foodcritic
- id: cookstyle
- id: rspec
- id: chef-cookbook-version
43 changes: 43 additions & 0 deletions bin/common.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# frozen_string_literal: true

def metadata_walk(path)
dir = File.directory?(path) ? path : File.dirname(path)
if File.exist?(File.join(dir, 'metadata.rb')) || File.exist?(File.join(dir, 'metadata.json'))
[dir, File.exist?(File.join(dir, 'metadata.json')) ? 'json' : 'rb']
elsif ['.', '/'].include?(dir)
false
else
metadata_walk(File.dirname(dir))
end
end

def bump_required?(file)
%w[
metadata.(rb|json)
Berksfile
Berksfile.lock
Policyfile.rb
Policyfile.lock.json
recipes/.*
attributes/.*
libraries/.*
files/.*
templates/.*
].each do |regex|
break true if file.match?("#{regex}$")
end == true
end

def changed_cookbooks(bump_check: true)
changed_cookbooks = []
ARGV.each do |file|
cookbook, type = metadata_walk(file)
next if cookbook == false || changed_cookbooks.map(&:first).include?(cookbook) || file.include?('/test/')

next if bump_check && !bump_required?(file)

changed_cookbooks << [cookbook, type]
end
changed_cookbooks.sort!
changed_cookbooks
end
43 changes: 4 additions & 39 deletions bin/cookbook-wrapper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,7 @@

require 'fileutils'
require 'json'

def metadata_walk(path)
dir = File.directory?(path) ? path : File.dirname(path)
if File.exist?(File.join(dir, 'metadata.rb')) || File.exist?(File.join(dir, 'metadata.json'))
[dir, File.exist?(File.join(dir, 'metadata.json')) ? 'json' : 'rb']
elsif ['.', '/'].include?(dir)
false
else
metadata_walk(File.dirname(dir))
end
end

def bump_required?(file)
%w[
metadata.(rb|json)
Berksfile
Berksfile.lock
Policyfile.rb
Policyfile.lock.json
recipes/.*
attributes/.*
libraries/.*
files/.*
templates/.*
].each do |regex|
break true if file.match?("#{regex}$")
end == true
end
require_relative 'common'

def higher?(old_version, new_version)
old_version = old_version.split('.')
Expand Down Expand Up @@ -63,7 +36,7 @@ def empty?
@data.empty?
end

def method_missing(sym, *args, &_block) # rubocop:disable Metrics/AbcSize, Style/MethodMissingSuper, Style/MissingRespondToMissing, Metrics/LineLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
def method_missing(sym, *args, &_block) # rubocop:disable Metrics/AbcSize, Style/MethodMissingSuper, Style/MissingRespondToMissing, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
return @data[sym] if args.empty?

if args.length > 1
Expand All @@ -81,14 +54,6 @@ def method_missing(sym, *args, &_block) # rubocop:disable Metrics/AbcSize, Style

# Check each changed file for a metadata file in its heirarchy
success = true
changed_cookbooks = []
ARGV.each do |file|
cookbook, type = metadata_walk(file)
next if cookbook == false || changed_cookbooks.map(&:first).include?(cookbook)

changed_cookbooks << [cookbook, type] if bump_required?(file)
end

exit(success) if changed_cookbooks.empty?

IO.popen('git fetch origin') { |_f| true }
Expand All @@ -100,10 +65,10 @@ def method_missing(sym, *args, &_block) # rubocop:disable Metrics/AbcSize, Style
type = cb_data[1]

if type == 'rb'
old_metadata = MetadataReader.new(file_from_git_history("#{cookbook}/metadata.rb"), "#{cookbook}/metadata.rb") # rubocop:disable Metrics/LineLength
old_metadata = MetadataReader.new(file_from_git_history("#{cookbook}/metadata.rb"), "#{cookbook}/metadata.rb")
new_metadata = MetadataReader.new(IO.read("#{cookbook}/metadata.rb"), "#{cookbook}/metadata.rb")
else
old_metadata = JSON.parse(file_from_git_history("#{cookbook}/metadata.json")) rescue {} # rubocop:disable Style/RescueModifier, Metrics/LineLength
old_metadata = JSON.parse(file_from_git_history("#{cookbook}/metadata.json")) rescue {} # rubocop:disable Style/RescueModifier
new_metadata = JSON.parse(IO.read("#{cookbook}/metadata.json"))
end

Expand Down
22 changes: 22 additions & 0 deletions bin/cookstyle-wrapper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/usr/bin/env ruby
# frozen_string_literal: true

require_relative 'common'

# Check each changed file for a spec directory in its heirarchy
fix = ''
Array.new(ARGV).each do |arg|
next unless arg == '--fix'

fix = '-a'
ARGV.delete('--fix')
break
end

# Exit early if there are no paths to lint
success = true
exit(success) if changed_cookbooks(bump_check: false).empty?

# Install cookstyle and drop args that are paths
system('bundle install >/dev/null') || exit(false)
system("bundle exec cookstyle --color #{fix} #{changed_cookbooks.map(&:first).join(' ')}") || exit(false)

0 comments on commit 70dc069

Please sign in to comment.