Class: Asgard::Base
Direct Known Subclasses
Class Method Summary collapse
-
._build_dep_graph(stages) ⇒ Object
Translate stages into a DependencyGraph-compatible hash.
- ._cond ⇒ Object
- ._deps ⇒ Object
- ._done ⇒ Object
- ._ran_mutex ⇒ Object
-
._reset_ran! ⇒ Object
Reset execution tracking for a fresh asgard invocation.
- ._running ⇒ Object
- .default_task(meth = nil) ⇒ Object
-
.depends_on(*tasks) ⇒ Object
Declare dependencies for the next task.
-
.desc(usage_or_desc, description = nil, options = {}) ⇒ Object
Allow single-argument desc: desc “Run the tests” The usage string defaults to the method name when the description is the only arg.
- .dotenv(path = ".env") ⇒ Object
- .inherited(subclass) ⇒ Object
- .method_added(method_name) ⇒ Object
- .subclasses ⇒ Object
-
.validate_deps! ⇒ Object
Validate the full dep graph for cycles using Dagwood::DependencyGraph.
Methods included from Shell
Class Method Details
._build_dep_graph(stages) ⇒ Object
Translate stages into a DependencyGraph-compatible hash.
stages: [[:one], [:two, :three], [:four]]
→ { one: [], two: [:one], three: [:one], four: [:two, :three] }
61 62 63 64 65 66 67 68 |
# File 'lib/asgard/base.rb', line 61 def _build_dep_graph(stages) graph = {} stages.each_with_index do |stage, i| prev_stage = i.positive? ? stages[i - 1] : [] stage.each { |task| graph[task] = prev_stage.dup } end graph end |
._cond ⇒ Object
40 41 42 |
# File 'lib/asgard/base.rb', line 40 def _cond @_cond ||= Hash.new { |h, k| h[k] = ConditionVariable.new } end |
._deps ⇒ Object
28 29 30 |
# File 'lib/asgard/base.rb', line 28 def _deps @_deps ||= {} end |
._done ⇒ Object
36 37 38 |
# File 'lib/asgard/base.rb', line 36 def _done @_done ||= Set.new end |
._ran_mutex ⇒ Object
44 45 46 |
# File 'lib/asgard/base.rb', line 44 def _ran_mutex @_ran_mutex ||= Mutex.new end |
._reset_ran! ⇒ Object
Reset execution tracking for a fresh asgard invocation.
49 50 51 52 53 54 55 |
# File 'lib/asgard/base.rb', line 49 def _reset_ran! _ran_mutex.synchronize do @_running = Set.new @_done = Set.new @_cond = Hash.new { |h, k| h[k] = ConditionVariable.new } end end |
._running ⇒ Object
32 33 34 |
# File 'lib/asgard/base.rb', line 32 def _running @_running ||= Set.new end |
.default_task(meth = nil) ⇒ Object
100 101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/asgard/base.rb', line 100 def default_task(meth = nil) if meth && meth != :none && @_default_task_location here = caller_locations(1, 1).first warn "asgard: default_task :#{meth} at #{here.path}:#{here.lineno} " \ "overrides default_task :#{@_default_task_name} set at " \ "#{@_default_task_location.path}:#{@_default_task_location.lineno}" end if meth && meth != :none @_default_task_location = caller_locations(1, 1).first @_default_task_name = meth end super end |
.depends_on(*tasks) ⇒ Object
Declare dependencies for the next task. Bare symbols run sequentially; arrays within the splat run in parallel.
depends_on :build # sequential
depends_on :build, :lint # both sequential
depends_on [:build, :lint] # build and lint in parallel
depends_on :setup, [:build, :lint], :test # setup, then build+lint, then test
77 78 79 |
# File 'lib/asgard/base.rb', line 77 def depends_on(*tasks) @_pending_deps = tasks end |
.desc(usage_or_desc, description = nil, options = {}) ⇒ Object
Allow single-argument desc: desc “Run the tests” The usage string defaults to the method name when the description is the only arg.
83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/asgard/base.rb', line 83 def desc(usage_or_desc, description = nil, = {}) if description.nil? || description.is_a?(Hash) = description if description.is_a?(Hash) @_pending_single_desc = usage_or_desc @_pending_single_desc_opts = else @_pending_single_desc = nil @_pending_single_desc_opts = nil super end end |
.dotenv(path = ".env") ⇒ Object
95 96 97 98 |
# File 'lib/asgard/base.rb', line 95 def dotenv(path = ".env") require "dotenv" Dotenv.load(path) if File.exist?(path) end |
.inherited(subclass) ⇒ Object
15 16 17 18 19 20 21 22 23 24 25 26 |
# File 'lib/asgard/base.rb', line 15 def inherited(subclass) super Asgard::Base.subclasses << subclass subclass.instance_variable_set(:@_deps, {}) subclass.instance_variable_set(:@_pending_deps, []) subclass.instance_variable_set(:@_pending_single_desc, nil) subclass.instance_variable_set(:@_pending_single_desc_opts, nil) subclass.instance_variable_set(:@_running, Set.new) subclass.instance_variable_set(:@_done, Set.new) subclass.instance_variable_set(:@_cond, Hash.new { |h, k| h[k] = ConditionVariable.new }) subclass.instance_variable_set(:@_ran_mutex, Mutex.new) end |
.method_added(method_name) ⇒ Object
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 |
# File 'lib/asgard/base.rb', line 164 def method_added(method_name) if @_pending_single_desc && !no_commands? pending_desc = @_pending_single_desc pending_opts = @_pending_single_desc_opts || {} @_pending_single_desc = nil @_pending_single_desc_opts = nil desc(method_name.to_s, pending_desc, pending_opts) end return super unless @usage pending = Array(@_pending_deps).dup @_pending_deps = [] return super if pending.empty? return super if method_name.to_s.start_with?("_") # Each element is a Symbol (sequential) or Array (parallel group). _deps[method_name.to_sym] = pending.map { |d| Array(d).map(&:to_sym) } super end |
.subclasses ⇒ Object
11 12 13 |
# File 'lib/asgard/base.rb', line 11 def subclasses @subclasses ||= [] end |
.validate_deps! ⇒ Object
Validate the full dep graph for cycles using Dagwood::DependencyGraph.
115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/asgard/base.rb', line 115 def validate_deps! _check_orphaned_deps! return if _deps.empty? all_task_names = all_commands.keys.map(&:to_sym) _check_undefined_deps!(all_task_names) _check_dep_arities! _build_and_sort_graph(all_task_names) rescue TSort::Cyclic => e raise Asgard::CircularDependencyError, e. end |