dependabot-bundler 0.103.3 → 0.104.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: 214bad1306bd5538779ee55ebeeb76af02b308953e71fe653d7a63b673c2dd3c
4
- data.tar.gz: 47e3c1131ef1081a2ef05c7cd999c03520a2379864e387d459a875fff67bef46
3
+ metadata.gz: b3955c8a3cb5756607028ee4f13ca8ffd2f8578f9b4c5b247fc56ccc7f4865d2
4
+ data.tar.gz: 5b18aa92559e79eab68c4f70e39213ed32aee3e6324ce0f7acf38693d7f0c4b3
5
5
  SHA512:
6
- metadata.gz: 52b483b4826f43a8c7df4f3cd063078928549ec89c412cea2767287a66ff11ae571657fecf1b1dc3f2603e8db184bb3a6895cf9ddfaa205d64611a04595172e6
7
- data.tar.gz: f30c7a957cfc0e0dd1104a6c0b29f46c63b1adf0b1d1957dce8a5eaac826f8df0493adadf90e0a63d564d22e46cf5b477d815d83c7a2e5a16df1eea5035626fa
6
+ metadata.gz: dadadec7982214f33fadacc7708b0a238b62ef1fc64d07cf2de1600194c0a28fc179d45909f98ae96e37012f26f5a5d151f310560e2b20bccb36b0a60e634c07
7
+ data.tar.gz: d8ad86d4c6899e16442f021fe69d9aaf4bfc15703ae5bc8609c4e032603cb243e35af7518e4d48d0cd21236ef23a42fc9adb80d9ff55d721fe87d1d29e983b3f
@@ -6,6 +6,7 @@ require "dependabot/bundler/file_updater/requirement_replacer"
6
6
  require "dependabot/bundler/version"
7
7
  require "dependabot/git_commit_checker"
8
8
 
9
+ # rubocop:disable Metrics/ClassLength
9
10
  module Dependabot
10
11
  module Bundler
11
12
  class UpdateChecker < Dependabot::UpdateCheckers::Base
@@ -27,6 +28,18 @@ module Dependabot
27
28
  latest_resolvable_version_details&.fetch(:version)
28
29
  end
29
30
 
31
+ def lowest_resolvable_security_fix_version
32
+ raise "Dependency not vulnerable!" unless vulnerable?
33
+ return latest_resolvable_version if git_dependency?
34
+
35
+ lowest_fix =
36
+ latest_version_finder(remove_git_source: false).
37
+ lowest_security_fix_version
38
+ return unless lowest_fix
39
+
40
+ resolvable?(lowest_fix) ? lowest_fix : latest_resolvable_version
41
+ end
42
+
30
43
  def latest_resolvable_version_with_no_unlock
31
44
  current_ver = dependency.version
32
45
  return current_ver if git_dependency? && git_commit_checker.pinned?
@@ -63,18 +76,15 @@ module Dependabot
63
76
  updated_source: updated_source,
64
77
  latest_version: latest_version_details&.fetch(:version)&.to_s,
65
78
  latest_resolvable_version:
66
- latest_resolvable_version_details&.fetch(:version)&.to_s
79
+ preferred_resolvable_version_details&.fetch(:version)&.to_s
67
80
  ).updated_requirements
68
81
  end
69
82
  end
70
83
 
71
84
  def requirements_unlocked_or_can_be?
72
85
  dependency.requirements.
73
- reject { |r| r[:requirement].nil? }.
86
+ select { |r| requirement_class.new(r[:requirement]).specific? }.
74
87
  all? do |req|
75
- requirement = requirement_class.new(req[:requirement])
76
- next true if requirement.satisfied_by?(Gem::Version.new("100000"))
77
-
78
88
  file = dependency_files.find { |f| f.name == req.fetch(:file) }
79
89
  updated = FileUpdater::RequirementReplacer.new(
80
90
  dependency: dependency,
@@ -118,10 +128,36 @@ module Dependabot
118
128
  force_updater.updated_dependencies
119
129
  end
120
130
 
131
+ def preferred_resolvable_version_details
132
+ if vulnerable?
133
+ return { version: lowest_resolvable_security_fix_version }
134
+ end
135
+
136
+ latest_resolvable_version_details
137
+ end
138
+
121
139
  def git_dependency?
122
140
  git_commit_checker.git_dependency?
123
141
  end
124
142
 
143
+ def resolvable?(version)
144
+ @resolvable ||= {}
145
+ @resolvable[version] ||=
146
+ begin
147
+ ForceUpdater.new(
148
+ dependency: dependency,
149
+ dependency_files: dependency_files,
150
+ credentials: credentials,
151
+ target_version: version,
152
+ requirements_update_strategy: requirements_update_strategy,
153
+ update_multiple_dependencies: false
154
+ ).updated_dependencies
155
+ true
156
+ rescue Dependabot::DependencyFileNotResolvable
157
+ false
158
+ end
159
+ end
160
+
125
161
  def latest_version_details(remove_git_source: false)
126
162
  @latest_version_details ||= {}
127
163
  @latest_version_details[remove_git_source] ||=
@@ -331,7 +367,8 @@ module Dependabot
331
367
  dependency: dependency,
332
368
  dependency_files: prepared_dependency_files,
333
369
  credentials: credentials,
334
- ignored_versions: ignored_versions
370
+ ignored_versions: ignored_versions,
371
+ security_advisories: security_advisories
335
372
  )
336
373
  end
337
374
  end
@@ -349,6 +386,7 @@ module Dependabot
349
386
  end
350
387
  end
351
388
  end
389
+ # rubocop:enable Metrics/ClassLength
352
390
 
353
391
  Dependabot::UpdateCheckers.
354
392
  register("bundler", Dependabot::Bundler::UpdateChecker)
@@ -16,12 +16,14 @@ module Dependabot
16
16
  class UpdateChecker
17
17
  class ForceUpdater
18
18
  def initialize(dependency:, dependency_files:, credentials:,
19
- target_version:, requirements_update_strategy:)
19
+ target_version:, requirements_update_strategy:,
20
+ update_multiple_dependencies: true)
20
21
  @dependency = dependency
21
22
  @dependency_files = dependency_files
22
23
  @credentials = credentials
23
24
  @target_version = target_version
24
25
  @requirements_update_strategy = requirements_update_strategy
26
+ @update_multiple_dependencies = update_multiple_dependencies
25
27
  end
26
28
 
27
29
  def updated_dependencies
@@ -33,6 +35,10 @@ module Dependabot
33
35
  attr_reader :dependency, :dependency_files, :credentials,
34
36
  :target_version, :requirements_update_strategy
35
37
 
38
+ def update_multiple_dependencies?
39
+ @update_multiple_dependencies
40
+ end
41
+
36
42
  def force_update
37
43
  in_a_temporary_bundler_context do
38
44
  other_updates = []
@@ -43,6 +49,8 @@ module Dependabot
43
49
  specs = definition.resolve
44
50
  dependencies_from([dependency] + other_updates, specs)
45
51
  rescue ::Bundler::VersionConflict => e
52
+ raise unless update_multiple_dependencies?
53
+
46
54
  # TODO: Not sure this won't unlock way too many things...
47
55
  new_dependencies_to_unlock =
48
56
  new_dependencies_to_unlock_from(
@@ -19,82 +19,116 @@ module Dependabot
19
19
  include SharedBundlerHelpers
20
20
 
21
21
  def initialize(dependency:, dependency_files:, credentials:,
22
- ignored_versions:)
23
- @dependency = dependency
24
- @dependency_files = dependency_files
25
- @credentials = credentials
26
- @ignored_versions = ignored_versions
22
+ ignored_versions:, security_advisories:)
23
+ @dependency = dependency
24
+ @dependency_files = dependency_files
25
+ @credentials = credentials
26
+ @ignored_versions = ignored_versions
27
+ @security_advisories = security_advisories
27
28
  end
28
29
 
29
30
  def latest_version_details
30
31
  @latest_version_details ||= fetch_latest_version_details
31
32
  end
32
33
 
34
+ def lowest_security_fix_version
35
+ @lowest_security_fix_version ||= fetch_lowest_security_fix_version
36
+ end
37
+
33
38
  private
34
39
 
35
40
  attr_reader :dependency, :dependency_files, :credentials,
36
- :ignored_versions
41
+ :ignored_versions, :security_advisories
37
42
 
38
43
  def fetch_latest_version_details
39
- return latest_rubygems_version_details if dependency.name == "bundler"
40
-
41
- case dependency_source
42
- when NilClass then latest_rubygems_version_details
43
- when ::Bundler::Source::Rubygems
44
- if dependency_source.remotes.none? ||
45
- dependency_source.remotes.first.to_s == "https://rubygems.org/"
46
- latest_rubygems_version_details
47
- else
48
- latest_private_version_details
49
- end
50
- when ::Bundler::Source::Git then latest_git_version_details
44
+ if dependency_source.is_a?(::Bundler::Source::Git) &&
45
+ dependency.name != "bundler"
46
+ return latest_git_version_details
51
47
  end
48
+
49
+ relevant_versions = registry_versions
50
+ relevant_versions = filter_prerelease_versions(relevant_versions)
51
+ relevant_versions = filter_ignored_versions(relevant_versions)
52
+
53
+ relevant_versions.empty? ? nil : { version: relevant_versions.max }
52
54
  end
53
55
 
54
- def latest_rubygems_version_details
55
- response = Excon.get(
56
- "https://rubygems.org/api/v1/versions/#{dependency.name}.json",
57
- idempotent: true,
58
- **SharedHelpers.excon_defaults
59
- )
56
+ def fetch_lowest_security_fix_version
57
+ return if dependency_source.is_a?(::Bundler::Source::Git)
60
58
 
61
- relevant_versions =
62
- JSON.parse(response.body).
63
- reject do |d|
64
- version = Gem::Version.new(d["number"])
65
- next true if version.prerelease? && !wants_prerelease?
66
- next true if ignore_reqs.any? { |r| r.satisfied_by?(version) }
59
+ relevant_versions = registry_versions
60
+ relevant_versions = filter_prerelease_versions(relevant_versions)
61
+ relevant_versions = filter_ignored_versions(relevant_versions)
62
+ relevant_versions = filter_vulnerable_versions(relevant_versions)
63
+ relevant_versions = filter_lower_versions(relevant_versions)
67
64
 
68
- false
69
- end
65
+ relevant_versions.min
66
+ end
70
67
 
71
- dep = relevant_versions.max_by { |d| Gem::Version.new(d["number"]) }
72
- return unless dep
68
+ def filter_prerelease_versions(versions_array)
69
+ versions_array.
70
+ reject { |v| v.prerelease? && !wants_prerelease? }
71
+ end
72
+
73
+ def filter_ignored_versions(versions_array)
74
+ versions_array.
75
+ reject { |v| ignore_reqs.any? { |r| r.satisfied_by?(v) } }
76
+ end
77
+
78
+ def filter_vulnerable_versions(versions_array)
79
+ arr = versions_array
80
+
81
+ security_advisories.each do |advisory|
82
+ arr = arr.reject { |v| advisory.vulnerable?(v) }
83
+ end
84
+
85
+ arr
86
+ end
73
87
 
74
- {
75
- version: Gem::Version.new(dep["number"]),
76
- sha: dep["sha"]
77
- }
88
+ def filter_lower_versions(versions_array)
89
+ versions_array.
90
+ select { |version| version > Gem::Version.new(dependency.version) }
91
+ end
92
+
93
+ def registry_versions
94
+ return rubygems_versions if dependency.name == "bundler"
95
+ return rubygems_versions unless dependency_source
96
+ return [] unless dependency_source.is_a?(::Bundler::Source::Rubygems)
97
+
98
+ remote = dependency_source.remotes.first
99
+ return rubygems_versions if remote.nil?
100
+ return rubygems_versions if remote.to_s == "https://rubygems.org/"
101
+
102
+ private_registry_versions
103
+ end
104
+
105
+ def rubygems_versions
106
+ @rubygems_versions ||=
107
+ begin
108
+ response = Excon.get(
109
+ "https://rubygems.org/api/v1/versions/#{dependency.name}.json",
110
+ idempotent: true,
111
+ **SharedHelpers.excon_defaults
112
+ )
113
+
114
+ JSON.parse(response.body).
115
+ map { |d| Gem::Version.new(d["number"]) }
116
+ end
78
117
  rescue JSON::ParserError, Excon::Error::Timeout
79
- nil
118
+ @rubygems_versions = []
80
119
  end
81
120
 
82
- def latest_private_version_details
83
- in_a_temporary_bundler_context do
84
- spec =
121
+ def private_registry_versions
122
+ @private_registry_versions ||=
123
+ in_a_temporary_bundler_context do
85
124
  dependency_source.
86
- fetchers.flat_map do |fetcher|
87
- fetcher.
88
- specs_with_retry([dependency.name], dependency_source).
89
- search_all(dependency.name).
90
- reject { |s| s.version.prerelease? && !wants_prerelease? }.
91
- reject do |s|
92
- ignore_reqs.any? { |r| r.satisfied_by?(s.version) }
93
- end
94
- end.
95
- max_by(&:version)
96
- spec.nil? ? nil : { version: spec.version }
97
- end
125
+ fetchers.flat_map do |fetcher|
126
+ fetcher.
127
+ specs_with_retry([dependency.name], dependency_source).
128
+ search_all(dependency.name)
129
+ end.
130
+ map(&:version)
131
+ end
98
132
  end
99
133
 
100
134
  def latest_git_version_details
@@ -270,7 +270,8 @@ module Dependabot
270
270
  dependency: dependency,
271
271
  dependency_files: dependency_files,
272
272
  credentials: credentials,
273
- ignored_versions: ignored_versions
273
+ ignored_versions: ignored_versions,
274
+ security_advisories: []
274
275
  ).latest_version_details
275
276
  end
276
277
 
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.103.3
4
+ version: 0.104.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dependabot
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-04-14 00:00:00.000000000 Z
11
+ date: 2019-04-16 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.103.3
19
+ version: 0.104.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: 0.103.3
26
+ version: 0.104.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: byebug
29
29
  requirement: !ruby/object:Gem::Requirement