guard-cookstyle 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +5 -0
- data/README.md +95 -0
- data/guard-cookstyle.gemspec +28 -0
- data/lib/guard/cookstyle.rb +100 -0
- data/lib/guard/cookstyle/monkey_patch/listen.rb +13 -0
- data/lib/guard/cookstyle/runner.rb +145 -0
- data/lib/guard/cookstyle/templates/Guardfile +6 -0
- data/lib/guard/cookstyle/version.rb +5 -0
- metadata +109 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 4aa7c641c016b0f1678e8a9cb3e2c71894629d52
|
4
|
+
data.tar.gz: 241418cd7783dbff5556abe1112fca1cfaaf9535
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 50d6c01f906309a8a4f36d64c986cd9957be4c4a48c4eff4275505100fe93b138894ef389f2f05e6c00945078a86b45e8c5de18e9362552545ca916d2739f6d5
|
7
|
+
data.tar.gz: d3df5e6de2cf75e3ceb56055339f6b311934e394295f9d473e819fd870918527f226348e662fd0ca3db5558a4f4527ee2124fea47de1d5af9fa09f797b90a4f3
|
data/README.md
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
# Guard::Cookstyle
|
2
|
+
|
3
|
+
Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/guard/cookstyle`. To experiment with that code, run `bin/console` for an interactive prompt.
|
4
|
+
|
5
|
+
guard-rubocop allows you to automatically check Chef cookbook style with [Cookstyle](https://github.com/chef/cookstyle) when files are modified.
|
6
|
+
|
7
|
+
Cookstyle is a wrapper of rubocop, so most of the codes were based on [yujinakayama/guard-rubocop]((https://github.com/yujinakayama/guard-rubocop)).
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Add this line to your application's Gemfile:
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
gem 'guard-cookstyle'
|
15
|
+
```
|
16
|
+
|
17
|
+
And then execute:
|
18
|
+
|
19
|
+
```
|
20
|
+
$ bundle
|
21
|
+
```
|
22
|
+
|
23
|
+
Or install it yourself as:
|
24
|
+
|
25
|
+
```
|
26
|
+
$ gem install guard-cookstyle
|
27
|
+
```
|
28
|
+
|
29
|
+
Add the default Guard::Cookstyle definition to your Guardfile by running:
|
30
|
+
|
31
|
+
```
|
32
|
+
$ guard init cookstyle
|
33
|
+
```
|
34
|
+
|
35
|
+
Rules of Rubocop definition are loaded from `.cookstyle.yml` by default.
|
36
|
+
|
37
|
+
## Usage
|
38
|
+
|
39
|
+
Please read the [Guard usage documentation](https://github.com/guard/guard#readme).
|
40
|
+
|
41
|
+
## Options
|
42
|
+
|
43
|
+
You can pass some options in `Guardfile` like the following example:
|
44
|
+
|
45
|
+
```ruby
|
46
|
+
guard :cookstyle, all_on_start: false, cli: ['--format', 'clang'], cookbook_dirs: ['mycookbooks'], rubocop_config: '.rubocop.yml' do
|
47
|
+
# ...
|
48
|
+
end
|
49
|
+
```
|
50
|
+
|
51
|
+
### Available Options
|
52
|
+
|
53
|
+
```ruby
|
54
|
+
all_on_start: true # Check all files at Guard startup.
|
55
|
+
# default: true
|
56
|
+
cli: '--rails' # Pass arbitrary Cookstyle CLI arguments. (almost same of RuboCop)
|
57
|
+
# An array or string is acceptable.
|
58
|
+
# default: nil
|
59
|
+
hide_stdout: false # Do not display console output (in case outputting to file).
|
60
|
+
# default: false
|
61
|
+
keep_failed: true # Keep failed files until they pass.
|
62
|
+
# default: true
|
63
|
+
notification: :failed # Display Growl notification after each run.
|
64
|
+
# true - Always notify
|
65
|
+
# false - Never notify
|
66
|
+
# :failed - Notify only when failed
|
67
|
+
# default: :failed
|
68
|
+
launchy: nil # Filename to launch using Launchy after RuboCop runs.
|
69
|
+
# default: nil
|
70
|
+
cookbook_dirs: [] # Directory of Cookbooks to check.
|
71
|
+
# default: %w[cookbooks site-cookbooks]
|
72
|
+
rubocop_config: # Rubocop Config path.
|
73
|
+
# default: '.cookstyle.yml'
|
74
|
+
```
|
75
|
+
|
76
|
+
### Tips
|
77
|
+
|
78
|
+
In order to use it with Rubocop, we recommend that `.cookstyle.yml` inherits `.rubocop.yml` and add cookbook specific rules.
|
79
|
+
|
80
|
+
```
|
81
|
+
---
|
82
|
+
inherit_from: .rubocop.yml
|
83
|
+
|
84
|
+
... rules for cookbooks
|
85
|
+
|
86
|
+
```
|
87
|
+
|
88
|
+
## Contributing
|
89
|
+
|
90
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/higanworks/guard-cookstyle.
|
91
|
+
|
92
|
+
|
93
|
+
## License
|
94
|
+
|
95
|
+
Licensed under the Apache License, Version 2.0.
|
@@ -0,0 +1,28 @@
|
|
1
|
+
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "guard/cookstyle/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "guard-cookstyle"
|
8
|
+
spec.version = GuardCookstyleVersion.to_s
|
9
|
+
spec.authors = ['sawanoboly']
|
10
|
+
spec.email = ['sawanoboriyu@higanworks.com']
|
11
|
+
|
12
|
+
spec.summary = 'Guard plugin for Cookstyle'
|
13
|
+
spec.description = 'Guard::Cookstyle automatically checks Ruby code style with Cookstyle when files are modified.'
|
14
|
+
spec.homepage = 'https://github.com/higanworks/guard-cookstyle'
|
15
|
+
spec.license = 'Apache-2.0'
|
16
|
+
|
17
|
+
spec.files = Dir['README.md','CHANGELOG.md','guard-cookstyle.gemspec','lib/**/*']
|
18
|
+
spec.bindir = "bin"
|
19
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
20
|
+
spec.test_files = spec.files.grep(/^spec\//)
|
21
|
+
spec.require_paths = ["lib"]
|
22
|
+
|
23
|
+
spec.add_runtime_dependency 'guard'
|
24
|
+
|
25
|
+
spec.add_development_dependency "bundler", "~> 1.16"
|
26
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
27
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
28
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'guard'
|
2
|
+
require 'guard/plugin'
|
3
|
+
require "guard/cookstyle/version"
|
4
|
+
require "guard/cookstyle/monkey_patch/listen"
|
5
|
+
|
6
|
+
module Guard
|
7
|
+
class Cookstyle < Plugin
|
8
|
+
autoload :Runner, 'guard/cookstyle/runner'
|
9
|
+
|
10
|
+
attr_reader :options, :failed_paths
|
11
|
+
|
12
|
+
def initialize(options = {})
|
13
|
+
super
|
14
|
+
|
15
|
+
@options = {
|
16
|
+
all_on_start: true,
|
17
|
+
keep_failed: true,
|
18
|
+
notification: :failed,
|
19
|
+
cli: nil,
|
20
|
+
hide_stdout: false,
|
21
|
+
cookbook_dirs: %w[cookbooks site-cookbooks],
|
22
|
+
rubocop_config: '.cookstyle.yml',
|
23
|
+
}.merge(options)
|
24
|
+
|
25
|
+
@failed_paths = []
|
26
|
+
end
|
27
|
+
|
28
|
+
def start
|
29
|
+
run_all if @options[:all_on_start]
|
30
|
+
end
|
31
|
+
|
32
|
+
def run_all
|
33
|
+
UI.info 'Inspecting Chef Cookbook style of all files'
|
34
|
+
inspect_with_cookstyle
|
35
|
+
end
|
36
|
+
|
37
|
+
def run_on_additions(paths)
|
38
|
+
run_partially(paths)
|
39
|
+
end
|
40
|
+
|
41
|
+
def run_on_modifications(paths)
|
42
|
+
run_partially(paths)
|
43
|
+
end
|
44
|
+
|
45
|
+
def reload
|
46
|
+
@failed_paths = []
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def run_partially(paths)
|
52
|
+
paths += @failed_paths if @options[:keep_failed]
|
53
|
+
paths = clean_paths(paths)
|
54
|
+
|
55
|
+
return if paths.empty?
|
56
|
+
|
57
|
+
displayed_paths = paths.map { |path| smart_path(path) }
|
58
|
+
UI.info "Inspecting Chef Cookbook style: #{displayed_paths.join(' ')}"
|
59
|
+
|
60
|
+
inspect_with_cookstyle(paths)
|
61
|
+
end
|
62
|
+
|
63
|
+
def inspect_with_cookstyle(paths = [])
|
64
|
+
runner = Runner.new(@options)
|
65
|
+
passed = runner.run(paths)
|
66
|
+
@failed_paths = runner.failed_paths
|
67
|
+
throw :task_has_failed unless passed
|
68
|
+
rescue StandardError => error
|
69
|
+
UI.error 'The following exception occurred while running guard-cookstyle: ' \
|
70
|
+
"#{error.backtrace.first} #{error.message} (#{error.class.name})"
|
71
|
+
end
|
72
|
+
|
73
|
+
def clean_paths(paths)
|
74
|
+
paths = paths.dup
|
75
|
+
paths.map! { |path| File.expand_path(path) }
|
76
|
+
paths.uniq!
|
77
|
+
paths.reject! do |path|
|
78
|
+
next true unless File.exist?(path)
|
79
|
+
included_in_other_path?(path, paths)
|
80
|
+
end
|
81
|
+
paths
|
82
|
+
end
|
83
|
+
|
84
|
+
def included_in_other_path?(target_path, other_paths)
|
85
|
+
dir_paths = other_paths.select { |path| File.directory?(path) }
|
86
|
+
dir_paths.delete(target_path)
|
87
|
+
dir_paths.any? do |dir_path|
|
88
|
+
target_path.start_with?(dir_path)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def smart_path(path)
|
93
|
+
if path.start_with?(Dir.pwd)
|
94
|
+
Pathname.new(path).relative_path_from(Pathname.getwd).to_s
|
95
|
+
else
|
96
|
+
path
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# https://github.com/guard/listen/wiki/Duplicate-directory-errors
|
2
|
+
if Gem::Version.new(2.8) < Gem::Version.new(Listen::VERSION)
|
3
|
+
require 'listen/record/symlink_detector'
|
4
|
+
module Listen
|
5
|
+
class Record
|
6
|
+
class SymlinkDetector
|
7
|
+
def _fail(_, _)
|
8
|
+
fail Error, "Don't watch locally-symlinked directory twice"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,145 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module Guard
|
4
|
+
class Cookstyle
|
5
|
+
# This class runs `cookstyle` command, retrieves result and notifies.
|
6
|
+
# An instance of this class is intended to invoke `cookstyle` only once in its lifetime.
|
7
|
+
class Runner
|
8
|
+
def initialize(options)
|
9
|
+
@options = options
|
10
|
+
end
|
11
|
+
|
12
|
+
def run(paths = [])
|
13
|
+
command = build_command(paths)
|
14
|
+
passed = system(*command)
|
15
|
+
|
16
|
+
case @options[:notification]
|
17
|
+
when :failed
|
18
|
+
notify(passed) unless passed
|
19
|
+
when true
|
20
|
+
notify(passed)
|
21
|
+
end
|
22
|
+
|
23
|
+
open_launchy_if_needed
|
24
|
+
|
25
|
+
passed
|
26
|
+
end
|
27
|
+
|
28
|
+
def build_command(paths)
|
29
|
+
command = ['cookstyle']
|
30
|
+
|
31
|
+
if should_add_default_formatter_for_console?
|
32
|
+
command.concat(%w[--format progress]) # Keep default formatter for console.
|
33
|
+
end
|
34
|
+
|
35
|
+
command.concat(['--config', @options[:rubocop_config]])
|
36
|
+
command.concat(['--format', 'json', '--out', json_file_path])
|
37
|
+
command << '--force-exclusion'
|
38
|
+
command.concat(args_specified_by_user)
|
39
|
+
|
40
|
+
if paths.any?
|
41
|
+
command.concat(paths)
|
42
|
+
else
|
43
|
+
command.concat(@options[:cookbook_dirs])
|
44
|
+
end
|
45
|
+
command
|
46
|
+
end
|
47
|
+
|
48
|
+
def should_add_default_formatter_for_console?
|
49
|
+
!@options[:hide_stdout] && !include_formatter_for_console?(args_specified_by_user)
|
50
|
+
end
|
51
|
+
|
52
|
+
def args_specified_by_user
|
53
|
+
@args_specified_by_user ||= begin
|
54
|
+
args = @options[:cli]
|
55
|
+
case args
|
56
|
+
when Array then args
|
57
|
+
when String then args.shellsplit
|
58
|
+
when NilClass then []
|
59
|
+
else raise ArgumentError, ':cli option must be either an array or string'
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def include_formatter_for_console?(cli_args)
|
65
|
+
index = -1
|
66
|
+
formatter_args = cli_args.group_by do |arg|
|
67
|
+
index += 1 if arg == '--format' || arg.start_with?('-f')
|
68
|
+
index
|
69
|
+
end
|
70
|
+
formatter_args.delete(-1)
|
71
|
+
|
72
|
+
formatter_args.each_value.any? do |args|
|
73
|
+
args.none? { |a| a == '--out' || a.start_with?('-o') }
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def json_file_path
|
78
|
+
@json_file_path ||= begin
|
79
|
+
# Just generate random tempfile path.
|
80
|
+
basename = self.class.name.downcase.gsub('::', '_')
|
81
|
+
tempfile = Tempfile.new(basename)
|
82
|
+
tempfile.close
|
83
|
+
tempfile.path
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def result
|
88
|
+
@result ||= begin
|
89
|
+
File.open(json_file_path) do |file|
|
90
|
+
# Rubinius 2.0.0.rc1 does not support `JSON.load` with 3 args.
|
91
|
+
JSON.parse(file.read, symbolize_names: true)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def notify(passed)
|
97
|
+
image = passed ? :success : :failed
|
98
|
+
Notifier.notify(summary_text, title: 'Cookstyle results', image: image)
|
99
|
+
end
|
100
|
+
|
101
|
+
def summary_text
|
102
|
+
summary = result[:summary]
|
103
|
+
|
104
|
+
text = pluralize(summary[:inspected_file_count], 'file')
|
105
|
+
text << ' inspected, '
|
106
|
+
|
107
|
+
offense_count = summary[:offense_count] || summary[:offence_count]
|
108
|
+
text << pluralize(offense_count, 'offense', no_for_zero: true)
|
109
|
+
text << ' detected'
|
110
|
+
end
|
111
|
+
|
112
|
+
def failed_paths
|
113
|
+
failed_files = result[:files].reject do |file|
|
114
|
+
offenses = file[:offenses] || file[:offences]
|
115
|
+
offenses.empty?
|
116
|
+
end
|
117
|
+
failed_files.map do |file|
|
118
|
+
file[:path]
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def pluralize(number, thing, options = {})
|
123
|
+
text = ''
|
124
|
+
|
125
|
+
if number.zero? && options[:no_for_zero]
|
126
|
+
text = 'no'
|
127
|
+
else
|
128
|
+
text << number.to_s
|
129
|
+
end
|
130
|
+
|
131
|
+
text << " #{thing}"
|
132
|
+
text << 's' unless number == 1
|
133
|
+
|
134
|
+
text
|
135
|
+
end
|
136
|
+
|
137
|
+
def open_launchy_if_needed
|
138
|
+
return unless (output_path = @options[:launchy])
|
139
|
+
return unless File.exist?(output_path)
|
140
|
+
require 'launchy'
|
141
|
+
::Launchy.open(output_path)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
metadata
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: guard-cookstyle
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- sawanoboly
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-05-09 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: guard
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.16'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.16'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '10.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '10.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.0'
|
69
|
+
description: Guard::Cookstyle automatically checks Ruby code style with Cookstyle
|
70
|
+
when files are modified.
|
71
|
+
email:
|
72
|
+
- sawanoboriyu@higanworks.com
|
73
|
+
executables: []
|
74
|
+
extensions: []
|
75
|
+
extra_rdoc_files: []
|
76
|
+
files:
|
77
|
+
- CHANGELOG.md
|
78
|
+
- README.md
|
79
|
+
- guard-cookstyle.gemspec
|
80
|
+
- lib/guard/cookstyle.rb
|
81
|
+
- lib/guard/cookstyle/monkey_patch/listen.rb
|
82
|
+
- lib/guard/cookstyle/runner.rb
|
83
|
+
- lib/guard/cookstyle/templates/Guardfile
|
84
|
+
- lib/guard/cookstyle/version.rb
|
85
|
+
homepage: https://github.com/higanworks/guard-cookstyle
|
86
|
+
licenses:
|
87
|
+
- Apache-2.0
|
88
|
+
metadata: {}
|
89
|
+
post_install_message:
|
90
|
+
rdoc_options: []
|
91
|
+
require_paths:
|
92
|
+
- lib
|
93
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
98
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
103
|
+
requirements: []
|
104
|
+
rubyforge_project:
|
105
|
+
rubygems_version: 2.6.13
|
106
|
+
signing_key:
|
107
|
+
specification_version: 4
|
108
|
+
summary: Guard plugin for Cookstyle
|
109
|
+
test_files: []
|