forked from sds/overcommit
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfoodcritic.rb
149 lines (140 loc) · 4.62 KB
/
foodcritic.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# frozen_string_literal: true
module Overcommit::Hook::PreCommit
# Runs `foodcritic` against any modified Ruby files from Chef directory structure.
#
# @see http://www.foodcritic.io/
#
# There are two "modes" you can run this hook in based on the repo:
#
# SINGLE COOKBOOK REPO MODE
# -------------------------
# The default. Use this if your repository contains just a single cookbook,
# i.e. the top-level repo directory contains directories called `attributes`,
# `libraries`, `recipes`, etc.
#
# To get this to work well, you'll want to set your Overcommit configuration
# for this hook to something like:
#
# PreCommit:
# Foodcritic:
# enabled: true
# include:
# - 'attributes/**/*'
# - 'definitions/**/*'
# - 'files/**/*'
# - 'libraries/**/*'
# - 'providers/**/*'
# - 'recipes/**/*'
# - 'resources/**/*'
# - 'templates/**/*'
#
# MONOLITHIC REPO MODE
# --------------------
# Use this if you store multiple cookbooks, environments, and roles (or any
# combination thereof) in a single repository.
#
# There are three configuration options relevant here:
#
# * `cookbooks_directory`
# When set, hook will treat the path as a directory containing cookbooks.
# Each subdirectory of this directory will be treated as a separate
# cookbook.
#
# * `environments_directory`
# When set, hook will treat the path as a directory containing environment
# files.
#
# * `roles_directory`
# When set, hook will treat the given path as a directory containing role
# files.
#
# In order to run in monolithic repo mode, YOU MUST SET `cookbooks_directory`.
# The other configuration options are optional, if you happen to store
# environments/roles in another repo.
#
# To get this to work well, you'll want to set your Overcommit configuration
# for this hook to something like:
#
# PreCommit:
# Foodcritic:
# enabled: true
# cookbooks_directory: 'cookbooks'
# environments_directory: 'environments'
# roles_directory: 'roles'
# include:
# - 'cookbooks/**/*'
# - 'environments/**/*'
# - 'roles/**/*'
#
# ADDITIONAL CONFIGURATION
# ------------------------
# You can disable rules using the `flags` hook option. For example:
#
# PreCommit:
# Foodcritic:
# enabled: true
# ...
# flags:
# - '--epic-fail=any'
# - '-t~FC011' # Missing README in markdown format
# - '-t~FC064' # Ensure issues_url is set in metadata
#
# Any other command line flag supported by the `foodcritic` executable can be
# specified here.
#
# If you want the hook run to fail (and not just warn), set the `on_warn`
# option for the hook to `fail`:
#
# PreCommit:
# Foodcritic:
# enabled: true
# on_warn: fail
# ...
#
# This will treat any warnings as failures and cause the hook to exit
# unsuccessfully.
class Foodcritic < Base
def run
args = modified_cookbooks_args + modified_environments_args + modified_roles_args
result = execute(command, args: args)
if result.success?
:pass
else
return [:warn, result.stderr + result.stdout]
end
end
private
def directories_changed(dir_prefix)
applicable_files.
select { |path| path.start_with?(dir_prefix) }.
map { |path| path.gsub(%r{^#{dir_prefix}/}, '') }.
group_by { |path| path.split('/').first }.
keys.
map { |path| File.join(dir_prefix, path) }
end
def modified_environments_args
modified('environments').map { |env| %W[-E #{env}] }.flatten
end
def modified_roles_args
modified('roles').map { |role| %W[-R #{role}] }.flatten
end
def modified_cookbooks_args
# Return the repo root if repository contains a single cookbook
if !config['cookbooks_directory'] || config['cookbooks_directory'].empty?
['-B', Overcommit::Utils.repo_root]
else
# Otherwise return all modified cookbooks in the cookbook directory
modified('cookbooks').map { |cookbook| ['-B', cookbook] }.flatten
end
end
def modified(type)
return [] if !config["#{type}_directory"] || config["#{type}_directory"].empty?
@modified ||= {}
@modified[type] ||= directories_changed(full_directory_path("#{type}_directory"))
end
def full_directory_path(config_option)
return config[config_option] if config[config_option].start_with?(File::SEPARATOR)
File.absolute_path(File.join(Overcommit::Utils.repo_root, config[config_option]))
end
end
end