sleeping_king_studios-tasks 0.1.0.rc.0

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