nocode 0.0.5 → 0.0.6
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/CHANGELOG.md +5 -0
- data/exe/nocode +2 -0
- data/lib/nocode/context.rb +8 -3
- data/lib/nocode/job_executor.rb +63 -0
- data/lib/nocode/steps/each.rb +31 -0
- data/lib/nocode/steps_executor.rb +79 -0
- data/lib/nocode/util/optionable.rb +8 -0
- data/lib/nocode/version.rb +1 -1
- data/lib/nocode.rb +2 -2
- metadata +4 -2
- data/lib/nocode/executor.rb +0 -90
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bb204abe5d0c62fce45c1c9afd052fe90e21c9f422020b7acb497dd3e226c22b
|
4
|
+
data.tar.gz: dedd69881e903e5a1778303ea5adcd114fdcba10fbadbe2605c7e72b867beb83
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1e36a07d157d207d70606a067561cbfd049fab0842c124ebb252ef7e15d2bf1e397f5e683b17cead76f92e75112596038d627189ad9e37372bf7236341d500ef
|
7
|
+
data.tar.gz: dfb6f8759f55c3234fc04bae3e1701679b59d6e2678ae12d81190d9775f22a1f87beb6de63e0e58da5e7454d47ba72e3ec3791df66ce43a4e015a6ab8892878a
|
data/CHANGELOG.md
CHANGED
data/exe/nocode
CHANGED
data/lib/nocode/context.rb
CHANGED
@@ -4,7 +4,12 @@ module Nocode
|
|
4
4
|
# Describes the environment for each running step. An instance is initialized when a job
|
5
5
|
# kicks off and then is passed from step to step.
|
6
6
|
class Context
|
7
|
-
|
7
|
+
PARAMETERS_KEY = 'parameters'
|
8
|
+
REGISTERS_KEY = 'registers'
|
9
|
+
|
10
|
+
attr_reader :io,
|
11
|
+
:parameters,
|
12
|
+
:registers
|
8
13
|
|
9
14
|
def initialize(io: $stdout, parameters: {}, registers: {})
|
10
15
|
@io = io || $stdout
|
@@ -24,8 +29,8 @@ module Nocode
|
|
24
29
|
|
25
30
|
def to_h
|
26
31
|
{
|
27
|
-
|
28
|
-
|
32
|
+
REGISTERS_KEY => registers,
|
33
|
+
PARAMETERS_KEY => parameters
|
29
34
|
}
|
30
35
|
end
|
31
36
|
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'context'
|
4
|
+
require_relative 'steps_executor'
|
5
|
+
|
6
|
+
module Nocode
|
7
|
+
# Manages the lifecycle and executes a job.
|
8
|
+
class JobExecutor
|
9
|
+
PARAMETERS_KEY = 'parameters'
|
10
|
+
REGISTERS_KEY = 'registers'
|
11
|
+
STEPS_KEY = 'steps'
|
12
|
+
|
13
|
+
attr_reader :yaml, :io
|
14
|
+
|
15
|
+
def initialize(yaml, io: $stdout)
|
16
|
+
@yaml = yaml.respond_to?(:read) ? yaml.read : yaml
|
17
|
+
@yaml = YAML.safe_load(@yaml) || {}
|
18
|
+
@io = io
|
19
|
+
|
20
|
+
freeze
|
21
|
+
end
|
22
|
+
|
23
|
+
def execute
|
24
|
+
steps = yaml[STEPS_KEY] || []
|
25
|
+
parameters = yaml[PARAMETERS_KEY] || {}
|
26
|
+
registers = yaml[REGISTERS_KEY] || {}
|
27
|
+
|
28
|
+
context = Context.new(
|
29
|
+
io: io,
|
30
|
+
parameters: parameters,
|
31
|
+
registers: registers
|
32
|
+
)
|
33
|
+
|
34
|
+
log_title
|
35
|
+
|
36
|
+
StepsExecutor.new(context: context, steps: steps).execute
|
37
|
+
|
38
|
+
log("Ended: #{DateTime.now}")
|
39
|
+
log_line
|
40
|
+
|
41
|
+
context
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def log_title
|
47
|
+
log_line
|
48
|
+
|
49
|
+
log('Nocode Execution')
|
50
|
+
log("Started: #{DateTime.now}")
|
51
|
+
|
52
|
+
log_line
|
53
|
+
end
|
54
|
+
|
55
|
+
def log_line
|
56
|
+
log('-' * 50)
|
57
|
+
end
|
58
|
+
|
59
|
+
def log(msg)
|
60
|
+
io.puts(msg)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Nocode
|
4
|
+
module Steps
|
5
|
+
# Iterate over a register. Each iteration will store the current element and index in
|
6
|
+
# special registers called: _element and _index. You can prefix these registers by setting
|
7
|
+
# the element_register_prefix option.
|
8
|
+
class Each < Step
|
9
|
+
option :element_register_prefix,
|
10
|
+
:register,
|
11
|
+
:steps
|
12
|
+
|
13
|
+
skip_options_evaluation!
|
14
|
+
|
15
|
+
# rubocop:disable Metrics/AbcSize
|
16
|
+
def perform
|
17
|
+
entries = array(registers[register_option])
|
18
|
+
|
19
|
+
entries.each_with_index do |entry, index|
|
20
|
+
steps = array(steps_option)
|
21
|
+
|
22
|
+
registers["#{element_register_prefix_option}_element"] = entry
|
23
|
+
registers["#{element_register_prefix_option}_index"] = index
|
24
|
+
|
25
|
+
StepsExecutor.new(context: context, steps: steps).execute
|
26
|
+
end
|
27
|
+
end
|
28
|
+
# rubocop:enable Metrics/AbcSize
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'step_registry'
|
4
|
+
|
5
|
+
module Nocode
|
6
|
+
# Class that knows how to execute a series of steps given a context.
|
7
|
+
class StepsExecutor
|
8
|
+
extend Forwardable
|
9
|
+
|
10
|
+
NAME_KEY = 'name'
|
11
|
+
OPTIONS_KEY = 'options'
|
12
|
+
TYPE_KEY = 'type'
|
13
|
+
|
14
|
+
attr_reader :context, :steps
|
15
|
+
|
16
|
+
def_delegators :context, :io
|
17
|
+
|
18
|
+
def initialize(context:, steps:)
|
19
|
+
@context = context
|
20
|
+
@steps = steps
|
21
|
+
|
22
|
+
freeze
|
23
|
+
end
|
24
|
+
|
25
|
+
def execute
|
26
|
+
steps.each do |step|
|
27
|
+
step_instance = make_step(step)
|
28
|
+
|
29
|
+
execute_step(step_instance)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
# TODO: It could be better encapsulated to move the evaluation logic into the step itself
|
36
|
+
# and let it deal with compilation. This may call for re-working the lifecycle of the Step
|
37
|
+
# class so I will temporarily defer this refactoring.
|
38
|
+
def make_step(step)
|
39
|
+
evaluated_step = Util::ObjectTemplate.new(step).evaluate(context.to_h)
|
40
|
+
type = evaluated_step[TYPE_KEY].to_s
|
41
|
+
name = evaluated_step[NAME_KEY].to_s
|
42
|
+
step_class = StepRegistry.constant!(type)
|
43
|
+
|
44
|
+
options =
|
45
|
+
if step_class.skip_options_evaluation?
|
46
|
+
step[OPTIONS_KEY]
|
47
|
+
else
|
48
|
+
evaluated_step[OPTIONS_KEY]
|
49
|
+
end
|
50
|
+
|
51
|
+
step_class.new(
|
52
|
+
options: Util::Dictionary.new(options),
|
53
|
+
context: context,
|
54
|
+
name: name,
|
55
|
+
type: type
|
56
|
+
)
|
57
|
+
end
|
58
|
+
|
59
|
+
def execute_step(step)
|
60
|
+
log(step.name) unless step.name.empty?
|
61
|
+
log("Step: #{step.type}")
|
62
|
+
log("Class: #{step.class}")
|
63
|
+
|
64
|
+
time_in_seconds = Benchmark.measure { step.perform }.real
|
65
|
+
|
66
|
+
log("Completed in #{time_in_seconds.round(3)} second(s)")
|
67
|
+
|
68
|
+
log_line
|
69
|
+
end
|
70
|
+
|
71
|
+
def log_line
|
72
|
+
log('-' * 50)
|
73
|
+
end
|
74
|
+
|
75
|
+
def log(msg)
|
76
|
+
io.puts(msg)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -23,6 +23,14 @@ module Nocode
|
|
23
23
|
|
24
24
|
# Class-level DSL Methods
|
25
25
|
module ClassMethods
|
26
|
+
def skip_options_evaluation?
|
27
|
+
@skip_options_evaluation || false
|
28
|
+
end
|
29
|
+
|
30
|
+
def skip_options_evaluation!
|
31
|
+
@skip_options_evaluation = true
|
32
|
+
end
|
33
|
+
|
26
34
|
def option(*values)
|
27
35
|
values.each { |v| options << v.to_s }
|
28
36
|
end
|
data/lib/nocode/version.rb
CHANGED
data/lib/nocode.rb
CHANGED
@@ -12,14 +12,14 @@ require 'yaml'
|
|
12
12
|
require 'nocode/util'
|
13
13
|
|
14
14
|
# Core
|
15
|
-
require 'nocode/
|
15
|
+
require 'nocode/job_executor'
|
16
16
|
|
17
17
|
# Establish main top-level namespace
|
18
18
|
module Nocode
|
19
19
|
# Default consumer entrypoint into the library.
|
20
20
|
class << self
|
21
21
|
def execute(yaml, io: $stdout)
|
22
|
-
|
22
|
+
JobExecutor.new(yaml, io: io).execute
|
23
23
|
end
|
24
24
|
end
|
25
25
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nocode
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matthew Ruggio
|
@@ -175,7 +175,7 @@ files:
|
|
175
175
|
- exe/nocode
|
176
176
|
- lib/nocode.rb
|
177
177
|
- lib/nocode/context.rb
|
178
|
-
- lib/nocode/
|
178
|
+
- lib/nocode/job_executor.rb
|
179
179
|
- lib/nocode/step.rb
|
180
180
|
- lib/nocode/step_registry.rb
|
181
181
|
- lib/nocode/steps/copy.rb
|
@@ -188,6 +188,7 @@ files:
|
|
188
188
|
- lib/nocode/steps/deserialize/csv.rb
|
189
189
|
- lib/nocode/steps/deserialize/json.rb
|
190
190
|
- lib/nocode/steps/deserialize/yaml.rb
|
191
|
+
- lib/nocode/steps/each.rb
|
191
192
|
- lib/nocode/steps/io/read.rb
|
192
193
|
- lib/nocode/steps/io/write.rb
|
193
194
|
- lib/nocode/steps/log.rb
|
@@ -196,6 +197,7 @@ files:
|
|
196
197
|
- lib/nocode/steps/serialize/yaml.rb
|
197
198
|
- lib/nocode/steps/set.rb
|
198
199
|
- lib/nocode/steps/sleep.rb
|
200
|
+
- lib/nocode/steps_executor.rb
|
199
201
|
- lib/nocode/util.rb
|
200
202
|
- lib/nocode/util/arrayable.rb
|
201
203
|
- lib/nocode/util/class_loader.rb
|
data/lib/nocode/executor.rb
DELETED
@@ -1,90 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative 'context'
|
4
|
-
require_relative 'step_registry'
|
5
|
-
|
6
|
-
module Nocode
|
7
|
-
# Manages the lifecycle and executes a job.
|
8
|
-
class Executor
|
9
|
-
NAME_KEY = 'name'
|
10
|
-
OPTIONS_KEY = 'options'
|
11
|
-
PARAMETERS_KEY = 'parameters'
|
12
|
-
STEPS_KEY = 'steps'
|
13
|
-
TYPE_KEY = 'type'
|
14
|
-
|
15
|
-
attr_reader :yaml, :io
|
16
|
-
|
17
|
-
def initialize(yaml, io: $stdout)
|
18
|
-
@yaml = yaml.respond_to?(:read) ? yaml.read : yaml
|
19
|
-
@yaml = YAML.safe_load(@yaml) || {}
|
20
|
-
@io = io
|
21
|
-
|
22
|
-
freeze
|
23
|
-
end
|
24
|
-
|
25
|
-
def execute
|
26
|
-
steps = yaml[STEPS_KEY] || []
|
27
|
-
parameters = yaml[PARAMETERS_KEY] || {}
|
28
|
-
context = Context.new(io: io, parameters: parameters)
|
29
|
-
|
30
|
-
log_title
|
31
|
-
|
32
|
-
steps.each do |step|
|
33
|
-
step_instance = make_step(step, context)
|
34
|
-
|
35
|
-
execute_step(step_instance)
|
36
|
-
end
|
37
|
-
|
38
|
-
log("Ended: #{DateTime.now}")
|
39
|
-
log_line
|
40
|
-
|
41
|
-
context
|
42
|
-
end
|
43
|
-
|
44
|
-
private
|
45
|
-
|
46
|
-
def make_step(step, context)
|
47
|
-
step = Util::ObjectTemplate.new(step).evaluate(context.to_h)
|
48
|
-
type = step[TYPE_KEY].to_s
|
49
|
-
name = step[NAME_KEY].to_s
|
50
|
-
options = step[OPTIONS_KEY] || {}
|
51
|
-
step_class = StepRegistry.constant!(type)
|
52
|
-
|
53
|
-
step_class.new(
|
54
|
-
options: Util::Dictionary.new(options),
|
55
|
-
context: context,
|
56
|
-
name: name,
|
57
|
-
type: type
|
58
|
-
)
|
59
|
-
end
|
60
|
-
|
61
|
-
def execute_step(step)
|
62
|
-
log(step.name) unless step.name.empty?
|
63
|
-
log("Step: #{step.type}")
|
64
|
-
log("Class: #{step.class}")
|
65
|
-
|
66
|
-
time_in_seconds = Benchmark.measure { step.perform }.real
|
67
|
-
|
68
|
-
log("Completed in #{time_in_seconds.round(3)} second(s)")
|
69
|
-
|
70
|
-
log_line
|
71
|
-
end
|
72
|
-
|
73
|
-
def log_title
|
74
|
-
log_line
|
75
|
-
|
76
|
-
log('Nocode Execution')
|
77
|
-
log("Started: #{DateTime.now}")
|
78
|
-
|
79
|
-
log_line
|
80
|
-
end
|
81
|
-
|
82
|
-
def log_line
|
83
|
-
log('-' * 50)
|
84
|
-
end
|
85
|
-
|
86
|
-
def log(msg)
|
87
|
-
io.puts(msg)
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|