sleeping_king_studios-tasks 0.1.0.rc.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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