sleeping_king_studios-tasks 0.1.0.rc.0 → 0.3.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 (30) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +12 -0
  3. data/DEVELOPMENT.md +9 -4
  4. data/README.md +4 -2
  5. data/lib/sleeping_king_studios/tasks/apps/bundle/tasks.thor +15 -0
  6. data/lib/sleeping_king_studios/tasks/apps/ci/rspec_task.rb +1 -1
  7. data/lib/sleeping_king_studios/tasks/apps/ci/rubocop_task.rb +1 -1
  8. data/lib/sleeping_king_studios/tasks/apps/ci/tasks.thor +20 -0
  9. data/lib/sleeping_king_studios/tasks/ci/cucumber_parser.rb +4 -3
  10. data/lib/sleeping_king_studios/tasks/ci/cucumber_results.rb +2 -2
  11. data/lib/sleeping_king_studios/tasks/ci/cucumber_task.rb +1 -1
  12. data/lib/sleeping_king_studios/tasks/ci/eslint_results.rb +112 -0
  13. data/lib/sleeping_king_studios/tasks/ci/eslint_runner.rb +51 -0
  14. data/lib/sleeping_king_studios/tasks/ci/eslint_task.rb +32 -0
  15. data/lib/sleeping_king_studios/tasks/ci/jest_results.rb +106 -0
  16. data/lib/sleeping_king_studios/tasks/ci/jest_runner.rb +51 -0
  17. data/lib/sleeping_king_studios/tasks/ci/jest_task.rb +43 -0
  18. data/lib/sleeping_king_studios/tasks/ci/rspec_each_task.rb +18 -2
  19. data/lib/sleeping_king_studios/tasks/ci/rspec_task.rb +12 -2
  20. data/lib/sleeping_king_studios/tasks/ci/rubocop_task.rb +1 -1
  21. data/lib/sleeping_king_studios/tasks/ci/tasks.thor +24 -0
  22. data/lib/sleeping_king_studios/tasks/configuration.rb +25 -4
  23. data/lib/sleeping_king_studios/tasks/file/new_task.rb +14 -12
  24. data/lib/sleeping_king_studios/tasks/file/tasks.thor +13 -0
  25. data/lib/sleeping_king_studios/tasks/file/templates/rspec.erb +13 -0
  26. data/lib/sleeping_king_studios/tasks/file/templates/ruby.erb +28 -0
  27. data/lib/sleeping_king_studios/tasks/process_runner.rb +14 -4
  28. data/lib/sleeping_king_studios/tasks/version.rb +3 -3
  29. data/lib/sleeping_king_studios/tools/toolbox/configuration.rb +280 -0
  30. metadata +32 -28
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 23b7118b16d2e49bdf0cce8ae9fc851a9dc15e65
4
- data.tar.gz: 871a76c2aca5508af7274c523b490b280e5bf88e
2
+ SHA256:
3
+ metadata.gz: c9380cfb581917cac00ae5102325dd895fcbd1364b4d8a53844f9ead55a41173
4
+ data.tar.gz: 69647411117043bf53bf24c4f47231de7d970de6c3adff412cc4a5228af7939e
5
5
  SHA512:
6
- metadata.gz: cd3215b9178f05d13cbc1242de1a29fadbe73b4d09c69c7fcb867135286e945df6ad16073945174afd352d93fe8393a6ad49c647c538a90a92cc8fdf6a1e96fb
7
- data.tar.gz: 9d07f269ef18d991864ae874b6355c531d1c111857b4f4891adf8f782b1a490062e49c314790d762c581dce0d7bad25b363cc6f42ee062f29280ce6ef1c32289
6
+ metadata.gz: 563983af6ab016118a21b810e8c5b2f61ef915ddee3bdce425f8945c5bf2bfb5dfc21a14acf8a07a7c08776443fd0cf7e46e5f96ff2c708a88f0834e4d856e51
7
+ data.tar.gz: 0b2d75151cc7513903514ed8f60041c5b7e73b2723373ceedb7f904a65059e8815f100f9cb54f745c6619274650f3ca7b2da063b50082b5548159fcf0d3918d9
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.3.0
4
+
5
+ - Fix deprecation warnings in Ruby 2.7.
6
+ - Add support for Thor 1.0.
7
+
8
+ ## 0.2.0
9
+
10
+ ### Ci
11
+
12
+ - Implement tasks for Jest.js, ESLint.
13
+ - Add --format option, configuration value for RSpec, RSpec (Each) tasks.
14
+
3
15
  ## 0.1.0
4
16
 
5
17
  Initial commit.
@@ -1,13 +1,12 @@
1
1
  ## Tasks
2
2
 
3
- ### 0.1.0
3
+ ### Version 0.2.1
4
4
 
5
- - task names should be strings, not symbols
6
- - formalize (public) task names as _Task, _task.rb ?
7
- - documentation pass
5
+ - add --retry option to Cucumber task.
8
6
 
9
7
  ### Future Tasks
10
8
 
9
+ - add documentation for "ci" option in applications.yml
11
10
  - integration testing for RSpec, RSpecEach tasks
12
11
  - sample spec files with known output(s)
13
12
  - extract common Results object superclass
@@ -22,6 +21,12 @@
22
21
 
23
22
  #### CI
24
23
 
24
+ - configurable --format options for CI steps
25
+
26
+ - task ci:rspec_each: |
27
+
28
+ Default to displaying --format=progress.
29
+
25
30
  - task ci:steps: |
26
31
 
27
32
  Add --diff option
data/README.md CHANGED
@@ -169,9 +169,11 @@ In addition, the cucumber step has the additional option:
169
169
 
170
170
  - `default_files [Array]`: Files that are always loaded when running Cucumber, such as step definitions or support files. By default, this includes 'step_definitions.rb' and the 'step_definitions' directory inside 'features'.
171
171
 
172
- `config.ci.rspec [Hash]`: Step configuration for the RSpec step. Has the same options as `config.ci.cucumber`, above, except for the aforementioned `default_files` option.
172
+ `config.ci.rspec [Hash]`: Step configuration for the RSpec step. Has the same options as `config.ci.cucumber`, above, except for the aforementioned `default_files` option. In addition, the RSpec task has the following option:
173
173
 
174
- `config.ci.rspec_each [Hash]`: Step configuration for the RSpec Each step.
174
+ - `format [String]`: The RSpec formatter used to format the spec results. Defaults to 'documentation'.
175
+
176
+ `config.ci.rspec_each [Hash]`: Step configuration for the RSpec Each step. Has the same configuration options as the RSpec step.
175
177
 
176
178
  `config.ci.rubocop [Hash]`: Step configuration for the RuboCop step.
177
179
 
@@ -0,0 +1,15 @@
1
+ # lib/sleeping_king_studios/tasks/apps/bundle/tasks.thor
2
+
3
+ require 'sleeping_king_studios/tasks/apps/bundle'
4
+ require 'sleeping_king_studios/tasks/apps/bundle/install_task'
5
+ require 'sleeping_king_studios/tasks/apps/bundle/update_task'
6
+
7
+ module SleepingKingStudios::Tasks::Apps::Bundle
8
+ # Thor integration for application gem dependency tasks.
9
+ class Tasks < SleepingKingStudios::Tasks::TaskGroup
10
+ namespace :"apps:bundle"
11
+
12
+ task SleepingKingStudios::Tasks::Apps::Bundle::InstallTask
13
+ task SleepingKingStudios::Tasks::Apps::Bundle::UpdateTask
14
+ end # class
15
+ end # module
@@ -22,7 +22,7 @@ module SleepingKingStudios::Tasks::Apps::Ci
22
22
 
23
23
  def call *applications
24
24
  SleepingKingStudios::Tasks::Apps::Ci::StepsTask.
25
- new(options.merge('only' => %w(rspec))).
25
+ new(options.merge('only' => %w[rspec])).
26
26
  call(*applications)
27
27
  end # method call
28
28
  end # class
@@ -22,7 +22,7 @@ module SleepingKingStudios::Tasks::Apps::Ci
22
22
 
23
23
  def call *applications
24
24
  SleepingKingStudios::Tasks::Apps::Ci::StepsTask.
25
- new(options.merge('only' => %w(rubocop))).
25
+ new(options.merge('only' => %w[rubocop])).
26
26
  call(*applications)
27
27
  end # method call
28
28
  end # class
@@ -0,0 +1,20 @@
1
+ # lib/sleeping_king_studios/tasks/apps/ci/tasks.thor
2
+
3
+ require 'sleeping_king_studios/tasks/apps/ci'
4
+ require 'sleeping_king_studios/tasks/apps/ci/rspec_task'
5
+ require 'sleeping_king_studios/tasks/apps/ci/rubocop_task'
6
+ require 'sleeping_king_studios/tasks/apps/ci/simplecov_task'
7
+ require 'sleeping_king_studios/tasks/apps/ci/steps_task'
8
+
9
+ module SleepingKingStudios::Tasks::Apps::Ci
10
+ # Thor integration for continuous integration tasks in semi-distributed
11
+ # applications.
12
+ class Tasks < SleepingKingStudios::Tasks::TaskGroup
13
+ namespace :"apps:ci"
14
+
15
+ task SleepingKingStudios::Tasks::Apps::Ci::RSpecTask
16
+ task SleepingKingStudios::Tasks::Apps::Ci::RuboCopTask
17
+ task SleepingKingStudios::Tasks::Apps::Ci::SimpleCovTask
18
+ task SleepingKingStudios::Tasks::Apps::Ci::StepsTask
19
+ end # class
20
+ end # module
@@ -65,11 +65,12 @@ module SleepingKingStudios::Tasks::Ci
65
65
 
66
66
  status = step_status(step) || 'failed'
67
67
 
68
- if status == 'failed'
68
+ case status
69
+ when 'failed'
69
70
  report['failing_step_count'] += 1
70
- elsif status == 'pending' || status == 'skipped'
71
+ when 'pending', 'skipped'
71
72
  report['pending_step_count'] += 1
72
- end # if
73
+ end
73
74
 
74
75
  status
75
76
  end # method parse_step
@@ -167,7 +167,7 @@ module SleepingKingStudios::Tasks::Ci
167
167
  end # method build_summary_details
168
168
 
169
169
  def keys
170
- %w(
170
+ %w[
171
171
  duration
172
172
  step_count
173
173
  pending_step_count
@@ -175,7 +175,7 @@ module SleepingKingStudios::Tasks::Ci
175
175
  scenario_count
176
176
  pending_scenarios
177
177
  failing_scenarios
178
- ) # end keys
178
+ ] # end keys
179
179
  end # method keys
180
180
 
181
181
  def pluralize count, singular, plural = nil
@@ -33,7 +33,7 @@ module SleepingKingStudios::Tasks::Ci
33
33
  private
34
34
 
35
35
  def cucumber_runner
36
- opts = %w(--color)
36
+ opts = %w[--color]
37
37
  opts << '--format=pretty' unless quiet?
38
38
 
39
39
  CucumberRunner.new(:options => opts)
@@ -0,0 +1,112 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'sleeping_king_studios/tasks/ci'
4
+
5
+ module SleepingKingStudios::Tasks::Ci
6
+ # Encapsulates the results of an Eslint call.
7
+ class EslintResults
8
+ # @param results [Hash] The raw results of the Eslint call.
9
+ def initialize results
10
+ @results = results
11
+ end
12
+
13
+ # @param other [EslintResults] 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?(Array)
18
+ empty? ? other.empty? : @results == other
19
+ elsif other.is_a?(EslintResults)
20
+ to_h == other.to_h
21
+ else
22
+ false
23
+ end
24
+ end
25
+
26
+ # @return [Boolean] True if there are no inspected files, otherwise false.
27
+ def empty?
28
+ inspected_file_count.zero?
29
+ end
30
+
31
+ # @return [Integer] The total number of error results across all files.
32
+ def error_count
33
+ @error_count ||= @results.map { |hsh| hsh['errorCount'] }.sum
34
+ end
35
+
36
+ # @return [Boolean] True if there are no errors or warnings, otherwise
37
+ # false.
38
+ def failing?
39
+ !(error_count.zero? && warning_count.zero?)
40
+ end
41
+
42
+ # @return [Integer] The number of inspected files.
43
+ def inspected_file_count
44
+ @results.size
45
+ end
46
+
47
+ # @return [Boolean] Always false. Both warnings and errors trigger a failure
48
+ # state.
49
+ def pending?
50
+ false
51
+ end
52
+
53
+ # @return [Hash] The hash representation of the results.
54
+ def to_h
55
+ {
56
+ 'inspected_file_count' => inspected_file_count,
57
+ 'error_count' => error_count,
58
+ 'warning_count' => warning_count
59
+ }
60
+ end
61
+
62
+ # @return [String] The string representation of the results.
63
+ def to_s # rubocop:disable Metrics/AbcSize
64
+ str = +"#{pluralize inspected_file_count, 'file'} inspected"
65
+
66
+ str << ", #{pluralize error_count, 'error'}"
67
+
68
+ str << ", #{pluralize warning_count, 'warning'}"
69
+
70
+ str << "\n" unless non_empty_results.empty?
71
+
72
+ non_empty_results.each do |hsh|
73
+ str << "\n #{format_result_item(hsh)}"
74
+ end
75
+
76
+ str
77
+ end
78
+
79
+ # @return [Integer] The total number of warning results across all files.
80
+ def warning_count
81
+ @warning_count ||= @results.map { |hsh| hsh['warningCount'] }.sum
82
+ end
83
+
84
+ private
85
+
86
+ def format_result_item hsh
87
+ str = +relative_path(hsh['filePath'])
88
+
89
+ str << ": #{pluralize hsh['errorCount'], 'error'}"
90
+
91
+ str << ", #{pluralize hsh['warningCount'], 'warning'}"
92
+ end
93
+
94
+ def non_empty_results
95
+ @results.reject do |hsh|
96
+ hsh['errorCount'].zero? && hsh['warningCount'].zero?
97
+ end
98
+ end
99
+
100
+ def pluralize count, singular, plural = nil
101
+ "#{count} #{tools.integer.pluralize count, singular, plural}"
102
+ end
103
+
104
+ def relative_path path
105
+ path.sub(/\A#{Dir.getwd}#{File::SEPARATOR}?/, '')
106
+ end
107
+
108
+ def tools
109
+ SleepingKingStudios::Tools::Toolbelt.instance
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
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 Eslint as an external process with the specified
8
+ # parameters.
9
+ class EslintRunner < SleepingKingStudios::Tasks::ProcessRunner
10
+ def call env: {}, files: [], options: [], report: true
11
+ report = 'tmp/ci/eslint.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
+ )
19
+
20
+ stream_process(command)
21
+
22
+ report ? load_report(:report => report) : []
23
+ end
24
+
25
+ private
26
+
27
+ def base_command
28
+ 'yarn eslint'
29
+ end
30
+
31
+ def build_options files:, options:, report:, **_kwargs
32
+ files = default_files if files.empty?
33
+ options += ['--format=json', "--output-file=#{report}"] if report
34
+
35
+ super :files => files, :options => options
36
+ end
37
+
38
+ def default_files
39
+ SleepingKingStudios::Tasks.configuration.ci.eslint.
40
+ fetch(:default_files, '"**/*.js"')
41
+ end
42
+
43
+ def load_report report:
44
+ raw = File.read report
45
+
46
+ JSON.parse raw
47
+ rescue
48
+ []
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'sleeping_king_studios/tasks/ci'
4
+ require 'sleeping_king_studios/tasks/ci/eslint_results'
5
+ require 'sleeping_king_studios/tasks/ci/eslint_runner'
6
+
7
+ module SleepingKingStudios::Tasks::Ci
8
+ # Defines a Thor task for running the Eslint linter.
9
+ class EslintTask < SleepingKingStudios::Tasks::Task
10
+ def self.description
11
+ 'Runs the ESLint linter.'
12
+ end
13
+
14
+ def self.task_name
15
+ 'eslint'
16
+ end
17
+
18
+ def call *files
19
+ results = eslint_runner.call(:files => files)
20
+
21
+ EslintResults.new(results)
22
+ end
23
+
24
+ private
25
+
26
+ def eslint_runner
27
+ opts = %w[--color]
28
+
29
+ EslintRunner.new(:options => opts)
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,106 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'sleeping_king_studios/tasks/ci'
4
+
5
+ module SleepingKingStudios::Tasks::Ci
6
+ # Encapsulates the results of a Jest call.
7
+ class JestResults
8
+ # @param results [Hash] The raw results of the Jest call.
9
+ def initialize results
10
+ @results = results
11
+ end
12
+
13
+ # @param other [JestResults] 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? : @results == other
19
+ elsif other.is_a?(JestResults)
20
+ to_h == other.to_h
21
+ else
22
+ false
23
+ end
24
+ end
25
+
26
+ # @return [Float] The duration value, in seconds.
27
+ def duration
28
+ (end_time - start_time).to_f / 1000
29
+ end
30
+
31
+ # @return [Boolean] True if there are no tests, otherwise false.
32
+ def empty?
33
+ test_count.zero?
34
+ end
35
+
36
+ # @return [Boolean] True if there are any failing tests, otherwise false.
37
+ def failing?
38
+ !failure_count.zero?
39
+ end
40
+
41
+ # @return [Integer] The number of failing tests.
42
+ def failure_count
43
+ @results.fetch('numFailedTests', 0)
44
+ end
45
+
46
+ # @return [Boolean] True if there are any pending tests, otherwise false.
47
+ def pending?
48
+ !pending_count.zero?
49
+ end
50
+
51
+ # @return [Intger] The number of pending tests.
52
+ def pending_count
53
+ @results.fetch('numPendingTests', 0)
54
+ end
55
+
56
+ # @return [Integer] The total number of tests.
57
+ def test_count
58
+ @results.fetch('numTotalTests', 0)
59
+ end
60
+
61
+ # @return [Hash] The hash representation of the results.
62
+ def to_h
63
+ {
64
+ 'duration' => duration,
65
+ 'failure_count' => failure_count,
66
+ 'pending_count' => pending_count,
67
+ 'test_count' => test_count
68
+ }
69
+ end
70
+
71
+ # @return [String] The string representation of the results.
72
+ def to_s # rubocop:disable Metrics/AbcSize
73
+ str = +pluralize(test_count, 'test')
74
+
75
+ str << ', ' << pluralize(failure_count, 'failure')
76
+
77
+ str << ', ' << pending_count.to_s << ' pending' if pending?
78
+
79
+ str << " in #{duration.round(2)} seconds"
80
+ end
81
+
82
+ private
83
+
84
+ def end_time
85
+ return 0 unless @results['testResults']
86
+
87
+ @results['testResults'].
88
+ map { |test_result| test_result['endTime'] }.
89
+ reduce do |memo, time|
90
+ [memo, time].max
91
+ end
92
+ end
93
+
94
+ def pluralize count, singular, plural = nil
95
+ "#{count} #{tools.integer.pluralize count, singular, plural}"
96
+ end
97
+
98
+ def start_time
99
+ @results['startTime'] || 0
100
+ end
101
+
102
+ def tools
103
+ SleepingKingStudios::Tools::Toolbelt.instance
104
+ end
105
+ end
106
+ end