dor-workflow-client 3.19.0 → 3.23.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1fdb8fc01a2ed982c1fd0e0d2e0aaaf58e9ac4dd89171c879c491fccaf02a83d
4
- data.tar.gz: 50503e224f5c8c0e23cd9111de9c889b0f2773697a9acc1eb5985d8bca916111
3
+ metadata.gz: 7b6a0ed1dac951da79aabe808df201cd4064ef5e1699d803673e1675d4b9dc0f
4
+ data.tar.gz: 8ada5b31dda45a87efaad45a420a300fd907d376cbe85f52b93a099eb5859d27
5
5
  SHA512:
6
- metadata.gz: ed1e22bad5aebd865bff1c03ab340b37a73eb7b4d6671436ad4fa2b5375c68667deb26fdd630800dad6d1392a4f27877c9c32611e54495947488f0d7ad0ab0de
7
- data.tar.gz: 604a0981194c0d857b93ddc7925a3c4036eb560141e1ba61226367e8324ee26206cd92f2abe61ce6710ac89493c1ce563d001e64bc206605aad6af25544ad652
6
+ metadata.gz: 47ad0a88123584d64c7324adc24d19c597475edb884510faca16ee4b2abb8c2f18ef6f1a70ca74008de4e9ce4b6aa2af6fe52f94e92febd72667c2d02ed25838
7
+ data.tar.gz: 4d19c76451e137c4a8c7a4cbc443115324f65b722ee747168b75d2898c278abfec3ee3ece4d7e0e81cafd154bea5cff5ec945d5b09061d1f7105ed791f0a960e
@@ -0,0 +1,35 @@
1
+ version: 2.1
2
+
3
+ jobs:
4
+ build:
5
+ docker:
6
+ - image: circleci/ruby:2.7.1
7
+ environment:
8
+ CC_TEST_REPORTER_ID: 3853bc688a88a4de1a5568eaa8163d20db8637fe988540a935aff028190cff6a
9
+ RAILS_ENV: test
10
+ steps:
11
+ - checkout
12
+ - run:
13
+ name: Install Bundler
14
+ command: gem install bundler
15
+ - run:
16
+ name: Which bundler?
17
+ command: bundle -v
18
+ - run:
19
+ name: Bundle Install
20
+ command: bundle check || bundle install
21
+ - run:
22
+ name: Lint using rubocop
23
+ command: bundle exec rubocop
24
+ - run:
25
+ name: Setup Code Climate test-reporter
26
+ command: |
27
+ curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
28
+ chmod +x ./cc-test-reporter
29
+ ./cc-test-reporter before-build
30
+ - run:
31
+ name: rspec
32
+ command: bundle exec rspec
33
+ - run:
34
+ name: upload test coverage report to Code Climate
35
+ command: ./cc-test-reporter after-build --coverage-input-type simplecov --exit-code $?
@@ -0,0 +1,12 @@
1
+ ## Why was this change made?
2
+
3
+
4
+
5
+ ## How was this change tested?
6
+
7
+
8
+
9
+ ## Which documentation and/or configurations were updated?
10
+
11
+
12
+
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- [![Build Status](https://travis-ci.org/sul-dlss/dor-workflow-client.svg?branch=master)](https://travis-ci.org/sul-dlss/dor-workflow-client)
1
+ [![CircleCI](https://circleci.com/gh/sul-dlss/dor-workflow-client.svg?style=svg)](https://circleci.com/gh/sul-dlss/dor-workflow-client)
2
2
  [![Test Coverage](https://api.codeclimate.com/v1/badges/fba77ff479c468f8510f/test_coverage)](https://codeclimate.com/github/sul-dlss/dor-services-client/test_coverage)
3
3
  [![Maintainability](https://api.codeclimate.com/v1/badges/fba77ff479c468f8510f/maintainability)](https://codeclimate.com/github/sul-dlss/dor-services-client/maintainability)
4
4
  [![Gem Version](https://badge.fury.io/rb/dor-workflow-client.svg)](https://badge.fury.io/rb/dor-workflow-client)
@@ -37,7 +37,7 @@ client.update_status(druid: 'druid:bc123df4567',
37
37
 
38
38
  Show "milestones" for an object
39
39
  ```ruby
40
- client.milestones('dor', 'druid:gv054hp4128')
40
+ client.milestones(druid: 'druid:gv054hp4128')
41
41
  #=> [{version: '1', milestone: 'published'}]
42
42
  ```
43
43
 
@@ -1,4 +1,4 @@
1
- # frozen_string_literal: true
1
+ # frozen_string_literal: true
2
2
 
3
3
  lib = File.expand_path('lib', __dir__)
4
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
@@ -27,7 +27,7 @@ Gem::Specification.new do |gem|
27
27
  gem.add_development_dependency 'rake'
28
28
  gem.add_development_dependency 'rspec', '~> 3.3'
29
29
  gem.add_development_dependency 'rubocop', '~> 0.63.1'
30
- gem.add_development_dependency 'simplecov'
30
+ gem.add_development_dependency 'simplecov', '~> 0.17.0' # CodeClimate cannot use SimpleCov >= 0.18.0 for generating test coverage
31
31
  gem.add_development_dependency 'webmock'
32
32
  gem.add_development_dependency 'yard'
33
33
  end
@@ -82,7 +82,7 @@ module Dor
82
82
  end
83
83
 
84
84
  def status(druid:, version:)
85
- @status ||= Status.new(druid: druid, version: version, lifecycle_routes: lifecycle_routes)
85
+ Status.new(druid: druid, version: version, lifecycle_routes: lifecycle_routes)
86
86
  end
87
87
 
88
88
  private
@@ -10,37 +10,102 @@ module Dor
10
10
  end
11
11
 
12
12
  # Returns the Date for a requested milestone from workflow lifecycle
13
- # @param [String] repo repository name
13
+ #
14
+ # @param [String] repo The repository the object resides in. This parameter is deprecated
14
15
  # @param [String] druid object id
15
16
  # @param [String] milestone_name the name of the milestone being queried for
16
17
  # @param [Number] version the version to query for
17
18
  # @param [Boolean] active_only (false) if true, return only lifecycle steps for versions that have all processes complete
18
19
  # @return [Time] when the milestone was achieved. Returns nil if the milestone does not exist
19
20
  #
20
- def lifecycle(repo, druid, milestone_name, version: nil, active_only: false)
21
- filter_milestone(query_lifecycle(repo, druid, version: version, active_only: active_only), milestone_name)
21
+ # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
22
+ def lifecycle(*args)
23
+ case args.size
24
+ when 4
25
+ Deprecation.warn(self, 'you provided 4 args, but lifecycle now takes kwargs')
26
+ (repo, druid, milestone_name) = args[0..2]
27
+ version = args[3][:version]
28
+ active_only = args[3][:active_only] || false
29
+ when 3
30
+ Deprecation.warn(self, 'you provided 3 args, but lifecycle now takes kwargs')
31
+ (repo, druid, milestone_name) = args
32
+ version = nil
33
+ active_only = false
34
+ when 1
35
+ opts = args.first
36
+ repo = opts[:repo]
37
+ druid = opts[:druid]
38
+ milestone_name = opts[:milestone_name]
39
+ version = opts[:version]
40
+ active_only = opts[:active_only] || false
41
+ else
42
+ raise ArgumentError, 'wrong number of arguments, must be 1, or 3-5'
43
+ end
44
+
45
+ Deprecation.warn(self, 'passing the repo parameter to lifecycle is no longer necessary. This will raise an error in dor-workflow-client version 4') if repo
46
+
47
+ filter_milestone(query_lifecycle(druid, version: version, active_only: active_only), milestone_name)
22
48
  end
49
+ # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
23
50
 
24
51
  # Returns the Date for a requested milestone ONLY for the current version.
25
52
  # This is slow as the workflow server will query dor-services-app for the version.
26
53
  # A better approach is #lifecycle with the version tag.
27
- # @param [String] repo repository name
28
54
  # @param [String] druid object id
29
55
  # @param [String] milestone_name the name of the milestone being queried for
30
56
  # @param [Number] version the version to query for
31
57
  # @return [Time] when the milestone was achieved. Returns nil if the milestone does not exis
32
58
  #
33
- def active_lifecycle(repo, druid, milestone_name, version: nil)
34
- lifecycle(repo, druid, milestone_name, version: version, active_only: true)
59
+ # rubocop:disable Metrics/MethodLength
60
+ def active_lifecycle(*args)
61
+ case args.size
62
+ when 4
63
+ Deprecation.warn(self, 'you provided 4 args, but active_lifecycle now takes kwargs')
64
+ (repo, druid, milestone_name) = args[0..2]
65
+ version = args[3][:version]
66
+ when 3
67
+ Deprecation.warn(self, 'you provided 3 args, but active_lifecycle now takes kwargs')
68
+ (repo, druid, milestone_name) = args
69
+ version = nil
70
+ when 1
71
+ opts = args.first
72
+ repo = opts[:repo]
73
+ druid = opts[:druid]
74
+ milestone_name = opts[:milestone_name]
75
+ version = opts[:version]
76
+ else
77
+ raise ArgumentError, 'wrong number of arguments, must be 1, 3, or 4'
78
+ end
79
+
80
+ Deprecation.warn(self, 'passing the repo parameter to active_lifecycle is no longer necessary. This will raise an error in dor-workflow-client version 4') if repo
81
+
82
+ lifecycle(druid: druid, milestone_name: milestone_name, version: version, active_only: true)
35
83
  end
84
+ # rubocop:enable Metrics/MethodLength
85
+
86
+ # @return [Array<Hash>]
87
+ # rubocop:disable Metrics/MethodLength
88
+ def milestones(*args)
89
+ case args.size
90
+ when 2
91
+ Deprecation.warn(self, 'you provided 2 args, but active_lifecycle now takes kwargs')
92
+ (repo, druid) = args
93
+ when 1
94
+ opts = args.first
95
+ repo = opts[:repo]
96
+ druid = opts.fetch(:druid)
97
+ else
98
+ raise ArgumentError, 'wrong number of arguments, must be 1-2'
99
+ end
100
+
101
+ Deprecation.warn(self, 'passing the repo parameter to active_lifecycle is no longer necessary. This will raise an error in dor-workflow-client version 4') if repo
36
102
 
37
- # @return [Hash]
38
- def milestones(repo, druid)
39
- doc = query_lifecycle(repo, druid, active_only: false)
103
+ doc = query_lifecycle(druid, active_only: false)
40
104
  doc.xpath('//lifecycle/milestone').collect do |node|
41
105
  { milestone: node.text, at: Time.parse(node['date']), version: node['version'] }
42
106
  end
43
107
  end
108
+ # rubocop:enable Metrics/MethodLength
44
109
 
45
110
  private
46
111
 
@@ -51,7 +116,6 @@ module Dor
51
116
  Time.parse(milestone['date'])
52
117
  end
53
118
 
54
- # @param [String] repo repository name
55
119
  # @param [String] druid object id
56
120
  # @param [Boolean] active_only (false) if true, return only lifecycle steps for versions that have all processes complete
57
121
  # @param [Number] version the version to query for
@@ -63,8 +127,8 @@ module Dor
63
127
  # <milestone date="2010-06-15T16:08:58-0700">released</milestone>
64
128
  # </lifecycle>
65
129
  #
66
- def query_lifecycle(repo, druid, active_only:, version: nil)
67
- req = "#{repo}/objects/#{druid}/lifecycle"
130
+ def query_lifecycle(druid, active_only:, version: nil)
131
+ req = "objects/#{druid}/lifecycle"
68
132
  params = []
69
133
  params << "version=#{version}" if version
70
134
  params << 'active-only=true' if active_only
@@ -11,39 +11,59 @@ module Dor
11
11
 
12
12
  # Returns all the distinct laneIds for a given workflow step
13
13
  #
14
- # @param [String] repo The repository the object resides in. The service recoginzes "dor" and "sdr" at the moment
14
+ # @param [String] repo -- deprecated, ignored by workflow service
15
15
  # @param [String] workflow name
16
16
  # @param [String] process name
17
17
  # @return [Array<String>] all of the distinct laneIds. Array will be empty if no lane ids were found
18
- def lane_ids(repo, workflow, process)
19
- uri = "workflow_queue/lane_ids?step=#{repo}:#{workflow}:#{process}"
18
+ def lane_ids(*args)
19
+ if args.count == 3
20
+ Deprecation.warn(
21
+ self,
22
+ '`#lane_ids` only takes two args: workflow name, & process/step name. This will raise an exception in Dor::Workflow::Client 4.0.0'
23
+ )
24
+ args.shift # ditch the `repo` argument
25
+ end
26
+ uri = "workflow_queue/lane_ids?step=#{args.first}:#{args.second}"
20
27
  doc = Nokogiri::XML(requestor.request(uri))
21
- nodes = doc.xpath('/lanes/lane')
22
- nodes.map { |n| n['id'] }
28
+ doc.xpath('/lanes/lane').map { |n| n['id'] }
23
29
  end
24
30
 
25
31
  # Gets all of the workflow steps that have a status of 'queued' that have a last-updated timestamp older than the number of hours passed in
26
32
  # This will enable re-queueing of jobs that have been lost by the job manager
27
- # @param [String] repository name of the repository you want to query, like 'dor' or 'sdr'
33
+ # @param [String] repository -- deprecated, ignored by workflow service
28
34
  # @param [Hash] opts optional values for query
29
35
  # @option opts [Integer] :hours_ago steps older than this value will be returned by the query. If not passed in, the service defaults to 0 hours,
30
36
  # meaning you will get all queued workflows
31
37
  # @option opts [Integer] :limit sets the maximum number of workflow steps that can be returned. Defaults to no limit
32
38
  # @return [Array[Hash]] each Hash represents a workflow step. It will have the following keys:
33
39
  # :workflow, :step, :druid, :lane_id
34
- def stale_queued_workflows(repository, opts = {})
35
- uri_string = build_queued_uri(repository, opts)
40
+ def stale_queued_workflows(*args)
41
+ if args.count == 2
42
+ Deprecation.warn(
43
+ self,
44
+ '`#stale_queued_workflows` only takes one arg: a hash. This will raise an exception in Dor::Workflow::Client 4.0.0'
45
+ )
46
+ args.shift # ditch the `repo` argument
47
+ end
48
+ uri_string = build_queued_uri(args.first)
36
49
  parse_queued_workflows_response requestor.request(uri_string)
37
50
  end
38
51
 
39
52
  # Returns a count of workflow steps that have a status of 'queued' that have a last-updated timestamp older than the number of hours passed in
40
- # @param [String] repository name of the repository you want to query, like 'dor' or 'sdr'
53
+ # @param [String] repository -- deprecated, ignored by workflow service
41
54
  # @param [Hash] opts optional values for query
42
55
  # @option opts [Integer] :hours_ago steps older than this value will be returned by the query. If not passed in, the service defaults to 0 hours,
43
56
  # meaning you will get all queued workflows
44
57
  # @return [Integer] number of stale, queued steps if the :count_only option was set to true
45
- def count_stale_queued_workflows(repository, opts = {})
46
- uri_string = build_queued_uri(repository, opts) + '&count-only=true'
58
+ def count_stale_queued_workflows(*args)
59
+ if args.count == 2
60
+ Deprecation.warn(
61
+ self,
62
+ '`#count_stale_queued_workflows` only takes one arg: a hash. This will raise an exception in Dor::Workflow::Client 4.0.0'
63
+ )
64
+ args.shift # ditch the `repo` argument
65
+ end
66
+ uri_string = build_queued_uri(args.first) + '&count-only=true'
47
67
  doc = Nokogiri::XML(requestor.request(uri_string))
48
68
  doc.at_xpath('/objects/@count').value.to_i
49
69
  end
@@ -51,13 +71,11 @@ module Dor
51
71
  # Returns a list of druids from the workflow service that meet the criteria
52
72
  # of the passed in completed and waiting params
53
73
  #
54
- # @param [Array<String>, String] completed An array or single String of the completed steps, should use the qualified format: `repository:workflow:step-name`
74
+ # @param [Array<String>, String] completed An array or single String of the completed steps, should use the qualified format: `workflow:step-name`
55
75
  # @param [String] waiting name of the waiting step
56
- # @param [String] repository default repository to use if it isn't passed in the qualified-step-name
57
76
  # @param [String] workflow default workflow to use if it isn't passed in the qualified-step-name
58
77
  # @param [String] lane_id issue a query for a specific lane_id for the waiting step
59
78
  # @param [Hash] options
60
- # @param options [String] :default_repository repository to query for if not using the qualified format
61
79
  # @param options [String] :default_workflow workflow to query for if not using the qualified format
62
80
  # @option options [Integer] :limit maximum number of druids to return (nil for no limit)
63
81
  # @return [Array<String>] Array of druids
@@ -84,11 +102,12 @@ module Dor
84
102
  # }
85
103
  #
86
104
  def objects_for_workstep(completed, waiting, lane_id = 'default', options = {})
87
- waiting_param = qualify_step(options[:default_repository], options[:default_workflow], waiting)
105
+ Deprecation.warn(self, 'the `:default_repository` option in `#objects_for_workstep` is unused and will go away in Dor::Workflow::Client 4.0.0. omit argument to silence.') if options[:default_repository]
106
+ waiting_param = qualify_step(options[:default_workflow], waiting)
88
107
  uri_string = "workflow_queue?waiting=#{waiting_param}"
89
108
  if completed
90
109
  Array(completed).each do |step|
91
- completed_param = qualify_step(options[:default_repository], options[:default_workflow], step)
110
+ completed_param = qualify_step(options[:default_workflow], step)
92
111
  uri_string += "&completed=#{completed_param}"
93
112
  end
94
113
  end
@@ -107,33 +126,39 @@ module Dor
107
126
  # convert into:
108
127
  # ['druid:ab123de4567', 'druid:ab123de9012']
109
128
  #
110
- result = Nokogiri::XML(resp).xpath('//object[@id]')
111
- result.map { |n| n[:id] }
129
+ Nokogiri::XML(resp).xpath('//object[@id]').map { |n| n[:id] }
112
130
  end
113
131
 
114
132
  # Get a list of druids that have errored out in a particular workflow and step
115
133
  #
116
134
  # @param [String] workflow name
117
135
  # @param [String] step name
118
- # @param [String] repository -- optional, default=dor
136
+ # @param [String] repository -- deprecated, ignored by workflow service
119
137
  #
120
138
  # @return [Hash] hash of results, with key has a druid, and value as the error message
121
139
  # @example
122
140
  # client.errored_objects_for_workstep('accessionWF','content-metadata')
123
141
  # => {"druid:qd556jq0580"=>"druid:qd556jq0580 - Item error; caused by
124
142
  # #<Rubydora::FedoraInvalidRequest: Error modifying datastream contentMetadata for druid:qd556jq0580. See logger for details>"}
125
- def errored_objects_for_workstep(workflow, step, repository = 'dor')
126
- resp = requestor.request "workflow_queue?repository=#{repository}&workflow=#{workflow}&error=#{step}"
127
- result = {}
128
- Nokogiri::XML(resp).xpath('//object').collect do |node|
129
- result.merge!(node['id'] => node['errorMessage'])
130
- end
131
- result
143
+ def errored_objects_for_workstep(workflow, step, repository = nil)
144
+ Deprecation.warn(self, 'the third argument to `#errored_objects_for_workstep` is unused and will go away in Dor::Workflow::Client 4.0.0. omit argument to silence.') unless repository.nil?
145
+ resp = requestor.request "workflow_queue?workflow=#{workflow}&error=#{step}"
146
+ Nokogiri::XML(resp).xpath('//object').map do |node|
147
+ [node['id'], node['errorMessage']]
148
+ end.to_h
132
149
  end
133
150
 
134
151
  # Used by preservation robots stats reporter
135
- def count_objects_in_step(workflow, step, type, repo)
136
- resp = requestor.request "workflow_queue?repository=#{repo}&workflow=#{workflow}&#{type}=#{step}"
152
+ #
153
+ # @param [String] workflow name
154
+ # @param [String] step name
155
+ # @param [String] type
156
+ # @param [String] repo -- deprecated, ignored by workflow service
157
+ #
158
+ # @return [Hash] hash of results, with key has a druid, and value as the error message
159
+ def count_objects_in_step(workflow, step, type, repo = nil)
160
+ Deprecation.warn(self, 'the fourth argument to `#count_objects_in_step` is unused and will go away in Dor::Workflow::Client 4.0.0. omit argument to silence.') unless repo.nil?
161
+ resp = requestor.request "workflow_queue?workflow=#{workflow}&#{type}=#{step}"
137
162
  extract_object_count(resp)
138
163
  end
139
164
 
@@ -141,52 +166,50 @@ module Dor
141
166
  #
142
167
  # @param [String] workflow name
143
168
  # @param [String] step name
144
- # @param [String] repository -- optional, default=dor
169
+ # @param [String] repository -- deprecated, ignored by workflow service
145
170
  #
146
171
  # @return [Integer] Number of objects with this repository:workflow:step that have a status of 'error'
147
- def count_errored_for_workstep(workflow, step, repository = 'dor')
148
- count_objects_in_step(workflow, step, 'error', repository)
172
+ def count_errored_for_workstep(workflow, step, repository = nil)
173
+ Deprecation.warn(self, 'the third argument to `#count_errored_for_workstep` is unused and will go away in Dor::Workflow::Client 4.0.0. omit argument to silence.') unless repository.nil?
174
+ count_objects_in_step(workflow, step, 'error')
149
175
  end
150
176
 
151
177
  # Returns the number of objects that have a status of 'queued' in a particular workflow and step
152
178
  #
153
179
  # @param [String] workflow name
154
180
  # @param [String] step name
155
- # @param [String] repository -- optional, default=dor
181
+ # @param [String] repository -- deprecated, ignored by workflow service
156
182
  #
157
183
  # @return [Integer] Number of objects with this repository:workflow:step that have a status of 'queued'
158
- def count_queued_for_workstep(workflow, step, repository = 'dor')
159
- count_objects_in_step(workflow, step, 'queued', repository)
184
+ def count_queued_for_workstep(workflow, step, repository = nil)
185
+ Deprecation.warn(self, 'the third argument to `#count_queued_for_workstep` is unused and will go away in Dor::Workflow::Client 4.0.0. omit argument to silence.') unless repository.nil?
186
+ count_objects_in_step(workflow, step, 'queued')
160
187
  end
161
188
 
162
189
  private
163
190
 
164
191
  attr_reader :requestor
165
192
 
166
- def build_queued_uri(repository, opts = {})
167
- uri_string = "workflow_queue/all_queued?repository=#{repository}"
168
- uri_string += "&hours-ago=#{opts[:hours_ago]}" if opts[:hours_ago]
169
- uri_string += "&limit=#{opts[:limit]}" if opts[:limit]
170
- uri_string
193
+ def build_queued_uri(opts = {})
194
+ query_hash = opts.slice(:hours_ago, :limit).transform_keys { |key| key.to_s.tr('_', '-') }
195
+ query_string = URI.encode_www_form(query_hash)
196
+ "workflow_queue/all_queued?#{query_string}"
171
197
  end
172
198
 
173
- # Converts repo-workflow-step into repo:workflow:step
174
- # @param [String] default_repository
199
+ # Converts workflow-step into workflow:step
175
200
  # @param [String] default_workflow
176
201
  # @param [String] step if contains colon :, then the value for workflow and/or workflow/repository. For example: 'jp2-create', 'assemblyWF:jp2-create' or 'dor:assemblyWF:jp2-create'
177
- # @return [String] repo:workflow:step
202
+ # @return [String] workflow:step
178
203
  # @example
179
- # dor:assemblyWF:jp2-create
180
- def qualify_step(default_repository, default_workflow, step)
181
- current = step.split(/:/, 3)
182
- current.unshift(default_workflow) if current.length < 3
183
- current.unshift(default_repository) if current.length < 3
204
+ # assemblyWF:jp2-create
205
+ def qualify_step(default_workflow, step)
206
+ current = step.split(':').last(2)
207
+ current.unshift(default_workflow) if current.length < 2
184
208
  current.join(':')
185
209
  end
186
210
 
187
211
  def parse_queued_workflows_response(xml)
188
- doc = Nokogiri::XML(xml)
189
- doc.xpath('/workflows/workflow').collect do |wf_node|
212
+ Nokogiri::XML(xml).xpath('/workflows/workflow').collect do |wf_node|
190
213
  {
191
214
  workflow: wf_node['name'],
192
215
  step: wf_node['process'],