dependabot-hex 0.332.0 → 0.333.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: 65267b78a2189ab82e3a952dccb5468c5c786ee6f6dfc33e2bd0ed84161f136c
4
- data.tar.gz: b7412fa72b891da510e724fcf372ae1f1f5a00836c093b78c5411fd8bd3d7f22
3
+ metadata.gz: f286072dcda605590c5ba5f897e77265f75e0fe9d8921cbe61340a4588cff115
4
+ data.tar.gz: 2a9ad6bb806461c48df4d401301752ab0a61aa0f602f7c3c4940634ccd7da268
5
5
  SHA512:
6
- metadata.gz: a4230d09236ef6ceee11f6a9d0acf7ad846a80533ebeb9ea1069426a28eca6ec4b51e4eeb1e9ff473f08f44493768cbefccb2b6f1a039b33f35091f29567a71e
7
- data.tar.gz: 4074991d5ae39a2789755ef025951816deca60d1e8e22ad849d9f949f817bde59a4909341cd29b4cbaa9f5cb706b2d02f3a663a34ef2adc6b7dc2148191374ef
6
+ metadata.gz: c16d7e0dd44dc71a9f3d2209062715588b5d238b8eb144eb63caeff4e0901448147fb423c8f6e90445af9bb6bdce5d8d8542e39ded0eaa6183513e5f7a98a4b7
7
+ data.tar.gz: 3af81cc43c90df269cd7ddb72c3e740e7e399324978abf48da0b6483bb9805b6a444f21d49a218f8e8fa9550a7b47e72a6ef7cb95eeba4bf5ee3f5516f3772d1
@@ -4,6 +4,7 @@
4
4
  require "sorbet-runtime"
5
5
  require "dependabot/file_fetchers"
6
6
  require "dependabot/file_fetchers/base"
7
+ require "dependabot/file_filtering"
7
8
 
8
9
  module Dependabot
9
10
  module Hex
@@ -34,7 +35,12 @@ module Dependabot
34
35
  fetched_files << lockfile if lockfile
35
36
  fetched_files += subapp_mixfiles
36
37
  fetched_files += support_files
37
- fetched_files
38
+ # Apply final filtering to exclude any files that match the exclude_paths configuration
39
+ filtered_files = fetched_files.compact.reject do |file|
40
+ Dependabot::FileFiltering.should_exclude_path?(file.name, "file from final collection", @exclude_paths)
41
+ end
42
+
43
+ filtered_files
38
44
  end
39
45
 
40
46
  private
@@ -62,14 +68,22 @@ module Dependabot
62
68
  &.named_captures&.fetch("path")
63
69
  return [] unless apps_path
64
70
 
65
- repo_contents(dir: apps_path)
66
- .select { |f| f.type == "dir" }
67
- .map { |f| File.join(apps_path, f.name) }
71
+ directories = repo_contents(dir: apps_path)
72
+ .select { |f| f.type == "dir" }
73
+ .map { |f| File.join(apps_path, f.name) }
74
+
75
+ directories.reject do |dir|
76
+ Dependabot::FileFiltering.should_exclude_path?(dir, "umbrella app directory", @exclude_paths)
77
+ end
68
78
  end
69
79
 
70
80
  sig { returns(T::Array[String]) }
71
81
  def sub_project_directories
72
- T.must(T.must(mixfile).content).scan(PATH_DEPS_REGEX).flatten
82
+ directories = T.must(T.must(mixfile).content).scan(PATH_DEPS_REGEX).flatten
83
+
84
+ directories.reject do |dir|
85
+ Dependabot::FileFiltering.should_exclude_path?(dir, "path dependency directory", @exclude_paths)
86
+ end
73
87
  end
74
88
 
75
89
  sig { returns(T::Array[Dependabot::DependencyFile]) }
@@ -17,8 +17,10 @@ require "dependabot/errors"
17
17
  module Dependabot
18
18
  module Hex
19
19
  extend T::Sig
20
+
20
21
  class FileParser < Dependabot::FileParsers::Base
21
22
  extend T::Sig
23
+
22
24
  require "dependabot/file_parsers/base/dependency_set"
23
25
 
24
26
  sig { override.returns(T::Array[Dependabot::Dependency]) }
@@ -1,6 +1,8 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
+ require "sorbet-runtime"
5
+
4
6
  require "dependabot/hex/file_updater"
5
7
  require "dependabot/hex/file_updater/mixfile_updater"
6
8
  require "dependabot/hex/file_updater/mixfile_sanitizer"
@@ -14,13 +16,24 @@ module Dependabot
14
16
  module Hex
15
17
  class FileUpdater
16
18
  class LockfileUpdater
19
+ extend T::Sig
20
+
21
+ sig do
22
+ params(
23
+ dependencies: T::Array[Dependabot::Dependency],
24
+ dependency_files: T::Array[Dependabot::DependencyFile],
25
+ credentials: T::Array[Dependabot::Credential]
26
+ ).void
27
+ end
17
28
  def initialize(dependencies:, dependency_files:, credentials:)
18
- @dependencies = dependencies
19
- @dependency_files = dependency_files
20
- @credentials = credentials
29
+ @dependencies = T.let(dependencies, T::Array[Dependabot::Dependency])
30
+ @dependency_files = T.let(dependency_files, T::Array[Dependabot::DependencyFile])
31
+ @credentials = T.let(credentials, T::Array[Dependabot::Credential])
21
32
  end
22
33
 
34
+ sig { returns(String) }
23
35
  def updated_lockfile_content
36
+ @updated_lockfile_content = T.let(@updated_lockfile_content, T.nilable(String))
24
37
  @updated_lockfile_content ||=
25
38
  SharedHelpers.in_a_temporary_directory do
26
39
  write_temporary_dependency_files
@@ -41,23 +54,32 @@ module Dependabot
41
54
 
42
55
  private
43
56
 
57
+ sig { returns(T::Array[Dependabot::Dependency]) }
44
58
  attr_reader :dependencies
59
+
60
+ sig { returns(T::Array[Dependabot::DependencyFile]) }
45
61
  attr_reader :dependency_files
62
+
63
+ sig { returns(T::Array[Dependabot::Credential]) }
46
64
  attr_reader :credentials
47
65
 
66
+ sig { returns(Dependabot::Dependency) }
48
67
  def dependency
49
68
  # For now, we'll only ever be updating a single dep for Elixir
50
- dependencies.first
69
+ T.must(dependencies.first)
51
70
  end
52
71
 
72
+ sig { params(content: String).returns(String) }
53
73
  def post_process_lockfile(content)
54
- return content unless lockfile.content.start_with?("%{\"")
74
+ lockfile_content = T.must(lockfile.content)
75
+ return content unless lockfile_content.start_with?("%{\"")
55
76
  return content if content.start_with?("%{\"")
56
77
 
57
78
  # Substitute back old file beginning and ending
58
79
  content.sub(/\A%\{\n "/, "%{\"").sub("},\n}", "}}")
59
80
  end
60
81
 
82
+ sig { void }
61
83
  def write_temporary_dependency_files
62
84
  mixfiles.each do |file|
63
85
  path = file.name
@@ -65,21 +87,23 @@ module Dependabot
65
87
  File.write(path, mixfile_content_for_lockfile_generation(file))
66
88
  end
67
89
 
68
- File.write("mix.lock", lockfile.content)
90
+ File.write("mix.lock", T.must(lockfile.content))
69
91
 
70
92
  dependency_files.select(&:support_file).each do |file|
71
93
  path = file.name
72
94
  FileUtils.mkdir_p(Pathname.new(path).dirname)
73
- File.write(path, sanitize_mixfile(file.content))
95
+ File.write(path, sanitize_mixfile(T.must(file.content)))
74
96
  end
75
97
  end
76
98
 
99
+ sig { params(file: Dependabot::DependencyFile).returns(String) }
77
100
  def mixfile_content_for_lockfile_generation(file)
78
101
  content = updated_mixfile_content(file)
79
102
  content = lock_mixfile_dependency_versions(content, file.name)
80
103
  sanitize_mixfile(content)
81
104
  end
82
105
 
106
+ sig { params(file: Dependabot::DependencyFile).returns(String) }
83
107
  def updated_mixfile_content(file)
84
108
  MixfileUpdater.new(
85
109
  dependencies: dependencies,
@@ -87,6 +111,7 @@ module Dependabot
87
111
  ).updated_mixfile_content
88
112
  end
89
113
 
114
+ sig { params(mixfile_content: String, filename: String).returns(String) }
90
115
  def lock_mixfile_dependency_versions(mixfile_content, filename)
91
116
  dependencies
92
117
  .reduce(mixfile_content.dup) do |content, dep|
@@ -107,10 +132,12 @@ module Dependabot
107
132
  end
108
133
  end
109
134
 
135
+ sig { params(content: String).returns(String) }
110
136
  def sanitize_mixfile(content)
111
137
  MixfileSanitizer.new(mixfile_content: content).sanitized_content
112
138
  end
113
139
 
140
+ sig { returns(T::Hash[String, String]) }
114
141
  def mix_env
115
142
  {
116
143
  "MIX_EXS" => File.join(NativeHelpers.hex_helpers_dir, "mix.exs"),
@@ -118,20 +145,27 @@ module Dependabot
118
145
  }
119
146
  end
120
147
 
148
+ sig { returns(String) }
121
149
  def elixir_helper_path
122
150
  File.join(NativeHelpers.hex_helpers_dir, "lib/run.exs")
123
151
  end
124
152
 
153
+ sig { returns(String) }
125
154
  def elixir_helper_do_update_path
126
155
  File.join(NativeHelpers.hex_helpers_dir, "lib/do_update.exs")
127
156
  end
128
157
 
158
+ sig { returns(T::Array[Dependabot::DependencyFile]) }
129
159
  def mixfiles
130
160
  dependency_files.select { |f| f.name.end_with?("mix.exs") }
131
161
  end
132
162
 
163
+ sig { returns(Dependabot::DependencyFile) }
133
164
  def lockfile
134
- @lockfile ||= dependency_files.find { |f| f.name == "mix.lock" }
165
+ @lockfile ||= T.let(
166
+ T.must(dependency_files.find { |f| f.name == "mix.lock" }),
167
+ T.nilable(Dependabot::DependencyFile)
168
+ )
135
169
  end
136
170
  end
137
171
  end
@@ -1,6 +1,8 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
+ require "sorbet-runtime"
5
+
4
6
  require "dependabot/hex/file_updater"
5
7
  require "dependabot/shared_helpers"
6
8
 
@@ -8,16 +10,28 @@ module Dependabot
8
10
  module Hex
9
11
  class FileUpdater
10
12
  class MixfileRequirementUpdater
13
+ extend T::Sig
14
+
15
+ sig do
16
+ params(
17
+ dependency_name: String,
18
+ mixfile_content: String,
19
+ previous_requirement: T.nilable(String),
20
+ updated_requirement: T.nilable(String),
21
+ insert_if_bare: T::Boolean
22
+ ).void
23
+ end
11
24
  def initialize(dependency_name:, mixfile_content:,
12
25
  previous_requirement:, updated_requirement:,
13
26
  insert_if_bare: false)
14
- @dependency_name = dependency_name
15
- @mixfile_content = mixfile_content
16
- @previous_requirement = previous_requirement
17
- @updated_requirement = updated_requirement
18
- @insert_if_bare = insert_if_bare
27
+ @dependency_name = T.let(dependency_name, String)
28
+ @mixfile_content = T.let(mixfile_content, String)
29
+ @previous_requirement = T.let(previous_requirement, T.nilable(String))
30
+ @updated_requirement = T.let(updated_requirement, T.nilable(String))
31
+ @insert_if_bare = T.let(insert_if_bare, T::Boolean)
19
32
  end
20
33
 
34
+ sig { returns(String) }
21
35
  def updated_content
22
36
  updated_content = update_requirement(mixfile_content)
23
37
 
@@ -28,15 +42,24 @@ module Dependabot
28
42
 
29
43
  private
30
44
 
45
+ sig { returns(String) }
31
46
  attr_reader :dependency_name
47
+
48
+ sig { returns(String) }
32
49
  attr_reader :mixfile_content
50
+
51
+ sig { returns(T.nilable(String)) }
33
52
  attr_reader :previous_requirement
53
+
54
+ sig { returns(T.nilable(String)) }
34
55
  attr_reader :updated_requirement
35
56
 
57
+ sig { returns(T::Boolean) }
36
58
  def insert_if_bare?
37
- !@insert_if_bare.nil?
59
+ @insert_if_bare
38
60
  end
39
61
 
62
+ sig { params(content: String).returns(String) }
40
63
  def update_requirement(content)
41
64
  return content if previous_requirement.nil? && !insert_if_bare?
42
65
 
@@ -44,28 +67,33 @@ module Dependabot
44
67
  if previous_requirement
45
68
  /
46
69
  :#{Regexp.escape(dependency_name)}\s*,.*
47
- #{Regexp.escape(previous_requirement)}
70
+ #{Regexp.escape(T.must(previous_requirement))}
48
71
  /x
49
72
  else
50
73
  /:#{Regexp.escape(dependency_name)}(,|\s|\})/
51
74
  end
52
75
 
53
76
  content.gsub(requirement_line_regex) do |requirement_line|
54
- if previous_requirement
55
- requirement_line.gsub(previous_requirement, updated_requirement)
56
- else
77
+ if previous_requirement && updated_requirement
78
+ requirement_line.gsub(T.must(previous_requirement), T.must(updated_requirement))
79
+ elsif updated_requirement
57
80
  requirement_line.gsub(
58
81
  ":#{dependency_name}",
59
- ":#{dependency_name}, \"#{updated_requirement}\""
82
+ ":#{dependency_name}, \"#{T.must(updated_requirement)}\""
60
83
  )
84
+ else
85
+ # If we don't have an updated requirement, return the line unchanged
86
+ requirement_line
61
87
  end
62
88
  end
63
89
  end
64
90
 
91
+ sig { returns(T::Boolean) }
65
92
  def content_should_change?
66
93
  return false if previous_requirement == updated_requirement
94
+ return false if updated_requirement.nil? && !insert_if_bare?
67
95
 
68
- previous_requirement || insert_if_bare?
96
+ !previous_requirement.nil? || insert_if_bare?
69
97
  end
70
98
  end
71
99
  end
@@ -10,6 +10,7 @@ module Dependabot
10
10
  class FileUpdater
11
11
  class MixfileSanitizer
12
12
  extend T::Sig
13
+
13
14
  sig { params(mixfile_content: String).void }
14
15
  def initialize(mixfile_content:)
15
16
  @mixfile_content = mixfile_content
@@ -1,6 +1,7 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
+ require "sorbet-runtime"
4
5
  require "dependabot/hex/file_updater"
5
6
  require "dependabot/hex/file_updater/mixfile_requirement_updater"
6
7
  require "dependabot/hex/file_updater/mixfile_git_pin_updater"
@@ -9,15 +10,19 @@ module Dependabot
9
10
  module Hex
10
11
  class FileUpdater
11
12
  class MixfileUpdater
13
+ extend T::Sig
14
+
15
+ sig { params(mixfile: Dependabot::DependencyFile, dependencies: T::Array[Dependabot::Dependency]).void }
12
16
  def initialize(mixfile:, dependencies:)
13
- @mixfile = mixfile
14
- @dependencies = dependencies
17
+ @mixfile = T.let(mixfile, Dependabot::DependencyFile)
18
+ @dependencies = T.let(dependencies, T::Array[Dependabot::Dependency])
15
19
  end
16
20
 
21
+ sig { returns(String) }
17
22
  def updated_mixfile_content
18
23
  dependencies
19
24
  .select { |dep| requirement_changed?(mixfile, dep) }
20
- .reduce(mixfile.content.dup) do |content, dep|
25
+ .reduce(T.must(mixfile.content).dup) do |content, dep|
21
26
  updated_content = content
22
27
 
23
28
  updated_content = update_requirement(
@@ -40,25 +45,30 @@ module Dependabot
40
45
 
41
46
  private
42
47
 
48
+ sig { returns(Dependabot::DependencyFile) }
43
49
  attr_reader :mixfile
50
+
51
+ sig { returns(T::Array[Dependabot::Dependency]) }
44
52
  attr_reader :dependencies
45
53
 
54
+ sig { params(file: Dependabot::DependencyFile, dependency: Dependabot::Dependency).returns(T::Boolean) }
46
55
  def requirement_changed?(file, dependency)
47
56
  changed_requirements =
48
- dependency.requirements - dependency.previous_requirements
57
+ dependency.requirements - (dependency.previous_requirements || [])
49
58
 
50
59
  changed_requirements.any? { |f| f[:file] == file.name }
51
60
  end
52
61
 
62
+ sig { params(content: String, filename: String, dependency: Dependabot::Dependency).returns(String) }
53
63
  def update_requirement(content:, filename:, dependency:)
54
64
  updated_req =
55
65
  dependency.requirements.find { |r| r[:file] == filename }
56
- .fetch(:requirement)
66
+ &.fetch(:requirement)
57
67
 
58
68
  old_req =
59
69
  dependency.previous_requirements
60
- .find { |r| r[:file] == filename }
61
- .fetch(:requirement)
70
+ &.find { |r| r[:file] == filename }
71
+ &.fetch(:requirement)
62
72
 
63
73
  return content unless old_req
64
74
 
@@ -70,6 +80,7 @@ module Dependabot
70
80
  ).updated_content
71
81
  end
72
82
 
83
+ sig { params(content: String, filename: String, dependency: Dependabot::Dependency).returns(String) }
73
84
  def update_git_pin(content:, filename:, dependency:)
74
85
  updated_pin =
75
86
  dependency.requirements.find { |r| r[:file] == filename }
@@ -77,7 +88,7 @@ module Dependabot
77
88
 
78
89
  old_pin =
79
90
  dependency.previous_requirements
80
- .find { |r| r[:file] == filename }
91
+ &.find { |r| r[:file] == filename }
81
92
  &.dig(:source, :ref)
82
93
 
83
94
  return content unless old_pin
@@ -1,4 +1,4 @@
1
- # typed: strict
1
+ # typed: strong
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "dependabot/file_updaters"
@@ -1,4 +1,4 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "sorbet-runtime"
@@ -16,11 +16,16 @@ module Dependabot
16
16
  OR_SEPARATOR = /\s+or\s+/
17
17
 
18
18
  # Add the double-equality matcher to the list of allowed operations
19
- OPS = OPS.merge("==" => ->(v, r) { v == r })
19
+ OPS = T.let(
20
+ OPS.merge("==" => lambda { |v, r|
21
+ v == r
22
+ }),
23
+ T::Hash[String, T.proc.params(arg0: Gem::Version, arg1: Gem::Version).returns(T::Boolean)]
24
+ )
20
25
 
21
26
  # Override the version pattern to allow local versions
22
- quoted = OPS.keys.map { |k| Regexp.quote k }.join "|"
23
- PATTERN_RAW = "\\s*(#{quoted})?\\s*(#{Hex::Version::VERSION_PATTERN})\\s*".freeze
27
+ quoted = OPS.keys.map { |k| Regexp.quote k }.join("|")
28
+ PATTERN_RAW = T.let("\\s*(#{quoted})?\\s*(#{Hex::Version::VERSION_PATTERN})\\s*".freeze, String)
24
29
  PATTERN = /\A#{PATTERN_RAW}\z/
25
30
 
26
31
  # Returns an array of requirements. At least one requirement from the
@@ -35,6 +40,7 @@ module Dependabot
35
40
 
36
41
  # Patches Gem::Requirement to make it accept requirement strings like
37
42
  # "~> 4.2.5, >= 4.2.5.1" without first needing to split them.
43
+ sig { params(requirements: T.any(String, T::Array[String])).void }
38
44
  def initialize(*requirements)
39
45
  requirements = requirements.flatten.flat_map do |req_string|
40
46
  req_string.split(",").map(&:strip)
@@ -44,6 +50,10 @@ module Dependabot
44
50
  end
45
51
 
46
52
  # Override the parser to create Hex::Versions
53
+ sig do
54
+ params(obj: T.any(String, Gem::Version))
55
+ .returns(T::Array[T.any(String, Gem::Version)])
56
+ end
47
57
  def self.parse(obj)
48
58
  return ["=", Hex::Version.new(obj.to_s)] if obj.is_a?(Gem::Version)
49
59
 
@@ -57,10 +67,11 @@ module Dependabot
57
67
  [matches[1] || "=", Hex::Version.new(T.must(matches[2]))]
58
68
  end
59
69
 
70
+ sig { params(version: T.any(String, Gem::Version, Dependabot::Version)).returns(T::Boolean) }
60
71
  def satisfied_by?(version)
61
72
  version = Hex::Version.new(version.to_s)
62
73
 
63
- requirements.all? { |op, rv| (OPS[op] || OPS["="]).call(version, rv) }
74
+ requirements.all? { |op, rv| T.must(OPS[op] || OPS["="]).call(version, rv) }
64
75
  end
65
76
  end
66
77
  end
@@ -1,4 +1,4 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "sorbet-runtime"
@@ -18,17 +18,27 @@ module Dependabot
18
18
  class FilePreparer
19
19
  extend T::Sig
20
20
 
21
+ sig do
22
+ params(
23
+ dependency_files: T::Array[Dependabot::DependencyFile],
24
+ dependency: Dependabot::Dependency,
25
+ unlock_requirement: T.any(T.nilable(Symbol), T::Boolean),
26
+ replacement_git_pin: T.nilable(String),
27
+ latest_allowable_version: T.nilable(Gem::Version)
28
+ ).void
29
+ end
21
30
  def initialize(dependency_files:, dependency:,
22
31
  unlock_requirement: true,
23
32
  replacement_git_pin: nil,
24
33
  latest_allowable_version: nil)
25
- @dependency_files = dependency_files
26
- @dependency = dependency
27
- @unlock_requirement = unlock_requirement
28
- @replacement_git_pin = replacement_git_pin
29
- @latest_allowable_version = latest_allowable_version
34
+ @dependency_files = T.let(dependency_files, T::Array[Dependabot::DependencyFile])
35
+ @dependency = T.let(dependency, Dependabot::Dependency)
36
+ @unlock_requirement = T.let(unlock_requirement ? true : false, T::Boolean)
37
+ @replacement_git_pin = T.let(replacement_git_pin, T.nilable(String))
38
+ @latest_allowable_version = T.let(latest_allowable_version, T.nilable(Gem::Version))
30
39
  end
31
40
 
41
+ sig { returns(T::Array[Dependabot::DependencyFile]) }
32
42
  def prepared_dependency_files
33
43
  files = []
34
44
  files += mixfiles.map do |file|
@@ -45,21 +55,31 @@ module Dependabot
45
55
 
46
56
  private
47
57
 
58
+ sig { returns(T::Array[Dependabot::DependencyFile]) }
48
59
  attr_reader :dependency_files
60
+
61
+ sig { returns(Dependabot::Dependency) }
49
62
  attr_reader :dependency
63
+
64
+ sig { returns(T.nilable(String)) }
50
65
  attr_reader :replacement_git_pin
66
+
67
+ sig { returns(T.nilable(Gem::Version)) }
51
68
  attr_reader :latest_allowable_version
52
69
 
70
+ sig { returns(T::Boolean) }
53
71
  def unlock_requirement?
54
72
  @unlock_requirement
55
73
  end
56
74
 
75
+ sig { returns(T::Boolean) }
57
76
  def replace_git_pin?
58
77
  !replacement_git_pin.nil?
59
78
  end
60
79
 
80
+ sig { params(file: Dependabot::DependencyFile).returns(String) }
61
81
  def mixfile_content_for_update_check(file)
62
- content = file.content
82
+ content = T.must(file.content)
63
83
 
64
84
  return sanitize_mixfile(content) unless dependency_appears_in_file?(file.name)
65
85
 
@@ -69,10 +89,11 @@ module Dependabot
69
89
  sanitize_mixfile(content)
70
90
  end
71
91
 
92
+ sig { params(content: String, filename: String).returns(String) }
72
93
  def relax_version(content, filename:)
73
94
  old_requirement =
74
95
  dependency.requirements.find { |r| r.fetch(:file) == filename }
75
- .fetch(:requirement)
96
+ &.fetch(:requirement)
76
97
  updated_requirement = updated_version_requirement_string(filename)
77
98
 
78
99
  Hex::FileUpdater::MixfileRequirementUpdater.new(
@@ -80,10 +101,11 @@ module Dependabot
80
101
  mixfile_content: content,
81
102
  previous_requirement: old_requirement,
82
103
  updated_requirement: updated_requirement,
83
- insert_if_bare: updated_requirement && updated_requirement != ">= 0"
104
+ insert_if_bare: !updated_requirement.nil?
84
105
  ).updated_content
85
106
  end
86
107
 
108
+ sig { params(filename: String).returns(T.nilable(String)) }
87
109
  def updated_version_requirement_string(filename)
88
110
  lower_bound_req = updated_version_req_lower_bound(filename)
89
111
 
@@ -96,6 +118,7 @@ module Dependabot
96
118
  # rubocop:disable Metrics/AbcSize
97
119
  # rubocop:disable Metrics/PerceivedComplexity
98
120
  # rubocop:disable Metrics/CyclomaticComplexity
121
+ sig { params(filename: String).returns(String) }
99
122
  def updated_version_req_lower_bound(filename)
100
123
  original_req = dependency.requirements
101
124
  .find { |r| r.fetch(:file) == filename }
@@ -126,6 +149,7 @@ module Dependabot
126
149
  # rubocop:enable Metrics/CyclomaticComplexity
127
150
  # rubocop:enable Metrics/AbcSize
128
151
 
152
+ sig { params(content: String, filename: String).returns(String) }
129
153
  def replace_git_pin(content, filename:)
130
154
  old_pin =
131
155
  dependency.requirements.find { |r| r.fetch(:file) == filename }
@@ -138,16 +162,18 @@ module Dependabot
138
162
  dependency_name: dependency.name,
139
163
  mixfile_content: content,
140
164
  previous_pin: old_pin,
141
- updated_pin: replacement_git_pin
165
+ updated_pin: T.must(replacement_git_pin)
142
166
  ).updated_content
143
167
  end
144
168
 
169
+ sig { params(content: String).returns(String) }
145
170
  def sanitize_mixfile(content)
146
171
  Hex::FileUpdater::MixfileSanitizer.new(
147
172
  mixfile_content: content
148
173
  ).sanitized_content
149
174
  end
150
175
 
176
+ sig { returns(T::Array[Dependabot::DependencyFile]) }
151
177
  def mixfiles
152
178
  mixfiles =
153
179
  dependency_files
@@ -157,14 +183,23 @@ module Dependabot
157
183
  mixfiles
158
184
  end
159
185
 
186
+ sig { returns(T.nilable(Dependabot::DependencyFile)) }
160
187
  def lockfile
161
- @lockfile ||= dependency_files.find { |f| f.name == "mix.lock" }
188
+ @lockfile ||= T.let(
189
+ dependency_files.find { |f| f.name == "mix.lock" },
190
+ T.nilable(Dependabot::DependencyFile)
191
+ )
162
192
  end
163
193
 
194
+ sig { returns(T::Array[Dependabot::DependencyFile]) }
164
195
  def support_files
165
- @support_files ||= dependency_files.select(&:support_file)
196
+ @support_files ||= T.let(
197
+ dependency_files.select(&:support_file),
198
+ T.nilable(T::Array[Dependabot::DependencyFile])
199
+ )
166
200
  end
167
201
 
202
+ sig { returns(T::Boolean) }
168
203
  def wants_prerelease?
169
204
  current_version = dependency.version
170
205
  if current_version &&
@@ -178,14 +213,17 @@ module Dependabot
178
213
  end
179
214
  end
180
215
 
216
+ sig { returns(T.class_of(Dependabot::Version)) }
181
217
  def version_class
182
218
  dependency.version_class
183
219
  end
184
220
 
221
+ sig { returns(Regexp) }
185
222
  def version_regex
186
- Dependabot::Hex::Version::VERSION_PATTERN
223
+ Regexp.new(Dependabot::Hex::Version::VERSION_PATTERN)
187
224
  end
188
225
 
226
+ sig { params(file_name: String).returns(T::Boolean) }
189
227
  def dependency_appears_in_file?(file_name)
190
228
  dependency.requirements.any? { |r| r[:file] == file_name }
191
229
  end
@@ -1,6 +1,8 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
+ require "sorbet-runtime"
5
+
4
6
  require "dependabot/hex/version"
5
7
  require "dependabot/hex/requirement"
6
8
  require "dependabot/hex/update_checker"
@@ -9,34 +11,50 @@ module Dependabot
9
11
  module Hex
10
12
  class UpdateChecker
11
13
  class RequirementsUpdater
14
+ extend T::Sig
15
+
12
16
  OPERATORS = />=|<=|>|<|==|~>/
13
17
  AND_SEPARATOR = /\s+and\s+/
14
18
  OR_SEPARATOR = /\s+or\s+/
15
19
  SEPARATOR = /#{AND_SEPARATOR}|#{OR_SEPARATOR}/
16
20
 
21
+ sig do
22
+ params(
23
+ requirements: T::Array[T::Hash[Symbol, T.untyped]],
24
+ latest_resolvable_version: T.nilable(String),
25
+ updated_source: T.nilable(T::Hash[Symbol, T.nilable(String)])
26
+ ).void
27
+ end
17
28
  def initialize(requirements:, latest_resolvable_version:,
18
29
  updated_source:)
19
- @requirements = requirements
20
- @updated_source = updated_source
30
+ @requirements = T.let(requirements, T::Array[T::Hash[Symbol, T.untyped]])
31
+ @updated_source = T.let(updated_source, T.nilable(T::Hash[Symbol, T.nilable(String)]))
32
+ @latest_resolvable_version = T.let(nil, T.nilable(Dependabot::Version))
21
33
 
22
34
  return unless latest_resolvable_version
23
35
  return unless Hex::Version.correct?(latest_resolvable_version)
24
36
 
25
- @latest_resolvable_version =
26
- Hex::Version.new(latest_resolvable_version)
37
+ @latest_resolvable_version = Hex::Version.new(latest_resolvable_version)
27
38
  end
28
39
 
40
+ sig { returns(T::Array[T::Hash[Symbol, T.untyped]]) }
29
41
  def updated_requirements
30
42
  requirements.map { |req| updated_mixfile_requirement(req) }
31
43
  end
32
44
 
33
45
  private
34
46
 
47
+ sig { returns(T::Array[T::Hash[Symbol, T.untyped]]) }
35
48
  attr_reader :requirements
49
+
50
+ sig { returns(T.nilable(Dependabot::Version)) }
36
51
  attr_reader :latest_resolvable_version
52
+
53
+ sig { returns(T.nilable(T::Hash[Symbol, T.nilable(String)])) }
37
54
  attr_reader :updated_source
38
55
  # rubocop:disable Metrics/PerceivedComplexity
39
56
  # rubocop:disable Metrics/AbcSize
57
+ sig { params(req: T::Hash[Symbol, T.untyped]).returns(T::Hash[Symbol, T.untyped]) }
40
58
  def updated_mixfile_requirement(req)
41
59
  req = update_source(req)
42
60
  return req unless latest_resolvable_version && req[:requirement]
@@ -49,10 +67,10 @@ module Dependabot
49
67
  new_requirement =
50
68
  if last_string_reqs.any? { |r| r.match(/^(?:\d|=)/) }
51
69
  exact_req = last_string_reqs.find { |r| r.match(/^(?:\d|=)/) }
52
- update_exact_version(exact_req, latest_resolvable_version).to_s
70
+ update_exact_version(exact_req, T.must(latest_resolvable_version)).to_s
53
71
  elsif last_string_reqs.any? { |r| r.start_with?("~>") }
54
72
  tw_req = last_string_reqs.find { |r| r.start_with?("~>") }
55
- update_twiddle_version(tw_req, latest_resolvable_version).to_s
73
+ update_twiddle_version(tw_req, T.must(latest_resolvable_version)).to_s
56
74
  else
57
75
  update_mixfile_range(last_string_reqs).map(&:to_s).join(" and ")
58
76
  end
@@ -64,6 +82,7 @@ module Dependabot
64
82
  # rubocop:enable Metrics/AbcSize
65
83
  # rubocop:enable Metrics/PerceivedComplexity
66
84
 
85
+ sig { params(requirement_hash: T::Hash[Symbol, T.untyped]).returns(T::Hash[Symbol, T.untyped]) }
67
86
  def update_source(requirement_hash)
68
87
  # Only git sources ever need to be updated. Anything else should be
69
88
  # left alone.
@@ -72,15 +91,18 @@ module Dependabot
72
91
  requirement_hash.merge(source: updated_source)
73
92
  end
74
93
 
94
+ sig { params(requirement_string: String).returns(T::Boolean) }
75
95
  def req_satisfied_by_latest_resolvable?(requirement_string)
76
96
  ruby_requirements(requirement_string)
77
- .any? { |r| r.satisfied_by?(latest_resolvable_version) }
97
+ .any? { |r| r.satisfied_by?(T.must(latest_resolvable_version)) }
78
98
  end
79
99
 
100
+ sig { params(requirement_string: String).returns(T::Array[Hex::Requirement]) }
80
101
  def ruby_requirements(requirement_string)
81
102
  requirement_class.requirements_array(requirement_string)
82
103
  end
83
104
 
105
+ sig { params(previous_req: String, new_version: Dependabot::Version).returns(String) }
84
106
  def update_exact_version(previous_req, new_version)
85
107
  op = previous_req.match(OPERATORS).to_s
86
108
  old_version =
@@ -89,6 +111,7 @@ module Dependabot
89
111
  "#{op} #{updated_version}".strip
90
112
  end
91
113
 
114
+ sig { params(previous_req: String, new_version: Dependabot::Version).returns(Hex::Requirement) }
92
115
  def update_twiddle_version(previous_req, new_version)
93
116
  previous_req = requirement_class.new(previous_req)
94
117
  old_version = previous_req.requirements.first.last
@@ -96,15 +119,16 @@ module Dependabot
96
119
  requirement_class.new("~> #{updated_version}")
97
120
  end
98
121
 
122
+ sig { params(requirements: T::Array[String]).returns(T::Array[Hex::Requirement]) }
99
123
  def update_mixfile_range(requirements)
100
124
  requirements = requirements.map { |r| requirement_class.new(r) }
101
125
  updated_requirements =
102
126
  requirements.flat_map do |r|
103
- next r if r.satisfied_by?(latest_resolvable_version)
127
+ next r if r.satisfied_by?(T.must(latest_resolvable_version))
104
128
 
105
129
  case op = r.requirements.first.first
106
130
  when "<", "<="
107
- [update_greatest_version(r, latest_resolvable_version)]
131
+ [update_greatest_version(r, T.must(latest_resolvable_version))]
108
132
  when "!="
109
133
  []
110
134
  else
@@ -116,6 +140,7 @@ module Dependabot
116
140
  binding_requirements(updated_requirements)
117
141
  end
118
142
 
143
+ sig { params(new_version: Dependabot::Version, old_version: Dependabot::Version).returns(String) }
119
144
  def at_same_precision(new_version, old_version)
120
145
  precision = old_version.to_s.split(".").count
121
146
  new_version.to_s.split(".").first(precision).join(".")
@@ -123,11 +148,10 @@ module Dependabot
123
148
 
124
149
  # Updates the version in a "<" or "<=" constraint to allow the given
125
150
  # version
151
+ sig do
152
+ params(requirement: Hex::Requirement, version_to_be_permitted: Dependabot::Version).returns(Hex::Requirement)
153
+ end
126
154
  def update_greatest_version(requirement, version_to_be_permitted)
127
- if version_to_be_permitted.is_a?(String)
128
- version_to_be_permitted =
129
- Hex::Version.new(version_to_be_permitted)
130
- end
131
155
  op, version = requirement.requirements.first
132
156
  version = version.release if version.prerelease?
133
157
 
@@ -138,7 +162,7 @@ module Dependabot
138
162
  if index < index_to_update
139
163
  version_to_be_permitted.segments[index]
140
164
  elsif index == index_to_update
141
- version_to_be_permitted.segments[index] + 1
165
+ version_to_be_permitted.segments[index].to_i + 1
142
166
  else
143
167
  0
144
168
  end
@@ -147,22 +171,29 @@ module Dependabot
147
171
  requirement_class.new("#{op} #{new_segments.join('.')}")
148
172
  end
149
173
 
174
+ sig { params(requirements: T::Array[Hex::Requirement]).returns(T::Array[Hex::Requirement]) }
150
175
  def binding_requirements(requirements)
151
176
  grouped_by_operator =
152
177
  requirements.group_by { |r| r.requirements.first.first }
153
178
 
154
179
  binding_reqs = grouped_by_operator.flat_map do |operator, reqs|
155
180
  case operator
156
- when "<", "<=" then reqs.min_by { |r| r.requirements.first.last }
157
- when ">", ">=" then reqs.max_by { |r| r.requirements.first.last }
158
- else requirements
181
+ when "<", "<="
182
+ min_req = reqs.min_by { |r| r.requirements.first.last }
183
+ min_req ? [min_req] : []
184
+ when ">", ">="
185
+ max_req = reqs.max_by { |r| r.requirements.first.last }
186
+ max_req ? [max_req] : []
187
+ else
188
+ requirements
159
189
  end
160
- end.uniq
190
+ end.uniq.compact
161
191
 
162
192
  binding_reqs << requirement_class.new if binding_reqs.empty?
163
193
  binding_reqs.sort_by { |r| r.requirements.first.last }
164
194
  end
165
195
 
196
+ sig { returns(T.class_of(Hex::Requirement)) }
166
197
  def requirement_class
167
198
  Hex::Requirement
168
199
  end
@@ -1,6 +1,8 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
+ require "sorbet-runtime"
5
+
4
6
  require "dependabot/hex/version"
5
7
  require "dependabot/hex/update_checker"
6
8
  require "dependabot/hex/credential_helpers"
@@ -13,25 +15,45 @@ module Dependabot
13
15
  module Hex
14
16
  class UpdateChecker
15
17
  class VersionResolver
18
+ extend T::Sig
19
+
20
+ sig do
21
+ params(
22
+ dependency: Dependabot::Dependency,
23
+ credentials: T::Array[Dependabot::Credential],
24
+ original_dependency_files: T::Array[Dependabot::DependencyFile],
25
+ prepared_dependency_files: T::Array[Dependabot::DependencyFile]
26
+ ).void
27
+ end
16
28
  def initialize(dependency:, credentials:,
17
29
  original_dependency_files:, prepared_dependency_files:)
18
- @dependency = dependency
19
- @original_dependency_files = original_dependency_files
20
- @prepared_dependency_files = prepared_dependency_files
21
- @credentials = credentials
30
+ @dependency = T.let(dependency, Dependabot::Dependency)
31
+ @original_dependency_files = T.let(original_dependency_files, T::Array[Dependabot::DependencyFile])
32
+ @prepared_dependency_files = T.let(prepared_dependency_files, T::Array[Dependabot::DependencyFile])
33
+ @credentials = T.let(credentials, T::Array[Dependabot::Credential])
34
+ @latest_resolvable_version = T.let(nil, T.nilable(T.any(Dependabot::Version, String, T::Boolean)))
22
35
  end
23
36
 
37
+ sig { returns(T.nilable(T.any(Dependabot::Version, String, T::Boolean))) }
24
38
  def latest_resolvable_version
25
39
  @latest_resolvable_version ||= fetch_latest_resolvable_version
26
40
  end
27
41
 
28
42
  private
29
43
 
44
+ sig { returns(Dependabot::Dependency) }
30
45
  attr_reader :dependency
46
+
47
+ sig { returns(T::Array[Dependabot::Credential]) }
31
48
  attr_reader :credentials
49
+
50
+ sig { returns(T::Array[Dependabot::DependencyFile]) }
32
51
  attr_reader :original_dependency_files
52
+
53
+ sig { returns(T::Array[Dependabot::DependencyFile]) }
33
54
  attr_reader :prepared_dependency_files
34
55
 
56
+ sig { returns(T.nilable(T.any(Dependabot::Version, String, T::Boolean))) }
35
57
  def fetch_latest_resolvable_version
36
58
  latest_resolvable_version =
37
59
  SharedHelpers.in_a_temporary_directory do
@@ -51,6 +73,7 @@ module Dependabot
51
73
  handle_hex_errors(e)
52
74
  end
53
75
 
76
+ sig { returns(String) }
54
77
  def run_elixir_update_checker
55
78
  SharedHelpers.run_helper_subprocess(
56
79
  env: mix_env,
@@ -61,6 +84,10 @@ module Dependabot
61
84
  )
62
85
  end
63
86
 
87
+ sig do
88
+ params(error: Dependabot::SharedHelpers::HelperSubprocessFailed)
89
+ .returns(T.nilable(T.any(Dependabot::Version, String, T::Boolean)))
90
+ end
64
91
  def handle_hex_errors(error)
65
92
  if (match = error.message.match(/No authenticated organization found for (?<repo>[a-z_]+)\./))
66
93
  raise Dependabot::PrivateSourceAuthenticationFailure, match[:repo]
@@ -98,25 +125,31 @@ module Dependabot
98
125
  raise error
99
126
  end
100
127
 
128
+ sig do
129
+ params(error: Dependabot::SharedHelpers::HelperSubprocessFailed).returns(T.any(Dependabot::Version, String,
130
+ T::Boolean))
131
+ end
101
132
  def error_result(error)
102
133
  return false unless includes_result?(error)
103
134
 
104
- result_json = error.message&.split("\n")&.last
105
- result = JSON.parse(result_json)["result"]
135
+ result_json = error.message.split("\n").last
136
+ result = JSON.parse(T.must(result_json))["result"]
106
137
  return version_class.new(result) if version_class.correct?(result)
107
138
 
108
139
  result
109
140
  end
110
141
 
142
+ sig { params(error: Dependabot::SharedHelpers::HelperSubprocessFailed).returns(T::Boolean) }
111
143
  def includes_result?(error)
112
- result = error.message&.split("\n")&.last
144
+ result = error.message.split("\n").last
113
145
  return false unless result
114
146
 
115
- JSON.parse(error.message&.split("\n")&.last).key?("result")
147
+ JSON.parse(result).key?("result")
116
148
  rescue JSON::ParserError
117
149
  false
118
150
  end
119
151
 
152
+ sig { returns(T.any(T::Boolean, Dependabot::Version, String)) }
120
153
  def check_original_requirements_resolvable
121
154
  SharedHelpers.in_a_temporary_directory do
122
155
  write_temporary_sanitized_dependency_files(prepared: false)
@@ -141,6 +174,7 @@ module Dependabot
141
174
  raise Dependabot::DependencyFileNotResolvable, e.message
142
175
  end
143
176
 
177
+ sig { params(prepared: T::Boolean).void }
144
178
  def write_temporary_sanitized_dependency_files(prepared: true)
145
179
  files = if prepared then prepared_dependency_files
146
180
  else
@@ -150,20 +184,23 @@ module Dependabot
150
184
  files.each do |file|
151
185
  path = file.name
152
186
  FileUtils.mkdir_p(Pathname.new(path).dirname)
153
- File.write(path, sanitize_mixfile(file.content))
187
+ File.write(path, sanitize_mixfile(T.must(file.content)))
154
188
  end
155
189
  end
156
190
 
191
+ sig { params(content: String).returns(String) }
157
192
  def sanitize_mixfile(content)
158
193
  Hex::FileUpdater::MixfileSanitizer.new(
159
194
  mixfile_content: content
160
195
  ).sanitized_content
161
196
  end
162
197
 
198
+ sig { returns(T.class_of(Dependabot::Version)) }
163
199
  def version_class
164
200
  dependency.version_class
165
201
  end
166
202
 
203
+ sig { returns(T::Hash[String, String]) }
167
204
  def mix_env
168
205
  {
169
206
  "MIX_EXS" => File.join(NativeHelpers.hex_helpers_dir, "mix.exs"),
@@ -171,10 +208,12 @@ module Dependabot
171
208
  }
172
209
  end
173
210
 
211
+ sig { returns(String) }
174
212
  def elixir_helper_path
175
213
  File.join(NativeHelpers.hex_helpers_dir, "lib/run.exs")
176
214
  end
177
215
 
216
+ sig { returns(String) }
178
217
  def elixir_helper_check_update_path
179
218
  File.join(NativeHelpers.hex_helpers_dir, "lib/check_update.exs")
180
219
  end
@@ -13,6 +13,7 @@ module Dependabot
13
13
  module Hex
14
14
  class UpdateChecker < Dependabot::UpdateCheckers::Base
15
15
  extend T::Sig
16
+
16
17
  require_relative "update_checker/file_preparer"
17
18
  require_relative "update_checker/requirements_updater"
18
19
  require_relative "update_checker/version_resolver"
@@ -20,26 +21,26 @@ module Dependabot
20
21
 
21
22
  sig { override.returns(T.nilable(T.any(String, Dependabot::Version, Gem::Version))) }
22
23
  def latest_version
23
- @latest_version = T.let(nil, T.nilable(T.any(String, Dependabot::Version, Gem::Version)))
24
-
25
- @latest_version ||=
24
+ @latest_version ||= T.let(
26
25
  if git_dependency?
27
26
  latest_version_for_git_dependency
28
27
  else
29
28
  latest_release_from_hex_registry || latest_resolvable_version
30
- end
29
+ end,
30
+ T.nilable(T.any(String, Dependabot::Version, Gem::Version))
31
+ )
31
32
  end
32
33
 
33
34
  sig { override.returns(T.nilable(T.any(String, Dependabot::Version, Gem::Version))) }
34
35
  def latest_resolvable_version
35
- @latest_resolvable_version = T.let(nil, T.nilable(T.any(String, Dependabot::Version, Gem::Version)))
36
-
37
- @latest_resolvable_version ||=
36
+ @latest_resolvable_version ||= T.let(
38
37
  if git_dependency?
39
38
  latest_resolvable_version_for_git_dependency
40
39
  else
41
40
  fetch_latest_resolvable_version(unlock_requirement: true)
42
- end
41
+ end,
42
+ T.nilable(T.any(String, Dependabot::Version, Gem::Version))
43
+ )
43
44
  end
44
45
 
45
46
  sig { override.returns(T.any(String, T.nilable(Dependabot::Version))) }
@@ -157,11 +158,13 @@ module Dependabot
157
158
  ).latest_resolvable_version
158
159
 
159
160
  @git_tag_resolvable = !resolver_result.nil?
161
+ @git_tag_resolvable
160
162
  rescue SharedHelpers::HelperSubprocessFailed,
161
163
  Dependabot::DependencyFileNotResolvable => e
162
164
  raise e unless e.message.include?("resolution failed")
163
165
 
164
166
  @git_tag_resolvable = T.let(false, T.nilable(T::Boolean))
167
+ false
165
168
  end
166
169
 
167
170
  sig { returns(T.nilable(T::Hash[T.untyped, T.untyped])) }
@@ -247,13 +250,13 @@ module Dependabot
247
250
 
248
251
  sig { returns(Dependabot::GitCommitChecker) }
249
252
  def git_commit_checker
250
- @git_commit_checker = T.let(nil, T.nilable(Dependabot::GitCommitChecker))
251
-
252
- @git_commit_checker ||=
253
+ @git_commit_checker ||= T.let(
253
254
  GitCommitChecker.new(
254
255
  dependency: dependency,
255
256
  credentials: credentials
256
- )
257
+ ),
258
+ T.nilable(Dependabot::GitCommitChecker)
259
+ )
257
260
  end
258
261
  end
259
262
  end
@@ -1,4 +1,4 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "sorbet-runtime"
@@ -15,33 +15,40 @@ module Dependabot
15
15
  class Version < Dependabot::Version
16
16
  extend T::Sig
17
17
 
18
+ sig { returns(T.nilable(String)) }
18
19
  attr_reader :build_info
19
20
 
20
- VERSION_PATTERN = Gem::Version::VERSION_PATTERN + '(\+[0-9a-zA-Z\-.]+)?'
21
- ANCHORED_VERSION_PATTERN = /\A\s*(#{VERSION_PATTERN})?\s*\z/
21
+ VERSION_PATTERN = T.let(Gem::Version::VERSION_PATTERN + '(\+[0-9a-zA-Z\-.]+)?', String)
22
+ ANCHORED_VERSION_PATTERN = T.let(/\A\s*(#{VERSION_PATTERN})?\s*\z/, Regexp)
22
23
 
24
+ sig { override.params(version: VersionParameter).returns(T::Boolean) }
23
25
  def self.correct?(version)
24
26
  return false if version.nil?
25
27
 
26
28
  version.to_s.match?(ANCHORED_VERSION_PATTERN)
27
29
  end
28
30
 
31
+ sig { override.params(version: VersionParameter).void }
29
32
  def initialize(version)
30
- @version_string = version.to_s
33
+ @version_string = T.let(version.to_s, String)
31
34
 
32
35
  version, @build_info = version.to_s.split("+") if version.to_s.include?("+")
36
+ @build_info = T.let(@build_info, T.nilable(String))
33
37
 
34
38
  super
35
39
  end
36
40
 
41
+ sig { override.returns(String) }
37
42
  def to_s
38
43
  @version_string
39
44
  end
40
45
 
46
+ sig { override.returns(String) }
41
47
  def inspect # :nodoc:
42
48
  "#<#{self.class} #{@version_string}>"
43
49
  end
44
50
 
51
+ sig { params(other: T.untyped).returns(T.nilable(Integer)) }
45
52
  def <=>(other)
46
53
  version_comparison = super
47
54
  return version_comparison unless version_comparison&.zero?
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.332.0
4
+ version: 0.333.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.332.0
18
+ version: 0.333.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.332.0
25
+ version: 0.333.0
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: debug
28
28
  requirement: !ruby/object:Gem::Requirement
@@ -211,14 +211,14 @@ dependencies:
211
211
  requirements:
212
212
  - - "~>"
213
213
  - !ruby/object:Gem::Version
214
- version: '3.18'
214
+ version: '3.25'
215
215
  type: :development
216
216
  prerelease: false
217
217
  version_requirements: !ruby/object:Gem::Requirement
218
218
  requirements:
219
219
  - - "~>"
220
220
  - !ruby/object:Gem::Version
221
- version: '3.18'
221
+ version: '3.25'
222
222
  - !ruby/object:Gem::Dependency
223
223
  name: webrick
224
224
  requirement: !ruby/object:Gem::Requirement
@@ -274,7 +274,7 @@ licenses:
274
274
  - MIT
275
275
  metadata:
276
276
  bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
277
- changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.332.0
277
+ changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.333.0
278
278
  rdoc_options: []
279
279
  require_paths:
280
280
  - lib