taski 0.3.1 → 0.4.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.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +101 -271
  3. data/Steepfile +19 -0
  4. data/docs/advanced-features.md +625 -0
  5. data/docs/api-guide.md +509 -0
  6. data/docs/error-handling.md +684 -0
  7. data/examples/README.md +98 -42
  8. data/examples/context_demo.rb +118 -0
  9. data/examples/data_pipeline_demo.rb +231 -0
  10. data/examples/parallel_progress_demo.rb +72 -0
  11. data/examples/quick_start.rb +4 -4
  12. data/examples/reexecution_demo.rb +127 -0
  13. data/examples/{section_configuration.rb → section_demo.rb} +49 -60
  14. data/lib/taski/context.rb +50 -0
  15. data/lib/taski/execution/coordinator.rb +63 -0
  16. data/lib/taski/execution/parallel_progress_display.rb +201 -0
  17. data/lib/taski/execution/registry.rb +72 -0
  18. data/lib/taski/execution/task_wrapper.rb +255 -0
  19. data/lib/taski/section.rb +26 -254
  20. data/lib/taski/static_analysis/analyzer.rb +46 -0
  21. data/lib/taski/static_analysis/dependency_graph.rb +90 -0
  22. data/lib/taski/static_analysis/visitor.rb +130 -0
  23. data/lib/taski/task.rb +199 -0
  24. data/lib/taski/version.rb +1 -1
  25. data/lib/taski.rb +68 -39
  26. data/rbs_collection.lock.yaml +116 -0
  27. data/rbs_collection.yaml +19 -0
  28. data/sig/taski.rbs +269 -62
  29. metadata +36 -32
  30. data/examples/advanced_patterns.rb +0 -119
  31. data/examples/progress_demo.rb +0 -166
  32. data/examples/tree_demo.rb +0 -205
  33. data/lib/taski/dependency_analyzer.rb +0 -232
  34. data/lib/taski/exceptions.rb +0 -17
  35. data/lib/taski/logger.rb +0 -158
  36. data/lib/taski/logging/formatter_factory.rb +0 -34
  37. data/lib/taski/logging/formatter_interface.rb +0 -19
  38. data/lib/taski/logging/json_formatter.rb +0 -26
  39. data/lib/taski/logging/simple_formatter.rb +0 -16
  40. data/lib/taski/logging/structured_formatter.rb +0 -44
  41. data/lib/taski/progress/display_colors.rb +0 -17
  42. data/lib/taski/progress/display_manager.rb +0 -117
  43. data/lib/taski/progress/output_capture.rb +0 -105
  44. data/lib/taski/progress/spinner_animation.rb +0 -49
  45. data/lib/taski/progress/task_formatter.rb +0 -25
  46. data/lib/taski/progress/task_status.rb +0 -38
  47. data/lib/taski/progress/terminal_controller.rb +0 -35
  48. data/lib/taski/progress_display.rb +0 -57
  49. data/lib/taski/reference.rb +0 -40
  50. data/lib/taski/task/base.rb +0 -91
  51. data/lib/taski/task/define_api.rb +0 -156
  52. data/lib/taski/task/dependency_resolver.rb +0 -73
  53. data/lib/taski/task/exports_api.rb +0 -29
  54. data/lib/taski/task/instance_management.rb +0 -201
  55. data/lib/taski/tree_colors.rb +0 -91
  56. data/lib/taski/utils/dependency_resolver_helper.rb +0 -85
  57. data/lib/taski/utils/tree_display_helper.rb +0 -68
  58. data/lib/taski/utils.rb +0 -107
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "tsort"
4
+
5
+ module Taski
6
+ module StaticAnalysis
7
+ # Builds a complete dependency graph from a root task class
8
+ # and provides topological sorting with cycle detection.
9
+ class DependencyGraph
10
+ include TSort
11
+
12
+ def initialize
13
+ @graph = {}
14
+ end
15
+
16
+ # Build dependency graph starting from root task class
17
+ # @param root_task_class [Class] The root task class to analyze
18
+ # @return [DependencyGraph] self for method chaining
19
+ def build_from(root_task_class)
20
+ collect_dependencies(root_task_class)
21
+ self
22
+ end
23
+
24
+ # Get topologically sorted task classes (dependencies first)
25
+ # @return [Array<Class>] Sorted task classes
26
+ # @raise [TSort::Cyclic] If circular dependency is detected
27
+ def sorted
28
+ tsort
29
+ end
30
+
31
+ # Check if the graph contains circular dependencies
32
+ # @return [Boolean] true if circular dependencies exist
33
+ def cyclic?
34
+ tsort
35
+ false
36
+ rescue TSort::Cyclic
37
+ true
38
+ end
39
+
40
+ # Get strongly connected components (useful for debugging cycles)
41
+ # @return [Array<Array<Class>>] Groups of mutually dependent classes
42
+ def strongly_connected_components
43
+ each_strongly_connected_component.to_a
44
+ end
45
+
46
+ # Get task classes involved in cycles
47
+ # @return [Array<Array<Class>>] Only components with size > 1 (cycles)
48
+ def cyclic_components
49
+ strongly_connected_components.select { |component| component.size > 1 }
50
+ end
51
+
52
+ # Get all task classes in the graph
53
+ # @return [Array<Class>] All registered task classes
54
+ def all_tasks
55
+ @graph.keys
56
+ end
57
+
58
+ # Get direct dependencies for a task class
59
+ # @param task_class [Class] The task class
60
+ # @return [Set<Class>] Direct dependencies
61
+ def dependencies_for(task_class)
62
+ @graph.fetch(task_class, Set.new)
63
+ end
64
+
65
+ # TSort interface: iterate over all nodes
66
+ def tsort_each_node(&block)
67
+ @graph.each_key(&block)
68
+ end
69
+
70
+ # TSort interface: iterate over children (dependencies) of a node
71
+ def tsort_each_child(node, &block)
72
+ @graph.fetch(node, Set.new).each(&block)
73
+ end
74
+
75
+ private
76
+
77
+ # Recursively collect all dependencies starting from a task class
78
+ def collect_dependencies(task_class)
79
+ return if @graph.key?(task_class)
80
+
81
+ dependencies = Analyzer.analyze(task_class)
82
+ @graph[task_class] = dependencies
83
+
84
+ dependencies.each do |dep_class|
85
+ collect_dependencies(dep_class)
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,130 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "prism"
4
+
5
+ module Taski
6
+ module StaticAnalysis
7
+ class Visitor < Prism::Visitor
8
+ attr_reader :dependencies
9
+
10
+ def initialize(target_task_class, target_method = :run)
11
+ super()
12
+ @target_task_class = target_task_class
13
+ @target_method = target_method
14
+ @dependencies = Set.new
15
+ @in_target_method = false
16
+ @current_namespace_path = []
17
+ end
18
+
19
+ def visit_class_node(node)
20
+ within_namespace(extract_constant_name(node.constant_path)) { super }
21
+ end
22
+
23
+ def visit_module_node(node)
24
+ within_namespace(extract_constant_name(node.constant_path)) { super }
25
+ end
26
+
27
+ def visit_def_node(node)
28
+ if node.name == @target_method && in_target_class?
29
+ @in_target_method = true
30
+ super
31
+ @in_target_method = false
32
+ else
33
+ super
34
+ end
35
+ end
36
+
37
+ def visit_call_node(node)
38
+ detect_task_dependency(node) if @in_target_method
39
+ super
40
+ end
41
+
42
+ def visit_constant_read_node(node)
43
+ detect_return_constant(node) if @in_target_method && @target_method == :impl
44
+ super
45
+ end
46
+
47
+ def visit_constant_path_node(node)
48
+ detect_return_constant(node) if @in_target_method && @target_method == :impl
49
+ super
50
+ end
51
+
52
+ private
53
+
54
+ def within_namespace(name)
55
+ @current_namespace_path.push(name)
56
+ yield
57
+ ensure
58
+ @current_namespace_path.pop
59
+ end
60
+
61
+ def in_target_class?
62
+ @current_namespace_path.join("::") == @target_task_class.name
63
+ end
64
+
65
+ def extract_constant_name(node)
66
+ node.slice
67
+ end
68
+
69
+ def detect_task_dependency(node)
70
+ return unless node.receiver
71
+
72
+ constant_name = extract_receiver_constant(node.receiver)
73
+ resolve_and_add_dependency(constant_name) if constant_name
74
+ end
75
+
76
+ def detect_return_constant(node)
77
+ constant_name = node.slice
78
+ resolve_and_add_dependency(constant_name)
79
+ end
80
+
81
+ def extract_receiver_constant(receiver)
82
+ case receiver
83
+ when Prism::ConstantReadNode, Prism::ConstantPathNode
84
+ receiver.slice
85
+ end
86
+ end
87
+
88
+ def resolve_and_add_dependency(constant_name)
89
+ task_class = resolve_constant(constant_name)
90
+ @dependencies.add(task_class) if task_class && valid_dependency?(task_class)
91
+ end
92
+
93
+ def resolve_constant(constant_name)
94
+ Object.const_get(constant_name)
95
+ rescue NameError
96
+ resolve_with_namespace_prefix(constant_name)
97
+ end
98
+
99
+ def resolve_with_namespace_prefix(constant_name)
100
+ return nil if @current_namespace_path.empty?
101
+
102
+ @current_namespace_path.length.downto(0) do |i|
103
+ prefix = @current_namespace_path.take(i).join("::")
104
+ full_name = prefix.empty? ? constant_name : "#{prefix}::#{constant_name}"
105
+
106
+ begin
107
+ return Object.const_get(full_name)
108
+ rescue NameError
109
+ next
110
+ end
111
+ end
112
+
113
+ nil
114
+ end
115
+
116
+ def valid_dependency?(klass)
117
+ klass.is_a?(Class) &&
118
+ (is_parallel_task?(klass) || is_parallel_section?(klass))
119
+ end
120
+
121
+ def is_parallel_task?(klass)
122
+ defined?(Taski::Task) && klass < Taski::Task
123
+ end
124
+
125
+ def is_parallel_section?(klass)
126
+ defined?(Taski::Section) && klass < Taski::Section
127
+ end
128
+ end
129
+ end
130
+ end
data/lib/taski/task.rb ADDED
@@ -0,0 +1,199 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "static_analysis/analyzer"
4
+ require_relative "execution/registry"
5
+ require_relative "execution/coordinator"
6
+ require_relative "execution/task_wrapper"
7
+
8
+ module Taski
9
+ class Task
10
+ class << self
11
+ def exports(*export_methods)
12
+ @exported_methods = export_methods
13
+
14
+ export_methods.each do |method|
15
+ define_instance_reader(method)
16
+ define_class_accessor(method)
17
+ end
18
+ end
19
+
20
+ def exported_methods
21
+ @exported_methods ||= []
22
+ end
23
+
24
+ # Each call creates a fresh TaskWrapper instance for re-execution support.
25
+ # Use class methods (e.g., MyTask.result) for cached single execution.
26
+ def new
27
+ Execution::TaskWrapper.new(
28
+ super,
29
+ registry: registry,
30
+ coordinator: coordinator
31
+ )
32
+ end
33
+
34
+ def cached_dependencies
35
+ @dependencies_cache ||= StaticAnalysis::Analyzer.analyze(self)
36
+ end
37
+
38
+ def clear_dependency_cache
39
+ @dependencies_cache = nil
40
+ end
41
+
42
+ def run(context: {})
43
+ Taski.start_context(options: context, root_task: self)
44
+ validate_no_circular_dependencies!
45
+ cached_wrapper.run
46
+ end
47
+
48
+ def clean(context: {})
49
+ Taski.start_context(options: context, root_task: self)
50
+ validate_no_circular_dependencies!
51
+ cached_wrapper.clean
52
+ end
53
+
54
+ def registry
55
+ Taski.global_registry
56
+ end
57
+
58
+ def coordinator
59
+ @coordinator ||= Execution::Coordinator.new(
60
+ registry: registry,
61
+ analyzer: StaticAnalysis::Analyzer
62
+ )
63
+ end
64
+
65
+ def reset!
66
+ registry.reset!
67
+ Taski.reset_global_registry!
68
+ Taski.reset_context!
69
+ @coordinator = nil
70
+ @circular_dependency_checked = false
71
+ end
72
+
73
+ def tree
74
+ build_tree(self, "", Set.new, false)
75
+ end
76
+
77
+ private
78
+
79
+ # ANSI color codes
80
+ COLORS = {
81
+ reset: "\e[0m",
82
+ task: "\e[32m", # green
83
+ section: "\e[34m", # blue
84
+ impl: "\e[33m", # yellow
85
+ tree: "\e[90m", # gray
86
+ name: "\e[1m" # bold
87
+ }.freeze
88
+
89
+ def build_tree(task_class, prefix, visited, is_impl)
90
+ type_label = colored_type_label(task_class)
91
+ impl_prefix = is_impl ? "#{COLORS[:impl]}[impl]#{COLORS[:reset]} " : ""
92
+ name = "#{COLORS[:name]}#{task_class.name}#{COLORS[:reset]}"
93
+ result = "#{impl_prefix}#{name} #{type_label}\n"
94
+ return result if visited.include?(task_class)
95
+
96
+ visited.add(task_class)
97
+ dependencies = task_class.cached_dependencies.to_a
98
+ is_section = section_class?(task_class)
99
+
100
+ dependencies.each_with_index do |dep, index|
101
+ is_last = (index == dependencies.size - 1)
102
+ result += format_dependency_branch(dep, prefix, is_last, visited, is_section)
103
+ end
104
+
105
+ result
106
+ end
107
+
108
+ def format_dependency_branch(dep, prefix, is_last, visited, is_impl)
109
+ connector, extension = tree_connector_chars(is_last)
110
+ dep_tree = build_tree(dep, "#{prefix}#{extension}", visited, is_impl)
111
+
112
+ result = "#{prefix}#{COLORS[:tree]}#{connector}#{COLORS[:reset]}"
113
+ lines = dep_tree.lines
114
+ result += lines.first
115
+ lines.drop(1).each { |line| result += line }
116
+ result
117
+ end
118
+
119
+ def tree_connector_chars(is_last)
120
+ if is_last
121
+ ["└── ", " "]
122
+ else
123
+ ["├── ", "│ "]
124
+ end
125
+ end
126
+
127
+ def colored_type_label(klass)
128
+ if section_class?(klass)
129
+ "#{COLORS[:section]}(Section)#{COLORS[:reset]}"
130
+ else
131
+ "#{COLORS[:task]}(Task)#{COLORS[:reset]}"
132
+ end
133
+ end
134
+
135
+ def section_class?(klass)
136
+ defined?(Taski::Section) && klass < Taski::Section
137
+ end
138
+
139
+ # Use allocate + initialize instead of new to avoid infinite loop
140
+ # since new is overridden to return TaskWrapper
141
+ def cached_wrapper
142
+ registry.get_or_create(self) do
143
+ task_instance = allocate
144
+ task_instance.send(:initialize)
145
+ Execution::TaskWrapper.new(
146
+ task_instance,
147
+ registry: registry,
148
+ coordinator: coordinator
149
+ )
150
+ end
151
+ end
152
+
153
+ def define_instance_reader(method)
154
+ undef_method(method) if method_defined?(method)
155
+
156
+ define_method(method) do
157
+ # @type self: Task
158
+ instance_variable_get("@#{method}")
159
+ end
160
+ end
161
+
162
+ def define_class_accessor(method)
163
+ singleton_class.undef_method(method) if singleton_class.method_defined?(method)
164
+
165
+ define_singleton_method(method) do
166
+ Taski.start_context(options: {}, root_task: self)
167
+ validate_no_circular_dependencies!
168
+ cached_wrapper.get_exported_value(method)
169
+ end
170
+ end
171
+
172
+ def validate_no_circular_dependencies!
173
+ return if @circular_dependency_checked
174
+
175
+ graph = StaticAnalysis::DependencyGraph.new.build_from(self)
176
+ cyclic_components = graph.cyclic_components
177
+
178
+ if cyclic_components.any?
179
+ raise Taski::CircularDependencyError.new(cyclic_components)
180
+ end
181
+
182
+ @circular_dependency_checked = true
183
+ end
184
+ end
185
+
186
+ def run
187
+ raise NotImplementedError, "Subclasses must implement the run method"
188
+ end
189
+
190
+ def clean
191
+ end
192
+
193
+ def reset!
194
+ self.class.exported_methods.each do |method|
195
+ instance_variable_set("@#{method}", nil)
196
+ end
197
+ end
198
+ end
199
+ end
data/lib/taski/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Taski
4
- VERSION = "0.3.1"
4
+ VERSION = "0.4.1"
5
5
  end
data/lib/taski.rb CHANGED
@@ -1,46 +1,75 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "monitor"
4
-
5
- # Load core components
6
3
  require_relative "taski/version"
7
- require_relative "taski/exceptions"
8
- require_relative "taski/logger"
9
- require_relative "taski/progress_display"
10
- require_relative "taski/reference"
11
- require_relative "taski/dependency_analyzer"
12
- require_relative "taski/utils"
13
- require_relative "taski/tree_colors"
14
-
15
- # Load Task class components
16
- require_relative "taski/task/base"
17
- require_relative "taski/task/exports_api"
18
- require_relative "taski/task/define_api"
19
- require_relative "taski/task/instance_management"
20
- require_relative "taski/task/dependency_resolver"
21
-
22
- # Load Section class
4
+ require_relative "taski/static_analysis/analyzer"
5
+ require_relative "taski/static_analysis/visitor"
6
+ require_relative "taski/static_analysis/dependency_graph"
7
+ require_relative "taski/execution/registry"
8
+ require_relative "taski/execution/coordinator"
9
+ require_relative "taski/execution/task_wrapper"
10
+ require_relative "taski/execution/parallel_progress_display"
11
+ require_relative "taski/context"
12
+ require_relative "taski/task"
23
13
  require_relative "taski/section"
24
14
 
25
15
  module Taski
26
- # Main module for the Taski task framework
27
- #
28
- # Taski provides a framework for defining and managing task dependencies
29
- # with three complementary APIs:
30
- # 1. Exports API - Export instance variables as class methods (static dependencies)
31
- # 2. Define API - Define lazy-evaluated values with dynamic dependency resolution
32
- # 3. Section API - Abstraction layers with runtime implementation selection
33
- #
34
- # API Selection Guide:
35
- # - Use Exports API for simple static dependencies
36
- # - Use Define API for conditional dependencies analyzed at class definition time
37
- # - Use Section API for environment-specific implementations with static analysis
38
- #
39
- # Features:
40
- # - Automatic dependency resolution (static and dynamic)
41
- # - Static analysis of method dependencies
42
- # - Runtime implementation selection with Section API
43
- # - Thread-safe task building
44
- # - Circular dependency detection
45
- # - Memory leak prevention
16
+ class TaskAbortException < StandardError
17
+ end
18
+
19
+ # Raised when circular dependencies are detected between tasks
20
+ class CircularDependencyError < StandardError
21
+ attr_reader :cyclic_tasks
22
+
23
+ # @param cyclic_tasks [Array<Array<Class>>] Groups of mutually dependent task classes
24
+ def initialize(cyclic_tasks)
25
+ @cyclic_tasks = cyclic_tasks
26
+ task_names = cyclic_tasks.map { |group| group.map(&:name).join(" <-> ") }.join(", ")
27
+ super("Circular dependency detected: #{task_names}")
28
+ end
29
+ end
30
+
31
+ @context_monitor = Monitor.new
32
+
33
+ # Get the current execution context
34
+ # @return [Context, nil] The current context or nil if no task is running
35
+ def self.context
36
+ @context_monitor.synchronize { @context }
37
+ end
38
+
39
+ # Start a new execution context (internal use only)
40
+ # @api private
41
+ def self.start_context(options:, root_task:)
42
+ @context_monitor.synchronize do
43
+ return if @context
44
+ @context = Context.new(options: options, root_task: root_task)
45
+ end
46
+ end
47
+
48
+ # Reset the execution context (internal use only)
49
+ # @api private
50
+ def self.reset_context!
51
+ @context_monitor.synchronize { @context = nil }
52
+ end
53
+
54
+ def self.global_registry
55
+ @global_registry ||= Execution::Registry.new
56
+ end
57
+
58
+ def self.reset_global_registry!
59
+ @global_registry = nil
60
+ end
61
+
62
+ def self.progress_display
63
+ return nil unless progress_enabled?
64
+ @progress_display ||= Execution::ParallelProgressDisplay.new
65
+ end
66
+
67
+ def self.progress_enabled?
68
+ ENV["TASKI_PROGRESS"] == "1" || ENV["TASKI_FORCE_PROGRESS"] == "1"
69
+ end
70
+
71
+ def self.reset_progress_display!
72
+ @progress_display&.stop
73
+ @progress_display = nil
74
+ end
46
75
  end
@@ -0,0 +1,116 @@
1
+ ---
2
+ path: ".gem_rbs_collection"
3
+ gems:
4
+ - name: ast
5
+ version: '2.4'
6
+ source:
7
+ type: git
8
+ name: ruby/gem_rbs_collection
9
+ revision: 3a33fa6f8e486f880c80ca401f2be1c1f621cf11
10
+ remote: https://github.com/ruby/gem_rbs_collection.git
11
+ repo_dir: gems
12
+ - name: fileutils
13
+ version: '0'
14
+ source:
15
+ type: stdlib
16
+ - name: io-console
17
+ version: '0'
18
+ source:
19
+ type: stdlib
20
+ - name: json
21
+ version: '0'
22
+ source:
23
+ type: stdlib
24
+ - name: minitest
25
+ version: '5.25'
26
+ source:
27
+ type: git
28
+ name: ruby/gem_rbs_collection
29
+ revision: 3a33fa6f8e486f880c80ca401f2be1c1f621cf11
30
+ remote: https://github.com/ruby/gem_rbs_collection.git
31
+ repo_dir: gems
32
+ - name: parallel
33
+ version: '1.20'
34
+ source:
35
+ type: git
36
+ name: ruby/gem_rbs_collection
37
+ revision: 3a33fa6f8e486f880c80ca401f2be1c1f621cf11
38
+ remote: https://github.com/ruby/gem_rbs_collection.git
39
+ repo_dir: gems
40
+ - name: parser
41
+ version: '3.2'
42
+ source:
43
+ type: git
44
+ name: ruby/gem_rbs_collection
45
+ revision: 3a33fa6f8e486f880c80ca401f2be1c1f621cf11
46
+ remote: https://github.com/ruby/gem_rbs_collection.git
47
+ repo_dir: gems
48
+ - name: pp
49
+ version: '0'
50
+ source:
51
+ type: stdlib
52
+ - name: prettyprint
53
+ version: '0'
54
+ source:
55
+ type: stdlib
56
+ - name: prism
57
+ version: 1.6.0
58
+ source:
59
+ type: rubygems
60
+ - name: rainbow
61
+ version: '3.0'
62
+ source:
63
+ type: git
64
+ name: ruby/gem_rbs_collection
65
+ revision: 3a33fa6f8e486f880c80ca401f2be1c1f621cf11
66
+ remote: https://github.com/ruby/gem_rbs_collection.git
67
+ repo_dir: gems
68
+ - name: rake
69
+ version: '13.0'
70
+ source:
71
+ type: git
72
+ name: ruby/gem_rbs_collection
73
+ revision: 3a33fa6f8e486f880c80ca401f2be1c1f621cf11
74
+ remote: https://github.com/ruby/gem_rbs_collection.git
75
+ repo_dir: gems
76
+ - name: rdoc
77
+ version: '0'
78
+ source:
79
+ type: stdlib
80
+ - name: regexp_parser
81
+ version: '2.8'
82
+ source:
83
+ type: git
84
+ name: ruby/gem_rbs_collection
85
+ revision: 3a33fa6f8e486f880c80ca401f2be1c1f621cf11
86
+ remote: https://github.com/ruby/gem_rbs_collection.git
87
+ repo_dir: gems
88
+ - name: rubocop
89
+ version: '1.57'
90
+ source:
91
+ type: git
92
+ name: ruby/gem_rbs_collection
93
+ revision: 3a33fa6f8e486f880c80ca401f2be1c1f621cf11
94
+ remote: https://github.com/ruby/gem_rbs_collection.git
95
+ repo_dir: gems
96
+ - name: rubocop-ast
97
+ version: '1.30'
98
+ source:
99
+ type: git
100
+ name: ruby/gem_rbs_collection
101
+ revision: 3a33fa6f8e486f880c80ca401f2be1c1f621cf11
102
+ remote: https://github.com/ruby/gem_rbs_collection.git
103
+ repo_dir: gems
104
+ - name: simplecov
105
+ version: '0.22'
106
+ source:
107
+ type: git
108
+ name: ruby/gem_rbs_collection
109
+ revision: 3a33fa6f8e486f880c80ca401f2be1c1f621cf11
110
+ remote: https://github.com/ruby/gem_rbs_collection.git
111
+ repo_dir: gems
112
+ - name: tsort
113
+ version: '0'
114
+ source:
115
+ type: stdlib
116
+ gemfile_lock_path: Gemfile.lock
@@ -0,0 +1,19 @@
1
+ # Download sources
2
+ sources:
3
+ - type: git
4
+ name: ruby/gem_rbs_collection
5
+ remote: https://github.com/ruby/gem_rbs_collection.git
6
+ revision: main
7
+ repo_dir: gems
8
+
9
+ # You can specify local directories as sources also.
10
+ # - type: local
11
+ # path: path/to/your/local/repository
12
+
13
+ # A directory to install the downloaded RBSs
14
+ path: .gem_rbs_collection
15
+
16
+ # gems:
17
+ # # If you want to avoid installing rbs files for gems, you can specify them here.
18
+ # - name: GEM_NAME
19
+ # ignore: true