dependabot-hex 0.316.0 → 0.317.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: 35ac3ee29a60a6fb5e99abd18fdc2546dc2e5f4a3c8b1abefb96177ffde24137
4
- data.tar.gz: 8133bdfd85bba1a0535a16d0467d3916abf10e00a573f68388a512923e1bd24c
3
+ metadata.gz: 5f097b29911ce4e4e5a66d70b5d19b9b5e00a926d0002b21297ce08728b1ce9c
4
+ data.tar.gz: cd4dce441d5487bf3ff183cad03528f2f476342bb2a148d7d2e98f0590ebf8cb
5
5
  SHA512:
6
- metadata.gz: '09300a5e8ad34d961a657f290f26c4df26112265f6469d866ea65012b07fb0217ab3e74ecffa0d88f931c6ca1890a5b63a41b1e58e9e16bca8cfd43c30a72f7a'
7
- data.tar.gz: 53fff986fe0a530f17181322d6b4cb717f94b7dbefe7ee840f35a50523abbc13e702fe294799654efc246e5e4db57aa27d734a5308044f5ec94fb37b56518785
6
+ metadata.gz: d038b8da57cc411b7fedfe9587ee9beb4d56a18f908e1f3ca65df24e600bd315fd2987940ab86ccaf2171047a0e48d5c718546aacabfd7d193450e7f7cee90db
7
+ data.tar.gz: edbf6d10a78e9fe729dbb61b5ee2d4c3ac9afd99f1ec2225d47b68f2ac74e67be5368394888bb5822550f1a64195e2cac4d452d237069c7f854adf2e360a9ab9
@@ -0,0 +1,64 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ require "json"
5
+ require "time"
6
+ require "cgi"
7
+ require "excon"
8
+ require "nokogiri"
9
+ require "sorbet-runtime"
10
+ require "dependabot/registry_client"
11
+ require "dependabot/hex"
12
+ require "dependabot/hex/version"
13
+ require "dependabot/package/package_release"
14
+ require "dependabot/package/package_details"
15
+
16
+ module Dependabot
17
+ module Hex
18
+ module Package
19
+ class PackageDetailsFetcher
20
+ extend T::Sig
21
+
22
+ sig do
23
+ params(
24
+ dependency: Dependabot::Dependency
25
+ ).void
26
+ end
27
+ def initialize(dependency:)
28
+ @dependency = dependency
29
+
30
+ @dependency_url = T.let("https://hex.pm/api/packages/#{dependency.name}", T.nilable(String))
31
+ end
32
+
33
+ sig { returns(Dependabot::Dependency) }
34
+ attr_reader :dependency
35
+
36
+ sig { returns(T.nilable(T::Array[Dependabot::Package::PackageRelease])) }
37
+ def fetch_package_releases
38
+ releases = T.let([], T::Array[Dependabot::Package::PackageRelease])
39
+
40
+ begin
41
+ Dependabot.logger.info("Fetching package (hex) info for #{@dependency.name}")
42
+
43
+ response = Dependabot::RegistryClient.get(url: T.must(@dependency_url))
44
+ return releases unless response.status == 200
45
+
46
+ package_metadata = JSON.parse(response.body)&.fetch("releases", []) || []
47
+ package_metadata.each do |release|
48
+ releases << Dependabot::Package::PackageRelease.new(
49
+ version: Hex::Version.new(release["version"]),
50
+ released_at: release["inserted_at"] ? Time.new(release["inserted_at"]) : nil,
51
+ url: release["url"]
52
+ )
53
+ end
54
+
55
+ releases
56
+ rescue StandardError => e
57
+ Dependabot.logger.error("Error while fetching package info for hex packages: #{e.message}")
58
+ releases
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,120 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ require "excon"
5
+ require "json"
6
+ require "sorbet-runtime"
7
+
8
+ require "dependabot/errors"
9
+ require "dependabot/package/package_latest_version_finder"
10
+ require "dependabot/shared_helpers"
11
+ require "dependabot/update_checkers/version_filters"
12
+ require "dependabot/hex/file_parser"
13
+ require "dependabot/hex/package/package_details_fetcher"
14
+ require "dependabot/hex/requirement"
15
+ require "dependabot/hex/update_checker"
16
+ require "dependabot/hex/update_checker/requirements_updater"
17
+
18
+ module Dependabot
19
+ module Hex
20
+ class UpdateChecker
21
+ class LatestVersionFinder < Dependabot::Package::PackageLatestVersionFinder
22
+ extend T::Sig
23
+
24
+ sig do
25
+ params(
26
+ dependency: Dependabot::Dependency,
27
+ dependency_files: T::Array[Dependabot::DependencyFile],
28
+ credentials: T::Array[Dependabot::Credential],
29
+ ignored_versions: T::Array[String],
30
+ security_advisories: T::Array[Dependabot::SecurityAdvisory],
31
+ raise_on_ignored: T::Boolean,
32
+ options: T::Hash[Symbol, T.untyped],
33
+ cooldown_options: T.nilable(Dependabot::Package::ReleaseCooldownOptions)
34
+ ).void
35
+ end
36
+ def initialize(
37
+ dependency:,
38
+ dependency_files:,
39
+ credentials:,
40
+ ignored_versions:,
41
+ security_advisories:,
42
+ raise_on_ignored:,
43
+ options: {},
44
+ cooldown_options: nil
45
+ )
46
+ @dependency = dependency
47
+ @dependency_files = dependency_files
48
+ @credentials = credentials
49
+ @ignored_versions = ignored_versions
50
+ @security_advisories = security_advisories
51
+ @raise_on_ignored = raise_on_ignored
52
+ @options = options
53
+ @cooldown_options = cooldown_options
54
+ super
55
+ end
56
+
57
+ sig { returns(Dependabot::Dependency) }
58
+ attr_reader :dependency
59
+ sig { returns(T::Array[Dependabot::Credential]) }
60
+ attr_reader :credentials
61
+ sig { returns(T.nilable(Dependabot::Package::ReleaseCooldownOptions)) }
62
+ attr_reader :cooldown_options
63
+ sig { returns(T::Array[String]) }
64
+ attr_reader :ignored_versions
65
+ sig { returns(T::Array[Dependabot::SecurityAdvisory]) }
66
+ attr_reader :security_advisories
67
+ sig { override.returns(T.nilable(Dependabot::Package::PackageDetails)) }
68
+ def package_details; end
69
+
70
+ sig { returns(T.nilable(Dependabot::Version)) }
71
+ def release_version
72
+ releases = package_releases
73
+
74
+ releases = filter_prerelease_versions(T.must(releases))
75
+ releases = filter_ignored_versions(releases)
76
+ releases = filter_by_cooldown(releases)
77
+
78
+ releases.max_by(&:version)&.version
79
+ end
80
+
81
+ private
82
+
83
+ sig { returns(T.nilable(T::Array[Dependabot::Package::PackageRelease])) }
84
+ def package_releases
85
+ @package_releases = T.let(Dependabot::Hex::Package::PackageDetailsFetcher
86
+ .new(dependency: dependency)
87
+ .fetch_package_releases, T.nilable(T::Array[Dependabot::Package::PackageRelease]))
88
+ end
89
+
90
+ sig { override.returns(T::Boolean) }
91
+ def cooldown_enabled?
92
+ Dependabot::Experiments.enabled?(:enable_cooldown_for_hex)
93
+ end
94
+
95
+ sig { returns(T::Boolean) }
96
+ def wants_prerelease?
97
+ return true if current_version&.prerelease?
98
+
99
+ dependency.requirements.any? do |req|
100
+ req[:requirement]&.match?(/\d-[A-Za-z0-9]/)
101
+ end
102
+ end
103
+
104
+ sig { returns(T.nilable(Dependabot::Version)) }
105
+ def current_version
106
+ @current_version ||=
107
+ T.let(
108
+ dependency.numeric_version,
109
+ T.nilable(Dependabot::Version)
110
+ )
111
+ end
112
+
113
+ sig { returns(T.class_of(Dependabot::Version)) }
114
+ def version_class
115
+ dependency.version_class
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end
@@ -1,4 +1,4 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "excon"
@@ -12,11 +12,16 @@ require "json"
12
12
  module Dependabot
13
13
  module Hex
14
14
  class UpdateChecker < Dependabot::UpdateCheckers::Base
15
+ extend T::Sig
15
16
  require_relative "update_checker/file_preparer"
16
17
  require_relative "update_checker/requirements_updater"
17
18
  require_relative "update_checker/version_resolver"
19
+ require_relative "update_checker/latest_version_finder"
18
20
 
21
+ sig { override.returns(T.nilable(T.any(String, Dependabot::Version, Gem::Version))) }
19
22
  def latest_version
23
+ @latest_version = T.let(nil, T.nilable(T.any(String, Dependabot::Version, Gem::Version)))
24
+
20
25
  @latest_version ||=
21
26
  if git_dependency?
22
27
  latest_version_for_git_dependency
@@ -25,7 +30,10 @@ module Dependabot
25
30
  end
26
31
  end
27
32
 
33
+ sig { override.returns(T.nilable(T.any(String, Dependabot::Version, Gem::Version))) }
28
34
  def latest_resolvable_version
35
+ @latest_resolvable_version = T.let(nil, T.nilable(T.any(String, Dependabot::Version, Gem::Version)))
36
+
29
37
  @latest_resolvable_version ||=
30
38
  if git_dependency?
31
39
  latest_resolvable_version_for_git_dependency
@@ -34,7 +42,12 @@ module Dependabot
34
42
  end
35
43
  end
36
44
 
45
+ sig { override.returns(T.any(String, T.nilable(Dependabot::Version))) }
37
46
  def latest_resolvable_version_with_no_unlock
47
+ @latest_resolvable_version_with_no_unlock = T.let(
48
+ nil, T.any(String, T.nilable(Dependabot::Version))
49
+ )
50
+
38
51
  @latest_resolvable_version_with_no_unlock ||=
39
52
  if git_dependency?
40
53
  latest_resolvable_commit_with_unchanged_git_source
@@ -43,6 +56,7 @@ module Dependabot
43
56
  end
44
57
  end
45
58
 
59
+ sig { override.returns(T::Array[T::Hash[Symbol, T.untyped]]) }
46
60
  def updated_requirements
47
61
  RequirementsUpdater.new(
48
62
  requirements: dependency.requirements,
@@ -53,19 +67,18 @@ module Dependabot
53
67
 
54
68
  private
55
69
 
70
+ sig { override.returns(T::Boolean) }
56
71
  def latest_version_resolvable_with_full_unlock?
57
72
  # Full unlock checks aren't implemented for Elixir (yet)
58
73
  false
59
74
  end
60
75
 
76
+ sig { override.returns(T::Array[Dependabot::Dependency]) }
61
77
  def updated_dependencies_after_full_unlock
62
78
  raise NotImplementedError
63
79
  end
64
80
 
65
- def latest_version_for_git_dependency
66
- latest_git_version_sha
67
- end
68
-
81
+ sig { returns(T.any(String, T.nilable(Dependabot::Version))) }
69
82
  def latest_resolvable_version_for_git_dependency
70
83
  # If the gem isn't pinned, the latest version is just the latest
71
84
  # commit for the specified branch.
@@ -77,13 +90,14 @@ module Dependabot
77
90
  if git_commit_checker.pinned_ref_looks_like_version? &&
78
91
  latest_git_tag_is_resolvable?
79
92
  new_tag = git_commit_checker.local_tag_for_latest_version
80
- return new_tag.fetch(:commit_sha)
93
+ return T.must(new_tag).fetch(:commit_sha)
81
94
  end
82
95
 
83
96
  # If the dependency is pinned then there's nothing we can do.
84
97
  dependency.version
85
98
  end
86
99
 
100
+ sig { returns(T.any(String, T.nilable(Dependabot::Version))) }
87
101
  def latest_resolvable_commit_with_unchanged_git_source
88
102
  fetch_latest_resolvable_version(unlock_requirement: false)
89
103
  rescue SharedHelpers::HelperSubprocessFailed,
@@ -95,11 +109,13 @@ module Dependabot
95
109
  raise e
96
110
  end
97
111
 
112
+ sig { returns(T::Boolean) }
98
113
  def git_dependency?
99
114
  git_commit_checker.git_dependency?
100
115
  end
101
116
 
102
- def latest_git_version_sha
117
+ sig { returns(T.nilable(T.any(String, Dependabot::Version))) }
118
+ def latest_version_for_git_dependency
103
119
  # If the gem isn't pinned, the latest version is just the latest
104
120
  # commit for the specified branch.
105
121
  return git_commit_checker.head_commit_for_current_branch unless git_commit_checker.pinned?
@@ -117,10 +133,11 @@ module Dependabot
117
133
  dependency.version
118
134
  end
119
135
 
136
+ sig { returns(T::Boolean) }
120
137
  def latest_git_tag_is_resolvable?
121
- return @git_tag_resolvable if @latest_git_tag_is_resolvable_checked
138
+ return T.must(@git_tag_resolvable) if @latest_git_tag_is_resolvable_checked
122
139
 
123
- @latest_git_tag_is_resolvable_checked = true
140
+ @latest_git_tag_is_resolvable_checked = T.let(true, T.nilable(T::Boolean))
124
141
 
125
142
  return false if git_commit_checker.local_tag_for_latest_version.nil?
126
143
 
@@ -129,7 +146,7 @@ module Dependabot
129
146
  prepared_files = FilePreparer.new(
130
147
  dependency: dependency,
131
148
  dependency_files: dependency_files,
132
- replacement_git_pin: replacement_tag.fetch(:tag)
149
+ replacement_git_pin: T.must(replacement_tag).fetch(:tag)
133
150
  ).prepared_dependency_files
134
151
 
135
152
  resolver_result = VersionResolver.new(
@@ -144,9 +161,10 @@ module Dependabot
144
161
  Dependabot::DependencyFileNotResolvable => e
145
162
  raise e unless e.message.include?("resolution failed")
146
163
 
147
- @git_tag_resolvable = false
164
+ @git_tag_resolvable = T.let(false, T.nilable(T::Boolean))
148
165
  end
149
166
 
167
+ sig { returns(T.nilable(T::Hash[T.untyped, T.untyped])) }
150
168
  def updated_source
151
169
  # Never need to update source, unless a git_dependency
152
170
  return dependency_source_details unless git_dependency?
@@ -155,26 +173,32 @@ module Dependabot
155
173
  if git_commit_checker.pinned_ref_looks_like_version? &&
156
174
  latest_git_tag_is_resolvable?
157
175
  new_tag = git_commit_checker.local_tag_for_latest_version
158
- return dependency_source_details.merge(ref: new_tag.fetch(:tag))
176
+ return T.must(dependency_source_details).merge(ref: T.must(new_tag).fetch(:tag))
159
177
  end
160
178
 
161
179
  # Otherwise return the original source
162
180
  dependency_source_details
163
181
  end
164
182
 
183
+ sig { returns(T.nilable(T::Hash[T.any(String, Symbol), T.untyped])) }
165
184
  def dependency_source_details
166
185
  dependency.source_details
167
186
  end
168
187
 
188
+ sig do
189
+ params(unlock_requirement: T.any(T.nilable(Symbol), T::Boolean))
190
+ .returns(T.any(String, T.nilable(Dependabot::Version)))
191
+ end
169
192
  def fetch_latest_resolvable_version(unlock_requirement:)
170
- @latest_resolvable_version_hash ||= {}
193
+ @latest_resolvable_version_hash ||= T.let({}, T.nilable(T::Hash[T.untyped, T.untyped]))
171
194
  @latest_resolvable_version_hash[unlock_requirement] ||=
172
195
  version_resolver(unlock_requirement: unlock_requirement)
173
196
  .latest_resolvable_version
174
197
  end
175
198
 
199
+ sig { params(unlock_requirement: T.any(T.nilable(Symbol), T::Boolean)).returns(VersionResolver) }
176
200
  def version_resolver(unlock_requirement:)
177
- @version_resolver ||= {}
201
+ @version_resolver ||= T.let({}, T.nilable(T::Hash[T.untyped, T.untyped]))
178
202
  @version_resolver[unlock_requirement] ||=
179
203
  begin
180
204
  prepared_dependency_files = prepared_dependency_files(
@@ -191,6 +215,11 @@ module Dependabot
191
215
  end
192
216
  end
193
217
 
218
+ sig do
219
+ params(unlock_requirement: T.any(T.nilable(Symbol), T::Boolean),
220
+ latest_allowable_version: T.nilable(Dependabot::Version))
221
+ .returns(T::Array[Dependabot::DependencyFile])
222
+ end
194
223
  def prepared_dependency_files(unlock_requirement:,
195
224
  latest_allowable_version: nil)
196
225
  FilePreparer.new(
@@ -201,65 +230,25 @@ module Dependabot
201
230
  ).prepared_dependency_files
202
231
  end
203
232
 
204
- # rubocop:disable Metrics/PerceivedComplexity
233
+ sig { returns(T.nilable(Dependabot::Version)) }
205
234
  def latest_release_from_hex_registry
206
235
  @latest_release_from_hex_registry ||=
207
- begin
208
- versions = hex_registry_response&.fetch("releases", []) || []
209
- versions =
210
- versions
211
- .select { |release| version_class.correct?(release["version"]) }
212
- .map { |release| version_class.new(release["version"]) }
213
-
214
- versions.reject!(&:prerelease?) unless wants_prerelease?
215
-
216
- filtered = versions.reject do |v|
217
- ignore_requirements.any? { |r| r.satisfied_by?(v) }
218
- end
219
-
220
- if @raise_on_ignored && filter_lower_versions(filtered).empty? && filter_lower_versions(versions).any?
221
- raise AllVersionsIgnored
222
- end
223
-
224
- filtered.max
225
- end
226
- end
227
- # rubocop:enable Metrics/PerceivedComplexity
228
-
229
- def filter_lower_versions(versions_array)
230
- return versions_array unless current_version
231
-
232
- versions_array.select do |version|
233
- version > current_version
234
- end
235
- end
236
-
237
- def hex_registry_response
238
- return @hex_registry_response if @hex_registry_requested
239
-
240
- @hex_registry_requested = true
241
-
242
- response = Dependabot::RegistryClient.get(url: dependency_url)
243
- return unless response.status == 200
244
-
245
- @hex_registry_response = JSON.parse(response.body)
246
- rescue Excon::Error::Socket, Excon::Error::Timeout
247
- nil
248
- end
249
-
250
- def wants_prerelease?
251
- return true if current_version&.prerelease?
252
-
253
- dependency.requirements.any? do |req|
254
- req[:requirement]&.match?(/\d-[A-Za-z0-9]/)
255
- end
256
- end
257
-
258
- def dependency_url
259
- "https://hex.pm/api/packages/#{dependency.name}"
236
+ T.let(LatestVersionFinder.new(
237
+ dependency: dependency,
238
+ credentials: credentials,
239
+ dependency_files: dependency_files,
240
+ security_advisories: security_advisories,
241
+ ignored_versions: ignored_versions,
242
+ raise_on_ignored: raise_on_ignored,
243
+ cooldown_options: update_cooldown
244
+ ).release_version,
245
+ T.nilable(T.nilable(Dependabot::Version)))
260
246
  end
261
247
 
248
+ sig { returns(Dependabot::GitCommitChecker) }
262
249
  def git_commit_checker
250
+ @git_commit_checker = T.let(nil, T.nilable(Dependabot::GitCommitChecker))
251
+
263
252
  @git_commit_checker ||=
264
253
  GitCommitChecker.new(
265
254
  dependency: dependency,
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dependabot-hex
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.316.0
4
+ version: 0.317.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dependabot
@@ -15,14 +15,14 @@ dependencies:
15
15
  requirements:
16
16
  - - '='
17
17
  - !ruby/object:Gem::Version
18
- version: 0.316.0
18
+ version: 0.317.0
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - '='
24
24
  - !ruby/object:Gem::Version
25
- version: 0.316.0
25
+ version: 0.317.0
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: debug
28
28
  requirement: !ruby/object:Gem::Requirement
@@ -260,10 +260,12 @@ files:
260
260
  - lib/dependabot/hex/language.rb
261
261
  - lib/dependabot/hex/metadata_finder.rb
262
262
  - lib/dependabot/hex/native_helpers.rb
263
+ - lib/dependabot/hex/package/package_details_fetcher.rb
263
264
  - lib/dependabot/hex/package_manager.rb
264
265
  - lib/dependabot/hex/requirement.rb
265
266
  - lib/dependabot/hex/update_checker.rb
266
267
  - lib/dependabot/hex/update_checker/file_preparer.rb
268
+ - lib/dependabot/hex/update_checker/latest_version_finder.rb
267
269
  - lib/dependabot/hex/update_checker/requirements_updater.rb
268
270
  - lib/dependabot/hex/update_checker/version_resolver.rb
269
271
  - lib/dependabot/hex/version.rb
@@ -272,7 +274,7 @@ licenses:
272
274
  - MIT
273
275
  metadata:
274
276
  bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
275
- changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.316.0
277
+ changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.317.0
276
278
  rdoc_options: []
277
279
  require_paths:
278
280
  - lib