cmdx 1.12.0 → 1.13.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: 5dffef0df3a8abb190fc0ca6a194383614fdd81f3eebf22ecab59d8ec047d1d7
4
- data.tar.gz: 0f38ccaa12a07c41b64fb4fd3f0685bafb45b7de0b3830243f85a53de4d331c4
3
+ metadata.gz: 0b1cd7841d40aeac40b6eb36a7ff87a5ace03deae3496e1aef5cb10e34f8f42d
4
+ data.tar.gz: 303333d4635690575ceda40a2564be417b47f5ec4c2992af542c509710289ae3
5
5
  SHA512:
6
- metadata.gz: 8649dadb0908d88f7441b80d6e3dce03e7f0d20095216d8ac24cc0bf8b1446f57b4552f021a324f47d860112e431b531695a5cd78e84a4b2cf0c3be0dff1224e
7
- data.tar.gz: 5e88be6d5a3070d75abbbcb20e25d900db3a44f011f71ed55c61f748cda77e9be4297f12829ab9f28daac66a4b2c511725318ae4e1455793eef8b8f806c3864c
6
+ metadata.gz: 18cde5cf4b6c7fa974ffb7a3827e09d0a5c2ac5f3c2c01427abbc94de71ef1bc03aee78e25032900761f09c8d39e89e52a4ea1d5fa33e07c86f060b483fe839f
7
+ data.tar.gz: 5ed05ecdb682ae160be47cf6399c76081486011b6143f95f9884a06b588474ba64e3e000efd72ba2dcd6abb343e3e12985d2691ca15ee7575873f90daff6e70f
data/CHANGELOG.md CHANGED
@@ -6,6 +6,15 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
 
7
7
  ## [UNRELEASED]
8
8
 
9
+ ## [1.13.0] - 2025-12-23
10
+
11
+ ### Added
12
+
13
+ - Added task execution rollback tracking and logging
14
+ - Added `dry_run` option to task execution with inheritance support for nested tasks
15
+ - Added context `delete` alias for `delete!`
16
+ - Added context `merge` alias for `merge!`
17
+
9
18
  ## [1.12.0] - 2025-12-18
10
19
 
11
20
  ### Added
@@ -11,6 +11,33 @@ Both methods return results, but handle failures differently:
11
11
  | `execute` | Always returns `CMDx::Result` | Never raises | Predictable result handling |
12
12
  | `execute!` | Returns `CMDx::Result` on success | Raises `CMDx::Fault` when skipped or failed | Exception-based control flow |
13
13
 
14
+ ```mermaid
15
+ flowchart LR
16
+ subgraph Methods
17
+ E[execute]
18
+ EB[execute!]
19
+ end
20
+
21
+ subgraph Returns [Returns CMDx::Result]
22
+ Success
23
+ Failed
24
+ Skipped
25
+ end
26
+
27
+ subgraph Raises [Raises CMDx::Fault]
28
+ FailFault
29
+ SkipFault
30
+ end
31
+
32
+ E --> Success
33
+ E --> Failed
34
+ E --> Skipped
35
+
36
+ EB --> Success
37
+ EB --> FailFault
38
+ EB --> SkipFault
39
+ ```
40
+
14
41
  ## Non-bang Execution
15
42
 
16
43
  Always returns a `CMDx::Result`, never raises exceptions. Perfect for most use cases.
@@ -94,3 +121,32 @@ result.chain #=> Task execution chain
94
121
  result.context #=> Context with all task data
95
122
  result.metadata #=> Hash with execution metadata
96
123
  ```
124
+
125
+ ## Dry Run
126
+
127
+ Execute tasks in dry-run mode to simulate execution without performing side effects. Pass `dry_run: true` in the context when initializing or executing the task.
128
+
129
+ Inside your task, use the `dry_run?` method to conditionally skip side effects.
130
+
131
+ ```ruby
132
+ class CloseStripeCard < CMDx::Task
133
+ def work
134
+ context.stripe_result =
135
+ if dry_run?
136
+ FactoryBot.build(:stripe_closed_card)
137
+ else
138
+ StripeApi.close_card(context.card_id)
139
+ end
140
+ end
141
+ end
142
+
143
+ # Execute in dry-run mode
144
+ result = CloseStripeCard.execute(card_id: "card_abc123", dry_run: true)
145
+ result.success? # => true
146
+
147
+ # FactoryBot object
148
+ result.context.stripe_result = {
149
+ card_id: "card_abc123",
150
+ status: "closed"
151
+ }
152
+ ```
data/docs/basics/setup.md CHANGED
@@ -29,13 +29,14 @@ IncompleteTask.execute #=> raises CMDx::UndefinedMethodError
29
29
  Undo any operations linked to the given status, helping to restore a pristine state.
30
30
 
31
31
  ```ruby
32
- class ValidateDocument < CMDx::Task
32
+ class ChargeCard < CMDx::Task
33
33
  def work
34
- # Your logic here...
34
+ # Your logic here, ex: charge $100
35
35
  end
36
36
 
37
+ # Called automatically if a later step in the workflow fails
37
38
  def rollback
38
- # Your undo logic...
39
+ # Your undo logic, ex: void $100 charge
39
40
  end
40
41
  end
41
42
  ```
@@ -70,6 +71,28 @@ end
70
71
 
71
72
  Tasks follow a predictable execution pattern:
72
73
 
74
+ ```mermaid
75
+ stateDiagram-v2
76
+ Initialized: Instantiation
77
+ Initialized --> Validating: execute
78
+ Validating --> Executing: Valid?
79
+ Validating --> Failed: Invalid
80
+ Executing --> Success: Work done
81
+ Executing --> Skipped: skip!
82
+ Executing --> Failed: fail! / Exception
83
+ Executed
84
+
85
+ state Executed {
86
+ Success
87
+ Skipped
88
+ Failed
89
+ Rollback
90
+
91
+ Skipped --> Rollback
92
+ Failed --> Rollback
93
+ }
94
+ ```
95
+
73
96
  !!! danger "Caution"
74
97
 
75
98
  Tasks are single-use objects. Once executed, they're frozen and immutable.
data/docs/deprecation.md CHANGED
@@ -32,8 +32,6 @@ Allow execution while tracking deprecation in logs. Ideal for gradual migrations
32
32
  ```ruby
33
33
  class ProcessLegacyFormat < CMDx::Task
34
34
  settings(deprecated: :log)
35
-
36
- # Same
37
35
  settings(deprecated: true)
38
36
 
39
37
  def work
@@ -43,6 +43,13 @@ If not using Rails, manually copy the [configuration file](https://github.com/dr
43
43
 
44
44
  CMDx embraces the Compose, Execute, React, Observe (CERO, pronounced "zero") pattern—a simple yet powerful approach to building reliable business logic.
45
45
 
46
+ ```mermaid
47
+ flowchart LR
48
+ Compose --> Execute
49
+ Execute --> React
50
+ Execute -.-> Observe
51
+ ```
52
+
46
53
  ### Compose
47
54
 
48
55
  Build reusable, single-responsibility tasks with typed attributes, validation, and callbacks. Tasks can be chained together in workflows to create complex business processes from simple building blocks.
@@ -93,6 +100,10 @@ I, [2022-07-17T18:43:15.000000 #3784] INFO -- CMDx:
93
100
  index=0 chain_id="018c2b95-b764-7615-a924-cc5b910ed1e5" type="Task" class="AnalyzeMetrics" state="complete" status="success" metadata={runtime: 187}
94
101
  ```
95
102
 
103
+ !!! note
104
+
105
+ This represents a log-only event-sourcing approach, enabling full traceability and a complete, time-ordered view of system behavior.
106
+
96
107
  ## Task Generator
97
108
 
98
109
  Generate new CMDx tasks quickly using the built-in generator:
data/docs/logging.md CHANGED
@@ -18,20 +18,16 @@ Sample output:
18
18
 
19
19
  ```log
20
20
  <!-- Success (INFO level) -->
21
- I, [2022-07-17T18:43:15.000000 #3784] INFO -- GenerateInvoice:
22
- index=0 chain_id="018c2b95-b764-7615-a924-cc5b910ed1e5" type="Task" class="GenerateInvoice" state="complete" status="success" metadata={runtime: 187}
21
+ I, [2025-12-23T17:04:07.292614Z #20108] INFO -- cmdx: {index: 1, chain_id: "019b4c2b-087b-79be-8ef2-96c11b659df5", type: "Task", tags: [], class: "GenerateInvoice", dry_run: false, id: "019b4c2b-0878-704d-ba0b-daa5410123ec", state: "complete", status: "success", outcome: "success", metadata: {runtime: 187}}
23
22
 
24
- <!-- Skipped (WARN level) -->
25
- W, [2022-07-17T18:43:15.000000 #3784] WARN -- ValidateCustomer:
26
- index=1 chain_id="018c2b95-b764-7615-a924-cc5b910ed1e5" type="Task" class="ValidateCustomer" state="interrupted" status="skipped" reason="Customer already validated"
23
+ <!-- Skipped (INFO level) -->
24
+ I, [2025-12-23T17:04:11.496881Z #20139] INFO -- cmdx: {index: 2, chain_id: "019b4c2b-18e8-7af6-a38b-63b042c4fbed", type: "Task", tags: [], class: "ValidateCustomer", dry_run: false, id: "019b4c2b-18e5-7230-af7e-5b4a4bd7cda2", state: "interrupted", status: "skipped", outcome: "skipped", metadata: {}, reason: "Customer already validated", cause: #<CMDx::SkipFault: Customer already validated>, rolled_back: false}
27
25
 
28
- <!-- Failed (ERROR level) -->
29
- E, [2022-07-17T18:43:15.000000 #3784] ERROR -- CalculateTax:
30
- index=2 chain_id="018c2b95-b764-7615-a924-cc5b910ed1e5" type="Task" class="CalculateTax" state="interrupted" status="failed" metadata={error_code: "TAX_SERVICE_UNAVAILABLE"}
26
+ <!-- Failed (INFO level) -->
27
+ I, [2025-12-23T17:04:15.875306Z #20173] INFO -- cmdx: {index: 3, chain_id: "019b4c2b-2a02-7dbc-b713-b20a7379704f", type: "Task", tags: [], class: "CalculateTax", dry_run: false, id: "019b4c2b-2a00-70b7-9fab-2f14db9139ef", state: "interrupted", status: "failed", outcome: "failed", metadata: {error_code: "TAX_SERVICE_UNAVAILABLE"}, reason: "Validation failed", cause: #<CMDx::FailFault: Validation failed>, rolled_back: false}
31
28
 
32
29
  <!-- Failed Chain -->
33
- E, [2022-07-17T18:43:15.000000 #3784] ERROR -- BillingWorkflow:
34
- index=3 chain_id="018c2b95-b764-7615-a924-cc5b910ed1e5" type="Task" class="BillingWorkflow" state="interrupted" status="failed" caused_failure={index: 2, class: "CalculateTax", status: "failed"} threw_failure={index: 1, class: "ValidateCustomer", status: "failed"}
30
+ I, [2025-12-23T17:04:20.972539Z #20209] INFO -- cmdx: {index: 0, chain_id: "019b4c2b-3de9-71f7-bcc3-2a98836bcfd7", type: "Workflow", tags: [], class: "BillingWorkflow", dry_run: false, id: "019b4c2b-3de6-70b9-9c16-5be13b1a463c", state: "interrupted", status: "failed", outcome: "interrupted", metadata: {}, reason: "Validation failed", cause: #<CMDx::FailFault: Validation failed>, rolled_back: false, threw_failure: {index: 3, chain_id: "019b4c2b-3de9-71f7-bcc3-2a98836bcfd7", type: "Task", tags: [], class: "CalculateTax", id: "019b4c2b-3dec-70b3-969b-c5b7896e3b27", state: "interrupted", status: "failed", outcome: "failed", metadata: {error_code: "TAX_SERVICE_UNAVAILABLE"}, reason: "Validation failed", cause: #<CMDx::FailFault: Validation failed>, rolled_back: false}, caused_failure: {index: 3, chain_id: "019b4c2b-3de9-71f7-bcc3-2a98836bcfd7", type: "Task", tags: [], class: "CalculateTax", id: "019b4c2b-3dec-70b3-969b-c5b7896e3b27", state: "interrupted", status: "failed", outcome: "failed", metadata: {error_code: "TAX_SERVICE_UNAVAILABLE"}, reason: "Validation failed", cause: #<CMDx::FailFault: Validation failed>, rolled_back: false}}
35
31
  ```
36
32
 
37
33
  !!! tip
@@ -30,7 +30,7 @@ result.metadata #=> { error_code: "BUILD_TOOL.NOT_FOUND" }
30
30
 
31
31
  ## Lifecycle Information
32
32
 
33
- Check execution state and status with predicate methods:
33
+ Check execution state, status, and rollback with predicate methods:
34
34
 
35
35
  ```ruby
36
36
  result = BuildApplication.execute(version: "1.2.3")
@@ -48,6 +48,9 @@ result.skipped? #=> false (not skipped)
48
48
  # Outcome categorization
49
49
  result.good? #=> true (success or skipped)
50
50
  result.bad? #=> false (skipped or failed)
51
+
52
+ # Rollback Status
53
+ result.rolled_back? #=> true (execution was rolled back)
51
54
  ```
52
55
 
53
56
  ## Outcome Analysis
data/lib/cmdx/chain.rb CHANGED
@@ -39,9 +39,10 @@ module CMDx
39
39
  # @return [Chain] A new chain instance
40
40
  #
41
41
  # @rbs () -> void
42
- def initialize
42
+ def initialize(dry_run: false)
43
43
  @id = Identifier.generate
44
44
  @results = []
45
+ @dry_run = !!dry_run
45
46
  end
46
47
 
47
48
  class << self
@@ -102,16 +103,28 @@ module CMDx
102
103
  # puts "Chain size: #{chain.size}"
103
104
  #
104
105
  # @rbs (Result result) -> Chain
105
- def build(result)
106
+ def build(result, dry_run: false)
106
107
  raise TypeError, "must be a CMDx::Result" unless result.is_a?(Result)
107
108
 
108
- self.current ||= new
109
+ self.current ||= new(dry_run:)
109
110
  current.results << result
110
111
  current
111
112
  end
112
113
 
113
114
  end
114
115
 
116
+ # Returns whether the chain is running in dry-run mode.
117
+ #
118
+ # @return [Boolean] Whether the chain is running in dry-run mode
119
+ #
120
+ # @example
121
+ # chain.dry_run? # => true
122
+ #
123
+ # @rbs () -> bool
124
+ def dry_run?
125
+ !!@dry_run
126
+ end
127
+
115
128
  # Converts the chain to a hash representation.
116
129
  #
117
130
  # @option return [String] :id The chain identifier
@@ -127,7 +140,8 @@ module CMDx
127
140
  # @rbs () -> Hash[Symbol, untyped]
128
141
  def to_h
129
142
  {
130
- id: id,
143
+ id:,
144
+ dry_run: dry_run?,
131
145
  results: results.map(&:to_h)
132
146
  }
133
147
  end
data/lib/cmdx/context.rb CHANGED
@@ -164,6 +164,7 @@ module CMDx
164
164
  args.to_h.each { |key, value| self[key.to_sym] = value }
165
165
  self
166
166
  end
167
+ alias merge merge!
167
168
 
168
169
  # Deletes a key-value pair from the context.
169
170
  #
@@ -182,6 +183,7 @@ module CMDx
182
183
  def delete!(key, &)
183
184
  table.delete(key.to_sym, &)
184
185
  end
186
+ alias delete delete!
185
187
 
186
188
  # Compares this context with another object for equality.
187
189
  #
data/lib/cmdx/executor.rb CHANGED
@@ -8,6 +8,8 @@ module CMDx
8
8
  # and proper error handling for different types of failures.
9
9
  class Executor
10
10
 
11
+ extend Forwardable
12
+
11
13
  # Returns the task being executed.
12
14
  #
13
15
  # @return [Task] The task instance
@@ -18,6 +20,8 @@ module CMDx
18
20
  # @rbs @task: Task
19
21
  attr_reader :task
20
22
 
23
+ def_delegators :task, :result
24
+
21
25
  # @param task [CMDx::Task] The task to execute
22
26
  #
23
27
  # @return [CMDx::Executor] A new executor instance
@@ -65,13 +69,13 @@ module CMDx
65
69
  rescue UndefinedMethodError => e
66
70
  raise(e) # No need to clear the Chain since exception is not being re-raised
67
71
  rescue Fault => e
68
- task.result.throw!(e.result, halt: false, cause: e)
72
+ result.throw!(e.result, halt: false, cause: e)
69
73
  rescue StandardError => e
70
74
  retry if retry_execution?(e)
71
- task.result.fail!("[#{e.class}] #{e.message}", halt: false, cause: e)
75
+ result.fail!("[#{e.class}] #{e.message}", halt: false, cause: e)
72
76
  task.class.settings[:exception_handler]&.call(task, e)
73
77
  ensure
74
- task.result.executed!
78
+ result.executed!
75
79
  post_execution!
76
80
  end
77
81
 
@@ -96,14 +100,14 @@ module CMDx
96
100
  rescue UndefinedMethodError => e
97
101
  raise_exception(e)
98
102
  rescue Fault => e
99
- task.result.throw!(e.result, halt: false, cause: e)
103
+ result.throw!(e.result, halt: false, cause: e)
100
104
  halt_execution?(e) ? raise_exception(e) : post_execution!
101
105
  rescue StandardError => e
102
106
  retry if retry_execution?(e)
103
- task.result.fail!("[#{e.class}] #{e.message}", halt: false, cause: e)
107
+ result.fail!("[#{e.class}] #{e.message}", halt: false, cause: e)
104
108
  raise_exception(e)
105
109
  else
106
- task.result.executed!
110
+ result.executed!
107
111
  post_execution!
108
112
  end
109
113
 
@@ -137,14 +141,14 @@ module CMDx
137
141
  available_retries = (task.class.settings[:retries] || 0).to_i
138
142
  return false unless available_retries.positive?
139
143
 
140
- current_retries = (task.result.metadata[:retries] ||= 0).to_i
144
+ current_retries = (result.metadata[:retries] ||= 0).to_i
141
145
  remaining_retries = available_retries - current_retries
142
146
  return false unless remaining_retries.positive?
143
147
 
144
148
  exceptions = Array(task.class.settings[:retry_on] || StandardError)
145
149
  return false unless exceptions.any? { |e| exception.class <= e }
146
150
 
147
- task.result.metadata[:retries] += 1
151
+ result.metadata[:retries] += 1
148
152
 
149
153
  task.logger.warn do
150
154
  reason = "[#{exception.class}] #{exception.message}"
@@ -208,7 +212,7 @@ module CMDx
208
212
  task.class.settings[:attributes].define_and_verify(task)
209
213
  return if task.errors.empty?
210
214
 
211
- task.result.fail!(
215
+ result.fail!(
212
216
  Locale.t("cmdx.faults.invalid"),
213
217
  errors: {
214
218
  full_message: task.errors.to_s,
@@ -223,7 +227,7 @@ module CMDx
223
227
  def execution!
224
228
  invoke_callbacks(:before_execution)
225
229
 
226
- task.result.executing!
230
+ result.executing!
227
231
  task.work
228
232
  end
229
233
 
@@ -231,12 +235,12 @@ module CMDx
231
235
  #
232
236
  # @rbs () -> void
233
237
  def post_execution!
234
- invoke_callbacks(:"on_#{task.result.state}")
235
- invoke_callbacks(:on_executed) if task.result.executed?
238
+ invoke_callbacks(:"on_#{result.state}")
239
+ invoke_callbacks(:on_executed) if result.executed?
236
240
 
237
- invoke_callbacks(:"on_#{task.result.status}")
238
- invoke_callbacks(:on_good) if task.result.good?
239
- invoke_callbacks(:on_bad) if task.result.bad?
241
+ invoke_callbacks(:"on_#{result.status}")
242
+ invoke_callbacks(:on_good) if result.good?
243
+ invoke_callbacks(:on_bad) if result.bad?
240
244
  end
241
245
 
242
246
  # Finalizes execution by freezing the task, logging results, and rolling back work.
@@ -246,26 +250,25 @@ module CMDx
246
250
  log_execution!
247
251
  log_backtrace! if task.class.settings[:backtrace]
248
252
 
253
+ rollback_execution!
249
254
  freeze_execution!
250
255
  clear_chain!
251
-
252
- rollback_execution!
253
256
  end
254
257
 
255
258
  # Logs the execution result at the configured log level.
256
259
  #
257
260
  # @rbs () -> void
258
261
  def log_execution!
259
- task.logger.info { task.result.to_h }
262
+ task.logger.info { result.to_h }
260
263
  end
261
264
 
262
265
  # Logs the backtrace of the exception if the task failed.
263
266
  #
264
267
  # @rbs () -> void
265
268
  def log_backtrace!
266
- return unless task.result.failed?
269
+ return unless result.failed?
267
270
 
268
- exception = task.result.caused_failure.cause
271
+ exception = result.caused_failure.cause
269
272
  return if exception.is_a?(Fault)
270
273
 
271
274
  task.logger.error do
@@ -287,11 +290,11 @@ module CMDx
287
290
  return if Coercions::Boolean.call(skip_freezing)
288
291
 
289
292
  task.freeze
290
- task.result.freeze
293
+ result.freeze
291
294
 
292
295
  # Freezing the context and chain can only be done
293
296
  # once the outer-most task has completed.
294
- return unless task.result.index.zero?
297
+ return unless result.index.zero?
295
298
 
296
299
  task.context.freeze
297
300
  task.chain.freeze
@@ -301,7 +304,7 @@ module CMDx
301
304
  #
302
305
  # @rbs () -> void
303
306
  def clear_chain!
304
- return unless task.result.index.zero?
307
+ return unless result.index.zero?
305
308
 
306
309
  Chain.clear
307
310
  end
@@ -310,12 +313,14 @@ module CMDx
310
313
  #
311
314
  # @rbs () -> void
312
315
  def rollback_execution!
316
+ return if result.rolled_back?
313
317
  return unless task.respond_to?(:rollback)
314
318
 
315
319
  statuses = task.class.settings[:rollback_on]
316
320
  statuses = Array(statuses).map(&:to_s).uniq
317
- return unless statuses.include?(task.result.status)
321
+ return unless statuses.include?(result.status)
318
322
 
323
+ result.rolled_back!
319
324
  task.rollback
320
325
  end
321
326
 
data/lib/cmdx/result.rb CHANGED
@@ -95,7 +95,7 @@ module CMDx
95
95
  # @rbs @cause: (Exception | nil)
96
96
  attr_reader :cause
97
97
 
98
- def_delegators :task, :context, :chain, :errors
98
+ def_delegators :task, :context, :chain, :errors, :dry_run?
99
99
  alias ctx context
100
100
 
101
101
  # @param task [CMDx::Task] The task instance this result represents
@@ -118,6 +118,7 @@ module CMDx
118
118
  @metadata = {}
119
119
  @reason = nil
120
120
  @cause = nil
121
+ @rolled_back = false
121
122
  end
122
123
 
123
124
  STATES.each do |s|
@@ -419,6 +420,27 @@ module CMDx
419
420
  failed? && !caused_failure?
420
421
  end
421
422
 
423
+ # @return [void]
424
+ #
425
+ # @example
426
+ # result.rolled_back!
427
+ # result.rolled_back? # => true
428
+ #
429
+ # @rbs () -> void
430
+ def rolled_back!
431
+ @rolled_back = true
432
+ end
433
+
434
+ # @return [Boolean] Whether the result has been rolled back
435
+ #
436
+ # @example
437
+ # result.rolled_back? # => true
438
+ #
439
+ # @rbs () -> bool
440
+ def rolled_back?
441
+ !!@rolled_back
442
+ end
443
+
422
444
  # @return [Integer] Index of this result in the chain
423
445
  #
424
446
  # @example
@@ -457,6 +479,7 @@ module CMDx
457
479
  if interrupted?
458
480
  hash[:reason] = reason
459
481
  hash[:cause] = cause
482
+ hash[:rolled_back] = rolled_back?
460
483
  end
461
484
 
462
485
  if failed?
data/lib/cmdx/task.rb CHANGED
@@ -71,6 +71,7 @@ module CMDx
71
71
  attr_reader :chain
72
72
 
73
73
  def_delegators :result, :skip!, :fail!, :throw!
74
+ def_delegators :chain, :dry_run?
74
75
 
75
76
  # @param context [Hash, Context] The initial context for the task
76
77
  #
@@ -94,7 +95,7 @@ module CMDx
94
95
  @id = Identifier.generate
95
96
  @context = Context.build(context)
96
97
  @result = Result.new(self)
97
- @chain = Chain.build(@result)
98
+ @chain = Chain.build(@result, dry_run: @context.delete(:dry_run))
98
99
  end
99
100
 
100
101
  class << self
@@ -341,6 +342,7 @@ module CMDx
341
342
  type: self.class.include?(Workflow) ? "Workflow" : "Task",
342
343
  tags: self.class.settings[:tags],
343
344
  class: self.class.name,
345
+ dry_run: dry_run?,
344
346
  id:
345
347
  }
346
348
  end
data/lib/cmdx/version.rb CHANGED
@@ -5,6 +5,6 @@ module CMDx
5
5
  # @return [String] the version of the CMDx gem
6
6
  #
7
7
  # @rbs return: String
8
- VERSION = "1.12.0"
8
+ VERSION = "1.13.0"
9
9
 
10
10
  end
data/mkdocs.yml CHANGED
@@ -65,7 +65,11 @@ markdown_extensions:
65
65
  - attr_list
66
66
  - md_in_html
67
67
  - pymdownx.details
68
- - pymdownx.superfences
68
+ - pymdownx.superfences:
69
+ custom_fences:
70
+ - name: mermaid
71
+ class: mermaid
72
+ format: !!python/name:pymdownx.superfences.fence_code_format
69
73
  - pymdownx.highlight:
70
74
  anchor_linenums: true
71
75
  line_spans: __span
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cmdx
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.12.0
4
+ version: 1.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Juan Gomez