sdr-client 0.86.0 → 0.89.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: 860f2f6a8c4d48b484b5cc4f9a2b8d7c0ac0f4c682af36bff84edce9053a66fe
4
- data.tar.gz: a8b452c7f6c305178013510d482fe74a055f254be706acaab61496403520915b
3
+ metadata.gz: 0e749426dd330fcaf3d0988f32707bde37010f2f305c6cdc383992c73f16ff3e
4
+ data.tar.gz: 1526a4e18c42b5e1ce30ae4283173112cedbe83b24bdb78b928c2e84b5471b1a
5
5
  SHA512:
6
- metadata.gz: 4daba12917fa1e63e75af8ca662d68773355df1950b93e901e6cd5dd8e085f2757e302abfeb0f7105733a3997aa6ead2cb6134f01e977976739911430f3a9903
7
- data.tar.gz: c1216fa3fef31a1d7534ba97c255fa404f9ffb3d028c4d278300a7bc69d0b80ec3ff9ce21beeea7abab2cab2f487a7a11247306e4b230d80b22be6064813da13
6
+ metadata.gz: bc684b73cf7e8d9cbc2d4f0da3c02c1cc0db8277941c8a7888273ed5ed1c98e1eb83d979ec419342d182604dbcbb8231d6a3547e9a5905a88f1db6b53dcdea94
7
+ data.tar.gz: 7acff379f70c228a728bfeb7a31119adde73f60703e350a0d413524194578e31c19ee02a4137232ae215b66a96953812294190103aa5de48ca85b26be4f6b6d9
data/.circleci/config.yml CHANGED
@@ -1,6 +1,6 @@
1
1
  version: 2.1
2
2
  orbs:
3
- ruby-rails: sul-dlss/ruby-rails@2.0.0
3
+ ruby-rails: sul-dlss/ruby-rails@3.1.2
4
4
  workflows:
5
5
  build:
6
6
  jobs:
data/.gitignore CHANGED
@@ -10,5 +10,3 @@
10
10
 
11
11
  # rspec failure tracking
12
12
  .rspec_status
13
-
14
- Gemfile.lock
data/.rubocop.yml CHANGED
@@ -27,7 +27,7 @@ Naming/FileName:
27
27
  Exclude:
28
28
  - 'lib/sdr-client.rb'
29
29
 
30
- Gemspec/DateAssignment: # new in 1.10
30
+ Gemspec/DeprecatedAttributeAssignment: # new in 1.10
31
31
  Enabled: true
32
32
  Gemspec/RequireMFA: # new in 1.23
33
33
  Enabled: true
@@ -157,3 +157,21 @@ RSpec/BeNil: # new in 2.9.0
157
157
  Enabled: true
158
158
  RSpec/VerifiedDoubleReference: # new in 2.10.0
159
159
  Enabled: true
160
+ Layout/LineContinuationLeadingSpace: # new in 1.31
161
+ Enabled: true
162
+ Layout/LineContinuationSpacing: # new in 1.31
163
+ Enabled: true
164
+ Lint/ConstantOverwrittenInRescue: # new in 1.31
165
+ Enabled: true
166
+ Lint/NonAtomicFileOperation: # new in 1.31
167
+ Enabled: true
168
+ Style/EnvHome: # new in 1.29
169
+ Enabled: true
170
+ Style/MapCompactWithConditionalBlock: # new in 1.30
171
+ Enabled: true
172
+ RSpec/ChangeByZero: # new in 2.11.0
173
+ Enabled: true
174
+ RSpec/Capybara/SpecificMatcher: # new in 2.12
175
+ Enabled: true
176
+ RSpec/Rails/HaveHttpStatus: # new in 2.12
177
+ Enabled: true
data/Gemfile.lock ADDED
@@ -0,0 +1,179 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ sdr-client (0.89.0)
5
+ activesupport
6
+ cocina-models (~> 0.83.0)
7
+ dry-monads
8
+ faraday (>= 0.16)
9
+
10
+ GEM
11
+ remote: https://rubygems.org/
12
+ specs:
13
+ activesupport (7.0.3.1)
14
+ concurrent-ruby (~> 1.0, >= 1.0.2)
15
+ i18n (>= 1.6, < 2)
16
+ minitest (>= 5.1)
17
+ tzinfo (~> 2.0)
18
+ addressable (2.8.0)
19
+ public_suffix (>= 2.0.2, < 5.0)
20
+ ast (2.4.2)
21
+ attr_extras (6.2.5)
22
+ byebug (11.1.3)
23
+ cocina-models (0.83.0)
24
+ activesupport
25
+ deprecation
26
+ dry-struct (~> 1.0)
27
+ dry-types (~> 1.1)
28
+ edtf
29
+ equivalent-xml
30
+ jsonpath
31
+ nokogiri
32
+ openapi3_parser
33
+ openapi_parser (>= 0.11.1, < 1.0)
34
+ rss
35
+ super_diff
36
+ thor
37
+ zeitwerk (~> 2.1)
38
+ commonmarker (0.23.5)
39
+ concurrent-ruby (1.1.10)
40
+ crack (0.4.5)
41
+ rexml
42
+ deprecation (1.1.0)
43
+ activesupport
44
+ diff-lcs (1.5.0)
45
+ docile (1.4.0)
46
+ dry-container (0.10.0)
47
+ concurrent-ruby (~> 1.0)
48
+ dry-core (0.7.1)
49
+ concurrent-ruby (~> 1.0)
50
+ dry-inflector (0.3.0)
51
+ dry-logic (1.2.0)
52
+ concurrent-ruby (~> 1.0)
53
+ dry-core (~> 0.5, >= 0.5)
54
+ dry-monads (1.4.0)
55
+ concurrent-ruby (~> 1.0)
56
+ dry-core (~> 0.7)
57
+ dry-struct (1.4.0)
58
+ dry-core (~> 0.5, >= 0.5)
59
+ dry-types (~> 1.5)
60
+ ice_nine (~> 0.11)
61
+ dry-types (1.5.1)
62
+ concurrent-ruby (~> 1.0)
63
+ dry-container (~> 0.3)
64
+ dry-core (~> 0.5, >= 0.5)
65
+ dry-inflector (~> 0.1, >= 0.1.2)
66
+ dry-logic (~> 1.0, >= 1.0.2)
67
+ edtf (3.1.0)
68
+ activesupport (>= 3.0, < 8.0)
69
+ equivalent-xml (0.6.0)
70
+ nokogiri (>= 1.4.3)
71
+ faraday (2.3.0)
72
+ faraday-net_http (~> 2.0)
73
+ ruby2_keywords (>= 0.0.4)
74
+ faraday-net_http (2.0.3)
75
+ hashdiff (1.0.1)
76
+ i18n (1.11.0)
77
+ concurrent-ruby (~> 1.0)
78
+ ice_nine (0.11.2)
79
+ json (2.6.2)
80
+ jsonpath (1.1.2)
81
+ multi_json
82
+ mini_portile2 (2.8.0)
83
+ minitest (5.16.2)
84
+ multi_json (1.15.0)
85
+ nokogiri (1.13.6)
86
+ mini_portile2 (~> 2.8.0)
87
+ racc (~> 1.4)
88
+ nokogiri (1.13.6-x86_64-darwin)
89
+ racc (~> 1.4)
90
+ openapi3_parser (0.9.2)
91
+ commonmarker (~> 0.17)
92
+ openapi_parser (0.15.0)
93
+ optimist (3.0.1)
94
+ parallel (1.22.1)
95
+ parser (3.1.2.0)
96
+ ast (~> 2.4.1)
97
+ patience_diff (1.2.0)
98
+ optimist (~> 3.0)
99
+ public_suffix (4.0.7)
100
+ racc (1.6.0)
101
+ rainbow (3.1.1)
102
+ rake (13.0.6)
103
+ regexp_parser (2.5.0)
104
+ rexml (3.2.5)
105
+ rspec (3.11.0)
106
+ rspec-core (~> 3.11.0)
107
+ rspec-expectations (~> 3.11.0)
108
+ rspec-mocks (~> 3.11.0)
109
+ rspec-core (3.11.0)
110
+ rspec-support (~> 3.11.0)
111
+ rspec-expectations (3.11.0)
112
+ diff-lcs (>= 1.2.0, < 2.0)
113
+ rspec-support (~> 3.11.0)
114
+ rspec-mocks (3.11.1)
115
+ diff-lcs (>= 1.2.0, < 2.0)
116
+ rspec-support (~> 3.11.0)
117
+ rspec-support (3.11.0)
118
+ rspec_junit_formatter (0.5.1)
119
+ rspec-core (>= 2, < 4, != 2.12.0)
120
+ rss (0.2.9)
121
+ rexml
122
+ rubocop (1.31.2)
123
+ json (~> 2.3)
124
+ parallel (~> 1.10)
125
+ parser (>= 3.1.0.0)
126
+ rainbow (>= 2.2.2, < 4.0)
127
+ regexp_parser (>= 1.8, < 3.0)
128
+ rexml (>= 3.2.5, < 4.0)
129
+ rubocop-ast (>= 1.18.0, < 2.0)
130
+ ruby-progressbar (~> 1.7)
131
+ unicode-display_width (>= 1.4.0, < 3.0)
132
+ rubocop-ast (1.19.1)
133
+ parser (>= 3.1.1.0)
134
+ rubocop-rake (0.6.0)
135
+ rubocop (~> 1.0)
136
+ rubocop-rspec (2.12.1)
137
+ rubocop (~> 1.31)
138
+ ruby-progressbar (1.11.0)
139
+ ruby2_keywords (0.0.5)
140
+ simplecov (0.21.2)
141
+ docile (~> 1.1)
142
+ simplecov-html (~> 0.11)
143
+ simplecov_json_formatter (~> 0.1)
144
+ simplecov-html (0.12.3)
145
+ simplecov_json_formatter (0.1.4)
146
+ super_diff (0.9.0)
147
+ attr_extras (>= 6.2.4)
148
+ diff-lcs
149
+ patience_diff
150
+ thor (1.2.1)
151
+ tzinfo (2.0.4)
152
+ concurrent-ruby (~> 1.0)
153
+ unicode-display_width (2.2.0)
154
+ webmock (3.14.0)
155
+ addressable (>= 2.8.0)
156
+ crack (>= 0.3.2)
157
+ hashdiff (>= 0.4.0, < 2.0.0)
158
+ zeitwerk (2.6.0)
159
+
160
+ PLATFORMS
161
+ x86_64-darwin-21
162
+ x86_64-linux
163
+
164
+ DEPENDENCIES
165
+ bundler (~> 2.0)
166
+ byebug
167
+ rake (~> 13.0)
168
+ rspec (~> 3.0)
169
+ rspec_junit_formatter
170
+ rubocop (~> 1.24)
171
+ rubocop-rake
172
+ rubocop-rspec (~> 2.1)
173
+ sdr-client!
174
+ simplecov
175
+ thor
176
+ webmock (~> 3.7)
177
+
178
+ BUNDLED WITH
179
+ 2.3.17
data/README.md CHANGED
@@ -95,9 +95,12 @@ sdr update druid:bb408qn5061 --url https://sdr-api-server:3000 --license "https:
95
95
  # Change access controls
96
96
  sdr update druid:bb408qn5061 --url https://sdr-api-server:3000 --view "location-based" --download "none" --location "music" --cdl false
97
97
 
98
- # Change Cocina wholesale from a file (note that you can use this flag with the
99
- # others above, and the flags above will replace what's supplied in the cocina file)
98
+ # Change Cocina wholesale, either:
99
+ # 1. From a file
100
100
  sdr update druid:bb408qn5061 --url https://sdr-api-server:3000 --cocina-file bb408qn5061.json
101
+ # 2. Piped in on the command-line
102
+ sdr get druid:b408qn5061 --url https://sdr-api-server:3000 | exe/remove_w3cdtf_encoding_from_event_dates | sdr update druid:bb408qn5061 --url https://sdr-api-server:3000 --cocina-pipe
103
+ # Note that you can use either of these flags with the others above, and the flags above will replace what's supplied in the cocina file or pipe
101
104
  ```
102
105
 
103
106
  ## Testing
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ $LOAD_PATH.unshift 'lib'
5
+
6
+ require 'sdr_client'
7
+
8
+ output = JSON.parse($stdin.read).tap do |hash|
9
+ hash.dig('description', 'event').each do |event|
10
+ event['date'].each do |event_date|
11
+ event_date.delete('encoding') if event_date.dig('encoding', 'code') == 'w3cdtf'
12
+ end
13
+ end
14
+ end.to_json
15
+
16
+ puts output
@@ -31,7 +31,7 @@ module SdrClient
31
31
 
32
32
  desc 'get DRUID', 'Retrieve an object from the SDR'
33
33
  def get(druid)
34
- say SdrClient::Find.run(druid, url: options[:url])
34
+ say SdrClient::Find.run(druid, url: options[:url], logger: Logger.new($stderr))
35
35
  rescue SdrClient::Credentials::NoCredentialsError
36
36
  say_error 'Log in first'
37
37
  exit(1)
@@ -71,10 +71,11 @@ module SdrClient
71
71
  option :location, enum: %w[spec music ars art hoover m&m], desc: 'Access location for the object'
72
72
  option :cdl, type: :boolean, default: false, desc: 'Controlled digital lending'
73
73
  option :cocina_file, desc: 'Path to a file containing Cocina JSON'
74
+ option :cocina_pipe, type: :boolean, default: false, desc: 'Indicate Cocina JSON is being piped in'
74
75
  def update(druid)
75
76
  validate_druid!(druid)
76
77
  job_id = SdrClient::Update.run(druid, **options)
77
- poll_for_job_complete(job_id: job_id, url: options[:url]) # TODO: add an option that skips this
78
+ poll_for_job_complete(job_id: job_id, url: options[:url])
78
79
  rescue SdrClient::Credentials::NoCredentialsError
79
80
  say_error 'Log in first'
80
81
  exit(1)
@@ -156,7 +157,7 @@ module SdrClient
156
157
  # the extra args to `say` prevent appending a newline
157
158
  say('SDR is processing your request.', nil, false)
158
159
  result = nil
159
- (1).upto(60) do
160
+ 1.upto(60) do
160
161
  result = SdrClient::BackgroundJobResults.show(url: url, job_id: job_id)
161
162
  break unless %w[pending processing].include?(result['status'])
162
163
 
@@ -8,7 +8,7 @@ module SdrClient
8
8
  # @param [String] a json string that contains a field 'token'
9
9
  def self.write(body)
10
10
  json = JSON.parse(body)
11
- Dir.mkdir(credentials_path, 0o700) unless Dir.exist?(credentials_path)
11
+ FileUtils.mkdir_p(credentials_path, mode: 0o700)
12
12
  File.atomic_write(credentials_file) do |file|
13
13
  file.write(json.fetch('token'))
14
14
  end
@@ -5,9 +5,10 @@ module SdrClient
5
5
  # Creates a resource (metadata) in SDR
6
6
  class CreateResource
7
7
  DRO_PATH = '/v1/resources'
8
-
9
- def self.run(accession:, metadata:, logger:, connection:, assign_doi: false)
8
+ # rubocop:disable Metrics/ParameterLists
9
+ def self.run(accession:, metadata:, logger:, connection:, assign_doi: false, priority: nil)
10
10
  new(accession: accession,
11
+ priority: priority,
11
12
  assign_doi: assign_doi,
12
13
  metadata: metadata,
13
14
  logger: logger,
@@ -18,13 +19,17 @@ module SdrClient
18
19
  # @param [Boolean] assign_doi should a DOI be assigned to this item
19
20
  # @param [Cocina::Models::RequestDRO, Cocina::Models::RequestCollection] metadata
20
21
  # @param [Hash<Symbol,String>] the result of the metadata call
21
- def initialize(accession:, assign_doi:, metadata:, logger:, connection:)
22
+ # @param [String] priority what processing priority should be used
23
+ # either 'low' or 'default'
24
+ def initialize(accession:, assign_doi:, metadata:, logger:, connection:, priority: nil)
22
25
  @accession = accession
26
+ @priority = priority
23
27
  @assign_doi = assign_doi
24
28
  @metadata = metadata
25
29
  @logger = logger
26
30
  @connection = connection
27
31
  end
32
+ # rubocop:enable Metrics/ParameterLists
28
33
 
29
34
  # @param [Hash<Symbol,String>] the result of the metadata call
30
35
  # @return [String] job id for the background job result
@@ -39,7 +44,7 @@ module SdrClient
39
44
 
40
45
  private
41
46
 
42
- attr_reader :metadata, :logger, :connection
47
+ attr_reader :metadata, :logger, :connection, :priority
43
48
 
44
49
  def metadata_request
45
50
  json = metadata.to_json
@@ -60,6 +65,7 @@ module SdrClient
60
65
 
61
66
  def path
62
67
  params = { accession: accession? }
68
+ params[:priority] = priority if priority
63
69
  params[:assign_doi] = true if assign_doi? # false is default
64
70
  DRO_PATH + '?' + params.map { |k, v| "#{k}=#{v}" }.join('&')
65
71
  end
@@ -9,6 +9,8 @@ module SdrClient
9
9
  # @param [Request] metadata information about the object
10
10
  # @param [String] connection the server connection to use
11
11
  # @param [Boolean] accession should the accessionWF be started
12
+ # @param [String] priority (nil) what processing priority should be used
13
+ # either 'low' or 'default'
12
14
  # @param [Class] grouping_strategy class whose run method groups an array of uploads
13
15
  # @param [Class] file_set_type_strategy class whose run method determines file_set type
14
16
  # @param [Array<String>] files a list of file names to upload
@@ -19,6 +21,7 @@ module SdrClient
19
21
  def initialize(metadata:,
20
22
  connection:,
21
23
  accession:,
24
+ priority: nil,
22
25
  grouping_strategy: SingleFileGroupingStrategy,
23
26
  file_set_type_strategy: FileTypeFileSetStrategy,
24
27
  files: [],
@@ -31,6 +34,7 @@ module SdrClient
31
34
  @grouping_strategy = grouping_strategy
32
35
  @file_set_type_strategy = file_set_type_strategy
33
36
  @accession = accession
37
+ @priority = priority
34
38
  @assign_doi = assign_doi
35
39
  end
36
40
  # rubocop:enable Metrics/ParameterLists
@@ -51,6 +55,7 @@ module SdrClient
51
55
  request = metadata_builder.with_uploads(upload_responses)
52
56
  model = Cocina::Models.build_request(request.as_json.with_indifferent_access)
53
57
  CreateResource.run(accession: @accession,
58
+ priority: @priority,
54
59
  assign_doi: @assign_doi,
55
60
  metadata: model,
56
61
  logger: logger,
@@ -27,6 +27,7 @@ module SdrClient
27
27
  files: [],
28
28
  files_metadata: {},
29
29
  accession: false,
30
+ priority: nil,
30
31
  grouping_strategy: SingleFileGroupingStrategy,
31
32
  file_set_type_strategy: FileTypeFileSetStrategy,
32
33
  logger: Logger.new($stdout))
@@ -51,6 +52,7 @@ module SdrClient
51
52
  grouping_strategy: grouping_strategy,
52
53
  file_set_type_strategy: file_set_type_strategy,
53
54
  accession: accession,
55
+ priority: priority,
54
56
  logger: logger).run
55
57
  end
56
58
  # rubocop:enable Metrics/MethodLength
@@ -50,10 +50,22 @@ module SdrClient
50
50
  @cocina_hash_from_file ||= JSON.parse(File.read(options[:cocina_file]), symbolize_names: true)
51
51
  end
52
52
 
53
+ def cocina_hash_from_pipe
54
+ @cocina_hash_from_pipe ||= JSON.parse($stdin.read, symbolize_names: true)
55
+ end
56
+
53
57
  # Update the Cocina in full
54
58
  def update_cocina(cocina_object)
55
- return cocina_object unless options[:cocina_file]
59
+ if options[:cocina_file]
60
+ update_cocina_from_file(cocina_object)
61
+ elsif options[:cocina_pipe]
62
+ update_cocina_from_pipe(cocina_object)
63
+ else
64
+ cocina_object
65
+ end
66
+ end
56
67
 
68
+ def update_cocina_from_file(cocina_object)
57
69
  if !File.file?(options[:cocina_file]) || !File.readable?(options[:cocina_file])
58
70
  raise "File not found: #{options[:cocina_file]}"
59
71
  end
@@ -66,6 +78,17 @@ module SdrClient
66
78
  cocina_object.new(cocina_hash_from_file)
67
79
  end
68
80
 
81
+ def update_cocina_from_pipe(cocina_object)
82
+ raise 'No pipe provided' unless $stdin.stat.pipe?
83
+
84
+ # NOTE: We may want to add more checks later. For now, make sure the identifiers match.
85
+ if cocina_object.externalIdentifier != cocina_hash_from_pipe[:externalIdentifier]
86
+ raise "Cocina piped in has a different external identifier than #{cocina_object.externalIdentifier}: #{cocina_hash_from_pipe[:externalIdentifier]}"
87
+ end
88
+
89
+ cocina_object.new(cocina_hash_from_pipe)
90
+ end
91
+
69
92
  # Update the APO of a Cocina item if the options specify a new one, else return the original
70
93
  def update_apo(cocina_object)
71
94
  return cocina_object unless options[:apo]
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SdrClient
4
- VERSION = '0.86.0'
4
+ VERSION = '0.89.0'
5
5
  end
data/sdr-client.gemspec CHANGED
@@ -28,7 +28,7 @@ Gem::Specification.new do |spec|
28
28
  spec.require_paths = ['lib']
29
29
 
30
30
  spec.add_dependency 'activesupport'
31
- spec.add_dependency 'cocina-models', '~> 0.81.0'
31
+ spec.add_dependency 'cocina-models', '~> 0.83.0'
32
32
  spec.add_dependency 'dry-monads'
33
33
  spec.add_dependency 'faraday', '>= 0.16'
34
34
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sdr-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.86.0
4
+ version: 0.89.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Coyne
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-06-01 00:00:00.000000000 Z
11
+ date: 2022-07-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 0.81.0
33
+ version: 0.83.0
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 0.81.0
40
+ version: 0.83.0
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: dry-monads
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -197,6 +197,7 @@ description: This provides a way to deposit repository objects into the Stanford
197
197
  email:
198
198
  - jcoyne@justincoyne.com
199
199
  executables:
200
+ - remove_w3cdtf_encoding_from_event_dates
200
201
  - sdr
201
202
  extensions: []
202
203
  extra_rdoc_files: []
@@ -208,11 +209,13 @@ files:
208
209
  - ".rubocop.yml"
209
210
  - ".rubocop_todo.yml"
210
211
  - Gemfile
212
+ - Gemfile.lock
211
213
  - LICENSE
212
214
  - README.md
213
215
  - Rakefile
214
216
  - bin/console
215
217
  - bin/setup
218
+ - exe/remove_w3cdtf_encoding_from_event_dates
216
219
  - exe/sdr
217
220
  - lib/sdr-client.rb
218
221
  - lib/sdr_client.rb
@@ -271,7 +274,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
271
274
  - !ruby/object:Gem::Version
272
275
  version: '0'
273
276
  requirements: []
274
- rubygems_version: 3.3.9
277
+ rubygems_version: 3.3.7
275
278
  signing_key:
276
279
  specification_version: 4
277
280
  summary: The CLI for https://github.com/sul-dlss/sdr-api