gush 2.0.1 → 2.1.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 +4 -4
- data/.github/workflows/ruby.yml +71 -0
- data/.gitignore +2 -0
- data/CHANGELOG.md +12 -5
- data/Gemfile +4 -0
- data/README.md +37 -8
- data/bin/gush +2 -2
- data/gush.gemspec +8 -9
- data/lib/gush/cli/overview.rb +13 -13
- data/lib/gush/cli.rb +51 -20
- data/lib/gush/client.rb +39 -57
- data/lib/gush/configuration.rb +14 -10
- data/lib/gush/graph.rb +43 -32
- data/lib/gush/worker.rb +18 -2
- data/spec/features/integration_spec.rb +5 -7
- data/spec/gush/client_spec.rb +8 -2
- data/spec/gush/configuration_spec.rb +6 -0
- data/spec/gush/graph_spec.rb +37 -20
- data/spec/gush/worker_spec.rb +20 -0
- data/spec/spec_helper.rb +18 -9
- metadata +36 -39
- data/.travis.yml +0 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dc70498c39ad506749bed1f55c139d29691e540b849dd39e2ba132b54b511d66
|
4
|
+
data.tar.gz: 700d093574e0ff4772c7d36bfeb7792cda44550dd162a48afe17bec5551250cd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ac4c1647f57a87600466445a8d24660e3d95016f17adf9e2fe8f99260ba82a2b3e22a339b9456f653834c89c6e4b9ed6bcb50ebc337b804e07355f9a513ce8ca
|
7
|
+
data.tar.gz: 1ae01511acfc2e23bb0a671328a7b3e9b650b8589b9620461c2b9667ff9d80a47f03b8a156f249746b4f69e613863db0833be8d6221acdabd211d7eba2daee15
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# This workflow uses actions that are not certified by GitHub.
|
2
|
+
# They are provided by a third-party and are governed by
|
3
|
+
# separate terms of service, privacy policy, and support
|
4
|
+
# documentation.
|
5
|
+
# This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
|
6
|
+
# For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
|
7
|
+
|
8
|
+
name: Ruby
|
9
|
+
|
10
|
+
on:
|
11
|
+
pull_request:
|
12
|
+
paths-ignore:
|
13
|
+
- 'README.md'
|
14
|
+
push:
|
15
|
+
paths-ignore:
|
16
|
+
- 'README.md'
|
17
|
+
|
18
|
+
jobs:
|
19
|
+
test:
|
20
|
+
services:
|
21
|
+
redis:
|
22
|
+
image: redis:alpine
|
23
|
+
ports: ["6379:6379"]
|
24
|
+
options: --entrypoint redis-server
|
25
|
+
|
26
|
+
runs-on: ubuntu-latest
|
27
|
+
strategy:
|
28
|
+
matrix:
|
29
|
+
rails_version: ['4.2.7', '5.1.0', '5.2.0', '6.0.0', '6.1.0', '7.0']
|
30
|
+
ruby-version: ['2.6', '2.7', '3.0', '3.1']
|
31
|
+
exclude:
|
32
|
+
- ruby-version: '3.0'
|
33
|
+
rails_version: '4.2.7'
|
34
|
+
- ruby-version: '3.1'
|
35
|
+
rails_version: '4.2.7'
|
36
|
+
- ruby-version: '3.0'
|
37
|
+
rails_version: '5.0'
|
38
|
+
- ruby-version: '3.1'
|
39
|
+
rails_version: '5.0'
|
40
|
+
- ruby-version: '3.0'
|
41
|
+
rails_version: '5.1'
|
42
|
+
- ruby-version: '3.1'
|
43
|
+
rails_version: '5.1'
|
44
|
+
- ruby-version: '3.0'
|
45
|
+
rails_version: '5.2'
|
46
|
+
- ruby-version: '3.1'
|
47
|
+
rails_version: '5.2'
|
48
|
+
- ruby-version: '3.0'
|
49
|
+
rails_version: '6.0'
|
50
|
+
- ruby-version: '3.1'
|
51
|
+
rails_version: '6.0'
|
52
|
+
- ruby-version: '3.1'
|
53
|
+
rails_version: '6.1'
|
54
|
+
- ruby-version: '2.6'
|
55
|
+
rails_version: '7.0'
|
56
|
+
steps:
|
57
|
+
- uses: actions/checkout@v2
|
58
|
+
- name: Set up Ruby
|
59
|
+
uses: ruby/setup-ruby@v1
|
60
|
+
with:
|
61
|
+
ruby-version: ${{ matrix.ruby-version }}
|
62
|
+
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
|
63
|
+
env:
|
64
|
+
RAILS_VERSION: "${{ matrix.rails_version }}"
|
65
|
+
- name: Install Graphviz
|
66
|
+
run: sudo apt-get install graphviz
|
67
|
+
- name: Run tests
|
68
|
+
run: bundle exec rspec
|
69
|
+
env:
|
70
|
+
REDIS_URL: redis://localhost:6379/1
|
71
|
+
RAILS_VERSION: "${{ matrix.rails_version }}"
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
@@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file.
|
|
5
5
|
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
6
6
|
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
7
7
|
|
8
|
+
## 2.1.0
|
9
|
+
|
10
|
+
### Added
|
11
|
+
|
12
|
+
- Allow RedisMutex’s locking duration and polling interval to be customizable, thanks to @thukim! [See pull request](https://github.com/chaps-io/gush/pull/74)
|
13
|
+
- Support for Rails 7.0 and Ruby 3.0-3.1, thanks to @joshRpowell and @kzkn!
|
14
|
+
|
8
15
|
## 2.0.1
|
9
16
|
|
10
17
|
### Fixed
|
@@ -13,31 +20,31 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|
13
20
|
|
14
21
|
## 2.0.0
|
15
22
|
|
16
|
-
|
23
|
+
### Changed
|
17
24
|
|
18
25
|
- *[BREAKING]* Store gush jobs on redis hash instead of plain keys - this improves performance when retrieving keys (Thanks to @Saicheg! [See pull request](https://github.com/chaps-io/gush/pull/56))
|
19
26
|
|
20
27
|
|
21
|
-
|
28
|
+
### Added
|
22
29
|
|
23
30
|
- Allow setting queue for each job via `:queue` option in `run` method (Thanks to @devilankur18! [See pull request](https://github.com/chaps-io/gush/pull/58))
|
24
31
|
|
25
32
|
|
26
33
|
## 1.1.1 - 2018-06-09
|
27
34
|
|
28
|
-
|
35
|
+
### Changed
|
29
36
|
|
30
37
|
- Relax dependency on ActiveSupport to work with 4.2 up to 5.X (Thanks to @iacobus! [See pull request](https://github.com/chaps-io/gush/pull/54))
|
31
38
|
|
32
39
|
|
33
40
|
## 1.1.0 - 2018-02-05
|
34
41
|
|
35
|
-
|
42
|
+
### Added
|
36
43
|
|
37
44
|
- Added ability to specify TTL for Redis keys and manually expire whole workflows (Thanks to @dmitrypol! [See pull request](https://github.com/chaps-io/gush/pull/48))
|
38
45
|
- Loosened dependency on redis-rb library to >= 3.2 and < 5.0 (Thanks to @mofumofu3n! [See pull request](https://github.com/chaps-io/gush/pull/52))
|
39
46
|
|
40
|
-
|
47
|
+
### Fixed
|
41
48
|
|
42
49
|
- Improved performance of (de)serializing workflows by not storing job array inside workflow JSON and other smaller improvements ([See pull request](https://github.com/chaps-io/gush/pull/53))
|
43
50
|
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,4 @@
|
|
1
|
-
# Gush
|
2
|
-
|
3
|
-
## [](https://chaps.io) proudly made by [Chaps](https://chaps.io)
|
1
|
+
# Gush
|
4
2
|
|
5
3
|
Gush is a parallel workflow runner using only Redis as storage and [ActiveJob](http://guides.rubyonrails.org/v4.2/active_job_basics.html#introduction) for scheduling and executing jobs.
|
6
4
|
|
@@ -10,14 +8,14 @@ Gush relies on directed acyclic graphs to store dependencies, see [Parallelizing
|
|
10
8
|
|
11
9
|
## **WARNING - version notice**
|
12
10
|
|
13
|
-
This README is about the `
|
11
|
+
This README is about the latest `master` code, which might differ from what is released on RubyGems. See tags to browse previous READMEs.
|
14
12
|
|
15
13
|
## Installation
|
16
14
|
|
17
15
|
### 1. Add `gush` to Gemfile
|
18
16
|
|
19
17
|
```ruby
|
20
|
-
gem 'gush', '~>
|
18
|
+
gem 'gush', '~> 2.0'
|
21
19
|
```
|
22
20
|
|
23
21
|
### 2. Create `Gushfile`
|
@@ -276,7 +274,7 @@ class EncodeVideo < Gush::Job
|
|
276
274
|
end
|
277
275
|
```
|
278
276
|
|
279
|
-
`payloads` is an array containing outputs from all ancestor jobs. So for our `
|
277
|
+
`payloads` is an array containing outputs from all ancestor jobs. So for our `EncodeVideo` job from above, the array will look like:
|
280
278
|
|
281
279
|
|
282
280
|
```ruby
|
@@ -323,6 +321,23 @@ it will generate a workflow with 5 `NotificationJob`s and one `AdminNotification
|
|
323
321
|
|
324
322
|

|
325
323
|
|
324
|
+
### Dynamic queue for jobs
|
325
|
+
|
326
|
+
There might be a case you want to configure different jobs in the workflow using different queues. Based on the above the example, we want to config `AdminNotificationJob` to use queue `admin` and `NotificationJob` use queue `user`.
|
327
|
+
|
328
|
+
```ruby
|
329
|
+
|
330
|
+
class NotifyWorkflow < Gush::Workflow
|
331
|
+
def configure(user_ids)
|
332
|
+
notification_jobs = user_ids.map do |user_id|
|
333
|
+
run NotificationJob, params: {user_id: user_id}, queue: 'user'
|
334
|
+
end
|
335
|
+
|
336
|
+
run AdminNotificationJob, after: notification_jobs, queue: 'admin'
|
337
|
+
end
|
338
|
+
end
|
339
|
+
```
|
340
|
+
|
326
341
|
## Command line interface (CLI)
|
327
342
|
|
328
343
|
### Checking status
|
@@ -348,9 +363,23 @@ This requires that you have imagemagick installed on your computer:
|
|
348
363
|
bundle exec gush viz <NameOfTheWorkflow>
|
349
364
|
```
|
350
365
|
|
366
|
+
### Customizing locking options
|
367
|
+
|
368
|
+
In order to prevent getting the RedisMutex::LockError error when having a large number of jobs, you can customize these 2 fields `locking_duration` and `polling_interval` as below
|
369
|
+
|
370
|
+
```ruby
|
371
|
+
# config/initializers/gush.rb
|
372
|
+
Gush.configure do |config|
|
373
|
+
config.redis_url = "redis://localhost:6379"
|
374
|
+
config.concurrency = 5
|
375
|
+
config.locking_duration = 2 # how long you want to wait for the lock to be released, in seconds
|
376
|
+
config.polling_interval = 0.3 # how long the polling interval should be, in seconds
|
377
|
+
end
|
378
|
+
```
|
379
|
+
|
351
380
|
### Cleaning up afterwards
|
352
381
|
|
353
|
-
Running `NotifyWorkflow.create` inserts multiple keys into Redis every time it is ran. This data might be useful for analysis but at a certain point it can be purged via Redis TTL. By default gush and Redis will keep keys forever. To configure expiration you need to 2 things. Create initializer (specify config.ttl in seconds, be different per environment).
|
382
|
+
Running `NotifyWorkflow.create` inserts multiple keys into Redis every time it is ran. This data might be useful for analysis but at a certain point it can be purged via Redis TTL. By default gush and Redis will keep keys forever. To configure expiration you need to 2 things. Create initializer (specify config.ttl in seconds, be different per environment).
|
354
383
|
|
355
384
|
```ruby
|
356
385
|
# config/initializers/gush.rb
|
@@ -361,7 +390,7 @@ Gush.configure do |config|
|
|
361
390
|
end
|
362
391
|
```
|
363
392
|
|
364
|
-
And you need to call `flow.expire!` (optionally passing custom TTL value overriding `config.ttl`). This gives you control whether to expire data for specific workflow. Best NOT to set TTL to be too short (like minutes) but about a week in length. And you can run `Client.expire_workflow` and `Client.expire_job` passing appropriate IDs and TTL (pass -1 to NOT expire) values.
|
393
|
+
And you need to call `flow.expire!` (optionally passing custom TTL value overriding `config.ttl`). This gives you control whether to expire data for specific workflow. Best NOT to set TTL to be too short (like minutes) but about a week in length. And you can run `Client.expire_workflow` and `Client.expire_job` passing appropriate IDs and TTL (pass -1 to NOT expire) values.
|
365
394
|
|
366
395
|
### Avoid overlapping workflows
|
367
396
|
|
data/bin/gush
CHANGED
@@ -12,7 +12,7 @@ require 'gush'
|
|
12
12
|
begin
|
13
13
|
Gush::CLI.start(ARGV)
|
14
14
|
rescue Gush::WorkflowNotFound
|
15
|
-
puts "Workflow not found"
|
15
|
+
puts Paint["Workflow not found", :red]
|
16
16
|
rescue Gush::DependencyLevelTooDeep
|
17
|
-
puts "Dependency level too deep. Perhaps you have a dependency cycle?"
|
17
|
+
puts Paint["Dependency level too deep. Perhaps you have a dependency cycle?", :red]
|
18
18
|
end
|
data/gush.gemspec
CHANGED
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
|
5
5
|
Gem::Specification.new do |spec|
|
6
6
|
spec.name = "gush"
|
7
|
-
spec.version = "2.0
|
7
|
+
spec.version = "2.1.0"
|
8
8
|
spec.authors = ["Piotrek Okoński"]
|
9
9
|
spec.email = ["piotrek@okonski.org"]
|
10
10
|
spec.summary = "Fast and distributed workflow runner based on ActiveJob and Redis"
|
@@ -17,20 +17,19 @@ Gem::Specification.new do |spec|
|
|
17
17
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
18
|
spec.require_paths = ["lib"]
|
19
19
|
|
20
|
-
spec.add_dependency "activejob", ">= 4.2.7", "<
|
21
|
-
spec.add_dependency "
|
20
|
+
spec.add_dependency "activejob", ">= 4.2.7", "< 7.1"
|
21
|
+
spec.add_dependency "concurrent-ruby", "~> 1.0"
|
22
22
|
spec.add_dependency "multi_json", "~> 1.11"
|
23
23
|
spec.add_dependency "redis", ">= 3.2", "< 5"
|
24
24
|
spec.add_dependency "redis-mutex", "~> 4.0.1"
|
25
25
|
spec.add_dependency "hiredis", "~> 0.6"
|
26
|
-
spec.add_dependency "
|
27
|
-
spec.add_dependency "terminal-table", "
|
28
|
-
spec.add_dependency "
|
29
|
-
spec.add_dependency "thor", "
|
26
|
+
spec.add_dependency "graphviz", "~> 1.2"
|
27
|
+
spec.add_dependency "terminal-table", ">= 1.4", "< 3.1"
|
28
|
+
spec.add_dependency "paint", "~> 2.2"
|
29
|
+
spec.add_dependency "thor", ">= 0.19", "< 1.3"
|
30
30
|
spec.add_dependency "launchy", "~> 2.4"
|
31
|
-
spec.add_development_dependency "bundler"
|
31
|
+
spec.add_development_dependency "bundler"
|
32
32
|
spec.add_development_dependency "rake", "~> 10.4"
|
33
33
|
spec.add_development_dependency "rspec", '~> 3.0'
|
34
34
|
spec.add_development_dependency "pry", '~> 0.10'
|
35
|
-
spec.add_development_dependency 'fakeredis', '~> 0.5'
|
36
35
|
end
|
data/lib/gush/cli/overview.rb
CHANGED
@@ -17,11 +17,11 @@ module Gush
|
|
17
17
|
elsif workflow.running?
|
18
18
|
running_status
|
19
19
|
elsif workflow.finished?
|
20
|
-
"done"
|
20
|
+
Paint["done", :green]
|
21
21
|
elsif workflow.stopped?
|
22
|
-
"stopped"
|
22
|
+
Paint["stopped", :red]
|
23
23
|
else
|
24
|
-
"ready to start"
|
24
|
+
Paint["ready to start", :blue]
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
@@ -48,10 +48,10 @@ module Gush
|
|
48
48
|
"ID" => workflow.id,
|
49
49
|
"Name" => workflow.class.to_s,
|
50
50
|
"Jobs" => workflow.jobs.count,
|
51
|
-
"Failed jobs" => failed_jobs_count
|
52
|
-
"Succeeded jobs" => succeeded_jobs_count
|
53
|
-
"Enqueued jobs" => enqueued_jobs_count
|
54
|
-
"Running jobs" => running_jobs_count
|
51
|
+
"Failed jobs" => Paint[failed_jobs_count, :red],
|
52
|
+
"Succeeded jobs" => Paint[succeeded_jobs_count, :green],
|
53
|
+
"Enqueued jobs" => Paint[enqueued_jobs_count, :yellow],
|
54
|
+
"Running jobs" => Paint[running_jobs_count, :blue],
|
55
55
|
"Remaining jobs" => remaining_jobs_count,
|
56
56
|
"Started at" => started_at,
|
57
57
|
"Status" => status
|
@@ -60,7 +60,7 @@ module Gush
|
|
60
60
|
|
61
61
|
def running_status
|
62
62
|
finished = succeeded_jobs_count.to_i
|
63
|
-
status = "running"
|
63
|
+
status = Paint["running", :yellow]
|
64
64
|
status += "\n#{finished}/#{total_jobs_count} [#{(finished*100)/total_jobs_count}%]"
|
65
65
|
end
|
66
66
|
|
@@ -69,7 +69,7 @@ module Gush
|
|
69
69
|
end
|
70
70
|
|
71
71
|
def failed_status
|
72
|
-
status = "failed"
|
72
|
+
status = Paint["failed", :red]
|
73
73
|
status += "\n#{failed_job} failed"
|
74
74
|
end
|
75
75
|
|
@@ -77,13 +77,13 @@ module Gush
|
|
77
77
|
name = job.name
|
78
78
|
case
|
79
79
|
when job.failed?
|
80
|
-
"[✗] #{name
|
80
|
+
"[✗] #{Paint[name, :red]} \n"
|
81
81
|
when job.finished?
|
82
|
-
"[✓] #{name
|
82
|
+
"[✓] #{Paint[name, :green]} \n"
|
83
83
|
when job.enqueued?
|
84
|
-
"[•] #{name
|
84
|
+
"[•] #{Paint[name, :yellow]} \n"
|
85
85
|
when job.running?
|
86
|
-
"[•] #{name
|
86
|
+
"[•] #{Paint[name, :blue]} \n"
|
87
87
|
else
|
88
88
|
"[ ] #{name} \n"
|
89
89
|
end
|
data/lib/gush/cli.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'terminal-table'
|
2
|
-
require '
|
4
|
+
require 'paint'
|
3
5
|
require 'thor'
|
4
6
|
require 'launchy'
|
5
7
|
|
@@ -12,43 +14,45 @@ module Gush
|
|
12
14
|
def initialize(*)
|
13
15
|
super
|
14
16
|
Gush.configure do |config|
|
15
|
-
config.gushfile
|
16
|
-
config.concurrency
|
17
|
-
config.redis_url
|
18
|
-
config.namespace
|
19
|
-
config.ttl
|
17
|
+
config.gushfile = options.fetch("gushfile", config.gushfile)
|
18
|
+
config.concurrency = options.fetch("concurrency", config.concurrency)
|
19
|
+
config.redis_url = options.fetch("redis", config.redis_url)
|
20
|
+
config.namespace = options.fetch("namespace", config.namespace)
|
21
|
+
config.ttl = options.fetch("ttl", config.ttl)
|
22
|
+
config.locking_duration = options.fetch("locking_duration", config.locking_duration)
|
23
|
+
config.polling_interval = options.fetch("polling_interval", config.polling_interval)
|
20
24
|
end
|
21
25
|
load_gushfile
|
22
26
|
end
|
23
27
|
|
24
|
-
desc "create
|
28
|
+
desc "create WORKFLOW_CLASS", "Registers new workflow"
|
25
29
|
def create(name)
|
26
30
|
workflow = client.create_workflow(name)
|
27
31
|
puts "Workflow created with id: #{workflow.id}"
|
28
32
|
puts "Start it with command: gush start #{workflow.id}"
|
29
33
|
end
|
30
34
|
|
31
|
-
desc "start [
|
35
|
+
desc "start WORKFLOW_ID [ARG ...]", "Starts Workflow with given ID"
|
32
36
|
def start(*args)
|
33
37
|
id = args.shift
|
34
38
|
workflow = client.find_workflow(id)
|
35
39
|
client.start_workflow(workflow, args)
|
36
40
|
end
|
37
41
|
|
38
|
-
desc "create_and_start [
|
42
|
+
desc "create_and_start WORKFLOW_CLASS [ARG ...]", "Create and instantly start the new workflow"
|
39
43
|
def create_and_start(name, *args)
|
40
44
|
workflow = client.create_workflow(name)
|
41
45
|
client.start_workflow(workflow.id, args)
|
42
46
|
puts "Created and started workflow with id: #{workflow.id}"
|
43
47
|
end
|
44
48
|
|
45
|
-
desc "stop
|
49
|
+
desc "stop WORKFLOW_ID", "Stops Workflow with given ID"
|
46
50
|
def stop(*args)
|
47
51
|
id = args.shift
|
48
52
|
client.stop_workflow(id)
|
49
53
|
end
|
50
54
|
|
51
|
-
desc "show
|
55
|
+
desc "show WORKFLOW_ID", "Shows details about workflow with given ID"
|
52
56
|
option :skip_overview, type: :boolean
|
53
57
|
option :skip_jobs, type: :boolean
|
54
58
|
option :jobs, default: :all
|
@@ -60,7 +64,7 @@ module Gush
|
|
60
64
|
display_jobs_list_for(workflow, options[:jobs]) unless options[:skip_jobs]
|
61
65
|
end
|
62
66
|
|
63
|
-
desc "rm
|
67
|
+
desc "rm WORKFLOW_ID", "Delete workflow with given ID"
|
64
68
|
def rm(workflow_id)
|
65
69
|
workflow = client.find_workflow(workflow_id)
|
66
70
|
client.destroy_workflow(workflow)
|
@@ -81,13 +85,39 @@ module Gush
|
|
81
85
|
puts Terminal::Table.new(headings: headers, rows: rows)
|
82
86
|
end
|
83
87
|
|
84
|
-
desc "viz
|
85
|
-
|
88
|
+
desc "viz {WORKFLOW_CLASS|WORKFLOW_ID}", "Displays graph, visualising job dependencies"
|
89
|
+
option :filename, type: :string, default: nil
|
90
|
+
option :open, type: :boolean, default: nil
|
91
|
+
def viz(class_or_id)
|
86
92
|
client
|
87
|
-
|
88
|
-
|
93
|
+
|
94
|
+
begin
|
95
|
+
workflow = client.find_workflow(class_or_id)
|
96
|
+
rescue WorkflowNotFound
|
97
|
+
workflow = nil
|
98
|
+
end
|
99
|
+
|
100
|
+
unless workflow
|
101
|
+
begin
|
102
|
+
workflow = class_or_id.constantize.new
|
103
|
+
rescue NameError => e
|
104
|
+
STDERR.puts Paint["'#{class_or_id}' is not a valid workflow class or id", :red]
|
105
|
+
exit 1
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
opts = {}
|
110
|
+
|
111
|
+
if options[:filename]
|
112
|
+
opts[:filename], opts[:path] = File.split(options[:filename])
|
113
|
+
end
|
114
|
+
|
115
|
+
graph = Graph.new(workflow, **opts)
|
89
116
|
graph.viz
|
90
|
-
|
117
|
+
|
118
|
+
if (options[:open].nil? && !options[:filename]) || options[:open]
|
119
|
+
Launchy.open Pathname.new(graph.path).realpath.to_s
|
120
|
+
end
|
91
121
|
end
|
92
122
|
|
93
123
|
private
|
@@ -118,13 +148,14 @@ module Gush
|
|
118
148
|
|
119
149
|
def load_gushfile
|
120
150
|
file = client.configuration.gushfile
|
121
|
-
|
122
|
-
|
151
|
+
|
152
|
+
unless gushfile.exist?
|
153
|
+
raise Thor::Error, Paint["#{file} not found, please add it to your project", :red]
|
123
154
|
end
|
124
155
|
|
125
156
|
load file.to_s
|
126
157
|
rescue LoadError
|
127
|
-
raise Thor::Error, "failed to require #{file}"
|
158
|
+
raise Thor::Error, Paint["failed to require #{file}", :red]
|
128
159
|
end
|
129
160
|
end
|
130
161
|
end
|