dor-services-client 15.12.0 → 15.14.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: 0d25cb073f436c9dd92ecc738e8279216a84088e61d9452a4f7c81c9889e3138
4
- data.tar.gz: 2d7db7153e6227ac47e93952ae44600fc0d7f1187127f96521bc4cdcbcd7b7a2
3
+ metadata.gz: bd62911db328e4acec57538baa18003ff2525c02929f2f96adbd9df74ba43e30
4
+ data.tar.gz: 9591c4c8977d9a81cffbf46a300e04778a60330c0ce9d9743232cc72bcca56e8
5
5
  SHA512:
6
- metadata.gz: 59aee4af11f92713f68e2a114af9db4be1cb684fd2d06660463a57c3bf9762dccfffad527c441abfe4cf8ac6a607f010676765b1d01b2792c955216a62b23f12
7
- data.tar.gz: 903bc3b83d1c664cd9b198e0a1985ad0e9727bb8fb50502e74faa265c7dbce3dd103e3fbc35e92a4af4617437dbcd2c70abf4dc8a6ff1248606e73a5388e70e9
6
+ metadata.gz: 8fa6acadd9432a53789fd3d33ab07bafca9d1078544536c80e2bfa661490921201a781c84e1b0a1898264c62e5d5a7d19ac95316409f894b074f88de917d91ea
7
+ data.tar.gz: 359df5ae75ca8e63aa4cc5d3fd56e13ce716e3ec67d3e74c4535906f573f4419c041683b1008cd563d098d0fbcf8750b698fe497ad85d825efd9d56528a6a379
data/Gemfile.lock CHANGED
@@ -1,12 +1,13 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- dor-services-client (15.12.0)
4
+ dor-services-client (15.14.0)
5
5
  activesupport (>= 7.0.0)
6
- cocina-models (~> 0.104.0)
6
+ cocina-models (~> 0.104.1)
7
7
  deprecation
8
8
  faraday (~> 2.0)
9
9
  faraday-retry
10
+ nokogiri
10
11
  zeitwerk (~> 2.1)
11
12
 
12
13
  GEM
@@ -33,7 +34,7 @@ GEM
33
34
  benchmark (0.4.1)
34
35
  bigdecimal (3.2.2)
35
36
  byebug (12.0.0)
36
- cocina-models (0.104.0)
37
+ cocina-models (0.104.1)
37
38
  activesupport
38
39
  deprecation
39
40
  dry-struct (~> 1.0)
data/README.md CHANGED
@@ -152,6 +152,25 @@ object_client.workspace.create(source: object_path_string)
152
152
  # Reindex
153
153
  object_client.reindex
154
154
 
155
+ # List workflows
156
+ object_client.workflows
157
+ # Find workflow
158
+ object_client.workflow('accessionWF').find
159
+ # Create workflow
160
+ object_client.workflow('etdSubmitWF').create(version: 2)
161
+ # Skip all workflow steps
162
+ object_client.workflow('accessionWF').skip_all(note: 'Cleaning up')
163
+
164
+ # Update workflow processes
165
+ object_client.workflow('accessionWF').process('shelve').update(status: 'completed')
166
+ object_client.workflow('accessionWF').process('shelve').update_error(error_msg: 'Something went wrong', error_text: 'Detailed error message')
167
+
168
+
169
+ # List milestones
170
+ object_client.milestones.list
171
+ # Get the date for a milestone
172
+ object_client.milestones.date(milestone_name: 'published')
173
+
155
174
  # Search for administrative tags:
156
175
  Dor::Services::Client.administrative_tags.search(q: 'Project')
157
176
 
@@ -25,10 +25,11 @@ Gem::Specification.new do |spec|
25
25
  spec.required_ruby_version = '>= 3.0', '< 4'
26
26
 
27
27
  spec.add_dependency 'activesupport', '>= 7.0.0'
28
- spec.add_dependency 'cocina-models', '~> 0.104.0'
28
+ spec.add_dependency 'cocina-models', '~> 0.104.1'
29
29
  spec.add_dependency 'deprecation', '>= 0'
30
30
  spec.add_dependency 'faraday', '~> 2.0'
31
31
  spec.add_dependency 'faraday-retry'
32
+ spec.add_dependency 'nokogiri'
32
33
  spec.add_dependency 'zeitwerk', '~> 2.1'
33
34
 
34
35
  spec.add_development_dependency 'bundler'
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dor
4
+ module Services
5
+ class Client
6
+ # API calls around milestones
7
+ class Milestones < VersionedService
8
+ # @param object_identifier [String] the druid for the object
9
+ def initialize(connection:, version:, object_identifier:)
10
+ super(connection: connection, version: version)
11
+ @object_identifier = object_identifier
12
+ end
13
+
14
+ # Returns the Date for a requested milestone from workflow lifecycle
15
+ #
16
+ # @param [String] druid object id
17
+ # @param [String] milestone_name the name of the milestone being queried for
18
+ # @param [Number] version (nil) the version to query for
19
+ # @param [Boolean] active_only (false) if true, return only lifecycle steps for versions that have all processes complete
20
+ # @return [Time] when the milestone was achieved. Returns nil if the milestone does not exist
21
+ def date(milestone_name:, version: nil, active_only: false)
22
+ filter_milestone(query_lifecycle(version: version, active_only: active_only), milestone_name)
23
+ end
24
+
25
+ # @return [Array<Hash>]
26
+ def list
27
+ doc = query_lifecycle(active_only: false)
28
+ doc.xpath('//lifecycle/milestone').collect do |node|
29
+ { milestone: node.text, at: Time.parse(node['date']), version: node['version'] }
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ attr_reader :object_identifier
36
+
37
+ def filter_milestone(lifecycle_doc, milestone_name)
38
+ milestone = lifecycle_doc.at_xpath("//lifecycle/milestone[text() = '#{milestone_name}']")
39
+ return unless milestone
40
+
41
+ Time.parse(milestone['date'])
42
+ end
43
+
44
+ # @param [String] druid object id
45
+ # @param [Boolean] active_only (false) if true, return only lifecycle steps for versions that have all processes complete
46
+ # @param [Number] version the version to query for
47
+ # @return [Nokogiri::XML::Document]
48
+ # @example An example lifecycle xml from the workflow service.
49
+ # <lifecycle objectId="druid:ct011cv6501">
50
+ # <milestone date="2010-04-27T11:34:17-0700">registered</milestone>
51
+ # <milestone date="2010-04-29T10:12:51-0700">inprocess</milestone>
52
+ # <milestone date="2010-06-15T16:08:58-0700">released</milestone>
53
+ # </lifecycle>
54
+ #
55
+ def query_lifecycle(active_only:, version: nil)
56
+ resp = connection.get do |req|
57
+ req.url "#{api_version}/objects/#{object_identifier}/lifecycles"
58
+ req.headers['Accept'] = 'application/xml'
59
+ req.params['version'] = version if version
60
+ req.params['active-only'] = 'true' if active_only
61
+ end
62
+ raise_exception_based_on_response!(resp) unless resp.success?
63
+
64
+ Nokogiri::XML(resp.body)
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -46,6 +46,18 @@ module Dor
46
46
  @accession ||= Accession.new(**parent_params.merge(params))
47
47
  end
48
48
 
49
+ def milestones
50
+ @milestones ||= Milestones.new(**parent_params)
51
+ end
52
+
53
+ def workflows
54
+ @workflows ||= ObjectWorkflows.new(**parent_params).list
55
+ end
56
+
57
+ def workflow(workflow_name)
58
+ @workflow ||= ObjectWorkflow.new(**parent_params.merge({ workflow_name: workflow_name }))
59
+ end
60
+
49
61
  # Retrieves the Cocina model
50
62
  # @param [boolean] validate validate the response object
51
63
  # @raise [NotFoundResponse] when the response is a 404 (object not found)
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dor
4
+ module Services
5
+ class Client
6
+ # API calls around workflow for an object.
7
+ class ObjectWorkflow < VersionedService
8
+ # @param object_identifier [String] the druid for the object
9
+ # @param [String] workflow_name The name of the workflow
10
+ def initialize(connection:, version:, object_identifier:, workflow_name:)
11
+ super(connection: connection, version: version)
12
+ @object_identifier = object_identifier
13
+ @workflow_name = workflow_name
14
+ end
15
+
16
+ # @return [Dor::Services::Client::Process]
17
+ def process(process)
18
+ @process ||= Process.new(connection: connection, version: api_version, object_identifier: object_identifier,
19
+ workflow_name: workflow_name, process: process)
20
+ end
21
+
22
+ # @return [Workflow::Response::Workflow]
23
+ def find
24
+ resp = connection.get do |req|
25
+ req.url "#{api_version}/objects/#{object_identifier}/workflows/#{workflow_name}"
26
+ req.headers['Accept'] = 'application/xml'
27
+ end
28
+
29
+ raise_exception_based_on_response!(resp) unless resp.success?
30
+
31
+ Dor::Services::Response::Workflow.new(xml: Nokogiri::XML(resp.body))
32
+ end
33
+
34
+ # Creates a workflow for a given object in the repository. If this particular workflow for this objects exists,
35
+ # it will replace the old workflow.
36
+ # @param [Integer] version
37
+ # @param [String] lane_id adds laneId attribute to all process elements in the wf_xml workflow xml. Defaults to a value of 'default'
38
+ # @param [Hash] context optional context to be included in the workflow (same for all processes for a given druid/version pair)
39
+ def create(version:, lane_id: 'default', context: nil) # rubocop:disable Metrics/AbcSize
40
+ resp = connection.post do |req|
41
+ req.url "#{api_version}/objects/#{object_identifier}/workflows/#{workflow_name}"
42
+ req.params['version'] = version
43
+ req.params['lane-id'] = lane_id
44
+ req.headers['Content-Type'] = 'application/json'
45
+ req.body = { context: context }.to_json if context
46
+ end
47
+
48
+ raise_exception_based_on_response!(resp) unless resp.success?
49
+ end
50
+
51
+ # Skips all steps in a workflow.
52
+ # @param note [String] a note to be added to the skipped steps
53
+ def skip_all(note:)
54
+ resp = connection.post do |req|
55
+ req.url "#{api_version}/objects/#{object_identifier}/workflows/#{workflow_name}/skip_all"
56
+ req.params['note'] = note
57
+ end
58
+
59
+ raise_exception_based_on_response!(resp) unless resp.success?
60
+ end
61
+
62
+ private
63
+
64
+ attr_reader :object_identifier, :workflow_name
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dor
4
+ module Services
5
+ class Client
6
+ # API calls around workflows for an object.
7
+ class ObjectWorkflows < VersionedService
8
+ # @param object_identifier [String] the druid for the object
9
+ def initialize(connection:, version:, object_identifier:)
10
+ super(connection: connection, version: version)
11
+ @object_identifier = object_identifier
12
+ end
13
+
14
+ # Retrieves all workflows for the given object
15
+ # @return [Dor::Services::Response::Workflows]
16
+ def list
17
+ resp = connection.get do |req|
18
+ req.url "#{api_version}/objects/#{object_identifier}/workflows"
19
+ req.headers['Accept'] = 'application/xml'
20
+ end
21
+ raise_exception_based_on_response!(resp) unless resp.success?
22
+
23
+ Dor::Services::Response::Workflows.new(xml: Nokogiri::XML(resp.body))
24
+ end
25
+
26
+ private
27
+
28
+ attr_reader :object_identifier
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dor
4
+ module Services
5
+ class Client
6
+ # API calls around workflow process for an object.
7
+ class Process < VersionedService
8
+ # @param object_identifier [String] the druid for the object
9
+ # @param [String] workflow_name The name of the workflow
10
+ # @param [String] process The name of the workflow step
11
+ def initialize(connection:, version:, object_identifier:, workflow_name:, process:)
12
+ super(connection: connection, version: version)
13
+ @object_identifier = object_identifier
14
+ @workflow_name = workflow_name
15
+ @process = process
16
+ end
17
+
18
+ # Updates the status of one step in a workflow.
19
+ # @param [String] status The status of the process.
20
+ # @param [Float] elapsed The number of seconds it took to complete this step. Can have a decimal. Is set to 0 if not passed in.
21
+ # @param [String] lifecycle Bookeeping label for this particular workflow step. Examples are: 'registered', 'shelved'
22
+ # @param [String] note Any kind of string annotation that you want to attach to the workflow
23
+ # @param [String] current_status Setting this string tells the workflow service to compare the current status to this value.
24
+ # @raise [Dor::Services::Client::ConflictResponse] if the current status does not match the value passed in current_status.
25
+ def update(status:, elapsed: 0, lifecycle: nil, note: nil, current_status: nil)
26
+ perform_update(status: status, elapsed: elapsed, lifecycle: lifecycle, note: note, current_status: current_status)
27
+ # resp = connection.get do |req|
28
+ # req.url "#{api_version}/objects/#{object_identifier}/workflows/#{workflow_name}"
29
+ # req.headers['Accept'] = 'application/xml'
30
+ # end
31
+
32
+ # raise_exception_based_on_response!(resp) unless resp.success?
33
+
34
+ # Dor::Services::Response::Workflow.new(xml: Nokogiri::XML(resp.body))
35
+ end
36
+
37
+ # Updates the status of one step in a workflow to error.
38
+ # @param [String] error_msg The error message. Ideally, this is a brief message describing the error
39
+ # @param [String] error_text A slot to hold more information about the error, like a full stacktrace
40
+ def update_error(error_msg:, error_text: nil)
41
+ perform_update(status: 'error', error_msg: error_msg, error_text: error_text)
42
+ end
43
+
44
+ private
45
+
46
+ attr_reader :object_identifier, :workflow_name, :process
47
+
48
+ def perform_update(**payload)
49
+ resp = connection.put do |req|
50
+ req.url "#{api_version}/objects/#{object_identifier}/workflows/#{workflow_name}/processes/#{process}"
51
+ req.headers['Content-Type'] = 'application/json'
52
+ req.body = payload.compact.to_json
53
+ end
54
+
55
+ raise_exception_based_on_response!(resp) unless resp.success?
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -3,7 +3,7 @@
3
3
  module Dor
4
4
  module Services
5
5
  class Client
6
- VERSION = '15.12.0'
6
+ VERSION = '15.14.0'
7
7
  end
8
8
  end
9
9
  end
@@ -10,6 +10,7 @@ require 'active_support/json'
10
10
  require 'cocina/models'
11
11
  require 'faraday'
12
12
  require 'faraday/retry'
13
+ require 'nokogiri'
13
14
  require 'singleton'
14
15
  require 'zeitwerk'
15
16
 
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dor
4
+ module Services
5
+ module Response
6
+ # Represents the status of an object doing a workflow process
7
+ class Process
8
+ # @params [Workflow] parent
9
+ # @params [Hash] attributes
10
+ def initialize(parent:, **attributes)
11
+ @parent = parent
12
+ @attributes = attributes
13
+ end
14
+
15
+ def name
16
+ @attributes[:name].presence
17
+ end
18
+
19
+ def status
20
+ @attributes[:status].presence
21
+ end
22
+
23
+ def datetime
24
+ @attributes[:datetime].presence
25
+ end
26
+
27
+ def elapsed
28
+ @attributes[:elapsed].presence
29
+ end
30
+
31
+ def attempts
32
+ @attributes[:attempts].presence
33
+ end
34
+
35
+ def lifecycle
36
+ @attributes[:lifecycle].presence
37
+ end
38
+
39
+ def note
40
+ @attributes[:note].presence
41
+ end
42
+
43
+ def error_message
44
+ @attributes[:errorMessage].presence
45
+ end
46
+
47
+ def lane_id
48
+ @attributes[:laneId].presence
49
+ end
50
+
51
+ # @return [Hash] the context for the process (or empty hash if none present)
52
+ def context
53
+ return {} unless @attributes[:context].present?
54
+
55
+ JSON.parse(@attributes[:context])
56
+ end
57
+
58
+ delegate :pid, :workflow_name, to: :parent
59
+
60
+ private
61
+
62
+ attr_reader :parent
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dor
4
+ module Services
5
+ module Response
6
+ # The response from asking the server about a workflow for an item
7
+ class Workflow
8
+ def initialize(xml:)
9
+ @xml = xml
10
+ end
11
+
12
+ def pid
13
+ workflow['objectId']
14
+ end
15
+
16
+ def workflow_name
17
+ workflow['id']
18
+ end
19
+
20
+ # Check if there are any processes for the provided version.
21
+ # @param [Integer] version the version we are checking for.
22
+ def active_for?(version:)
23
+ result = ng_xml.at_xpath("/workflow/process[@version=#{version}]")
24
+ result ? true : false
25
+ end
26
+
27
+ # Returns the process, for the most recent version that matches the given name:
28
+ def process_for_recent_version(name:)
29
+ nodes = process_nodes_for(name: name)
30
+ node = nodes.max { |a, b| a.attr('version').to_i <=> b.attr('version').to_i }
31
+ to_process(node)
32
+ end
33
+
34
+ def empty?
35
+ ng_xml.xpath('/workflow/process').empty?
36
+ end
37
+
38
+ # Check if all processes are skipped or complete for the provided version.
39
+ # @param [Integer] version the version we are checking for.
40
+ def complete_for?(version:)
41
+ # ng_xml.xpath("/workflow/process[@version=#{version}]/@status").map(&:value).all? { |p| %w[skipped completed].include?(p) }
42
+ incomplete_processes_for(version: version).empty?
43
+ end
44
+
45
+ def complete?
46
+ complete_for?(version: version)
47
+ end
48
+
49
+ def incomplete_processes_for(version:)
50
+ process_nodes = ng_xml.xpath("/workflow/process[@version=#{version}]")
51
+ incomplete_process_nodes = process_nodes.reject { |process_node| %w[skipped completed].include?(process_node.attr('status')) }
52
+ incomplete_process_nodes.map { |process_node| to_process(process_node) }
53
+ end
54
+
55
+ def incomplete_processes
56
+ incomplete_processes_for(version: version)
57
+ end
58
+
59
+ attr_reader :xml
60
+
61
+ private
62
+
63
+ # Return the max version in this workflow document
64
+ def version
65
+ ng_xml.xpath('/workflow/process/@version').map { |attr| attr.value.to_i }.max
66
+ end
67
+
68
+ def workflow
69
+ ng_xml.at_xpath('workflow')
70
+ end
71
+
72
+ def process_nodes_for(name:)
73
+ ng_xml.xpath("/workflow/process[@name = '#{name}']")
74
+ end
75
+
76
+ def ng_xml
77
+ @ng_xml ||= Nokogiri::XML(@xml)
78
+ end
79
+
80
+ def to_process(node)
81
+ attributes = node ? node.attributes.to_h { |k, v| [k.to_sym, v.value] } : {}
82
+ Process.new(parent: self, **attributes)
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dor
4
+ module Services
5
+ module Response
6
+ # The response from asking the server about all workflows for an item
7
+ class Workflows
8
+ def initialize(xml:)
9
+ @xml = xml
10
+ end
11
+
12
+ def pid
13
+ ng_xml.at_xpath('/workflows/@objectId').text
14
+ end
15
+
16
+ def workflows
17
+ @workflows ||= ng_xml.xpath('/workflows/workflow').map do |node|
18
+ Workflow.new(xml: node.to_xml)
19
+ end
20
+ end
21
+
22
+ # @return [Array<String>] returns a list of errors for any process for the current version
23
+ def errors_for(version:)
24
+ ng_xml.xpath("//workflow/process[@version='#{version}' and @status='error']/@errorMessage")
25
+ .map(&:text)
26
+ end
27
+
28
+ attr_reader :xml
29
+
30
+ private
31
+
32
+ def ng_xml
33
+ @ng_xml ||= Nokogiri::XML(@xml)
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
metadata CHANGED
@@ -1,14 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dor-services-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 15.12.0
4
+ version: 15.14.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Coyne
8
8
  - Michael Giarlo
9
+ autorequire:
9
10
  bindir: exe
10
11
  cert_chain: []
11
- date: 2025-06-24 00:00:00.000000000 Z
12
+ date: 2025-06-26 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: activesupport
@@ -30,14 +31,14 @@ dependencies:
30
31
  requirements:
31
32
  - - "~>"
32
33
  - !ruby/object:Gem::Version
33
- version: 0.104.0
34
+ version: 0.104.1
34
35
  type: :runtime
35
36
  prerelease: false
36
37
  version_requirements: !ruby/object:Gem::Requirement
37
38
  requirements:
38
39
  - - "~>"
39
40
  - !ruby/object:Gem::Version
40
- version: 0.104.0
41
+ version: 0.104.1
41
42
  - !ruby/object:Gem::Dependency
42
43
  name: deprecation
43
44
  requirement: !ruby/object:Gem::Requirement
@@ -80,6 +81,20 @@ dependencies:
80
81
  - - ">="
81
82
  - !ruby/object:Gem::Version
82
83
  version: '0'
84
+ - !ruby/object:Gem::Dependency
85
+ name: nokogiri
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ type: :runtime
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
83
98
  - !ruby/object:Gem::Dependency
84
99
  name: zeitwerk
85
100
  requirement: !ruby/object:Gem::Requirement
@@ -206,6 +221,7 @@ dependencies:
206
221
  - - ">="
207
222
  - !ruby/object:Gem::Version
208
223
  version: '0'
224
+ description:
209
225
  email:
210
226
  - jcoyne@justincoyne.com
211
227
  - leftwing@alumni.rutgers.edu
@@ -237,10 +253,14 @@ files:
237
253
  - lib/dor/services/client/error_faraday_middleware.rb
238
254
  - lib/dor/services/client/events.rb
239
255
  - lib/dor/services/client/members.rb
256
+ - lib/dor/services/client/milestones.rb
240
257
  - lib/dor/services/client/mutate.rb
241
258
  - lib/dor/services/client/object.rb
242
259
  - lib/dor/services/client/object_version.rb
260
+ - lib/dor/services/client/object_workflow.rb
261
+ - lib/dor/services/client/object_workflows.rb
243
262
  - lib/dor/services/client/objects.rb
263
+ - lib/dor/services/client/process.rb
244
264
  - lib/dor/services/client/release_tag.rb
245
265
  - lib/dor/services/client/release_tags.rb
246
266
  - lib/dor/services/client/response_error_formatter.rb
@@ -250,10 +270,14 @@ files:
250
270
  - lib/dor/services/client/virtual_objects.rb
251
271
  - lib/dor/services/client/workflows.rb
252
272
  - lib/dor/services/client/workspace.rb
273
+ - lib/dor/services/response/process.rb
274
+ - lib/dor/services/response/workflow.rb
275
+ - lib/dor/services/response/workflows.rb
253
276
  homepage: https://github.com/sul-dlss/dor-services-client
254
277
  licenses: []
255
278
  metadata:
256
279
  rubygems_mfa_required: 'true'
280
+ post_install_message:
257
281
  rdoc_options: []
258
282
  require_paths:
259
283
  - lib
@@ -271,7 +295,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
271
295
  - !ruby/object:Gem::Version
272
296
  version: '0'
273
297
  requirements: []
274
- rubygems_version: 3.6.2
298
+ rubygems_version: 3.5.11
299
+ signing_key:
275
300
  specification_version: 4
276
301
  summary: A client for dor-services-app
277
302
  test_files: []