flow-lite 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +108 -17
- data/lib/flow-lite.rb +88 -21
- data/lib/flow-lite/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1f61f94156b9718eb74e5a99f9e9c1128f067588
|
4
|
+
data.tar.gz: b3da7ea83777db3cbe01609ae431bd4ce043ef1d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 49523aa490c50d6b4602090df7c135899f234b9649c406c6f5ca22967bc976732e3a3c5d6589b6c8ebdd31049651b53d2096a038e611a20a1aa5aa5b85f1565f
|
7
|
+
data.tar.gz: 4321ffd322f70a5288f68d697b4020a8389ac45f273c4f3fd88c7d5e54f104e48e6b1d5be32ee130df158472a69a64e97d0705f2f5380a03e2b474d25132ea37
|
data/README.md
CHANGED
@@ -10,6 +10,7 @@ flow-lite gem - (yet) another (lite) workflow engine; let's you define your work
|
|
10
10
|
|
11
11
|
|
12
12
|
|
13
|
+
|
13
14
|
## Usage
|
14
15
|
|
15
16
|
|
@@ -19,12 +20,12 @@ Define the workflow steps in a Flowfile. Example:
|
|
19
20
|
``` ruby
|
20
21
|
step :first_step do
|
21
22
|
puts "first_step"
|
22
|
-
second_step # note: you can call other steps
|
23
|
+
step :second_step # note: you can call other steps with step
|
23
24
|
end
|
24
25
|
|
25
26
|
step :second_step do
|
26
27
|
puts "second_step"
|
27
|
-
third_step
|
28
|
+
step :third_step
|
28
29
|
end
|
29
30
|
|
30
31
|
step :third_step do
|
@@ -39,7 +40,28 @@ Example:
|
|
39
40
|
$ flow first_step
|
40
41
|
```
|
41
42
|
|
42
|
-
Note: By default the `flow` command line tool reads in
|
43
|
+
Note: By default the `flow` command line tool reads in and looks for `flowfile`, `Flowfile`, `flowfile.rb`, `Flowfile.rb`
|
44
|
+
in that order.
|
45
|
+
Use the `-f/--flowfile` option to use a different file
|
46
|
+
and use the `-r/--require` to (auto-)require
|
47
|
+
some extra libraries or scripts.
|
48
|
+
By default for now the "prelude / prolog" that always
|
49
|
+
gets auto-required includes:
|
50
|
+
|
51
|
+
``` ruby
|
52
|
+
require 'pp'
|
53
|
+
require 'time'
|
54
|
+
require 'date'
|
55
|
+
require 'json'
|
56
|
+
require 'yaml'
|
57
|
+
require 'fileutils'
|
58
|
+
|
59
|
+
require 'uri'
|
60
|
+
require 'net/http'
|
61
|
+
require 'net/https'
|
62
|
+
```
|
63
|
+
|
64
|
+
Tip: See the [`flow-lite.rb`](https://github.com/rubycoco/git/blob/master/flow-lite/lib/flow-lite.rb) source for the definite always up-to-date list.
|
43
65
|
|
44
66
|
|
45
67
|
That's it for now.
|
@@ -66,14 +88,17 @@ flowfile = Flow::Flowfile.load( <<TXT )
|
|
66
88
|
end
|
67
89
|
TXT
|
68
90
|
|
69
|
-
flow = flowfile.
|
70
|
-
|
71
|
-
flow.
|
72
|
-
flow.
|
91
|
+
flow = flowfile.flow_class.new # (auto-)build a flow class (see Note 1)
|
92
|
+
# and construct/return a new instance
|
93
|
+
flow.step_hello #=> "Hello, world!"
|
94
|
+
flow.step_hola #=> "¡Hola, mundo!"
|
95
|
+
flow.step( :hello ) #=> "Hello, world!"
|
96
|
+
flow.step( :hola ) #=> "¡Hola, mundo!"
|
97
|
+
flow.class.step_methods #=> [:hello, :hola]
|
73
98
|
|
74
99
|
# or use ruby's (regular) message/metaprogramming machinery
|
75
|
-
flow.send( :
|
76
|
-
flow.send( :
|
100
|
+
flow.send( :step_hello ) #=> "Hello, world!"
|
101
|
+
flow.send( :step_hola ) #=> "¡Hola, mundo!"
|
77
102
|
# or try
|
78
103
|
flow.class.instance_methods.grep( /^step_/ ) #=> [:step_hello, :step_hola]
|
79
104
|
# ...
|
@@ -95,19 +120,40 @@ gets used to (auto-) build (via metaprogramming) a flow class like:
|
|
95
120
|
|
96
121
|
``` ruby
|
97
122
|
class Greeter < Flow::Base
|
98
|
-
def
|
123
|
+
def step_hello
|
99
124
|
puts "Hello, world!"
|
100
125
|
end
|
101
|
-
alias_method :step_hello, :hello
|
102
126
|
|
103
|
-
def
|
127
|
+
def step_hola
|
104
128
|
puts "¡Hola, mundo!"
|
105
129
|
end
|
106
|
-
alias_method :step_hola, :hola
|
107
130
|
end
|
108
131
|
```
|
109
132
|
|
110
133
|
|
134
|
+
Note: Behind the stage the metaprogramming "class macro"
|
135
|
+
`define_step( symbol, method )`
|
136
|
+
or `define_step( symbol ) { block }` defined in `Flow::Base`
|
137
|
+
gets used, thus,
|
138
|
+
if you want to create steps in a "hand-coded" class
|
139
|
+
use:
|
140
|
+
|
141
|
+
|
142
|
+
``` ruby
|
143
|
+
class Greeter < Flow::Base
|
144
|
+
define_step :hello do
|
145
|
+
puts "Hello, world!"
|
146
|
+
end
|
147
|
+
|
148
|
+
define_step :hola do
|
149
|
+
puts "¡Hola, mundo!"
|
150
|
+
end
|
151
|
+
end
|
152
|
+
```
|
153
|
+
|
154
|
+
|
155
|
+
|
156
|
+
|
111
157
|
|
112
158
|
**Tips & Tricks**
|
113
159
|
|
@@ -115,7 +161,7 @@ Auto-include pre-build / pre-defined steps. Use a (regular) Module e.g.:
|
|
115
161
|
|
116
162
|
``` ruby
|
117
163
|
module GitHubActions
|
118
|
-
def
|
164
|
+
def step_setup
|
119
165
|
# setup ssh
|
120
166
|
ssh_key = ENV['SSH_KEY']
|
121
167
|
ssh_path = File.expand_path( '~/.ssh' )
|
@@ -133,8 +179,6 @@ module GitHubActions
|
|
133
179
|
|
134
180
|
# ...
|
135
181
|
end
|
136
|
-
# optional - for auto-discovery add a step alias
|
137
|
-
alias_method :step_setup, :setup
|
138
182
|
end
|
139
183
|
```
|
140
184
|
|
@@ -150,7 +194,54 @@ end
|
|
150
194
|
Flow::Base.include( GitHubActions )
|
151
195
|
```
|
152
196
|
|
153
|
-
Now all your flows can (re)use `setup` or any other methods you define.
|
197
|
+
Now all your flows can (re)use `setup` or any other step methods you define.
|
198
|
+
|
199
|
+
|
200
|
+
|
201
|
+
|
202
|
+
## Real World Examples
|
203
|
+
|
204
|
+
**Collect GitHub Statistics**
|
205
|
+
|
206
|
+
Use GitHub Actions to collect
|
207
|
+
GitHub Statistics via GitHub API calls
|
208
|
+
and update the JSON datasets
|
209
|
+
in the `/cache.github` repo at the `yorobot` org(anization):
|
210
|
+
|
211
|
+
``` ruby
|
212
|
+
step :clone do
|
213
|
+
Mono.clone( '@yorobot/cache.github' )
|
214
|
+
end
|
215
|
+
|
216
|
+
|
217
|
+
step :update do
|
218
|
+
Hubba.config.data_dir = Mono.real_path( '@yorobot/cache.github' )
|
219
|
+
|
220
|
+
username = 'geraldb'
|
221
|
+
h = Hubba.reposet( username )
|
222
|
+
pp h
|
223
|
+
|
224
|
+
Hubba.update_stats( h )
|
225
|
+
Hubba.update_traffic( h )
|
226
|
+
puts "Done."
|
227
|
+
end
|
228
|
+
|
229
|
+
|
230
|
+
step :push do
|
231
|
+
msg = "auto-update week #{Date.today.cweek}"
|
232
|
+
|
233
|
+
Mono.open( '@yorobot/cache.github' ) do |proj|
|
234
|
+
if proj.changes?
|
235
|
+
proj.add( "." )
|
236
|
+
proj.commit( msg )
|
237
|
+
proj.push
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
241
|
+
```
|
242
|
+
|
243
|
+
(Sources: [`Flowfile`](https://github.com/yorobot/backup/blob/master/Flowfile.rb), [`workflows/update.yml`](https://github.com/yorobot/backup/blob/master/.github/workflows/update.yml) @ `yorobot/backup`)
|
244
|
+
|
154
245
|
|
155
246
|
|
156
247
|
|
data/lib/flow-lite.rb
CHANGED
@@ -44,25 +44,70 @@ end # class Step
|
|
44
44
|
|
45
45
|
|
46
46
|
class Base ## base class for flow class (auto)-constructed/build from flowfile
|
47
|
-
def self.define_step(
|
48
|
-
|
47
|
+
def self.define_step( name_or_names, &block )
|
48
|
+
names = if name_or_names.is_a?( Array )
|
49
|
+
name_or_names
|
50
|
+
else
|
51
|
+
[name_or_names] ## assume single symbol (name); wrap in array
|
52
|
+
end
|
53
|
+
names = names.map {|name| name.to_sym } ## make sure we always use symbols
|
54
|
+
|
55
|
+
|
56
|
+
name = names[0]
|
49
57
|
puts "[flow] adding step >#{name}<..."
|
50
|
-
define_method( name, &
|
51
|
-
alias_method( :"step_#{name}", name ) ## (auto-)add step_<name> alias
|
58
|
+
define_method( :"step_#{name}", &block )
|
52
59
|
|
53
|
-
alt_names =
|
60
|
+
alt_names = names[1..-1]
|
54
61
|
alt_names.each do |alt_name|
|
55
62
|
puts "[flow] adding alias >#{alt_name}< for >#{name}<..."
|
56
|
-
alias_method( alt_name, name )
|
63
|
+
alias_method( :"step_#{alt_name}", :"step_#{name}" )
|
64
|
+
end
|
65
|
+
end # method self.define_step
|
66
|
+
|
67
|
+
|
68
|
+
|
69
|
+
## run step by symbol/name (e.g. step :hello - etc.)
|
70
|
+
def step( name )
|
71
|
+
name = :"step_#{name}" ## note: make sure we always use symbols
|
72
|
+
if respond_to?( name )
|
73
|
+
send( name )
|
74
|
+
else
|
75
|
+
puts "!! ERROR: step definition >#{name}< not found; cannot run/execute - known (defined) steps include:"
|
76
|
+
pp self.class.step_methods #=> e.g. [:hello, ...]
|
77
|
+
exit 1
|
57
78
|
end
|
79
|
+
end # method step
|
80
|
+
|
81
|
+
def self.step_methods
|
82
|
+
names = instance_methods.reduce([]) do |names, name|
|
83
|
+
names << $1.to_sym if name =~ /^step_(.+)/
|
84
|
+
names
|
85
|
+
end
|
86
|
+
names
|
58
87
|
end
|
59
88
|
end # class Base
|
60
89
|
|
61
90
|
|
62
91
|
|
92
|
+
|
63
93
|
class Flowfile
|
94
|
+
|
95
|
+
## find flowfile path by convention
|
96
|
+
## check for name by convention in this order:
|
97
|
+
FLOWFILES = ['flowfile', 'Flowfile',
|
98
|
+
'flowfile.rb', 'Flowfile.rb']
|
99
|
+
def self.find_file
|
100
|
+
FLOWFILES.each do |name|
|
101
|
+
return "./#{name}" if File.exist?( "./#{name}" )
|
102
|
+
end
|
103
|
+
|
104
|
+
STDERR.puts "!! ERROR - no flowfile found, sorry - looking for: #{FLOWFILES.join(', ')} in (#{Dir.pwd})"
|
105
|
+
exit 1
|
106
|
+
end # method self.find_file
|
107
|
+
|
108
|
+
|
64
109
|
## convenience method - use like Flowfile.load_file()
|
65
|
-
def self.load_file( path=
|
110
|
+
def self.load_file( path=find_file )
|
66
111
|
code = File.open( path, 'r:utf-8' ) { |f| f.read }
|
67
112
|
load( code )
|
68
113
|
end
|
@@ -76,9 +121,13 @@ class Flowfile
|
|
76
121
|
|
77
122
|
|
78
123
|
|
79
|
-
def flow
|
124
|
+
def flow
|
125
|
+
## todo/check: always return a new instance why? why not?
|
126
|
+
flow_class.new
|
127
|
+
end
|
128
|
+
|
129
|
+
def flow_class
|
80
130
|
@flow_class ||= build_flow_class
|
81
|
-
@flow_class.new ## todo/check: always return a new instance why? why not?
|
82
131
|
end
|
83
132
|
|
84
133
|
def build_flow_class
|
@@ -86,7 +135,7 @@ class Flowfile
|
|
86
135
|
klass = Class.new( Base )
|
87
136
|
|
88
137
|
steps.each do |step|
|
89
|
-
klass.define_step( step )
|
138
|
+
klass.define_step( step.names, &step.block )
|
90
139
|
end
|
91
140
|
|
92
141
|
klass
|
@@ -106,21 +155,15 @@ class Flowfile
|
|
106
155
|
@steps << Step.new( name, block )
|
107
156
|
end
|
108
157
|
|
109
|
-
|
110
158
|
def run( name )
|
111
|
-
|
112
|
-
|
113
|
-
flow.send( name )
|
114
|
-
else
|
115
|
-
puts "!! ERROR: step definition >#{name}< not found; cannot run/execute - known steps include:"
|
116
|
-
pp @steps
|
117
|
-
exit 1
|
118
|
-
end
|
159
|
+
## todo/check: always return/use a new instance why? why not?
|
160
|
+
flow_class.new.step( name )
|
119
161
|
end
|
120
162
|
end # class Flowfile
|
121
163
|
|
122
164
|
|
123
165
|
|
166
|
+
|
124
167
|
class Tool
|
125
168
|
def self.main( args=ARGV )
|
126
169
|
options = {}
|
@@ -128,17 +171,41 @@ class Tool
|
|
128
171
|
parser.on( '-f FILENAME', '--flowfile FILENAME' ) do |filename|
|
129
172
|
options[:flowfile] = filename
|
130
173
|
end
|
174
|
+
|
175
|
+
## note:
|
176
|
+
## you can add many/multiple modules
|
177
|
+
## e.g. -r gitti -r mono etc.
|
178
|
+
parser.on( '-r NAME', '--require NAME') do |name|
|
179
|
+
options[:requires] ||= []
|
180
|
+
options[:requires] << name
|
181
|
+
end
|
131
182
|
end.parse!( args )
|
132
183
|
|
133
|
-
|
184
|
+
|
185
|
+
## check for any (dynamic/auto) requires
|
186
|
+
if options[:requires]
|
187
|
+
names = options[:requires]
|
188
|
+
names.each do |name|
|
189
|
+
## todo/check: add some error/exception handling here - why? why not?
|
190
|
+
puts "[flow] (auto-)require >#{name}<..."
|
191
|
+
require( name )
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
|
196
|
+
path = options[:flowfile] || Flowfile.find_file
|
197
|
+
|
198
|
+
|
199
|
+
puts "[flow] loading >#{path}<..."
|
134
200
|
flowfile = Flowfile.load_file( path )
|
135
201
|
|
202
|
+
|
136
203
|
## allow multipe steps getting called - why? why not?
|
137
204
|
## flow setup clone update etc??
|
138
205
|
args.each do |arg|
|
139
206
|
flowfile.run( arg )
|
140
207
|
end
|
141
|
-
end
|
208
|
+
end # method self.main
|
142
209
|
end # class Tool
|
143
210
|
|
144
211
|
end # module Flow
|
data/lib/flow-lite/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: flow-lite
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gerald Bauer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-10-
|
11
|
+
date: 2020-10-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rdoc
|