dependabot-bundler 0.138.2 → 0.138.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,185 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "native_spec_helper"
4
+ require "shared_contexts"
5
+
6
+ RSpec.describe Functions::DependencySource do
7
+ include_context "in a temporary bundler directory"
8
+
9
+ let(:dependency_source) do
10
+ described_class.new(
11
+ gemfile_name: "Gemfile",
12
+ dependency_name: dependency_name
13
+ )
14
+ end
15
+
16
+ let(:dependency_name) { "business" }
17
+
18
+ let(:project_name) { "specified_source_no_lockfile" }
19
+ let(:registry_url) { "https://repo.fury.io/greysteil/" }
20
+ let(:gemfury_business_url) do
21
+ "https://repo.fury.io/greysteil/api/v1/dependencies?gems=business"
22
+ end
23
+
24
+ before do
25
+ stub_request(:get, registry_url + "versions").
26
+ with(basic_auth: ["SECRET_CODES", ""]).
27
+ to_return(status: 404)
28
+ stub_request(:get, registry_url + "api/v1/dependencies").
29
+ with(basic_auth: ["SECRET_CODES", ""]).
30
+ to_return(status: 200)
31
+ stub_request(:get, gemfury_business_url).
32
+ with(basic_auth: ["SECRET_CODES", ""]).
33
+ to_return(status: 200, body: fixture("ruby", "gemfury_response"))
34
+ end
35
+
36
+ describe "#private_registry_versions" do
37
+ subject(:private_registry_versions) do
38
+ in_tmp_folder { dependency_source.private_registry_versions }
39
+ end
40
+
41
+ it "returns all versions from the private source" do
42
+ is_expected.to eq([
43
+ Gem::Version.new("1.5.0"),
44
+ Gem::Version.new("1.9.0"),
45
+ Gem::Version.new("1.10.0.beta")
46
+ ])
47
+ end
48
+
49
+ context "specified as the default source" do
50
+ let(:project_name) { "specified_default_source_no_lockfile" }
51
+
52
+ it "returns all versions from the private source" do
53
+ is_expected.to eq([
54
+ Gem::Version.new("1.5.0"),
55
+ Gem::Version.new("1.9.0"),
56
+ Gem::Version.new("1.10.0.beta")
57
+ ])
58
+ end
59
+ end
60
+
61
+ context "that we don't have authentication details for" do
62
+ before do
63
+ stub_request(:get, registry_url + "versions").
64
+ with(basic_auth: ["SECRET_CODES", ""]).
65
+ to_return(status: 401)
66
+ stub_request(:get, registry_url + "api/v1/dependencies").
67
+ with(basic_auth: ["SECRET_CODES", ""]).
68
+ to_return(status: 401)
69
+ stub_request(:get, registry_url + "specs.4.8.gz").
70
+ with(basic_auth: ["SECRET_CODES", ""]).
71
+ to_return(status: 401)
72
+ end
73
+
74
+ it "blows up with a useful error" do
75
+ error_class = Bundler::Fetcher::BadAuthenticationError
76
+ expect { private_registry_versions }.
77
+ to raise_error do |error|
78
+ expect(error).to be_a(error_class)
79
+ expect(error.message).to include("Bad username or password for")
80
+ end
81
+ end
82
+ end
83
+
84
+ context "that we have bad authentication details for" do
85
+ before do
86
+ stub_request(:get, registry_url + "versions").
87
+ with(basic_auth: ["SECRET_CODES", ""]).
88
+ to_return(status: 403)
89
+ stub_request(:get, registry_url + "api/v1/dependencies").
90
+ with(basic_auth: ["SECRET_CODES", ""]).
91
+ to_return(status: 403)
92
+ stub_request(:get, registry_url + "specs.4.8.gz").
93
+ with(basic_auth: ["SECRET_CODES", ""]).
94
+ to_return(status: 403)
95
+ end
96
+
97
+ it "blows up with a useful error" do
98
+ error_class = Bundler::Fetcher::BadAuthenticationError
99
+ expect { private_registry_versions }.
100
+ to raise_error do |error|
101
+ expect(error).to be_a(error_class)
102
+ expect(error.message).to include("Bad username or password for")
103
+ end
104
+ end
105
+ end
106
+
107
+ context "that bad-requested, but was a private repo" do
108
+ before do
109
+ stub_request(:get, registry_url + "versions").
110
+ with(basic_auth: ["SECRET_CODES", ""]).
111
+ to_return(status: 400)
112
+ stub_request(:get, registry_url + "api/v1/dependencies").
113
+ with(basic_auth: ["SECRET_CODES", ""]).
114
+ to_return(status: 400)
115
+ stub_request(:get, registry_url + "specs.4.8.gz").
116
+ with(basic_auth: ["SECRET_CODES", ""]).
117
+ to_return(status: 400)
118
+ end
119
+
120
+ it "blows up with a useful error" do
121
+ expect { private_registry_versions }.
122
+ to raise_error do |error|
123
+ expect(error).to be_a(Bundler::HTTPError)
124
+ expect(error.message).
125
+ to include("Could not fetch specs from")
126
+ end
127
+ end
128
+ end
129
+
130
+ context "that doesn't have details of the gem" do
131
+ before do
132
+ stub_request(:get, gemfury_business_url).
133
+ with(basic_auth: ["SECRET_CODES", ""]).
134
+ to_return(status: 404)
135
+
136
+ # Stub indexes to return details of other gems (but not this one)
137
+ stub_request(:get, registry_url + "specs.4.8.gz").
138
+ to_return(
139
+ status: 200,
140
+ body: fixture("ruby", "contribsys_old_index_response")
141
+ )
142
+ stub_request(:get, registry_url + "prerelease_specs.4.8.gz").
143
+ to_return(
144
+ status: 200,
145
+ body: fixture("ruby", "contribsys_old_index_prerelease_response")
146
+ )
147
+ end
148
+
149
+ it { is_expected.to be_empty }
150
+ end
151
+
152
+ context "that only implements the old Bundler index format..." do
153
+ let(:project_name) { "sidekiq_pro" }
154
+ let(:dependency_name) { "sidekiq-pro" }
155
+ let(:registry_url) { "https://gems.contribsys.com/" }
156
+
157
+ before do
158
+ stub_request(:get, registry_url + "versions").
159
+ with(basic_auth: %w(username password)).
160
+ to_return(status: 404)
161
+ stub_request(:get, registry_url + "api/v1/dependencies").
162
+ with(basic_auth: %w(username password)).
163
+ to_return(status: 404)
164
+ stub_request(:get, registry_url + "specs.4.8.gz").
165
+ with(basic_auth: %w(username password)).
166
+ to_return(
167
+ status: 200,
168
+ body: fixture("ruby", "contribsys_old_index_response")
169
+ )
170
+ stub_request(:get, registry_url + "prerelease_specs.4.8.gz").
171
+ with(basic_auth: %w(username password)).
172
+ to_return(
173
+ status: 200,
174
+ body: fixture("ruby", "contribsys_old_index_prerelease_response")
175
+ )
176
+ end
177
+
178
+ it "returns all versions from the private source" do
179
+ expect(private_registry_versions.length).to eql(70)
180
+ expect(private_registry_versions.min).to eql(Gem::Version.new("1.0.0"))
181
+ expect(private_registry_versions.max).to eql(Gem::Version.new("3.5.2"))
182
+ end
183
+ end
184
+ end
185
+ end
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "native_spec_helper"
4
+ require "shared_contexts"
5
+
6
+ RSpec.describe Functions::VersionResolver do
7
+ include_context "in a temporary bundler directory"
8
+ include_context "stub rubygems compact index"
9
+
10
+ let(:version_resolver) do
11
+ described_class.new(
12
+ dependency_name: dependency_name,
13
+ dependency_requirements: dependency_requirements,
14
+ gemfile_name: "Gemfile",
15
+ lockfile_name: "Gemfile.lock"
16
+ )
17
+ end
18
+
19
+ let(:dependency_name) { "business" }
20
+ let(:dependency_requirements) do
21
+ [{
22
+ file: "Gemfile",
23
+ requirement: requirement_string,
24
+ groups: [],
25
+ source: source
26
+ }]
27
+ end
28
+ let(:source) { nil }
29
+
30
+ let(:rubygems_url) { "https://index.rubygems.org/api/v1/" }
31
+ let(:old_index_url) { rubygems_url + "dependencies" }
32
+
33
+ describe "#version_details" do
34
+ subject do
35
+ in_tmp_folder { version_resolver.version_details }
36
+ end
37
+
38
+ let(:project_name) { "gemfile" }
39
+ let(:requirement_string) { " >= 0" }
40
+
41
+ its([:version]) { is_expected.to eq(Gem::Version.new("1.4.0")) }
42
+ its([:fetcher]) { is_expected.to eq("Bundler::Fetcher::CompactIndex") }
43
+
44
+ context "with a private gemserver source" do
45
+ include_context "stub rubygems compact index"
46
+
47
+ let(:project_name) { "specified_source" }
48
+ let(:requirement_string) { ">= 0" }
49
+
50
+ before do
51
+ gemfury_url = "https://repo.fury.io/greysteil/"
52
+ gemfury_deps_url = gemfury_url + "api/v1/dependencies"
53
+
54
+ stub_request(:get, gemfury_url + "versions").
55
+ to_return(status: 200, body: fixture("ruby", "gemfury-index"))
56
+ stub_request(:get, gemfury_url + "info/business").to_return(status: 404)
57
+ stub_request(:get, gemfury_deps_url).to_return(status: 200)
58
+ stub_request(:get, gemfury_deps_url + "?gems=business,statesman").
59
+ to_return(status: 200, body: fixture("ruby", "gemfury_response"))
60
+ stub_request(:get, gemfury_deps_url + "?gems=business").
61
+ to_return(status: 200, body: fixture("ruby", "gemfury_response"))
62
+ stub_request(:get, gemfury_deps_url + "?gems=statesman").
63
+ to_return(status: 200, body: fixture("ruby", "gemfury_response"))
64
+ end
65
+
66
+ its([:version]) { is_expected.to eq(Gem::Version.new("1.9.0")) }
67
+ its([:fetcher]) { is_expected.to eq("Bundler::Fetcher::Dependency") }
68
+ end
69
+
70
+ context "with a git source" do
71
+ let(:project_name) { "git_source" }
72
+
73
+ its([:version]) { is_expected.to eq(Gem::Version.new("1.6.0")) }
74
+ its([:fetcher]) { is_expected.to be_nil }
75
+ end
76
+
77
+ context "when Bundler's compact index is down" do
78
+ before do
79
+ stub_request(:get, "https://index.rubygems.org/versions").
80
+ to_return(status: 500, body: "We'll be back soon")
81
+ stub_request(:get, "https://index.rubygems.org/info/public_suffix").
82
+ to_return(status: 500, body: "We'll be back soon")
83
+ stub_request(:get, old_index_url).to_return(status: 200)
84
+ stub_request(:get, old_index_url + "?gems=business,statesman").
85
+ to_return(
86
+ status: 200,
87
+ body: fixture("ruby",
88
+ "rubygems_responses",
89
+ "dependencies-default-gemfile")
90
+ )
91
+ end
92
+
93
+ its([:version]) { is_expected.to eq(Gem::Version.new("1.4.0")) }
94
+ its([:fetcher]) { is_expected.to eq("Bundler::Fetcher::Dependency") }
95
+ end
96
+ end
97
+ end
@@ -1,33 +1,24 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "native_spec_helper"
4
+ require "shared_contexts"
4
5
 
5
6
  RSpec.describe Functions do
6
- # Verify v1 method signatures are exist, but raise as NYI
7
- {
8
- vendor_cache_dir: [ :dir ],
9
- update_lockfile: [ :dir, :gemfile_name, :lockfile_name, :using_bundler2, :credentials, :dependencies ],
10
- force_update: [ :dir, :dependency_name, :target_version, :gemfile_name, :lockfile_name, :using_bundler2,
11
- :credentials, :update_multiple_dependencies ],
12
- dependency_source_type: [ :gemfile_name, :dependency_name, :dir, :credentials ],
13
- depencency_source_latest_git_version: [ :gemfile_name, :dependency_name, :dir, :credentials, :dependency_source_url,
14
- :dependency_source_branch ],
15
- private_registry_versions: [:gemfile_name, :dependency_name, :dir, :credentials ],
16
- resolve_version: [:dependency_name, :dependency_requirements, :gemfile_name, :lockfile_name, :using_bundler2,
17
- :dir, :credentials],
18
- jfrog_source: [:dir, :gemfile_name, :credentials, :using_bundler2],
19
- git_specs: [:dir, :gemfile_name, :credentials, :using_bundler2],
20
- conflicting_dependencies: [:dir, :dependency_name, :target_version, :lockfile_name, :using_bundler2, :credentials]
21
- }.each do |function, kwargs|
22
- describe "::#{function}" do
23
- let(:args) do
24
- kwargs.inject({}) do |args, keyword|
25
- args.merge({ keyword => anything })
26
- end
27
- end
7
+ include_context "in a temporary bundler directory"
8
+
9
+ describe "#jfrog_source" do
10
+ let(:project_name) { "jfrog_source" }
11
+
12
+ it "returns the jfrog source" do
13
+ in_tmp_folder do
14
+ jfrog_source = Functions.jfrog_source(
15
+ dir: tmp_path,
16
+ gemfile_name: "Gemfile",
17
+ credentials: {},
18
+ using_bundler2: true
19
+ )
28
20
 
29
- it "raises a NYI" do
30
- expect { Functions.send(function, **args) }.to raise_error(Functions::NotImplementedError)
21
+ expect(jfrog_source).to eq("test.jfrog.io")
31
22
  end
32
23
  end
33
24
  end
@@ -26,7 +26,11 @@ end
26
26
  LOCKFILE_ENDING = /(?<ending>\s*(?:RUBY VERSION|BUNDLED WITH).*)/m.freeze
27
27
 
28
28
  def project_dependency_files(project)
29
+ # TODO: Retrieve files from bundler2 folder once it is fully up to date
29
30
  project_path = File.expand_path(File.join("../../spec/fixtures/projects/bundler1", project))
31
+
32
+ raise "Fixture does not exist for project: '#{project}'" unless Dir.exist?(project_path)
33
+
30
34
  Dir.chdir(project_path) do
31
35
  # NOTE: Include dotfiles (e.g. .npmrc)
32
36
  files = Dir.glob("**/*", File::FNM_DOTMATCH)
@@ -167,6 +167,8 @@ module Dependabot
167
167
  req_string.include?(" ")
168
168
  end
169
169
 
170
+ EQUALITY_OPERATOR = /(?<![<>!])=/.freeze
171
+
170
172
  def use_equality_operator?(requirement_nodes)
171
173
  return true if requirement_nodes.none?
172
174
 
@@ -178,7 +180,7 @@ module Dependabot
178
180
  requirement_nodes.first.children.first.loc.expression.source
179
181
  end
180
182
 
181
- req_string.match?(/(?<![<>])=/)
183
+ req_string.match?(EQUALITY_OPERATOR)
182
184
  end
183
185
 
184
186
  def new_requirement_string(quote_characters:,
@@ -203,7 +205,7 @@ module Dependabot
203
205
  # Gem::Requirement serializes exact matches as a string starting
204
206
  # with `=`. We may need to remove that equality operator if it
205
207
  # wasn't used originally.
206
- tmp_req = tmp_req.gsub(/(?<![<>])=/, "") unless use_equality_operator
208
+ tmp_req = tmp_req.gsub(EQUALITY_OPERATOR, "") unless use_equality_operator
207
209
 
208
210
  tmp_req.strip
209
211
  end
@@ -359,20 +359,18 @@ module Dependabot
359
359
  @version_resolver ||= {}
360
360
  @version_resolver[remove_git_source] ||= {}
361
361
  @version_resolver[remove_git_source][unlock_requirement] ||=
362
- begin
363
- VersionResolver.new(
364
- dependency: dependency,
365
- unprepared_dependency_files: dependency_files,
366
- repo_contents_path: repo_contents_path,
367
- credentials: credentials,
368
- ignored_versions: ignored_versions,
369
- raise_on_ignored: raise_on_ignored,
370
- remove_git_source: remove_git_source,
371
- unlock_requirement: unlock_requirement,
372
- latest_allowable_version: latest_version,
373
- options: options
374
- )
375
- end
362
+ VersionResolver.new(
363
+ dependency: dependency,
364
+ unprepared_dependency_files: dependency_files,
365
+ repo_contents_path: repo_contents_path,
366
+ credentials: credentials,
367
+ ignored_versions: ignored_versions,
368
+ raise_on_ignored: raise_on_ignored,
369
+ remove_git_source: remove_git_source,
370
+ unlock_requirement: unlock_requirement,
371
+ latest_allowable_version: latest_version,
372
+ options: options
373
+ )
376
374
  end
377
375
 
378
376
  def latest_version_finder(remove_git_source:)
@@ -188,7 +188,7 @@ module Dependabot
188
188
  req
189
189
  end
190
190
  when "<", "<=" then [update_greatest_version(req, latest_version)]
191
- when "~>" then convert_twidle_to_range(req, latest_version)
191
+ when "~>" then convert_twiddle_to_range(req, latest_version)
192
192
  when "!=" then []
193
193
  when ">", ">=" then raise UnfixableRequirement
194
194
  else raise "Unexpected operation for requirement: #{op}"
@@ -214,7 +214,7 @@ module Dependabot
214
214
  end
215
215
  end
216
216
 
217
- def convert_twidle_to_range(requirement, version_to_be_permitted)
217
+ def convert_twiddle_to_range(requirement, version_to_be_permitted)
218
218
  version = requirement.requirements.first.last
219
219
  version = version.release if version.prerelease?
220
220
 
@@ -187,7 +187,9 @@ module Dependabot
187
187
  end
188
188
 
189
189
  def jfrog_source
190
- in_a_native_bundler_context(error_handling: false) do |dir|
190
+ return @jfrog_source unless defined?(@jfrog_source)
191
+
192
+ @jfrog_source = in_a_native_bundler_context(error_handling: false) do |dir|
191
193
  NativeHelpers.run_bundler_subprocess(
192
194
  bundler_version: bundler_version,
193
195
  function: "jfrog_source",
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dependabot-bundler
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.138.2
4
+ version: 0.138.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dependabot
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-03-23 00:00:00.000000000 Z
11
+ date: 2021-03-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dependabot-common
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 0.138.2
19
+ version: 0.138.7
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: 0.138.2
26
+ version: 0.138.7
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: byebug
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -100,14 +100,14 @@ dependencies:
100
100
  requirements:
101
101
  - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: 1.11.0
103
+ version: 1.12.0
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: 1.11.0
110
+ version: 1.12.0
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: simplecov
113
113
  requirement: !ruby/object:Gem::Requirement
@@ -210,12 +210,20 @@ files:
210
210
  - helpers/v2/Gemfile
211
211
  - helpers/v2/build
212
212
  - helpers/v2/lib/functions.rb
213
+ - helpers/v2/lib/functions/conflicting_dependency_resolver.rb
214
+ - helpers/v2/lib/functions/dependency_source.rb
213
215
  - helpers/v2/lib/functions/file_parser.rb
216
+ - helpers/v2/lib/functions/force_updater.rb
217
+ - helpers/v2/lib/functions/lockfile_updater.rb
218
+ - helpers/v2/lib/functions/version_resolver.rb
214
219
  - helpers/v2/monkey_patches/definition_bundler_version_patch.rb
215
220
  - helpers/v2/monkey_patches/definition_ruby_version_patch.rb
216
221
  - helpers/v2/monkey_patches/git_source_patch.rb
217
222
  - helpers/v2/run.rb
223
+ - helpers/v2/spec/functions/conflicting_dependency_resolver_spec.rb
224
+ - helpers/v2/spec/functions/dependency_source_spec.rb
218
225
  - helpers/v2/spec/functions/file_parser_spec.rb
226
+ - helpers/v2/spec/functions/version_resolver_spec.rb
219
227
  - helpers/v2/spec/functions_spec.rb
220
228
  - helpers/v2/spec/native_spec_helper.rb
221
229
  - helpers/v2/spec/shared_contexts.rb