ductwork 0.1.0 → 0.2.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 252ad8643950e6ea9e5024d0e63885aea8c3c7020bef1586faf0b414b41206f0
4
- data.tar.gz: 1133562c0ff6c84c6a91c87e3d73f734e01626842b42c31e49d87127aa25cd7d
3
+ metadata.gz: 10cf03c4f8237368de710c2ee604a9d20cf40c2dcebfda776fe490a38ba26aad
4
+ data.tar.gz: fd44065015e06a493905b493b847df2de01d779f7451662b186a458cb1cc9977
5
5
  SHA512:
6
- metadata.gz: 36460be6d4d35656be5ce2cc0006eaa539f00992c6b32f0c07610d42bc889ea0e198e17d9c405bdfca73469895f9d3076fda4335aea6ad7e6dc5011de4e41612
7
- data.tar.gz: ddb569815f9ac837881fa08b13541084a5048a34fceafe718026fc228966b35377d16af56edddd5dd74a8cf210a76a3b0986e40644a0d3d3d4efb2db91b475f6
6
+ metadata.gz: 712b5f00ad1a1a1c736dd186f04dce4a85f2ba3d57df234a5d1182d91483530f0722c9a153e1a4f8517142657ffc8f486e39e6bcd51c28b66f4df5a5958e5455
7
+ data.tar.gz: 18c7d56494dc4251310e73bffe47c56e80820634dce555ac2e8d2d46b65973242adc621004dada1efa94cb353063ab650bcb833cec2c7d0cffd635727b808fa1
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Ductwork Changelog
2
2
 
3
+ ## [0.2.0]
4
+
5
+ - fix: allow steps to be chained while pipeline is expanded or divided (before collapsing or combining) - before this incorrectly raised a `CollapseError` or `CombineError`
6
+ - feat: validate argument(s) passed to step transition DSL methods to be valid step class
7
+ - feat: validate all pipeline definitions on rails boot
8
+
3
9
  ## [0.1.0]
4
10
 
5
11
  - Initial release - see [documentation](https://docs.getductwork.io/) for details
data/README.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # Ductwork
2
2
 
3
+ [![CI](https://github.com/ductwork/ductwork/actions/workflows/main.yml/badge.svg)](https://github.com/ductwork/ductwork/actions/workflows/main.yml)
4
+ [![Gem Version](https://badge.fury.io/rb/ductwork.svg?icon=si%3Arubygems)](https://rubygems.org/gems/ductwork)
5
+
3
6
  A Ruby pipeline framework.
4
7
 
5
8
  Ductwork lets you build complex pipelines quickly and easily using intuitive Ruby tooling and a natural DSL. No need to learn complicated unified object models or stand up separate runner instances—just write Ruby code and let Ductwork handle the orchestration.
@@ -12,9 +12,12 @@ module Ductwork
12
12
  nodes: [],
13
13
  edges: {},
14
14
  }
15
+ @divisions = 0
16
+ @expansions = 0
15
17
  end
16
18
 
17
19
  def start(klass)
20
+ validate_classes!(klass)
18
21
  validate_start_once!
19
22
  add_new_nodes(klass)
20
23
 
@@ -24,6 +27,7 @@ module Ductwork
24
27
  # NOTE: there is a bug here that does not allow the user to reuse step
25
28
  # classes in the same pipeline. i'll fix this later
26
29
  def chain(klass)
30
+ validate_classes!(klass)
27
31
  validate_definition_started!(action: "chaining")
28
32
  add_edge_to_last_node(klass, type: :chain)
29
33
  add_new_nodes(klass)
@@ -32,10 +36,13 @@ module Ductwork
32
36
  end
33
37
 
34
38
  def divide(to:)
39
+ validate_classes!(to)
35
40
  validate_definition_started!(action: "dividing chain")
36
41
  add_edge_to_last_node(*to, type: :divide)
37
42
  add_new_nodes(*to)
38
43
 
44
+ @divisions += 1
45
+
39
46
  if block_given?
40
47
  branches = to.map do |klass|
41
48
  Ductwork::DSL::BranchBuilder
@@ -49,9 +56,12 @@ module Ductwork
49
56
  end
50
57
 
51
58
  def combine(into:)
59
+ validate_classes!(into)
52
60
  validate_definition_started!(action: "combining steps")
53
61
  validate_definition_divided!
54
62
 
63
+ @divisions -= 1
64
+
55
65
  last_nodes = definition[:nodes].reverse.select do |node|
56
66
  definition[:edges][node].empty?
57
67
  end
@@ -67,23 +77,31 @@ module Ductwork
67
77
  end
68
78
 
69
79
  def expand(to:)
80
+ validate_classes!(to)
70
81
  validate_definition_started!(action: "expanding chain")
71
82
  add_edge_to_last_node(to, type: :expand)
72
83
  add_new_nodes(to)
73
84
 
85
+ @expansions += 1
86
+
74
87
  self
75
88
  end
76
89
 
77
90
  def collapse(into:)
91
+ validate_classes!(into)
78
92
  validate_definition_started!(action: "collapsing steps")
79
93
  validate_definition_expanded!
80
94
  add_edge_to_last_node(into, type: :collapse)
81
95
  add_new_nodes(into)
82
96
 
97
+ @expansions -= 1
98
+
83
99
  self
84
100
  end
85
101
 
86
102
  def on_halt(klass)
103
+ validate_classes!(klass)
104
+
87
105
  definition[:metadata] ||= {}
88
106
  definition[:metadata][:on_halt] = {}
89
107
  definition[:metadata][:on_halt][:klass] = klass.name
@@ -99,7 +117,25 @@ module Ductwork
99
117
 
100
118
  private
101
119
 
102
- attr_reader :definition
120
+ attr_reader :definition, :divisions, :expansions
121
+
122
+ def validate_classes!(klasses)
123
+ valid = Array(klasses).all? do |klass|
124
+ klass.is_a?(Class) &&
125
+ klass.method_defined?(:execute) &&
126
+ klass.instance_method(:execute).arity.zero?
127
+ end
128
+
129
+ if !valid
130
+ word = if Array(klasses).length > 1
131
+ "Arguments"
132
+ else
133
+ "Argument"
134
+ end
135
+
136
+ raise ArgumentError, "#{word} must be a valid step class"
137
+ end
138
+ end
103
139
 
104
140
  def validate_start_once!
105
141
  if definition[:nodes].any?
@@ -114,25 +150,17 @@ module Ductwork
114
150
  end
115
151
 
116
152
  def validate_definition_divided!
117
- if last_edge.nil? || last_edge[:type] != :divide
153
+ if divisions.zero?
118
154
  raise CombineError, "Must divide pipeline definition before combining steps"
119
155
  end
120
156
  end
121
157
 
122
158
  def validate_definition_expanded!
123
- if last_edge.nil? || last_edge[:type] != :expand
159
+ if expansions.zero?
124
160
  raise CollapseError, "Must expand pipeline definition before collapsing steps"
125
161
  end
126
162
  end
127
163
 
128
- def last_edge
129
- last_edge_node = definition[:nodes].reverse.find do |node|
130
- definition[:edges][node].any?
131
- end
132
-
133
- definition.dig(:edges, last_edge_node, -1)
134
- end
135
-
136
164
  def add_new_nodes(*klasses)
137
165
  definition[:nodes].push(*klasses.map(&:name))
138
166
  klasses.each do |klass|
@@ -10,5 +10,15 @@ module Ductwork
10
10
  Ductwork.configuration ||= Ductwork::Configuration.new
11
11
  Ductwork.configuration.logger ||= Rails.logger
12
12
  end
13
+
14
+ initializer "ductwork.validate_definitions", after: :load_config_initializers do
15
+ ActiveSupport.on_load(:active_record) do
16
+ # Load steps and pipelines so definition validation runs and bugs
17
+ # can be caught simply by booting the app or running tests
18
+ loader = Rails.autoloaders.main
19
+ loader.eager_load_dir(Rails.root.join("app/steps"))
20
+ loader.eager_load_dir(Rails.root.join("app/pipelines"))
21
+ end
22
+ end
13
23
  end
14
24
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Ductwork
4
- VERSION = "0.1.0"
4
+ VERSION = "0.2.0"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ductwork
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tyler Ewing