taski 0.7.0 → 0.7.1
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.
- checksums.yaml +4 -4
- data/README.md +128 -0
- data/docs/GUIDE.md +54 -0
- data/examples/data_pipeline_demo.rb +1 -1
- data/examples/large_tree_demo.rb +519 -0
- data/examples/simple_progress_demo.rb +80 -0
- data/lib/taski/execution/base_progress_display.rb +348 -0
- data/lib/taski/execution/execution_context.rb +4 -0
- data/lib/taski/execution/executor.rb +111 -131
- data/lib/taski/execution/plain_progress_display.rb +76 -0
- data/lib/taski/execution/simple_progress_display.rb +173 -0
- data/lib/taski/execution/task_output_router.rb +91 -20
- data/lib/taski/execution/task_wrapper.rb +23 -30
- data/lib/taski/execution/tree_progress_display.rb +121 -271
- data/lib/taski/static_analysis/visitor.rb +3 -0
- data/lib/taski/task.rb +19 -24
- data/lib/taski/test_helper/errors.rb +13 -0
- data/lib/taski/test_helper/minitest.rb +38 -0
- data/lib/taski/test_helper/mock_registry.rb +51 -0
- data/lib/taski/test_helper/mock_wrapper.rb +46 -0
- data/lib/taski/test_helper/rspec.rb +38 -0
- data/lib/taski/test_helper.rb +214 -0
- data/lib/taski/version.rb +1 -1
- data/lib/taski.rb +79 -6
- metadata +13 -2
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Taski
|
|
4
|
+
module TestHelper
|
|
5
|
+
# Wraps a mocked task and returns pre-configured values without executing the task.
|
|
6
|
+
# Tracks which methods were accessed for verification in tests.
|
|
7
|
+
class MockWrapper
|
|
8
|
+
attr_reader :task_class, :mock_values
|
|
9
|
+
|
|
10
|
+
# @param task_class [Class] The task class being mocked
|
|
11
|
+
# @param mock_values [Hash{Symbol => Object}] Method names mapped to their return values
|
|
12
|
+
def initialize(task_class, mock_values)
|
|
13
|
+
@task_class = task_class
|
|
14
|
+
@mock_values = mock_values
|
|
15
|
+
@access_counts = Hash.new(0)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Returns the mocked value for a method and records the access.
|
|
19
|
+
# @param method_name [Symbol] The exported method name
|
|
20
|
+
# @return [Object] The pre-configured mock value
|
|
21
|
+
# @raise [KeyError] If method_name was not configured in the mock
|
|
22
|
+
def get_exported_value(method_name)
|
|
23
|
+
unless @mock_values.key?(method_name)
|
|
24
|
+
raise KeyError, "No mock value for method :#{method_name} on #{@task_class}"
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
@access_counts[method_name] += 1
|
|
28
|
+
@mock_values[method_name]
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Checks if a method was accessed at least once.
|
|
32
|
+
# @param method_name [Symbol] The method name to check
|
|
33
|
+
# @return [Boolean] true if accessed at least once
|
|
34
|
+
def accessed?(method_name)
|
|
35
|
+
@access_counts[method_name] > 0
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Returns the number of times a method was accessed.
|
|
39
|
+
# @param method_name [Symbol] The method name to check
|
|
40
|
+
# @return [Integer] Number of accesses (0 if never accessed)
|
|
41
|
+
def access_count(method_name)
|
|
42
|
+
@access_counts[method_name]
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../test_helper"
|
|
4
|
+
|
|
5
|
+
module Taski
|
|
6
|
+
module TestHelper
|
|
7
|
+
# RSpec integration module.
|
|
8
|
+
# Include this in your RSpec examples for automatic mock cleanup.
|
|
9
|
+
#
|
|
10
|
+
# @example In spec_helper.rb
|
|
11
|
+
# require 'taski/test_helper/rspec'
|
|
12
|
+
#
|
|
13
|
+
# RSpec.configure do |config|
|
|
14
|
+
# config.include Taski::TestHelper::RSpec
|
|
15
|
+
# end
|
|
16
|
+
#
|
|
17
|
+
# @example In individual specs
|
|
18
|
+
# RSpec.describe MyTask do
|
|
19
|
+
# include Taski::TestHelper::RSpec
|
|
20
|
+
#
|
|
21
|
+
# it "processes data" do
|
|
22
|
+
# mock_task(FetchData, result: "mocked")
|
|
23
|
+
# # ... test code ...
|
|
24
|
+
# end
|
|
25
|
+
# end
|
|
26
|
+
module RSpec
|
|
27
|
+
def self.included(base)
|
|
28
|
+
base.include(Taski::TestHelper)
|
|
29
|
+
|
|
30
|
+
# Add before/after hooks when included in RSpec
|
|
31
|
+
if base.respond_to?(:before) && base.respond_to?(:after)
|
|
32
|
+
base.before(:each) { Taski::TestHelper.reset_mocks! }
|
|
33
|
+
base.after(:each) { Taski::TestHelper.reset_mocks! }
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "test_helper/errors"
|
|
4
|
+
require_relative "test_helper/mock_wrapper"
|
|
5
|
+
require_relative "test_helper/mock_registry"
|
|
6
|
+
|
|
7
|
+
module Taski
|
|
8
|
+
# Test helper module for mocking Taski task dependencies in unit tests.
|
|
9
|
+
# Include this module in your test class to access mocking functionality.
|
|
10
|
+
#
|
|
11
|
+
# @example Minitest usage
|
|
12
|
+
# class BuildReportTest < Minitest::Test
|
|
13
|
+
# include Taski::TestHelper
|
|
14
|
+
#
|
|
15
|
+
# def test_builds_report
|
|
16
|
+
# mock_task(FetchData, users: [1, 2, 3])
|
|
17
|
+
# assert_equal 3, BuildReport.user_count
|
|
18
|
+
# end
|
|
19
|
+
# end
|
|
20
|
+
module TestHelper
|
|
21
|
+
# Module prepended to Task's singleton class to intercept define_class_accessor.
|
|
22
|
+
# @api private
|
|
23
|
+
module TaskExtension
|
|
24
|
+
def define_class_accessor(method)
|
|
25
|
+
singleton_class.undef_method(method) if singleton_class.method_defined?(method)
|
|
26
|
+
|
|
27
|
+
define_singleton_method(method) do
|
|
28
|
+
# Check for mock first
|
|
29
|
+
mock = MockRegistry.mock_for(self)
|
|
30
|
+
return mock.get_exported_value(method) if mock
|
|
31
|
+
|
|
32
|
+
# No mock - call original implementation via registry lookup
|
|
33
|
+
registry = Taski.current_registry
|
|
34
|
+
if registry
|
|
35
|
+
wrapper = registry.get_or_create(self) do
|
|
36
|
+
task_instance = allocate
|
|
37
|
+
task_instance.__send__(:initialize)
|
|
38
|
+
Execution::TaskWrapper.new(
|
|
39
|
+
task_instance,
|
|
40
|
+
registry: registry,
|
|
41
|
+
execution_context: Execution::ExecutionContext.current
|
|
42
|
+
)
|
|
43
|
+
end
|
|
44
|
+
wrapper.get_exported_value(method)
|
|
45
|
+
else
|
|
46
|
+
Taski.with_args(options: {}, root_task: self) do
|
|
47
|
+
validate_no_circular_dependencies!
|
|
48
|
+
fresh_wrapper.get_exported_value(method)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Module prepended to Scheduler to skip dependencies of mocked tasks.
|
|
56
|
+
# @api private
|
|
57
|
+
module SchedulerExtension
|
|
58
|
+
def build_dependency_graph(root_task_class)
|
|
59
|
+
queue = [root_task_class]
|
|
60
|
+
|
|
61
|
+
while (task_class = queue.shift)
|
|
62
|
+
next if @task_states.key?(task_class)
|
|
63
|
+
|
|
64
|
+
# Mocked tasks have no dependencies (isolates indirect dependencies)
|
|
65
|
+
mock = MockRegistry.mock_for(task_class)
|
|
66
|
+
deps = mock ? Set.new : task_class.cached_dependencies
|
|
67
|
+
@dependencies[task_class] = deps.dup
|
|
68
|
+
@task_states[task_class] = Taski::Execution::Scheduler::STATE_PENDING
|
|
69
|
+
|
|
70
|
+
deps.each { |dep| queue << dep }
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Module prepended to Executor to skip execution of mocked tasks.
|
|
76
|
+
# @api private
|
|
77
|
+
module ExecutorExtension
|
|
78
|
+
def execute_task(task_class, wrapper)
|
|
79
|
+
return if @registry.abort_requested?
|
|
80
|
+
|
|
81
|
+
# Skip execution if task is mocked
|
|
82
|
+
if MockRegistry.mock_for(task_class)
|
|
83
|
+
wrapper.mark_completed(nil)
|
|
84
|
+
@completion_queue.push({task_class: task_class, wrapper: wrapper})
|
|
85
|
+
return
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
super
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
class << self
|
|
93
|
+
# Checks if any mocks are currently registered.
|
|
94
|
+
# @return [Boolean] true if mocks exist
|
|
95
|
+
def mocks_active?
|
|
96
|
+
MockRegistry.mocks_active?
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Retrieves the mock wrapper for a task class.
|
|
100
|
+
# @param task_class [Class] The task class to look up
|
|
101
|
+
# @return [MockWrapper, nil] The mock wrapper or nil if not mocked
|
|
102
|
+
def mock_for(task_class)
|
|
103
|
+
MockRegistry.mock_for(task_class)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Clears all registered mocks.
|
|
107
|
+
# Called automatically by test framework integrations.
|
|
108
|
+
def reset_mocks!
|
|
109
|
+
MockRegistry.reset!
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Registers a mock for a task class with specified return values.
|
|
114
|
+
# @param task_class [Class] A Taski::Task or Taski::Section subclass
|
|
115
|
+
# @param values [Hash{Symbol => Object}] Method names mapped to return values
|
|
116
|
+
# @return [MockWrapper] The created mock wrapper
|
|
117
|
+
# @raise [InvalidTaskError] If task_class is not a Taski::Task/Section subclass
|
|
118
|
+
# @raise [InvalidMethodError] If any method name is not an exported method
|
|
119
|
+
#
|
|
120
|
+
# @example
|
|
121
|
+
# mock_task(FetchData, result: { users: [1, 2, 3] })
|
|
122
|
+
# mock_task(Config, timeout: 30, retries: 3)
|
|
123
|
+
def mock_task(task_class, **values)
|
|
124
|
+
validate_task_class!(task_class)
|
|
125
|
+
validate_exported_methods!(task_class, values.keys)
|
|
126
|
+
|
|
127
|
+
mock_wrapper = MockWrapper.new(task_class, values)
|
|
128
|
+
MockRegistry.register(task_class, mock_wrapper)
|
|
129
|
+
mock_wrapper
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# Asserts that a mocked task's method was accessed during the test.
|
|
133
|
+
# @param task_class [Class] The mocked task class
|
|
134
|
+
# @param method_name [Symbol] The exported method name
|
|
135
|
+
# @return [true] If assertion passes
|
|
136
|
+
# @raise [ArgumentError] If task_class was not mocked
|
|
137
|
+
# @raise [Minitest::Assertion, RSpec::Expectations::ExpectationNotMetError]
|
|
138
|
+
# If method was not accessed
|
|
139
|
+
def assert_task_accessed(task_class, method_name)
|
|
140
|
+
mock = fetch_mock!(task_class)
|
|
141
|
+
|
|
142
|
+
unless mock.accessed?(method_name)
|
|
143
|
+
raise assertion_error("Expected #{task_class}.#{method_name} to be accessed, but it was not")
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
true
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
# Asserts that a mocked task's method was NOT accessed during the test.
|
|
150
|
+
# @param task_class [Class] The mocked task class
|
|
151
|
+
# @param method_name [Symbol] The exported method name
|
|
152
|
+
# @return [true] If assertion passes
|
|
153
|
+
# @raise [ArgumentError] If task_class was not mocked
|
|
154
|
+
# @raise [Minitest::Assertion, RSpec::Expectations::ExpectationNotMetError]
|
|
155
|
+
# If method was accessed
|
|
156
|
+
def refute_task_accessed(task_class, method_name)
|
|
157
|
+
mock = fetch_mock!(task_class)
|
|
158
|
+
|
|
159
|
+
if mock.accessed?(method_name)
|
|
160
|
+
count = mock.access_count(method_name)
|
|
161
|
+
raise assertion_error(
|
|
162
|
+
"Expected #{task_class}.#{method_name} not to be accessed, but it was accessed #{count} time(s)"
|
|
163
|
+
)
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
true
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
private
|
|
170
|
+
|
|
171
|
+
def fetch_mock!(task_class)
|
|
172
|
+
mock = MockRegistry.mock_for(task_class)
|
|
173
|
+
return mock if mock
|
|
174
|
+
|
|
175
|
+
raise ArgumentError, "Task #{task_class} was not mocked. Call mock_task first."
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def validate_task_class!(task_class)
|
|
179
|
+
valid = task_class.is_a?(Class) &&
|
|
180
|
+
(task_class < Taski::Task || task_class == Taski::Task)
|
|
181
|
+
return if valid
|
|
182
|
+
|
|
183
|
+
raise InvalidTaskError,
|
|
184
|
+
"Cannot mock #{task_class}: not a Taski::Task or Taski::Section subclass"
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def validate_exported_methods!(task_class, method_names)
|
|
188
|
+
exported = task_class.exported_methods
|
|
189
|
+
method_names.each do |method_name|
|
|
190
|
+
unless exported.include?(method_name)
|
|
191
|
+
raise InvalidMethodError,
|
|
192
|
+
"Cannot mock :#{method_name} on #{task_class}: not an exported method. Exported: #{exported.inspect}"
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
def assertion_error(message)
|
|
198
|
+
# Use the appropriate assertion error class based on the test framework
|
|
199
|
+
# Use fully qualified names to avoid namespace conflicts
|
|
200
|
+
if defined?(::Minitest::Assertion)
|
|
201
|
+
::Minitest::Assertion.new(message)
|
|
202
|
+
elsif defined?(::RSpec::Expectations::ExpectationNotMetError)
|
|
203
|
+
::RSpec::Expectations::ExpectationNotMetError.new(message)
|
|
204
|
+
else
|
|
205
|
+
RuntimeError.new(message)
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
# Prepend extensions when test helper is loaded
|
|
212
|
+
Taski::Task.singleton_class.prepend(Taski::TestHelper::TaskExtension)
|
|
213
|
+
Taski::Execution::Scheduler.prepend(Taski::TestHelper::SchedulerExtension)
|
|
214
|
+
Taski::Execution::Executor.prepend(Taski::TestHelper::ExecutorExtension)
|
data/lib/taski/version.rb
CHANGED
data/lib/taski.rb
CHANGED
|
@@ -11,6 +11,8 @@ require_relative "taski/execution/scheduler"
|
|
|
11
11
|
require_relative "taski/execution/worker_pool"
|
|
12
12
|
require_relative "taski/execution/executor"
|
|
13
13
|
require_relative "taski/execution/tree_progress_display"
|
|
14
|
+
require_relative "taski/execution/simple_progress_display"
|
|
15
|
+
require_relative "taski/execution/plain_progress_display"
|
|
14
16
|
require_relative "taski/args"
|
|
15
17
|
|
|
16
18
|
module Taski
|
|
@@ -31,13 +33,15 @@ module Taski
|
|
|
31
33
|
|
|
32
34
|
# Represents a single task failure with its context
|
|
33
35
|
class TaskFailure
|
|
34
|
-
attr_reader :task_class, :error
|
|
36
|
+
attr_reader :task_class, :error, :output_lines
|
|
35
37
|
|
|
36
38
|
# @param task_class [Class] The task class that failed
|
|
37
39
|
# @param error [Exception] The exception that was raised
|
|
38
|
-
|
|
40
|
+
# @param output_lines [Array<String>] Recent output lines from the failed task
|
|
41
|
+
def initialize(task_class:, error:, output_lines: [])
|
|
39
42
|
@task_class = task_class
|
|
40
43
|
@error = error
|
|
44
|
+
@output_lines = output_lines
|
|
41
45
|
end
|
|
42
46
|
end
|
|
43
47
|
|
|
@@ -117,8 +121,19 @@ module Taski
|
|
|
117
121
|
|
|
118
122
|
def build_message
|
|
119
123
|
task_word = (errors.size == 1) ? "task" : "tasks"
|
|
120
|
-
"#{errors.size} #{task_word} failed
|
|
121
|
-
|
|
124
|
+
parts = ["#{errors.size} #{task_word} failed:"]
|
|
125
|
+
|
|
126
|
+
errors.each do |f|
|
|
127
|
+
parts << " - #{f.task_class.name}: #{f.error.message}"
|
|
128
|
+
|
|
129
|
+
# Include captured output if available
|
|
130
|
+
if f.output_lines && !f.output_lines.empty?
|
|
131
|
+
parts << " Output:"
|
|
132
|
+
f.output_lines.each { |line| parts << " #{line}" }
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
parts.join("\n")
|
|
122
137
|
end
|
|
123
138
|
end
|
|
124
139
|
|
|
@@ -132,10 +147,12 @@ module Taski
|
|
|
132
147
|
|
|
133
148
|
# Start new runtime arguments (internal use only)
|
|
134
149
|
# @api private
|
|
150
|
+
# @return [Boolean] true if this call created the args, false if args already existed
|
|
135
151
|
def self.start_args(options:, root_task:)
|
|
136
152
|
@args_monitor.synchronize do
|
|
137
|
-
return if @args
|
|
153
|
+
return false if @args
|
|
138
154
|
@args = Args.new(options: options, root_task: root_task)
|
|
155
|
+
true
|
|
139
156
|
end
|
|
140
157
|
end
|
|
141
158
|
|
|
@@ -145,21 +162,77 @@ module Taski
|
|
|
145
162
|
@args_monitor.synchronize { @args = nil }
|
|
146
163
|
end
|
|
147
164
|
|
|
165
|
+
# Execute a block with args lifecycle management.
|
|
166
|
+
# Creates args if they don't exist, and resets them only if this call created them.
|
|
167
|
+
# This prevents race conditions in concurrent execution.
|
|
168
|
+
#
|
|
169
|
+
# @param options [Hash] User-defined options
|
|
170
|
+
# @param root_task [Class] The root task class
|
|
171
|
+
# @yield The block to execute with args available
|
|
172
|
+
# @return [Object] The result of the block
|
|
173
|
+
def self.with_args(options:, root_task:)
|
|
174
|
+
created_args = start_args(options: options, root_task: root_task)
|
|
175
|
+
yield
|
|
176
|
+
ensure
|
|
177
|
+
reset_args! if created_args
|
|
178
|
+
end
|
|
179
|
+
|
|
148
180
|
# Progress display is enabled by default (tree-style).
|
|
149
181
|
# Environment variables:
|
|
150
182
|
# - TASKI_PROGRESS_DISABLE=1: Disable progress display entirely
|
|
183
|
+
# - TASKI_PROGRESS_MODE=simple|tree: Set display mode (default: tree)
|
|
151
184
|
def self.progress_display
|
|
152
185
|
return nil if progress_disabled?
|
|
153
|
-
@progress_display ||=
|
|
186
|
+
@progress_display ||= create_progress_display
|
|
154
187
|
end
|
|
155
188
|
|
|
156
189
|
def self.progress_disabled?
|
|
157
190
|
ENV["TASKI_PROGRESS_DISABLE"] == "1"
|
|
158
191
|
end
|
|
159
192
|
|
|
193
|
+
# Get the current progress mode (:tree or :simple)
|
|
194
|
+
# @return [Symbol] The current progress mode
|
|
195
|
+
def self.progress_mode
|
|
196
|
+
@progress_mode || progress_mode_from_env
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
# Set the progress mode (:tree or :simple)
|
|
200
|
+
# @param mode [Symbol] The mode to use (:tree or :simple)
|
|
201
|
+
def self.progress_mode=(mode)
|
|
202
|
+
@progress_mode = mode.to_sym
|
|
203
|
+
# Reset display so it will be recreated with new mode
|
|
204
|
+
@progress_display&.stop
|
|
205
|
+
@progress_display = nil
|
|
206
|
+
end
|
|
207
|
+
|
|
160
208
|
def self.reset_progress_display!
|
|
161
209
|
@progress_display&.stop
|
|
162
210
|
@progress_display = nil
|
|
211
|
+
@progress_mode = nil
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
# @api private
|
|
215
|
+
def self.create_progress_display
|
|
216
|
+
case progress_mode
|
|
217
|
+
when :simple
|
|
218
|
+
Execution::SimpleProgressDisplay.new
|
|
219
|
+
when :plain
|
|
220
|
+
Execution::PlainProgressDisplay.new
|
|
221
|
+
else
|
|
222
|
+
Execution::TreeProgressDisplay.new
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
# @api private
|
|
227
|
+
def self.progress_mode_from_env
|
|
228
|
+
case ENV["TASKI_PROGRESS_MODE"]
|
|
229
|
+
when "simple"
|
|
230
|
+
:simple
|
|
231
|
+
when "plain"
|
|
232
|
+
:plain
|
|
233
|
+
else
|
|
234
|
+
:tree
|
|
235
|
+
end
|
|
163
236
|
end
|
|
164
237
|
|
|
165
238
|
# Get the worker count from the current args (set via Task.run(workers: n))
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: taski
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.7.
|
|
4
|
+
version: 0.7.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- ahogappa
|
|
@@ -61,19 +61,24 @@ files:
|
|
|
61
61
|
- examples/clean_demo.rb
|
|
62
62
|
- examples/data_pipeline_demo.rb
|
|
63
63
|
- examples/group_demo.rb
|
|
64
|
+
- examples/large_tree_demo.rb
|
|
64
65
|
- examples/nested_section_demo.rb
|
|
65
66
|
- examples/parallel_progress_demo.rb
|
|
66
67
|
- examples/quick_start.rb
|
|
67
68
|
- examples/reexecution_demo.rb
|
|
68
69
|
- examples/section_demo.rb
|
|
70
|
+
- examples/simple_progress_demo.rb
|
|
69
71
|
- examples/system_call_demo.rb
|
|
70
72
|
- examples/tree_progress_demo.rb
|
|
71
73
|
- lib/taski.rb
|
|
72
74
|
- lib/taski/args.rb
|
|
75
|
+
- lib/taski/execution/base_progress_display.rb
|
|
73
76
|
- lib/taski/execution/execution_context.rb
|
|
74
77
|
- lib/taski/execution/executor.rb
|
|
78
|
+
- lib/taski/execution/plain_progress_display.rb
|
|
75
79
|
- lib/taski/execution/registry.rb
|
|
76
80
|
- lib/taski/execution/scheduler.rb
|
|
81
|
+
- lib/taski/execution/simple_progress_display.rb
|
|
77
82
|
- lib/taski/execution/task_output_pipe.rb
|
|
78
83
|
- lib/taski/execution/task_output_router.rb
|
|
79
84
|
- lib/taski/execution/task_wrapper.rb
|
|
@@ -84,6 +89,12 @@ files:
|
|
|
84
89
|
- lib/taski/static_analysis/dependency_graph.rb
|
|
85
90
|
- lib/taski/static_analysis/visitor.rb
|
|
86
91
|
- lib/taski/task.rb
|
|
92
|
+
- lib/taski/test_helper.rb
|
|
93
|
+
- lib/taski/test_helper/errors.rb
|
|
94
|
+
- lib/taski/test_helper/minitest.rb
|
|
95
|
+
- lib/taski/test_helper/mock_registry.rb
|
|
96
|
+
- lib/taski/test_helper/mock_wrapper.rb
|
|
97
|
+
- lib/taski/test_helper/rspec.rb
|
|
87
98
|
- lib/taski/version.rb
|
|
88
99
|
- rbs_collection.lock.yaml
|
|
89
100
|
- rbs_collection.yaml
|
|
@@ -108,7 +119,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
108
119
|
- !ruby/object:Gem::Version
|
|
109
120
|
version: '0'
|
|
110
121
|
requirements: []
|
|
111
|
-
rubygems_version:
|
|
122
|
+
rubygems_version: 4.0.3
|
|
112
123
|
specification_version: 4
|
|
113
124
|
summary: A simple yet powerful Ruby task runner with static dependency resolution
|
|
114
125
|
(in development).
|