pronto-bigfiles 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.
Files changed (54) hide show
  1. checksums.yaml +7 -0
  2. data/.circleci/config.yml +20 -0
  3. data/.gitignore +15 -0
  4. data/.pronto.yml +5 -0
  5. data/.rspec +3 -0
  6. data/.rubocop.yml +74 -0
  7. data/.ruby-version +1 -0
  8. data/.travis.yml +16 -0
  9. data/CODE_OF_CONDUCT.md +76 -0
  10. data/Gemfile +6 -0
  11. data/Gemfile.lock +234 -0
  12. data/LICENSE.txt +21 -0
  13. data/Makefile +16 -0
  14. data/README.md +78 -0
  15. data/Rakefile +0 -0
  16. data/bin/console +15 -0
  17. data/bin/setup +8 -0
  18. data/coverage/.last_run.json +5 -0
  19. data/exe/pronto-bigfiles +4 -0
  20. data/feature/pronto/big_files_cli_spec.rb +88 -0
  21. data/feature/spec_helper.rb +0 -0
  22. data/lib/pronto/bigfiles/message_creator.rb +31 -0
  23. data/lib/pronto/bigfiles/patch_inspector.rb +45 -0
  24. data/lib/pronto/bigfiles/patch_wrapper.rb +28 -0
  25. data/lib/pronto/bigfiles/version.rb +7 -0
  26. data/lib/pronto/bigfiles.rb +35 -0
  27. data/metrics/bigfiles_high_water_mark +1 -0
  28. data/metrics/brakeman_high_water_mark +1 -0
  29. data/metrics/bundle-audit_high_water_mark +1 -0
  30. data/metrics/cane_high_water_mark +1 -0
  31. data/metrics/eslint_high_water_mark +1 -0
  32. data/metrics/flake8_high_water_mark +1 -0
  33. data/metrics/flay_high_water_mark +1 -0
  34. data/metrics/flog_high_water_mark +1 -0
  35. data/metrics/jscs_high_water_mark +1 -0
  36. data/metrics/mdl_high_water_mark +1 -0
  37. data/metrics/punchlist_high_water_mark +1 -0
  38. data/metrics/pycodestyle_high_water_mark +1 -0
  39. data/metrics/rails_best_practices_high_water_mark +1 -0
  40. data/metrics/rubocop_high_water_mark +1 -0
  41. data/metrics/scalastyle_high_water_mark +1 -0
  42. data/metrics/shellcheck_high_water_mark +1 -0
  43. data/pronto-bigfiles.gemspec +49 -0
  44. data/rakelib/ci.rake +4 -0
  45. data/rakelib/clear_metrics.rake +8 -0
  46. data/rakelib/default.rake +3 -0
  47. data/rakelib/feature.rake +9 -0
  48. data/rakelib/gem_tasks.rake +3 -0
  49. data/rakelib/localtest.rake +4 -0
  50. data/rakelib/pronto.rake +15 -0
  51. data/rakelib/quality.rake +23 -0
  52. data/rakelib/spec.rake +9 -0
  53. data/rakelib/update_bundle_audit.rake +6 -0
  54. metadata +243 -0
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pronto/bigfiles'
4
+ require 'tmpdir'
5
+ require 'open3'
6
+
7
+ describe Pronto::BigFiles do
8
+ let(:env) do
9
+ {
10
+ # Avoid spurious deprecation warnings in things which are out of
11
+ # our control
12
+ 'RUBYOPT' => '-W0',
13
+ }
14
+ end
15
+
16
+ describe 'bundle exec pronto list' do
17
+ it 'lists this as a runner' do
18
+ out, exit_code = Open3.capture2e(env, 'bundle exec pronto list')
19
+ expect(out).to include("bigfiles\n")
20
+ expect(exit_code).to eq(0)
21
+ end
22
+ end
23
+
24
+ describe 'bundle exec pronto run --staged -r bigfiles -f text' do
25
+ let(:pronto_command) do
26
+ 'bundle exec pronto run --staged -r bigfiles -f text'
27
+ end
28
+
29
+ let(:results) { Open3.capture2e(env, pronto_command) }
30
+ let(:out) { results[0] }
31
+ let(:exit_code) { results[1] }
32
+
33
+ around do |example|
34
+ Dir.mktmpdir do |dir|
35
+ Dir.chdir(dir) do
36
+ system('git init')
37
+ system('git config user.email "you@example.com"')
38
+ system('git config user.name "Fake User"')
39
+ example_files_committed.each do |filename, contents|
40
+ File.write(filename, contents)
41
+ end
42
+ system('git add .')
43
+ system('git commit -m "First commit"')
44
+ example_files_staged.each do |filename, contents|
45
+ File.write(filename, contents)
46
+ end
47
+ system('git add .')
48
+ example.run
49
+ end
50
+ end
51
+ end
52
+
53
+ # Policy: We complain iff:
54
+ #
55
+ # a file is added to
56
+ # that is in the three complained about
57
+ # and the total ends up above 300
58
+ #
59
+ # ...and we only complain once per file
60
+ context 'when single file net added to ' \
61
+ 'that is one of the three complained about, ' \
62
+ 'and is above limit' do
63
+ let(:expected_output) do
64
+ "one_line_added_above_limit.rb:302 W: This file, one of the " \
65
+ "3 largest in the project, increased in size to 302 lines. " \
66
+ "The total size of those files is now 502 lines (target: 300). " \
67
+ "Is this file complex enough to refactor?\n"
68
+ end
69
+
70
+ let(:example_files_committed) do
71
+ {
72
+ 'one_line_added_above_limit.rb' => ("\n" * 301),
73
+ 'some_other_file_1.rb' => ("\n" * 100),
74
+ 'some_other_file_2.rb' => ("\n" * 100),
75
+ }
76
+ end
77
+
78
+ let(:example_files_staged) do
79
+ { 'one_line_added_above_limit.rb' => ("\n" * 302) }
80
+ end
81
+
82
+ it 'complains on line of first change' do
83
+ expect(out).to eq(expected_output)
84
+ expect(exit_code).to eq(0)
85
+ end
86
+ end
87
+ end
88
+ end
File without changes
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pronto'
4
+
5
+ module Pronto
6
+ # Performs incremental quality reporting for the bigfiles gem
7
+ class BigFiles < Runner
8
+ # Creates Pronto warning message objects
9
+ class MessageCreator
10
+ attr_reader :num_files, :total_lines, :target_num_lines
11
+
12
+ def initialize(num_files, total_lines, target_num_lines)
13
+ @num_files = num_files
14
+ @total_lines = total_lines
15
+ @target_num_lines = target_num_lines
16
+ end
17
+
18
+ def create_message(patch_wrapper, num_lines)
19
+ path = patch_wrapper.path
20
+ line = patch_wrapper.first_added_line
21
+ level = :warning
22
+ msg = "This file, one of the #{num_files} largest in the project, " \
23
+ "increased in size to #{num_lines} lines. The total size " \
24
+ "of those files is now #{total_lines} lines " \
25
+ "(target: #{target_num_lines}). Is this file complex " \
26
+ "enough to refactor?"
27
+ Message.new(path, line, level, msg)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pronto'
4
+ require_relative 'message_creator'
5
+
6
+ module Pronto
7
+ # Performs incremental quality reporting for the bigfiles gem
8
+ class BigFiles < Runner
9
+ # Inspects patches and returns a Pronto::Message class when appropriate
10
+ class PatchInspector
11
+ def initialize(bigfiles_result,
12
+ message_creator_class: MessageCreator,
13
+ bigfiles_config:)
14
+ @message_creator_class = message_creator_class
15
+ @bigfiles_result = bigfiles_result
16
+ @bigfiles_config = bigfiles_config
17
+ @message_creator =
18
+ @message_creator_class.new(@bigfiles_config.num_files,
19
+ total_lines,
20
+ @bigfiles_config.high_water_mark)
21
+ end
22
+
23
+ def under_limit?
24
+ @bigfiles_config.under_limit?(total_lines)
25
+ end
26
+
27
+ def total_lines
28
+ @bigfiles_result.map(&:num_lines).reduce(:+)
29
+ end
30
+
31
+ def inspect_patch(patch_wrapper)
32
+ path = patch_wrapper.path
33
+ file_with_line = @bigfiles_result.find { |f| f.filename == path }
34
+
35
+ return if file_with_line.nil?
36
+
37
+ return unless patch_wrapper.added_to?
38
+
39
+ return if under_limit?
40
+
41
+ @message_creator.create_message(patch_wrapper, file_with_line.num_lines)
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pronto'
4
+
5
+ module Pronto
6
+ class BigFiles < Runner
7
+ # Add convenience methods on top of Pronto::Git::Patch
8
+ class PatchWrapper
9
+ attr_reader :patch
10
+
11
+ def initialize(patch)
12
+ @patch = patch
13
+ end
14
+
15
+ def added_to?
16
+ (patch.additions - patch.deletions).positive?
17
+ end
18
+
19
+ def path
20
+ patch.delta.new_file[:path]
21
+ end
22
+
23
+ def first_added_line
24
+ patch.added_lines.first
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pronto
4
+ module BigFilesVersion
5
+ VERSION = '0.1.0'
6
+ end
7
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pronto/bigfiles/version'
4
+ require 'pronto/bigfiles/patch_inspector'
5
+ require 'pronto/bigfiles/patch_wrapper'
6
+ require 'bigfiles/inspector'
7
+ require 'bigfiles/config'
8
+ require 'pronto'
9
+
10
+ module Pronto
11
+ # Performs incremental quality reporting for the bigfiles gem
12
+ class BigFiles < Runner
13
+ def initialize(patches, commit = nil,
14
+ bigfiles_config: ::BigFiles::Config.new,
15
+ bigfiles_inspector: ::BigFiles::Inspector.new,
16
+ bigfiles_results: bigfiles_inspector.find_and_analyze,
17
+ patch_wrapper_class: PatchWrapper,
18
+ patch_inspector: PatchInspector.new(bigfiles_results,
19
+ bigfiles_config:
20
+ bigfiles_config))
21
+ super(patches, commit)
22
+ @patch_inspector = patch_inspector
23
+ @patch_wrapper_class = patch_wrapper_class
24
+ end
25
+
26
+ class Error < StandardError; end
27
+ def run
28
+ @patches.flat_map { |patch| inspect_patch(patch) }
29
+ end
30
+
31
+ def inspect_patch(patch)
32
+ @patch_inspector.inspect_patch(@patch_wrapper_class.new(patch))
33
+ end
34
+ end
35
+ end
@@ -0,0 +1 @@
1
+ 300
@@ -0,0 +1 @@
1
+ 0
@@ -0,0 +1 @@
1
+ 0
@@ -0,0 +1 @@
1
+ 0
@@ -0,0 +1 @@
1
+ 0
@@ -0,0 +1 @@
1
+ 0
@@ -0,0 +1 @@
1
+ 0
@@ -0,0 +1 @@
1
+ 0
@@ -0,0 +1 @@
1
+ 0
@@ -0,0 +1 @@
1
+ 0
@@ -0,0 +1 @@
1
+ 0
@@ -0,0 +1 @@
1
+ 0
@@ -0,0 +1 @@
1
+ 0
@@ -0,0 +1 @@
1
+ 0
@@ -0,0 +1 @@
1
+ 0
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/pronto/bigfiles/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'pronto-bigfiles'
7
+ spec.version = Pronto::BigFilesVersion::VERSION
8
+ spec.authors = ['Vince Broz']
9
+ spec.email = ['vince@broz.cc']
10
+
11
+ spec.summary = 'Pronto plugin for the bigfiles gem'
12
+ spec.description = <<~DESCRIPTION
13
+ Performs incremental quality reporting for the bigfiles gem.
14
+ BigFiles is a simple tool to find the largest source files in your
15
+ project; this gem plugs in with the 'pronto' gem, which does
16
+ incremental reporting using a variety of quality tools.
17
+ DESCRIPTION
18
+ spec.homepage = 'https://github.com/apiology/pronto-bigfiles'
19
+ spec.license = 'MIT'
20
+ spec.required_ruby_version = Gem::Requirement.new('>= 2.3.0')
21
+
22
+ spec.metadata['homepage_uri'] = spec.homepage
23
+ spec.metadata['source_code_uri'] =
24
+ 'https://github.com/apiology/pronto-bigfiles'
25
+
26
+ # Specify which files should be added to the gem when it is
27
+ # released. The `git ls-files -z` loads the files in the RubyGem
28
+ # that have been added into git.
29
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
30
+ `git ls-files -z`.split("\x0").reject do |f|
31
+ f.match(%r{^(test|spec|features)/})
32
+ end
33
+ end
34
+ spec.bindir = 'exe'
35
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
36
+ spec.require_paths = ['lib']
37
+
38
+ spec.add_dependency 'bigfiles', '>=0.2.0'
39
+ spec.add_dependency 'pronto'
40
+ spec.add_dependency 'quality', '>= 37'
41
+
42
+ spec.add_development_dependency 'bundler', '~> 2.0'
43
+ spec.add_development_dependency 'pronto-punchlist'
44
+ spec.add_development_dependency 'pronto-rubocop'
45
+ spec.add_development_dependency 'quality', '~> 37'
46
+ spec.add_development_dependency 'rake'
47
+ spec.add_development_dependency 'rspec'
48
+ spec.add_development_dependency 'simplecov'
49
+ end
data/rakelib/ci.rake ADDED
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ desc 'Run tasks to be done during a continuous integration (CI) build'
4
+ task ci: :localtest
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ desc 'Rebaseline quality thresholds to last commit'
4
+ task :clear_metrics do |_t|
5
+ ret =
6
+ system('git checkout coverage/.last_run.json metrics/*_high_water_mark')
7
+ raise unless ret
8
+ end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ task default: :localtest
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rspec/core/rake_task'
4
+
5
+ desc 'Run features'
6
+ RSpec::Core::RakeTask.new(:feature) do |task|
7
+ task.pattern = 'feature/**/*_spec.rb'
8
+ task.rspec_opts = '--format doc --default-path feature'
9
+ end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ desc 'Standard build when running on a workstation'
4
+ task localtest: %i[clear_metrics spec feature quality]
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ desc 'Look for incremental quality issues'
4
+ task :pronto do
5
+ formatter = '-f github_pr' if ENV.key? 'PRONTO_GITHUB_ACCESS_TOKEN'
6
+ if ENV.key? 'TRAVIS_PULL_REQUEST'
7
+ ENV['PRONTO_PULL_REQUEST_ID'] = ENV['TRAVIS_PULL_REQUEST']
8
+ elsif ENV.key? 'CIRCLE_PULL_REQUEST'
9
+ ENV['PRONTO_PULL_REQUEST_ID'] = ENV['CIRCLE_PULL_REQUEST'].split('/').last
10
+ end
11
+ sh "pronto run #{formatter} -c origin/master --no-exit-code --unstaged "\
12
+ "|| true"
13
+ sh "pronto run #{formatter} -c origin/master --no-exit-code --staged || true"
14
+ sh "pronto run #{formatter} -c origin/master --no-exit-code || true"
15
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'quality/rake/task'
4
+
5
+ Quality::Rake::Task.new do |task|
6
+ task.exclude_files = ['Gemfile.lock']
7
+ # cane deprecated in favor of rubocop, reek rarely actionable
8
+ task.skip_tools = %w[reek cane eslint jscs flake8]
9
+ task.output_dir = 'metrics'
10
+ task.punchlist_regexp = 'XX' \
11
+ 'X|TOD' \
12
+ 'O|FIXM' \
13
+ 'E|OPTIMIZ' \
14
+ 'E|HAC' \
15
+ 'K|REVIE' \
16
+ 'W|LATE' \
17
+ 'R|FIXI' \
18
+ 'T|xi' \
19
+ 't '
20
+ end
21
+
22
+ desc 'Static analysis and metrics enforcement'
23
+ task quality: %i[pronto update_bundle_audit]
data/rakelib/spec.rake ADDED
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rspec/core/rake_task'
4
+
5
+ desc 'Run specs'
6
+ RSpec::Core::RakeTask.new(:spec) do |task|
7
+ task.pattern = 'spec/**/*_spec.rb'
8
+ task.rspec_opts = '--format doc'
9
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ desc 'Update definitions used in bundle-audit'
4
+ task :update_bundle_audit do
5
+ sh 'bundle-audit update'
6
+ end