sleeping_king_studios-tasks 0.1.0.rc.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 (50) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +26 -0
  3. data/DEVELOPMENT.md +50 -0
  4. data/LICENSE +22 -0
  5. data/README.md +405 -0
  6. data/lib/sleeping_king_studios/tasks.rb +27 -0
  7. data/lib/sleeping_king_studios/tasks/apps.rb +49 -0
  8. data/lib/sleeping_king_studios/tasks/apps/app_configuration.rb +68 -0
  9. data/lib/sleeping_king_studios/tasks/apps/applications_task.rb +28 -0
  10. data/lib/sleeping_king_studios/tasks/apps/bundle.rb +8 -0
  11. data/lib/sleeping_king_studios/tasks/apps/bundle/install_runner.rb +21 -0
  12. data/lib/sleeping_king_studios/tasks/apps/bundle/install_task.rb +39 -0
  13. data/lib/sleeping_king_studios/tasks/apps/bundle/update_runner.rb +21 -0
  14. data/lib/sleeping_king_studios/tasks/apps/bundle/update_task.rb +39 -0
  15. data/lib/sleeping_king_studios/tasks/apps/ci.rb +8 -0
  16. data/lib/sleeping_king_studios/tasks/apps/ci/results_reporter.rb +69 -0
  17. data/lib/sleeping_king_studios/tasks/apps/ci/rspec_task.rb +29 -0
  18. data/lib/sleeping_king_studios/tasks/apps/ci/rspec_wrapper.rb +42 -0
  19. data/lib/sleeping_king_studios/tasks/apps/ci/rubocop_task.rb +29 -0
  20. data/lib/sleeping_king_studios/tasks/apps/ci/rubocop_wrapper.rb +29 -0
  21. data/lib/sleeping_king_studios/tasks/apps/ci/simplecov_task.rb +68 -0
  22. data/lib/sleeping_king_studios/tasks/apps/ci/step_wrapper.rb +49 -0
  23. data/lib/sleeping_king_studios/tasks/apps/ci/steps_runner.rb +37 -0
  24. data/lib/sleeping_king_studios/tasks/apps/ci/steps_task.rb +92 -0
  25. data/lib/sleeping_king_studios/tasks/ci.rb +8 -0
  26. data/lib/sleeping_king_studios/tasks/ci/cucumber_parser.rb +118 -0
  27. data/lib/sleeping_king_studios/tasks/ci/cucumber_results.rb +191 -0
  28. data/lib/sleeping_king_studios/tasks/ci/cucumber_runner.rb +53 -0
  29. data/lib/sleeping_king_studios/tasks/ci/cucumber_task.rb +47 -0
  30. data/lib/sleeping_king_studios/tasks/ci/results_helpers.rb +44 -0
  31. data/lib/sleeping_king_studios/tasks/ci/rspec_each_results.rb +118 -0
  32. data/lib/sleeping_king_studios/tasks/ci/rspec_each_task.rb +156 -0
  33. data/lib/sleeping_king_studios/tasks/ci/rspec_results.rb +126 -0
  34. data/lib/sleeping_king_studios/tasks/ci/rspec_runner.rb +62 -0
  35. data/lib/sleeping_king_studios/tasks/ci/rspec_task.rb +71 -0
  36. data/lib/sleeping_king_studios/tasks/ci/rubocop_results.rb +80 -0
  37. data/lib/sleeping_king_studios/tasks/ci/rubocop_runner.rb +46 -0
  38. data/lib/sleeping_king_studios/tasks/ci/rubocop_task.rb +44 -0
  39. data/lib/sleeping_king_studios/tasks/ci/simplecov_results.rb +62 -0
  40. data/lib/sleeping_king_studios/tasks/ci/simplecov_task.rb +25 -0
  41. data/lib/sleeping_king_studios/tasks/ci/steps_runner.rb +69 -0
  42. data/lib/sleeping_king_studios/tasks/ci/steps_task.rb +93 -0
  43. data/lib/sleeping_king_studios/tasks/configuration.rb +114 -0
  44. data/lib/sleeping_king_studios/tasks/file.rb +8 -0
  45. data/lib/sleeping_king_studios/tasks/file/new_task.rb +238 -0
  46. data/lib/sleeping_king_studios/tasks/process_runner.rb +70 -0
  47. data/lib/sleeping_king_studios/tasks/task.rb +95 -0
  48. data/lib/sleeping_king_studios/tasks/task_group.rb +37 -0
  49. data/lib/sleeping_king_studios/tasks/version.rb +58 -0
  50. metadata +271 -0
@@ -0,0 +1,62 @@
1
+ # lib/sleeping_king_studios/tasks/ci/rspec_runner.rb
2
+
3
+ require 'json'
4
+
5
+ require 'sleeping_king_studios/tasks/ci'
6
+ require 'sleeping_king_studios/tasks/process_runner'
7
+
8
+ module SleepingKingStudios::Tasks::Ci
9
+ # Service object to run RSpec as an external process with the specified
10
+ # parameters.
11
+ class RSpecRunner < SleepingKingStudios::Tasks::ProcessRunner
12
+ def call env: {}, files: [], options: [], report: true
13
+ report = 'tmp/ci/rspec.json' if report && !report.is_a?(String)
14
+ command =
15
+ build_command(
16
+ :env => env,
17
+ :files => files,
18
+ :options => options,
19
+ :report => report
20
+ ) # end build_command
21
+
22
+ stream_process(command)
23
+
24
+ report ? load_report(:report => report) : {}
25
+ end # method call
26
+
27
+ private
28
+
29
+ def base_command
30
+ 'bundle exec rspec'
31
+ end # method base_command
32
+
33
+ def build_options files:, options:, report:, **_kwargs
34
+ options += ['--format=json', "--out=#{report}"] if report
35
+
36
+ super :files => files, :options => options
37
+ end # method build_options
38
+
39
+ def load_report report:
40
+ raw = File.read report
41
+
42
+ return {} if raw.empty?
43
+
44
+ json = JSON.parse raw
45
+ hsh = json['summary']
46
+
47
+ hsh['error_count'] = parse_errors(json['summary_line'])
48
+
49
+ hsh
50
+ rescue
51
+ {}
52
+ end # method load_report
53
+
54
+ def parse_errors summary
55
+ return 0 unless summary && !summary.empty?
56
+
57
+ match = summary.match(/(?<digits>\d+) error/)
58
+
59
+ match ? match[:digits].to_i : 0
60
+ end # method parse_errors
61
+ end # class
62
+ end # module
@@ -0,0 +1,71 @@
1
+ # lib/sleeping_king_studios/tasks/ci/rspec_task.rb
2
+
3
+ require 'sleeping_king_studios/tasks/ci'
4
+ require 'sleeping_king_studios/tasks/ci/rspec_results'
5
+ require 'sleeping_king_studios/tasks/ci/rspec_runner'
6
+
7
+ module SleepingKingStudios::Tasks::Ci
8
+ # Defines a Thor task for running the full RSpec test suite.
9
+ class RSpecTask < SleepingKingStudios::Tasks::Task
10
+ def self.description
11
+ 'Runs the RSpec test suite.'
12
+ end # class method description
13
+
14
+ def self.task_name
15
+ 'rspec'
16
+ end # class method task_name
17
+
18
+ option :coverage,
19
+ :type => :boolean,
20
+ :desc => 'Enable or disable coverage with SimpleCov, if available.'
21
+ option :gemfile,
22
+ :type => :string,
23
+ :desc => 'The Gemfile used to run the specs.',
24
+ :default => ENV['BUNDLE_GEMFILE']
25
+ option :quiet,
26
+ :aliases => '-q',
27
+ :type => :boolean,
28
+ :default => false,
29
+ :desc => 'Do not write spec results to STDOUT.'
30
+ option :raw,
31
+ :aliases => '-r',
32
+ :type => :boolean,
33
+ :default => false,
34
+ :desc => 'Return a Hash instead of a results object.'
35
+
36
+ def call *files
37
+ results = rspec_runner(files.empty?).call(:files => files)
38
+
39
+ raw? ? results : RSpecResults.new(results)
40
+ end # method call
41
+
42
+ private
43
+
44
+ def default_gemfile
45
+ File.join(Dir.pwd, 'Gemfile')
46
+ end # method default_gemfile
47
+
48
+ def gemfile
49
+ return options['gemfile'] if options.key?('gemfile')
50
+
51
+ gemfile = ENV['BUNDLE_GEMFILE']
52
+
53
+ return gemfile if gemfile && gemfile != default_gemfile
54
+
55
+ nil
56
+ end # method gemfile
57
+
58
+ def rspec_runner default_coverage = true
59
+ coverage = options.fetch('coverage', default_coverage)
60
+
61
+ env = options.fetch('__env__', {})
62
+ env[:bundle_gemfile] = gemfile if gemfile
63
+ env[:coverage] = false unless coverage
64
+
65
+ opts = %w(--color --tty)
66
+ opts << '--format=documentation' unless quiet?
67
+
68
+ RSpecRunner.new(:env => env, :options => opts)
69
+ end # method rspec_runner
70
+ end # class
71
+ end # module
@@ -0,0 +1,80 @@
1
+ # lib/sleeping_king_studios/tasks/ci/rubocop_results.rb
2
+
3
+ require 'sleeping_king_studios/tasks/ci'
4
+
5
+ module SleepingKingStudios::Tasks::Ci
6
+ # Encapsulates the results of a RuboCop call.
7
+ class RuboCopResults
8
+ # @param results [Hash] The raw results of the RuboCop call.
9
+ def initialize results
10
+ @results = results
11
+ end # constructor
12
+
13
+ # @param other [RSpecResults] The other results object to compare.
14
+ #
15
+ # @return [Boolean] True if the results are equal, otherwise false.
16
+ def == other
17
+ if other.is_a?(Hash)
18
+ empty? ? other.empty? : to_h == other
19
+ elsif other.is_a?(RuboCopResults)
20
+ to_h == other.to_h
21
+ else
22
+ false
23
+ end # if-elsif-else
24
+ end # method ==
25
+
26
+ # @return [Boolean] True if there are no inspected files, otherwise false.
27
+ def empty?
28
+ inspected_file_count.zero?
29
+ end # method empty?
30
+
31
+ # @return [Boolean] True if there are any offenses, otherwise false.
32
+ def failing?
33
+ !offense_count.zero?
34
+ end # method failing?
35
+
36
+ # @return [Integer] The number of inspected files.
37
+ def inspected_file_count
38
+ @results.fetch('inspected_file_count', 0)
39
+ end # method inspected_file_count
40
+
41
+ # Adds the given result values and returns a new results object with the
42
+ # sums.
43
+ #
44
+ # @param other [RuboCopResults] The results to add.
45
+ #
46
+ # @return [RuboCopResults] The total results.
47
+ def merge other
48
+ self.class.new(
49
+ 'inspected_file_count' =>
50
+ inspected_file_count + other.inspected_file_count,
51
+ 'offense_count' => offense_count + other.offense_count
52
+ ) # end new
53
+ end # method merge
54
+
55
+ # @return [Integer] The number of detected offenses.
56
+ def offense_count
57
+ @results.fetch('offense_count', 0)
58
+ end # method offense_count
59
+
60
+ # @return [Boolean] False.
61
+ def pending?
62
+ false
63
+ end # method pending?
64
+
65
+ # @return [Hash] The hash representation of the results.
66
+ def to_h
67
+ {
68
+ 'inspected_file_count' => inspected_file_count,
69
+ 'offense_count' => offense_count
70
+ } # end hash
71
+ end # method to_h
72
+
73
+ # @return [String] The string representation of the results.
74
+ def to_s
75
+ str = "#{inspected_file_count} files inspected"
76
+
77
+ str << ", #{offense_count} offenses"
78
+ end # method to_s
79
+ end # class
80
+ end # module
@@ -0,0 +1,46 @@
1
+ # lib/sleeping_king_studios/tasks/ci/rubocop_runner.rb
2
+
3
+ require 'sleeping_king_studios/tasks/ci'
4
+ require 'sleeping_king_studios/tasks/process_runner'
5
+
6
+ module SleepingKingStudios::Tasks::Ci
7
+ # Service object to run RuboCop as an external process with the specified
8
+ # parameters.
9
+ class RuboCopRunner < SleepingKingStudios::Tasks::ProcessRunner
10
+ def call env: {}, files: [], options: [], report: true
11
+ report = 'tmp/ci/rubocop.json' if report && !report.is_a?(String)
12
+ command =
13
+ build_command(
14
+ :env => env,
15
+ :files => files,
16
+ :options => options,
17
+ :report => report
18
+ ) # end build_command
19
+
20
+ stream_process(command)
21
+
22
+ report ? load_report(:report => report) : {}
23
+ end # method call
24
+
25
+ private
26
+
27
+ def base_command
28
+ 'bundle exec rubocop'
29
+ end # method base_command
30
+
31
+ def build_options files:, options:, report:, **_kwargs
32
+ options += ['--format=json', "--out=#{report}"] if report
33
+
34
+ super :files => files, :options => options
35
+ end # method build_options
36
+
37
+ def load_report report:
38
+ raw = File.read report
39
+ json = JSON.parse raw
40
+
41
+ json['summary']
42
+ rescue
43
+ {}
44
+ end # method load_report
45
+ end # class
46
+ end # module
@@ -0,0 +1,44 @@
1
+ # lib/sleeping_king_studios/tasks/ci/rubocop_task.rb
2
+
3
+ require 'sleeping_king_studios/tasks/ci'
4
+ require 'sleeping_king_studios/tasks/ci/rubocop_results'
5
+ require 'sleeping_king_studios/tasks/ci/rubocop_runner'
6
+
7
+ module SleepingKingStudios::Tasks::Ci
8
+ # Defines a Thor task for running the RuboCop linter.
9
+ class RuboCopTask < SleepingKingStudios::Tasks::Task
10
+ def self.description
11
+ 'Runs the RuboCop linter.'
12
+ end # class method description
13
+
14
+ def self.task_name
15
+ 'rubocop'
16
+ end # class method task_name
17
+
18
+ option :quiet,
19
+ :aliases => '-q',
20
+ :type => :boolean,
21
+ :default => false,
22
+ :desc => 'Do not write lint results to STDOUT.'
23
+ option :raw,
24
+ :aliases => '-r',
25
+ :type => :boolean,
26
+ :default => false,
27
+ :desc => 'Return a Hash instead of a results object.'
28
+
29
+ def call *files
30
+ results = rubocop_runner.call(:files => files)
31
+
32
+ raw? ? results : RuboCopResults.new(results)
33
+ end # method call
34
+
35
+ private
36
+
37
+ def rubocop_runner
38
+ opts = %w(--color)
39
+ opts << '--format=progress' unless quiet?
40
+
41
+ RuboCopRunner.new(:options => opts)
42
+ end # method rubocop_runner
43
+ end # class
44
+ end # module
@@ -0,0 +1,62 @@
1
+ # lib/sleeping_king_studios/tasks/ci/simplecov_results.rb
2
+
3
+ require 'sleeping_king_studios/tools/toolbox/delegator'
4
+
5
+ require 'sleeping_king_studios/tasks/ci'
6
+
7
+ module SleepingKingStudios::Tasks::Ci
8
+ # Encapsulates the results of aggregated SimpleCov data.
9
+ class SimpleCovResults
10
+ extend SleepingKingStudios::Tools::Toolbox::Delegator
11
+
12
+ # @param results [SimpleCov::Result] The raw results of the SimpleCov call.
13
+ def initialize results
14
+ @results = results
15
+ end # constructor
16
+
17
+ delegate \
18
+ :covered_lines,
19
+ :covered_percent,
20
+ :missed_lines,
21
+ :total_lines,
22
+ :to => :@results
23
+
24
+ # @return [Boolean] True if there are no covered lines, otherwise false.
25
+ def empty?
26
+ covered_lines.zero?
27
+ end # method empty?
28
+
29
+ # @return [Boolean] True if the covered percentage is less than or equal to
30
+ # the configured value, otherwise false.
31
+ def failing?
32
+ covered_percent.round(1) <= failing_percent.round(1)
33
+ end # method failing?
34
+
35
+ # @return [Float] If the covered percentage is less than or equal to this
36
+ # value, the result is failing.
37
+ def failing_percent
38
+ 90.0
39
+ end # method failing_percent
40
+
41
+ # @return [Boolean] True if the covered percentage is less than or equal to
42
+ # the configured value, otherwise false.
43
+ def pending?
44
+ !failing? && covered_percent.round(1) <= pending_percent.round(1)
45
+ end # method pending?
46
+
47
+ # @return [Float] If the covered percentage is less than or equal to this
48
+ # value, the result is pending.
49
+ def pending_percent
50
+ 95.0
51
+ end # method failing_percent
52
+
53
+ # @return [String] The string representation of the results.
54
+ def to_s
55
+ str = "#{covered_percent.round(2)}% coverage"
56
+
57
+ str << ", #{missed_lines} missed lines"
58
+
59
+ str << ", #{total_lines} total lines"
60
+ end # method to_s
61
+ end # class
62
+ end # module
@@ -0,0 +1,25 @@
1
+ # lib/sleeping_king_studios/tasks/ci/simplecov_task.rb
2
+
3
+ require 'simplecov'
4
+
5
+ require 'sleeping_king_studios/tasks/ci'
6
+ require 'sleeping_king_studios/tasks/ci/simplecov_results'
7
+
8
+ module SleepingKingStudios::Tasks::Ci
9
+ # Defines a Thor task for aggregating SimpleCov results.
10
+ class SimpleCovTask < SleepingKingStudios::Tasks::Task
11
+ def self.description
12
+ 'Aggregates the SimpleCov results.'
13
+ end # class method description
14
+
15
+ def self.task_name
16
+ 'simplecov'
17
+ end # class method task_name
18
+
19
+ def call *_args
20
+ results = ::SimpleCov.result
21
+
22
+ SimpleCovResults.new(results)
23
+ end # method call
24
+ end # class
25
+ end # module
@@ -0,0 +1,69 @@
1
+ # lib/sleeping_king_studios/tasks/ci/steps_runner.rb
2
+
3
+ require 'sleeping_king_studios/tasks/ci'
4
+
5
+ module SleepingKingStudios::Tasks::Ci
6
+ # Abstract base class for running a sequence of tasks from a configured list.
7
+ class StepsRunner < SleepingKingStudios::Tasks::Task
8
+ def call *args
9
+ results = {}
10
+
11
+ filtered_steps.each do |name, config|
12
+ next if skip_step?(name, config)
13
+
14
+ title = config.fetch(:title, name)
15
+
16
+ results[title] = call_step(config, args)
17
+ end # reduce
18
+
19
+ results
20
+ end # method call
21
+
22
+ private
23
+
24
+ def ci_steps
25
+ []
26
+ end # method ci_steps
27
+
28
+ def call_step config, args
29
+ class_name = config[:class]
30
+ require_path = config.fetch(:require, require_path(class_name))
31
+
32
+ require require_path if require_path
33
+
34
+ step_class = Object.const_get(class_name)
35
+ instance = step_class.new(options)
36
+
37
+ instance.call(*args)
38
+ end # method call_step
39
+
40
+ # rubocop:disable Metrics/AbcSize
41
+ def filtered_steps
42
+ filtered = ci_steps
43
+
44
+ if options.key?('except') && !options['except'].empty?
45
+ filtered =
46
+ filtered.reject { |key, _| options['except'].include?(key.to_s) }
47
+ end # if
48
+
49
+ if options.key?('only') && !options['only'].empty?
50
+ filtered =
51
+ filtered.select { |key, _| options['only'].include?(key.to_s) }
52
+ end # if
53
+
54
+ filtered
55
+ end # method filtered_steps
56
+ # rubocop:enable Metrics/AbcSize
57
+
58
+ def require_path class_name
59
+ class_name.
60
+ split('::').
61
+ map { |str| tools.string.underscore(str) }.
62
+ join '/'
63
+ end # method require_path
64
+
65
+ def skip_step? _name, _config
66
+ false
67
+ end # method skip_step?
68
+ end # class
69
+ end # module