mudguard 0.1.4 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +8 -0
- data/.mudguard.yml +6 -0
- data/.rubocop.yml +2 -0
- data/Gemfile.lock +25 -23
- data/Guardfile +1 -1
- data/README.md +62 -9
- data/exe/mudguard +5 -12
- data/lib/mudguard.rb +2 -17
- data/lib/mudguard/application/application.rb +33 -0
- data/lib/mudguard/domain/const_visitor.rb +20 -0
- data/lib/mudguard/domain/consts.rb +81 -0
- data/lib/mudguard/domain/dependencies.rb +47 -0
- data/lib/mudguard/domain/dependency.rb +28 -0
- data/lib/mudguard/domain/dependency_visitor.rb +32 -0
- data/lib/mudguard/{error.rb → domain/error.rb} +3 -1
- data/lib/mudguard/domain/policies.rb +49 -0
- data/lib/mudguard/domain/source.rb +79 -0
- data/lib/mudguard/domain/source_policies.rb +8 -0
- data/lib/mudguard/domain/source_processor.rb +92 -0
- data/lib/mudguard/domain/texts.rb +42 -0
- data/lib/mudguard/infrastructure/cli/controller.rb +78 -0
- data/lib/mudguard/infrastructure/cli/notification_adapter.rb +26 -0
- data/lib/mudguard/infrastructure/cli/view.rb +14 -0
- data/lib/mudguard/infrastructure/persistence/.mudguard.template.yml +6 -0
- data/lib/mudguard/infrastructure/persistence/policy_file.rb +46 -0
- data/lib/mudguard/infrastructure/persistence/project_repository.rb +31 -0
- data/lib/mudguard/infrastructure/persistence/ruby_files.rb +39 -0
- data/lib/mudguard/infrastructure/rake/task.rb +28 -0
- data/lib/mudguard/version.rb +1 -1
- data/mudguard.gemspec +2 -1
- metadata +40 -11
- data/lib/mudguard/policies.rb +0 -23
- data/lib/mudguard/policy_file.rb +0 -17
- data/lib/mudguard/ruby_analyser.rb +0 -74
- data/lib/mudguard/ruby_files.rb +0 -17
- data/lib/tasks/gem.rake +0 -15
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "yaml"
|
4
|
+
require_relative "../../domain/policies"
|
5
|
+
require_relative "../../domain/error"
|
6
|
+
|
7
|
+
module Mudguard
|
8
|
+
module Infrastructure
|
9
|
+
module Persistence
|
10
|
+
# A file containing the Mudguard-Policies
|
11
|
+
class PolicyFile
|
12
|
+
class << self
|
13
|
+
def read(project_path)
|
14
|
+
policy_file = File.join(project_path, ".mudguard.yml")
|
15
|
+
policy_exists = File.exist?(policy_file)
|
16
|
+
|
17
|
+
unless policy_exists
|
18
|
+
template_file = File.join(__dir__, ".mudguard.template.yml")
|
19
|
+
FileUtils.cp(template_file, policy_file)
|
20
|
+
end
|
21
|
+
|
22
|
+
read_yml(policy_file)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def read_yml(policy_file)
|
28
|
+
yaml_file = File.read(policy_file)
|
29
|
+
yaml = YAML.safe_load(yaml_file, [Symbol], [], policy_file) || {}
|
30
|
+
yaml.transform_values { |value| (value || []).map(&method(:unsymbolize)) }
|
31
|
+
rescue Psych::SyntaxError => e
|
32
|
+
raise Mudguard::Domain::Error, "#{policy_file} is invalid (#{e.message})"
|
33
|
+
end
|
34
|
+
|
35
|
+
def unsymbolize(dependency)
|
36
|
+
if dependency.is_a?(Symbol)
|
37
|
+
":#{dependency}"
|
38
|
+
else
|
39
|
+
dependency
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "policy_file"
|
4
|
+
require_relative "ruby_files"
|
5
|
+
require_relative "../../domain/source_policies"
|
6
|
+
|
7
|
+
module Mudguard
|
8
|
+
module Infrastructure
|
9
|
+
module Persistence
|
10
|
+
# Provides access to the persisted source and policies
|
11
|
+
class ProjectRepository
|
12
|
+
class << self
|
13
|
+
def load_source_policies(project_path)
|
14
|
+
file = PolicyFile.read(project_path)
|
15
|
+
scopes = file.flat_map do |patterns, policies|
|
16
|
+
sources = RubyFiles.select(project_path, patterns: [patterns])
|
17
|
+
sources.flat_map { |s| { source: s, policies: policies } }
|
18
|
+
end
|
19
|
+
|
20
|
+
sources = scopes.group_by { |e| e[:source] }
|
21
|
+
|
22
|
+
sources.map do |source, group|
|
23
|
+
policies = group.flat_map { |r| r[:policies] }.uniq
|
24
|
+
Domain::SourcePolicies.new(source: source, policies: policies)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "pathname"
|
4
|
+
require "mudguard/domain/source"
|
5
|
+
|
6
|
+
module Mudguard
|
7
|
+
module Infrastructure
|
8
|
+
module Persistence
|
9
|
+
# Provides access to all ruby-files of a project
|
10
|
+
class RubyFiles
|
11
|
+
class << self
|
12
|
+
def select(project_path, patterns: nil)
|
13
|
+
project_exists = Dir.exist?(project_path)
|
14
|
+
|
15
|
+
unless project_exists
|
16
|
+
raise Mudguard::Domain::Error, "expected project #{project_path} doesn't exists"
|
17
|
+
end
|
18
|
+
|
19
|
+
patterns = [File.join("**", "*.rb")] if patterns.nil?
|
20
|
+
enumerate_files(project_path, patterns)
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def enumerate_files(project_path, patterns)
|
26
|
+
project_path_name = Pathname.new(project_path)
|
27
|
+
ruby_files = patterns.map { |p| File.join(project_path, p) }
|
28
|
+
Dir.glob(ruby_files).map do |f|
|
29
|
+
file_path_name = Pathname.new(f)
|
30
|
+
diff_path = file_path_name.relative_path_from(project_path_name).to_s
|
31
|
+
Mudguard::Domain::Source.new(location: File.join("./", diff_path),
|
32
|
+
code_loader: -> { File.read(f) })
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rake"
|
4
|
+
require "rake/tasklib"
|
5
|
+
require_relative "../../application/application"
|
6
|
+
require_relative "../../infrastructure/cli/notification_adapter"
|
7
|
+
require_relative "../../infrastructure/cli/view"
|
8
|
+
|
9
|
+
module Mudguard
|
10
|
+
module Infrastructure
|
11
|
+
module Rake
|
12
|
+
# Provides Mudguard Rake Tasks
|
13
|
+
class Task < ::Rake::TaskLib
|
14
|
+
def initialize(project_dir: Dir.pwd)
|
15
|
+
@project_dir = project_dir
|
16
|
+
|
17
|
+
desc "Run Mudguard"
|
18
|
+
task(:mudguard) do
|
19
|
+
view = Mudguard::Infrastructure::Cli::View.new
|
20
|
+
notification = Mudguard::Infrastructure::Cli::NotificationAdapter.new(view: view)
|
21
|
+
ok = Application.check(@project_dir, notification)
|
22
|
+
abort unless ok
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/mudguard/version.rb
CHANGED
data/mudguard.gemspec
CHANGED
@@ -12,7 +12,7 @@ Gem::Specification.new do |spec|
|
|
12
12
|
|
13
13
|
spec.summary = "mudguard helps your ruby project not becoming a "\
|
14
14
|
"'Big ball of mud'"
|
15
|
-
spec.homepage = "https://
|
15
|
+
spec.homepage = "https://github.com/Enceradeira/mudguard"
|
16
16
|
spec.license = "MIT"
|
17
17
|
|
18
18
|
spec.metadata["homepage_uri"] = spec.homepage
|
@@ -40,4 +40,5 @@ Gem::Specification.new do |spec|
|
|
40
40
|
spec.add_development_dependency "rubocop", "~>0.80"
|
41
41
|
|
42
42
|
spec.add_dependency "parser", "~>2.7"
|
43
|
+
spec.add_dependency "rake", "~> 13.0"
|
43
44
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mudguard
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jorg Jenni
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-06-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -150,6 +150,20 @@ dependencies:
|
|
150
150
|
- - "~>"
|
151
151
|
- !ruby/object:Gem::Version
|
152
152
|
version: '2.7'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: rake
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - "~>"
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '13.0'
|
160
|
+
type: :runtime
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - "~>"
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '13.0'
|
153
167
|
description:
|
154
168
|
email:
|
155
169
|
- jorg.jenni@jennius.co.uk
|
@@ -160,6 +174,7 @@ extra_rdoc_files: []
|
|
160
174
|
files:
|
161
175
|
- ".envrc"
|
162
176
|
- ".gitignore"
|
177
|
+
- ".mudguard.yml"
|
163
178
|
- ".rubocop.yml"
|
164
179
|
- ".ruby-version"
|
165
180
|
- CODE_OF_CONDUCT.md
|
@@ -171,23 +186,37 @@ files:
|
|
171
186
|
- Rakefile
|
172
187
|
- exe/mudguard
|
173
188
|
- lib/mudguard.rb
|
174
|
-
- lib/mudguard/
|
175
|
-
- lib/mudguard/
|
176
|
-
- lib/mudguard/
|
177
|
-
- lib/mudguard/
|
178
|
-
- lib/mudguard/
|
189
|
+
- lib/mudguard/application/application.rb
|
190
|
+
- lib/mudguard/domain/const_visitor.rb
|
191
|
+
- lib/mudguard/domain/consts.rb
|
192
|
+
- lib/mudguard/domain/dependencies.rb
|
193
|
+
- lib/mudguard/domain/dependency.rb
|
194
|
+
- lib/mudguard/domain/dependency_visitor.rb
|
195
|
+
- lib/mudguard/domain/error.rb
|
196
|
+
- lib/mudguard/domain/policies.rb
|
197
|
+
- lib/mudguard/domain/source.rb
|
198
|
+
- lib/mudguard/domain/source_policies.rb
|
199
|
+
- lib/mudguard/domain/source_processor.rb
|
200
|
+
- lib/mudguard/domain/texts.rb
|
201
|
+
- lib/mudguard/infrastructure/cli/controller.rb
|
202
|
+
- lib/mudguard/infrastructure/cli/notification_adapter.rb
|
203
|
+
- lib/mudguard/infrastructure/cli/view.rb
|
204
|
+
- lib/mudguard/infrastructure/persistence/.mudguard.template.yml
|
205
|
+
- lib/mudguard/infrastructure/persistence/policy_file.rb
|
206
|
+
- lib/mudguard/infrastructure/persistence/project_repository.rb
|
207
|
+
- lib/mudguard/infrastructure/persistence/ruby_files.rb
|
208
|
+
- lib/mudguard/infrastructure/rake/task.rb
|
179
209
|
- lib/mudguard/version.rb
|
180
|
-
- lib/tasks/gem.rake
|
181
210
|
- lib/tasks/rubocop.rake
|
182
211
|
- lib/tasks/test.rake
|
183
212
|
- mudguard.gemspec
|
184
213
|
- pkg/mudguard-0.1.0.gem
|
185
|
-
homepage: https://
|
214
|
+
homepage: https://github.com/Enceradeira/mudguard
|
186
215
|
licenses:
|
187
216
|
- MIT
|
188
217
|
metadata:
|
189
|
-
homepage_uri: https://
|
190
|
-
source_code_uri: https://
|
218
|
+
homepage_uri: https://github.com/Enceradeira/mudguard
|
219
|
+
source_code_uri: https://github.com/Enceradeira/mudguard
|
191
220
|
post_install_message:
|
192
221
|
rdoc_options: []
|
193
222
|
require_paths:
|
data/lib/mudguard/policies.rb
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative "ruby_analyser"
|
4
|
-
|
5
|
-
module Mudguard
|
6
|
-
# Contains the policies to be enforced
|
7
|
-
class Policies
|
8
|
-
def initialize(policies: [])
|
9
|
-
@policies = policies.map { |l| l.gsub(/\s/, "") }.map { |p| /^#{p}/ }
|
10
|
-
end
|
11
|
-
|
12
|
-
def check(sources)
|
13
|
-
sources.all? do |source|
|
14
|
-
dependencies = RubyAnalyser.find_mod_dependencies(source)
|
15
|
-
dependencies.all? do |d|
|
16
|
-
@policies.any? do |p|
|
17
|
-
d.match?(p)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
data/lib/mudguard/policy_file.rb
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative "policies"
|
4
|
-
require_relative "error"
|
5
|
-
|
6
|
-
module Mudguard
|
7
|
-
# A file containing the Mudguard-Policies
|
8
|
-
class PolicyFile
|
9
|
-
def self.read(policy_file)
|
10
|
-
policy_exists = File.exist?(policy_file)
|
11
|
-
|
12
|
-
raise Error, "expected policy file #{policy_file} doesn't exists" unless policy_exists
|
13
|
-
|
14
|
-
Policies.new(policies: File.readlines(policy_file))
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
@@ -1,74 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "parser/current"
|
4
|
-
|
5
|
-
module Mudguard
|
6
|
-
# Analyses Ruby-Source and returns extracted information
|
7
|
-
class RubyAnalyser
|
8
|
-
class << self
|
9
|
-
def find_mod_dependencies(source)
|
10
|
-
begin
|
11
|
-
root = Parser::CurrentRuby.parse(source)
|
12
|
-
rescue Parser::SyntaxError
|
13
|
-
return []
|
14
|
-
end
|
15
|
-
return [] if root.nil?
|
16
|
-
|
17
|
-
process(root)
|
18
|
-
end
|
19
|
-
|
20
|
-
private
|
21
|
-
|
22
|
-
def process(node, module_name = "")
|
23
|
-
case node
|
24
|
-
when type?(:module)
|
25
|
-
process_module(node.children)
|
26
|
-
when type?(:class)
|
27
|
-
process_class(node.children, module_name)
|
28
|
-
when type?(:const)
|
29
|
-
["#{module_name}->#{find_const_name(node.children)}"]
|
30
|
-
else
|
31
|
-
ignore_and_continue(node, module_name)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def ignore_and_continue(node, module_name)
|
36
|
-
case node
|
37
|
-
when children?
|
38
|
-
node.children.flat_map { |c| process(c, module_name) }
|
39
|
-
else
|
40
|
-
[]
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
def process_module(children)
|
45
|
-
module_name = find_const_name(children[0].children)
|
46
|
-
process(children[1], module_name)
|
47
|
-
end
|
48
|
-
|
49
|
-
def process_class(children, module_name)
|
50
|
-
process(children[1], module_name)
|
51
|
-
end
|
52
|
-
|
53
|
-
def find_const_name(children)
|
54
|
-
return nil if children.nil?
|
55
|
-
|
56
|
-
module_name = find_const_name(children[0]&.children)
|
57
|
-
const_name = children[1].to_s
|
58
|
-
if module_name.nil?
|
59
|
-
const_name
|
60
|
-
else
|
61
|
-
"#{module_name}::#{const_name}"
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
def children?
|
66
|
-
->(n) { n.respond_to?(:children) }
|
67
|
-
end
|
68
|
-
|
69
|
-
def type?(type)
|
70
|
-
->(n) { n.respond_to?(:type) && n.type == type }
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
data/lib/mudguard/ruby_files.rb
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Mudguard
|
4
|
-
# Provides access to all ruby-files of a project
|
5
|
-
class RubyFiles
|
6
|
-
class << self
|
7
|
-
def all(project_path)
|
8
|
-
project_exists = Dir.exist?(project_path)
|
9
|
-
|
10
|
-
raise Error, "expected project #{project_path} doesn't exists" unless project_exists
|
11
|
-
|
12
|
-
ruby_files = File.join(project_path, "**", "*.rb")
|
13
|
-
Dir.glob(ruby_files).lazy
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
data/lib/tasks/gem.rake
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "rspec/core/rake_task"
|
4
|
-
require "mudguard/version"
|
5
|
-
|
6
|
-
namespace :gem do
|
7
|
-
desc "Publishes the gem on rubygems.org"
|
8
|
-
task publish: "gem:build" do
|
9
|
-
exec("gem push mudguard-#{Mudguard::VERSION}.gem")
|
10
|
-
end
|
11
|
-
desc "Builds the gem"
|
12
|
-
task :build do
|
13
|
-
exec("gem build mudguard.gemspec")
|
14
|
-
end
|
15
|
-
end
|