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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +26 -0
- data/DEVELOPMENT.md +50 -0
- data/LICENSE +22 -0
- data/README.md +405 -0
- data/lib/sleeping_king_studios/tasks.rb +27 -0
- data/lib/sleeping_king_studios/tasks/apps.rb +49 -0
- data/lib/sleeping_king_studios/tasks/apps/app_configuration.rb +68 -0
- data/lib/sleeping_king_studios/tasks/apps/applications_task.rb +28 -0
- data/lib/sleeping_king_studios/tasks/apps/bundle.rb +8 -0
- data/lib/sleeping_king_studios/tasks/apps/bundle/install_runner.rb +21 -0
- data/lib/sleeping_king_studios/tasks/apps/bundle/install_task.rb +39 -0
- data/lib/sleeping_king_studios/tasks/apps/bundle/update_runner.rb +21 -0
- data/lib/sleeping_king_studios/tasks/apps/bundle/update_task.rb +39 -0
- data/lib/sleeping_king_studios/tasks/apps/ci.rb +8 -0
- data/lib/sleeping_king_studios/tasks/apps/ci/results_reporter.rb +69 -0
- data/lib/sleeping_king_studios/tasks/apps/ci/rspec_task.rb +29 -0
- data/lib/sleeping_king_studios/tasks/apps/ci/rspec_wrapper.rb +42 -0
- data/lib/sleeping_king_studios/tasks/apps/ci/rubocop_task.rb +29 -0
- data/lib/sleeping_king_studios/tasks/apps/ci/rubocop_wrapper.rb +29 -0
- data/lib/sleeping_king_studios/tasks/apps/ci/simplecov_task.rb +68 -0
- data/lib/sleeping_king_studios/tasks/apps/ci/step_wrapper.rb +49 -0
- data/lib/sleeping_king_studios/tasks/apps/ci/steps_runner.rb +37 -0
- data/lib/sleeping_king_studios/tasks/apps/ci/steps_task.rb +92 -0
- data/lib/sleeping_king_studios/tasks/ci.rb +8 -0
- data/lib/sleeping_king_studios/tasks/ci/cucumber_parser.rb +118 -0
- data/lib/sleeping_king_studios/tasks/ci/cucumber_results.rb +191 -0
- data/lib/sleeping_king_studios/tasks/ci/cucumber_runner.rb +53 -0
- data/lib/sleeping_king_studios/tasks/ci/cucumber_task.rb +47 -0
- data/lib/sleeping_king_studios/tasks/ci/results_helpers.rb +44 -0
- data/lib/sleeping_king_studios/tasks/ci/rspec_each_results.rb +118 -0
- data/lib/sleeping_king_studios/tasks/ci/rspec_each_task.rb +156 -0
- data/lib/sleeping_king_studios/tasks/ci/rspec_results.rb +126 -0
- data/lib/sleeping_king_studios/tasks/ci/rspec_runner.rb +62 -0
- data/lib/sleeping_king_studios/tasks/ci/rspec_task.rb +71 -0
- data/lib/sleeping_king_studios/tasks/ci/rubocop_results.rb +80 -0
- data/lib/sleeping_king_studios/tasks/ci/rubocop_runner.rb +46 -0
- data/lib/sleeping_king_studios/tasks/ci/rubocop_task.rb +44 -0
- data/lib/sleeping_king_studios/tasks/ci/simplecov_results.rb +62 -0
- data/lib/sleeping_king_studios/tasks/ci/simplecov_task.rb +25 -0
- data/lib/sleeping_king_studios/tasks/ci/steps_runner.rb +69 -0
- data/lib/sleeping_king_studios/tasks/ci/steps_task.rb +93 -0
- data/lib/sleeping_king_studios/tasks/configuration.rb +114 -0
- data/lib/sleeping_king_studios/tasks/file.rb +8 -0
- data/lib/sleeping_king_studios/tasks/file/new_task.rb +238 -0
- data/lib/sleeping_king_studios/tasks/process_runner.rb +70 -0
- data/lib/sleeping_king_studios/tasks/task.rb +95 -0
- data/lib/sleeping_king_studios/tasks/task_group.rb +37 -0
- data/lib/sleeping_king_studios/tasks/version.rb +58 -0
- 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,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,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
|