puppet_forge 3.2.0 → 4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 14fb262a13e9382bc404ebf162e70c8fa48ccd73f33f53113e75524da106bed9
4
- data.tar.gz: 0316cbac8bd7c7d3dc18d792a0dfc25a4cca095fce0974a5f54a50e546ef1c92
3
+ metadata.gz: bf36457b8298a66e2b7af77d53a0bf476b4881c2dd29de7b1e8a49a523400f53
4
+ data.tar.gz: e5926f236dbe38b61bf3e1b9e96677ef352db5afabb9de836d40d1be136830f5
5
5
  SHA512:
6
- metadata.gz: f909a3a4b8bf942f104f1a9f5a798edeb8a29e03adaaa24dbd4170efd97f2e09c23ef44b3b88ad406d32d5d10aba98d382d21ce10e1db115ee5c87d8cd01e30f
7
- data.tar.gz: 2da931edf4e563a6e0962d834c9e3db3dec6ff33fd9a172f5d50a12066863b336fae173c8ad860d6c85f6df1ef02da4e1e0fc61e0a3182e92552ac988db3ce7b
6
+ metadata.gz: d604d660f74c37ea1bdeeb048d94edf557b1037d46bc6e83963f1d8b9d1652ceb66d3aafb3b498c470ffc1083c7d2fbb5d22a410b3ae2e91e12b7381f2ee9c26
7
+ data.tar.gz: fbf2a345b0c6b538a7a0424965d13aa1ab54f9e064273fe983176b60516a1076b1f3bd7b8edca3bed5272b0380de1fb6448d81dde147d31f3961c99ea49fde26
@@ -14,7 +14,11 @@ jobs:
14
14
  runs-on: ubuntu-latest
15
15
  strategy:
16
16
  matrix:
17
- ruby: [2.7, 2.6, 2.5]
17
+ ruby:
18
+ - '3.1'
19
+ - '3.0'
20
+ - '2.7'
21
+ - '2.6'
18
22
 
19
23
  steps:
20
24
  - uses: actions/checkout@v1
@@ -22,9 +26,7 @@ jobs:
22
26
  uses: ruby/setup-ruby@v1
23
27
  with:
24
28
  ruby-version: ${{ matrix.ruby }}
29
+ bundler-cache: true
25
30
 
26
31
  - name: Build and test with Rspec
27
- run: |
28
- gem install bundler
29
- bundle install --jobs 4 --retry 3
30
- bundle exec rspec
32
+ run: bundle exec rspec
@@ -0,0 +1,24 @@
1
+ name: snyk_merge
2
+ on:
3
+ workflow_dispatch:
4
+ push:
5
+ branches:
6
+ - main
7
+ jobs:
8
+ security:
9
+ runs-on: ubuntu-latest
10
+ steps:
11
+ - uses: actions/checkout@master
12
+ - name: setup ruby
13
+ uses: ruby/setup-ruby@v1
14
+ with:
15
+ ruby-version: 2.7
16
+ - name: create lock
17
+ run: bundle lock
18
+ - name: Run Snyk to check for vulnerabilities
19
+ uses: snyk/actions/ruby@master
20
+ env:
21
+ SNYK_TOKEN: ${{ secrets.SNYK_FORGE_KEY }}
22
+ with:
23
+ command: monitor
24
+ args: --org=puppet-forge
data/CHANGELOG.md CHANGED
@@ -3,6 +3,16 @@
3
3
  Starting with v2.0.0, all notable changes to this project will be documented in this file.
4
4
  This project adheres to [Semantic Versioning](http://semver.org/).
5
5
 
6
+ ## v4.1.0 - 2023-02-21
7
+
8
+ * Add upload method functionality.
9
+ * Allows the user to search by an array of endorsements.
10
+
11
+ ## v4.0.0 - 2022-11-30
12
+
13
+ * Breaking: The `puppet_forge` gem now requires at least Ruby 2.6.0
14
+ * Update `faraday` gem to 2.x series
15
+
6
16
  ## v3.2.0 - 2021-11-09
7
17
 
8
18
  * Allow requests to follow redirects
data/README.md CHANGED
@@ -136,7 +136,23 @@ release.verify(Pathname(release_tarball))
136
136
  # @raise RuntimeError if it fails to extract the contents of the release tarball
137
137
  PuppetForge::Unpacker.unpack(release_tarball, dest_dir, tmp_dir)
138
138
  ```
139
+ ### Uploading a module release
139
140
 
141
+ You can upload new module versions to the forge by following the steps below.
142
+
143
+ > Note: This API requires authorization. See [Authorization](#authorization) for more information.
144
+
145
+ ```ruby
146
+ release_tarball = 'pkg/puppetlabs-apache-1.6.0.tar.gz'
147
+
148
+ # Upload a module tarball to the Puppet Forge
149
+ # Returns an instance of V3::Release class and the response from the forge upload
150
+ # @raise PuppetForge::ReleaseForbidden if a 403 response is recieved from the server
151
+ # @raise PuppetForge::ReleaseBadContent if the module to upload is not valid
152
+ # @raise Faraday::ClientError if any errors encountered in the upload
153
+ # @raise PuppetForge::FileNotFound if the given tarball cannot be found
154
+ release, response = PuppetForge::V3::Release.upload(release_tarball)
155
+ ```
140
156
 
141
157
  ### Paginated Collections
142
158
 
@@ -22,4 +22,4 @@ module PuppetForge
22
22
  end
23
23
  end
24
24
 
25
- Faraday::Middleware.register_middleware(:connection_failure => lambda { PuppetForge::Connection::ConnectionFailure })
25
+ Faraday::Middleware.register_middleware(:connection_failure => PuppetForge::Connection::ConnectionFailure)
@@ -1,7 +1,7 @@
1
1
  require 'puppet_forge/connection/connection_failure'
2
2
 
3
3
  require 'faraday'
4
- require 'faraday_middleware'
4
+ require 'faraday/follow_redirects'
5
5
 
6
6
  module PuppetForge
7
7
  # Provide a common mixin for adding a HTTP connection to classes.
@@ -115,7 +115,7 @@ module PuppetForge
115
115
  end
116
116
 
117
117
  Faraday.new(url, options) do |builder|
118
- builder.use FaradayMiddleware::FollowRedirects
118
+ builder.use Faraday::FollowRedirects::Middleware
119
119
  builder.response(:json, :content_type => /\bjson$/, :parser_options => { :symbolize_names => true })
120
120
  builder.response(:raise_error)
121
121
  builder.use(:connection_failure)
@@ -28,16 +28,32 @@ Could not install package
28
28
  end
29
29
  end
30
30
 
31
+
32
+ class ErrorWithDetail < PuppetForge::Error
33
+ def self.from_response(response)
34
+ body = JSON.parse(response[:body])
35
+
36
+ message = body['message']
37
+ if body.key?('errors') && !body['errors']&.empty?
38
+ message << "\nThe following errors were returned from the server:\n - #{body['errors'].join("\n - ")}"
39
+ end
40
+
41
+ new(message)
42
+ end
43
+ end
44
+
45
+ class FileNotFound < PuppetForge::Error
46
+ end
47
+
31
48
  class ModuleNotFound < PuppetForge::Error
32
49
  end
33
50
 
34
51
  class ReleaseNotFound < PuppetForge::Error
35
52
  end
36
53
 
37
- class ReleaseForbidden < PuppetForge::Error
38
- def self.from_response(response)
39
- body = JSON.parse(response[:body])
40
- new(body["message"])
41
- end
54
+ class ReleaseForbidden < PuppetForge::ErrorWithDetail
55
+ end
56
+
57
+ class ReleaseBadContent < PuppetForge::ErrorWithDetail
42
58
  end
43
59
  end
@@ -66,6 +66,9 @@ module PuppetForge
66
66
  uri_path = "v3/#{resource}/#{item}"
67
67
  end
68
68
 
69
+ # The API expects a space separated string. This allows the user to invoke it with a more natural feeling array.
70
+ params['endorsements'] = params['endorsements'].join(' ') if params['endorsements'].is_a? Array
71
+
69
72
  PuppetForge::V3::Base.conn.get uri_path, params
70
73
  end
71
74
 
@@ -2,6 +2,7 @@ require 'puppet_forge/v3/base'
2
2
  require 'puppet_forge/v3/module'
3
3
 
4
4
  require 'digest'
5
+ require 'base64'
5
6
 
6
7
  module PuppetForge
7
8
  module V3
@@ -38,6 +39,38 @@ module PuppetForge
38
39
  end
39
40
  end
40
41
 
42
+ # Uploads the tarbarll to the forge
43
+ #
44
+ # @param path [Pathname] tarball file path
45
+ # @return resp
46
+ def self.upload(path)
47
+ # We want to make sure that the file exists before trying to upload it
48
+ raise PuppetForge::FileNotFound, "The file '#{path}' does not exist." unless File.file?(path)
49
+
50
+ file = File.open(path, 'rb')
51
+ encoded_string = Base64.encode64(file.read)
52
+ data = { file: encoded_string }
53
+
54
+ resp = conn.post do |req|
55
+ req.url '/v3/releases'
56
+ req.headers['Content-Type'] = 'application/json'
57
+ req.body = data.to_json
58
+ end
59
+
60
+ [self, resp]
61
+ rescue Faraday::ClientError => e
62
+ if e.response
63
+ case e.response[:status]
64
+ when 403
65
+ raise PuppetForge::ReleaseForbidden.from_response(e.response)
66
+ when 400
67
+ raise PuppetForge::ReleaseBadContent.from_response(e.response)
68
+ end
69
+ end
70
+
71
+ raise e
72
+ end
73
+
41
74
  # Verify that a downloaded module matches the best available checksum in the metadata for this release,
42
75
  # validates SHA-256 checksum if available, otherwise validates MD5 checksum
43
76
  #
@@ -1,3 +1,3 @@
1
1
  module PuppetForge
2
- VERSION = '3.2.0' # Library version
2
+ VERSION = '4.1.0' # Library version
3
3
  end
data/puppet_forge.gemspec CHANGED
@@ -18,10 +18,10 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.required_ruby_version = '>= 2.4.0'
21
+ spec.required_ruby_version = '>= 2.6.0'
22
22
 
23
- spec.add_runtime_dependency "faraday", "~> 1.3"
24
- spec.add_runtime_dependency "faraday_middleware", "~> 1.0"
23
+ spec.add_runtime_dependency "faraday", "~> 2.0"
24
+ spec.add_runtime_dependency "faraday-follow_redirects", "~> 0.3.0"
25
25
  spec.add_dependency "semantic_puppet", "~> 1.0"
26
26
  spec.add_dependency "minitar"
27
27
 
@@ -31,8 +31,5 @@ Gem::Specification.new do |spec|
31
31
  spec.add_development_dependency "cane"
32
32
  spec.add_development_dependency "yard"
33
33
  spec.add_development_dependency "redcarpet"
34
-
35
- # Install the right pry debugging combo depending on ruby version.
36
- spec.add_development_dependency "pry-debugger" if RUBY_VERSION <= '1.9.3'
37
- spec.add_development_dependency "pry-byebug" if RUBY_VERSION >= '2.0.0'
34
+ spec.add_development_dependency "pry-byebug"
38
35
  end
@@ -218,5 +218,43 @@ describe PuppetForge::V3::Release do
218
218
  expect(release.created_at).to_not be nil
219
219
  end
220
220
  end
221
+
222
+ describe '#upload' do
223
+ let(:tarball) { "#{PROJECT_ROOT}/spec/tmp/module.tgz" }
224
+ let(:file_object) { double('file', read: 'file contents') }
225
+
226
+ let(:release) { PuppetForge::V3::Release.upload(tarball) }
227
+ let(:mock_conn) { instance_double('PuppetForge::V3::Connection', url_prefix: PuppetForge.host) }
228
+
229
+ context 'when there is no auth token provided' do
230
+ it 'raises PuppetForge::ReleaseForbidden' do
231
+ allow(File).to receive(:file?).and_return(true)
232
+ allow(File).to receive(:open).and_return(file_object)
233
+ allow(described_class).to receive(:conn).and_return(mock_conn)
234
+
235
+ response = { status: 403, body: { 'message' => 'Forbidden' }.to_json }
236
+ expect(mock_conn).to receive(:post).and_raise(Faraday::ClientError.new('Forbidden', response))
237
+ expect { release }.to raise_error(PuppetForge::ReleaseForbidden)
238
+ end
239
+ end
240
+
241
+ context 'when the module is not valid' do
242
+ it 'raises PuppetForge::ReleaseBadRequest' do
243
+ allow(File).to receive(:file?).and_return(true)
244
+ allow(File).to receive(:open).and_return(file_object)
245
+ allow(described_class).to receive(:conn).and_return(mock_conn)
246
+
247
+ response = { status: 400, body: { message: 'Bad Content' }.to_json }
248
+ expect(mock_conn).to receive(:post).and_raise(Faraday::ClientError.new('400', response))
249
+ expect { release }.to raise_error(PuppetForge::ReleaseBadContent)
250
+ end
251
+ end
252
+
253
+ context 'when the tarball does not exist' do
254
+ it 'raises PuppetForge::FileNotFound' do
255
+ expect { PuppetForge::V3::Release.upload(tarball) }.to raise_error(PuppetForge::FileNotFound)
256
+ end
257
+ end
258
+ end
221
259
  end
222
260
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: puppet_forge
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.2.0
4
+ version: 4.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Puppet Labs
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-11-09 00:00:00.000000000 Z
11
+ date: 2023-02-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -16,28 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.3'
19
+ version: '2.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.3'
26
+ version: '2.0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: faraday_middleware
28
+ name: faraday-follow_redirects
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '1.0'
33
+ version: 0.3.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: '1.0'
40
+ version: 0.3.0
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: semantic_puppet
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -173,6 +173,7 @@ extensions: []
173
173
  extra_rdoc_files: []
174
174
  files:
175
175
  - ".github/workflows/ruby-rspec.yml"
176
+ - ".github/workflows/snyk_merge.yml"
176
177
  - ".gitignore"
177
178
  - CHANGELOG.md
178
179
  - CODEOWNERS
@@ -250,7 +251,7 @@ homepage: https://github.com/puppetlabs/forge-ruby
250
251
  licenses:
251
252
  - Apache-2.0
252
253
  metadata: {}
253
- post_install_message:
254
+ post_install_message:
254
255
  rdoc_options: []
255
256
  require_paths:
256
257
  - lib
@@ -258,15 +259,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
258
259
  requirements:
259
260
  - - ">="
260
261
  - !ruby/object:Gem::Version
261
- version: 2.4.0
262
+ version: 2.6.0
262
263
  required_rubygems_version: !ruby/object:Gem::Requirement
263
264
  requirements:
264
265
  - - ">="
265
266
  - !ruby/object:Gem::Version
266
267
  version: '0'
267
268
  requirements: []
268
- rubygems_version: 3.1.6
269
- signing_key:
269
+ rubygems_version: 3.3.7
270
+ signing_key:
270
271
  specification_version: 4
271
272
  summary: Access the Puppet Forge API from Ruby for resource information and to download
272
273
  releases.