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,27 @@
1
+ # lib/sleeping_king_studios/tasks.rb
2
+
3
+ require 'sleeping_king_studios/tools'
4
+
5
+ # Hic iacet Arthurus, rex quondam, rexque futurus.
6
+ module SleepingKingStudios
7
+ # Toolkit providing an encapsulation layer around the Thor CLI library, with
8
+ # predefined tasks for development and continuous integration.
9
+ module Tasks
10
+ autoload :Configuration, 'sleeping_king_studios/tasks/configuration'
11
+ autoload :Task, 'sleeping_king_studios/tasks/task'
12
+ autoload :TaskGroup, 'sleeping_king_studios/tasks/task_group'
13
+
14
+ def self.configuration
15
+ @configuration ||= SleepingKingStudios::Tasks::Configuration.new
16
+ end # class method configuration
17
+
18
+ def self.configure
19
+ yield configuration
20
+ end # class method configure
21
+
22
+ # The file path to the root of the gem directory.
23
+ def self.gem_path
24
+ @gem_path ||= __dir__.sub %r{/lib/sleeping_king_studios\z}, ''
25
+ end # class method gem_path
26
+ end # module
27
+ end # module
@@ -0,0 +1,49 @@
1
+ # lib/sleeping_king_studios/tasks/apps.rb
2
+
3
+ require 'yaml'
4
+
5
+ require 'sleeping_king_studios/tasks'
6
+
7
+ module SleepingKingStudios::Tasks
8
+ # Thor tasks for semi-distributed applications.
9
+ module Apps
10
+ autoload :AppConfiguration,
11
+ 'sleeping_king_studios/tasks/apps/app_configuration'
12
+
13
+ # rubocop:disable Metrics/MethodLength
14
+ def self.configuration
15
+ @configuration ||=
16
+ begin
17
+ tools = SleepingKingStudios::Tools::Toolbelt.instance
18
+ apps = load_configuration
19
+ hsh = Hash.new do |_, key|
20
+ SleepingKingStudios::Tasks::Apps::AppConfiguration.
21
+ new(:name => key.to_s)
22
+ end # hash
23
+
24
+ apps.each do |key, data|
25
+ name = key.to_s
26
+ data = tools.hash.convert_keys_to_symbols(data)
27
+
28
+ data[:name] ||= name
29
+
30
+ hsh[key] =
31
+ SleepingKingStudios::Tasks::Apps::AppConfiguration.new(data)
32
+ end # each
33
+
34
+ hsh
35
+ end # begin-end
36
+ end # class method configuration
37
+ # rubocop:enable Metrics/MethodLength
38
+
39
+ def self.load_configuration
40
+ config_file = SleepingKingStudios::Tasks.configuration.apps.config_file
41
+ raw = ::File.read(config_file)
42
+
43
+ YAML.safe_load raw
44
+ rescue
45
+ {}
46
+ end # class method load_configuration
47
+ class << self; private :load_configuration; end
48
+ end # module
49
+ end # module
@@ -0,0 +1,68 @@
1
+ # lib/sleeping_king_studios/tasks/apps/app_configuration.rb
2
+
3
+ require 'sleeping_king_studios/tools/toolbox/configuration'
4
+
5
+ require 'sleeping_king_studios/tasks/apps'
6
+
7
+ module SleepingKingStudios::Tasks::Apps
8
+ # Application configuration options.
9
+ class AppConfiguration < SleepingKingStudios::Tools::Toolbox::Configuration
10
+ namespace :ci do
11
+ option :rspec, :default => {}
12
+
13
+ option :rubocop, :default => {}
14
+
15
+ option :simplecov, :default => {}
16
+
17
+ option :steps, :default =>
18
+ ->() { SleepingKingStudios::Tasks.configuration.apps.ci.steps }
19
+
20
+ define_method :steps_with_options do
21
+ steps.each.with_object({}) do |step, hsh|
22
+ value = send(step)
23
+
24
+ next hsh[step] = false if value == false
25
+
26
+ default =
27
+ SleepingKingStudios::Tasks.configuration.apps.ci.send(step)
28
+ hsh[step] = default.merge(value)
29
+ end # each
30
+ end # method steps_with_options
31
+ end # namespace
32
+
33
+ define_method :default_source_files do
34
+ files = [
35
+ "apps/#{short_name}",
36
+ "apps/#{short_name}.rb",
37
+ "lib/#{short_name}",
38
+ "lib/#{short_name}.rb"
39
+ ] # end files
40
+
41
+ files.select { |path| File.exist?(path) }
42
+ end # method default_source_files
43
+
44
+ define_method :default_spec_files do
45
+ files = ["apps/#{short_name}/spec", "spec/#{short_name}"]
46
+
47
+ files.select { |path| File.exist?(path) }
48
+ end # method default_spec_files
49
+
50
+ define_method :short_name do
51
+ # rubocop:disable Style/RedundantSelf
52
+ tools.string.underscore(self.name.gsub(/\s+/, '_'))
53
+ # rubocop:enable Style/RedundantSelf
54
+ end # define_method
55
+
56
+ define_method :tools do
57
+ SleepingKingStudios::Tools::Toolbelt.instance
58
+ end # method tools
59
+
60
+ option :gemfile, :default => 'Gemfile'
61
+
62
+ option :name
63
+
64
+ option :source_files, :default => ->() { default_source_files }
65
+
66
+ option :spec_files, :default => ->() { default_spec_files }
67
+ end # module
68
+ end # module
@@ -0,0 +1,28 @@
1
+ # lib/sleeping_king_studios/tasks/apps/applications_task.rb
2
+
3
+ require 'yaml'
4
+
5
+ require 'sleeping_king_studios/tasks/apps'
6
+
7
+ module SleepingKingStudios::Tasks::Apps
8
+ # Extension module with additional configuration for performing actions on a
9
+ # per-application basis.
10
+ module ApplicationsTask
11
+ private
12
+
13
+ def applications
14
+ SleepingKingStudios::Tasks::Apps.configuration
15
+ end # method applications
16
+
17
+ def filter_applications only: []
18
+ filtered = applications
19
+
20
+ if only && !only.empty?
21
+ normalized = only.map(&:to_s)
22
+ filtered = filtered.select { |key, _| normalized.include?(key) }
23
+ end # if
24
+
25
+ filtered
26
+ end # method filter_applications
27
+ end # class
28
+ end # module
@@ -0,0 +1,8 @@
1
+ # lib/sleeping_king_studios/tasks/apps/bundle.rb
2
+
3
+ require 'sleeping_king_studios/tasks/apps'
4
+
5
+ module SleepingKingStudios::Tasks::Apps
6
+ # Thor tasks for maintaing gem dependencies in semi-distributed applications.
7
+ module Bundle; end
8
+ end # module
@@ -0,0 +1,21 @@
1
+ # lib/sleeping_king_studios/tasks/apps/bundle/install_runner.rb
2
+
3
+ require 'sleeping_king_studios/tasks/apps/bundle'
4
+ require 'sleeping_king_studios/tasks/process_runner'
5
+
6
+ module SleepingKingStudios::Tasks::Apps::Bundle
7
+ # Service object to run bundle install as an external process.
8
+ class InstallRunner < SleepingKingStudios::Tasks::ProcessRunner
9
+ def call gemfile
10
+ command = build_command :env => { :bundle_gemfile => gemfile }
11
+
12
+ stream_process(command)
13
+ end # method call
14
+
15
+ private
16
+
17
+ def base_command
18
+ 'bundle install'
19
+ end # method base_command
20
+ end # module
21
+ end # module
@@ -0,0 +1,39 @@
1
+ # lib/sleeping_king_studios/tasks/apps/bundle/install_task.rb
2
+
3
+ require 'sleeping_king_studios/tasks/apps/applications_task'
4
+ require 'sleeping_king_studios/tasks/apps/bundle'
5
+ require 'sleeping_king_studios/tasks/apps/bundle/install_runner'
6
+
7
+ module SleepingKingStudios::Tasks::Apps::Bundle
8
+ # Defines a Thor task for installing gem dependencies for each application.
9
+ class InstallTask < SleepingKingStudios::Tasks::Task
10
+ include SleepingKingStudios::Tasks::Apps::ApplicationsTask
11
+
12
+ def self.description
13
+ 'Installs the Ruby gem dependencies for each application.'
14
+ end # class method description
15
+
16
+ def call *applications
17
+ filtered = filter_applications(:only => applications)
18
+
19
+ gemfiles(filtered).each do |gemfile|
20
+ say %(\nInstalling gems for gemfile "#{gemfile}")
21
+ say '-' * 80
22
+ say "\n"
23
+
24
+ install_runner.call(gemfile)
25
+ end # each
26
+ end # method call
27
+
28
+ private
29
+
30
+ def gemfiles applications
31
+ applications.map { |_, config| config.gemfile }.uniq
32
+ end # method gemfiles
33
+
34
+ def install_runner
35
+ @install_runner =
36
+ SleepingKingStudios::Tasks::Apps::Bundle::InstallRunner.new
37
+ end # method install_runner
38
+ end # module
39
+ end # module
@@ -0,0 +1,21 @@
1
+ # lib/sleeping_king_studios/tasks/apps/bundle/update_runner.rb
2
+
3
+ require 'sleeping_king_studios/tasks/apps/bundle'
4
+ require 'sleeping_king_studios/tasks/process_runner'
5
+
6
+ module SleepingKingStudios::Tasks::Apps::Bundle
7
+ # Service object to run bundle update as an external process.
8
+ class UpdateRunner < SleepingKingStudios::Tasks::ProcessRunner
9
+ def call gemfile
10
+ command = build_command :env => { :bundle_gemfile => gemfile }
11
+
12
+ stream_process(command)
13
+ end # method call
14
+
15
+ private
16
+
17
+ def base_command
18
+ 'bundle update'
19
+ end # method base_command
20
+ end # class
21
+ end # module
@@ -0,0 +1,39 @@
1
+ # lib/sleeping_king_studios/tasks/apps/bundle/update_task.rb
2
+
3
+ require 'sleeping_king_studios/tasks/apps/applications_task'
4
+ require 'sleeping_king_studios/tasks/apps/bundle'
5
+ require 'sleeping_king_studios/tasks/apps/bundle/update_runner'
6
+
7
+ module SleepingKingStudios::Tasks::Apps::Bundle
8
+ # Defines a Thor task for updating gem dependencies for each application.
9
+ class UpdateTask < SleepingKingStudios::Tasks::Task
10
+ include SleepingKingStudios::Tasks::Apps::ApplicationsTask
11
+
12
+ def self.description
13
+ 'Updates the Ruby gem dependencies for each application.'
14
+ end # class method description
15
+
16
+ def call *applications
17
+ filtered = filter_applications(:only => applications)
18
+
19
+ gemfiles(filtered).each do |gemfile|
20
+ say %(\nUpdating gems for gemfile "#{gemfile}")
21
+ say '-' * 80
22
+ say "\n"
23
+
24
+ update_runner.call(gemfile)
25
+ end # each
26
+ end # method call
27
+
28
+ private
29
+
30
+ def gemfiles applications
31
+ applications.map { |_, config| config.gemfile }.uniq
32
+ end # method gemfiles
33
+
34
+ def update_runner
35
+ @update_runner =
36
+ SleepingKingStudios::Tasks::Apps::Bundle::UpdateRunner.new
37
+ end # method update_runner
38
+ end # class
39
+ end # module
@@ -0,0 +1,8 @@
1
+ # lib/sleeping_king_studios/tasks/apps/ci.rb
2
+
3
+ require 'sleeping_king_studios/tasks/apps'
4
+
5
+ module SleepingKingStudios::Tasks::Apps
6
+ # Thor tasks for continuous integration in semi-distributed applications.
7
+ module Ci; end
8
+ end # module
@@ -0,0 +1,69 @@
1
+ # lib/sleeping_king_studios/tasks/apps/ci/results_reporter.rb
2
+
3
+ require 'sleeping_king_studios/tools/toolbox/delegator'
4
+
5
+ require 'sleeping_king_studios/tasks/apps/ci'
6
+ require 'sleeping_king_studios/tasks/ci/results_helpers'
7
+
8
+ module SleepingKingStudios::Tasks::Apps::Ci
9
+ # Reports on the results of a multi-application continuous integration
10
+ # process, printing the step results grouped by application.
11
+ class ResultsReporter
12
+ extend SleepingKingStudios::Tools::Toolbox::Delegator
13
+
14
+ include SleepingKingStudios::Tasks::Ci::ResultsHelpers
15
+
16
+ delegate \
17
+ :applications,
18
+ :print_table,
19
+ :say,
20
+ :set_color,
21
+ :to => :@context
22
+
23
+ def initialize context
24
+ @context = context
25
+ end # method initialize
26
+
27
+ def call results
28
+ width = 1 + heading_width(results)
29
+
30
+ results.each do |application, app_results|
31
+ report_application application, app_results, :width => width
32
+ end # each
33
+ end # method call
34
+
35
+ private
36
+
37
+ def heading_width results
38
+ results.reduce(0) do |memo, (_, hsh)|
39
+ [memo, *hsh.keys.map(&:size)].max
40
+ end # reduce
41
+ end # method heading_width
42
+
43
+ def generate_rows results, width:
44
+ results.map do |key, obj|
45
+ next nil if obj.nil?
46
+
47
+ badge = format(" %-#{width}.#{width}s", "#{key}:")
48
+
49
+ [set_color(badge, results_color(obj)), obj.to_s]
50
+ end. # rows
51
+ compact
52
+ end # method generate_rows
53
+
54
+ def report_application app_name, results, width:
55
+ config = applications.fetch(app_name, {})
56
+ app_name = config.fetch('name', app_name)
57
+ rows = generate_rows(results, :width => width)
58
+
59
+ return if rows.empty?
60
+
61
+ say "#{app_name}:"
62
+ say "\n"
63
+
64
+ print_table rows
65
+
66
+ say "\n"
67
+ end # method report_application
68
+ end # class
69
+ end # module
@@ -0,0 +1,29 @@
1
+ # lib/sleeping_king_studios/tasks/apps/ci/rspec_task.rb
2
+
3
+ require 'sleeping_king_studios/tasks/apps/ci'
4
+ require 'sleeping_king_studios/tasks/apps/ci/steps_task'
5
+
6
+ module SleepingKingStudios::Tasks::Apps::Ci
7
+ # Defines a Thor task for running the RSpec test suite for each application.
8
+ class RSpecTask < SleepingKingStudios::Tasks::Task
9
+ def self.description
10
+ 'Runs the RSpec test suite for each application.'
11
+ end # class method description
12
+
13
+ def self.task_name
14
+ 'rspec'
15
+ end # class method task_name
16
+
17
+ option :quiet,
18
+ :aliases => '-q',
19
+ :type => :boolean,
20
+ :default => false,
21
+ :desc => 'Do not write spec results to STDOUT.'
22
+
23
+ def call *applications
24
+ SleepingKingStudios::Tasks::Apps::Ci::StepsTask.
25
+ new(options.merge('only' => %w(rspec))).
26
+ call(*applications)
27
+ end # method call
28
+ end # class
29
+ end # module
@@ -0,0 +1,42 @@
1
+ # lib/sleeping_king_studios/tasks/apps/ci/rspec_wrapper.rb
2
+
3
+ require 'sleeping_king_studios/tasks/apps/ci'
4
+ require 'sleeping_king_studios/tasks/apps/ci/step_wrapper'
5
+ require 'sleeping_king_studios/tasks/ci/rspec_results'
6
+
7
+ module SleepingKingStudios::Tasks::Apps::Ci
8
+ # Wrapper class for calling an RSpec Ci task for a specific application.
9
+ class RSpecWrapper < SleepingKingStudios::Tasks::Apps::Ci::StepWrapper
10
+ def call application
11
+ super
12
+
13
+ if spec_files.empty?
14
+ return SleepingKingStudios::Tasks::Ci::RSpecResults.new({})
15
+ end # if
16
+
17
+ run_step(*spec_files)
18
+ end # method call
19
+
20
+ private
21
+
22
+ def spec_files
23
+ SleepingKingStudios::Tasks::Apps.
24
+ configuration[current_application].
25
+ spec_files
26
+ end # method spec_files
27
+
28
+ def step_key
29
+ :rspec
30
+ end # method step_key
31
+
32
+ def step_options
33
+ gemfile = applications[current_application].fetch('gemfile', 'Gemfile')
34
+
35
+ super.merge(
36
+ 'coverage' => true,
37
+ 'gemfile' => gemfile,
38
+ '__env__' => { :app_name => current_application }
39
+ ) # end merge
40
+ end # method step_options
41
+ end # class
42
+ end # module