dependabot-swift 0.309.0 → 0.310.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: def941d448813d13dca186196a3ac7af51f17aa15eb394dd58435bde0ffa1d0c
4
- data.tar.gz: 92e7551fa11eb1f2dbf4f2ca4a34bdb97bda5655213fa728a8de299d28d0ea05
3
+ metadata.gz: 3296c203aea249a1771176e1d51c18009c4dec28e0becc4f45eacb6d35a4a0d9
4
+ data.tar.gz: 84c8ff4fd0ed2c2808e7c5d76a764c27c78c7b306f973c48d156a3b28ba88de3
5
5
  SHA512:
6
- metadata.gz: 6ae4f8dd8e6b0ac5c4b5ddd428eb527efc10d44c541561f6d52e70bd295f159cf29ff50e9491d1ebc4c2d9f0b2f9812c0224236049d4cd70104c3cdfcda6e1cb
7
- data.tar.gz: 7d9bcc974dd8ec8b7c1af6a25612b08ab239b4163a8f09f03ab9ade594c754dcba5a5db4fd9655efab9988df4c32da50898ef7c8b8250824797338ea704e03d1
6
+ metadata.gz: e2de9a09b1bc6ee96a7c7e97a9b63ba74930ce9df5929115dd96f065039140ff3f64e69086b01b15e169729716e48fe9e726ea549042994f0f858db90cb03688
7
+ data.tar.gz: ee379e432ea24ba9ea6c6adb9c5418cdc1f8158b04b9af49bfd88e77339ab24b63273294f9b160f060fbe262273615912800987d18dd5912d9cf334d493b1987
@@ -1,4 +1,4 @@
1
- # typed: true
1
+ # typed: strong
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "sorbet-runtime"
@@ -9,12 +9,13 @@ module Dependabot
9
9
  module Swift
10
10
  class FileFetcher < Dependabot::FileFetchers::Base
11
11
  extend T::Sig
12
- extend T::Helpers
13
12
 
13
+ sig { override.params(filenames: T::Array[String]).returns(T::Boolean) }
14
14
  def self.required_files_in?(filenames)
15
15
  filenames.include?("Package.swift")
16
16
  end
17
17
 
18
+ sig { override.returns(String) }
18
19
  def self.required_files_message
19
20
  "Repo must contain a Package.swift configuration file."
20
21
  end
@@ -29,14 +30,14 @@ module Dependabot
29
30
 
30
31
  private
31
32
 
33
+ sig { returns(Dependabot::DependencyFile) }
32
34
  def package_manifest
33
- @package_manifest ||= fetch_file_from_host("Package.swift")
35
+ @package_manifest ||= T.let(fetch_file_from_host("Package.swift"), T.nilable(DependencyFile))
34
36
  end
35
37
 
38
+ sig { returns(T.nilable(DependencyFile)) }
36
39
  def package_resolved
37
- return @package_resolved if defined?(@package_resolved)
38
-
39
- @package_resolved = fetch_file_if_present("Package.resolved")
40
+ @package_resolved = T.let(fetch_file_if_present("Package.resolved"), T.nilable(DependencyFile))
40
41
  end
41
42
  end
42
43
  end
@@ -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/file_parsers/base"
5
6
  require "dependabot/shared_helpers"
6
7
  require "dependabot/dependency"
@@ -11,14 +12,25 @@ module Dependabot
11
12
  module Swift
12
13
  class FileParser < Dependabot::FileParsers::Base
13
14
  class DependencyParser
15
+ extend T::Sig
16
+
17
+ sig do
18
+ params(
19
+ dependency_files: T::Array[Dependabot::DependencyFile],
20
+ repo_contents_path: T.nilable(String),
21
+ credentials: T::Array[Dependabot::Credential]
22
+ )
23
+ .void
24
+ end
14
25
  def initialize(dependency_files:, repo_contents_path:, credentials:)
15
26
  @dependency_files = dependency_files
16
27
  @repo_contents_path = repo_contents_path
17
28
  @credentials = credentials
18
29
  end
19
30
 
31
+ sig { returns(T::Array[Dependabot::Dependency]) }
20
32
  def parse
21
- SharedHelpers.in_a_temporary_repo_directory(dependency_files.first.directory, repo_contents_path) do
33
+ SharedHelpers.in_a_temporary_repo_directory(T.must(dependency_files.first).directory, repo_contents_path) do
22
34
  write_temporary_dependency_files
23
35
 
24
36
  SharedHelpers.with_git_configured(credentials: credentials) do
@@ -29,12 +41,14 @@ module Dependabot
29
41
 
30
42
  private
31
43
 
44
+ sig { void }
32
45
  def write_temporary_dependency_files
33
46
  dependency_files.each do |file|
34
47
  File.write(file.name, file.content)
35
48
  end
36
49
  end
37
50
 
51
+ sig { returns(T::Hash[String, T.untyped]) }
38
52
  def formatted_deps
39
53
  deps = SharedHelpers.run_shell_command(
40
54
  "swift package show-dependencies --format json",
@@ -44,10 +58,24 @@ module Dependabot
44
58
  JSON.parse(deps)
45
59
  end
46
60
 
61
+ sig do
62
+ params(
63
+ data: T::Hash[String, T.untyped],
64
+ level: Integer
65
+ )
66
+ .returns(T::Array[Dependabot::Dependency])
67
+ end
47
68
  def subdependencies(data, level: 0)
48
69
  data["dependencies"].flat_map { |root| all_dependencies(root, level: level) }
49
70
  end
50
71
 
72
+ sig do
73
+ params(
74
+ data: T::Hash[String, T.untyped],
75
+ level: Integer
76
+ )
77
+ .returns(T::Array[Dependabot::Dependency])
78
+ end
51
79
  def all_dependencies(data, level: 0)
52
80
  identity = data["identity"]
53
81
  url = SharedHelpers.scp_to_standard(data["url"])
@@ -69,14 +97,20 @@ module Dependabot
69
97
  [dep, *subdependencies(data, level: level + 1)].compact
70
98
  end
71
99
 
100
+ sig { params(source: String).returns(String) }
72
101
  def normalize(source)
73
102
  uri = URI.parse(source.downcase)
74
103
 
75
104
  "#{uri.host}#{uri.path}".delete_prefix("www.").delete_suffix(".git")
76
105
  end
77
106
 
107
+ sig { returns(T::Array[Dependabot::DependencyFile]) }
78
108
  attr_reader :dependency_files
109
+
110
+ sig { returns(T.nilable(String)) }
79
111
  attr_reader :repo_contents_path
112
+
113
+ sig { returns(T::Array[Dependabot::Credential]) }
80
114
  attr_reader :credentials
81
115
  end
82
116
  end
@@ -36,7 +36,7 @@ module Dependabot
36
36
  return [] unless found
37
37
 
38
38
  declaration = T.cast(found, T::Array[String]).first
39
- requirement = NativeRequirement.new(T.cast(found, T::Array[String]).last)
39
+ requirement = NativeRequirement.new(T.must(T.cast(found, T::Array[String]).last))
40
40
 
41
41
  [
42
42
  {
@@ -1,4 +1,4 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "dependabot/dependency"
@@ -12,16 +12,19 @@ require "dependabot/swift/language"
12
12
  module Dependabot
13
13
  module Swift
14
14
  class FileParser < Dependabot::FileParsers::Base
15
+ extend T::Sig
16
+
15
17
  require "dependabot/file_parsers/base/dependency_set"
16
18
 
19
+ sig { override.returns(T::Array[Dependabot::Dependency]) }
17
20
  def parse
18
21
  dependency_set = DependencySet.new
19
22
 
20
23
  dependency_parser.parse.map do |dep|
21
24
  if dep.top_level?
22
- source = dep.requirements.first[:source]
25
+ source = T.must(dep.requirements.first)[:source]
23
26
 
24
- requirements = ManifestParser.new(package_manifest_file, source: source).requirements
27
+ requirements = ManifestParser.new(T.must(package_manifest_file), source: source).requirements
25
28
 
26
29
  dependency_set << Dependency.new(
27
30
  name: dep.name,
@@ -51,6 +54,7 @@ module Dependabot
51
54
 
52
55
  private
53
56
 
57
+ sig { returns(Dependabot::Swift::FileParser::DependencyParser) }
54
58
  def dependency_parser
55
59
  DependencyParser.new(
56
60
  dependency_files: dependency_files,
@@ -59,13 +63,15 @@ module Dependabot
59
63
  )
60
64
  end
61
65
 
66
+ sig { override.void }
62
67
  def check_required_files
63
68
  raise "No Package.swift!" unless package_manifest_file
64
69
  end
65
70
 
71
+ sig { returns(T.nilable(Dependabot::DependencyFile)) }
66
72
  def package_manifest_file
67
73
  # TODO: Select version-specific manifest
68
- @package_manifest_file ||= get_original_file("Package.swift")
74
+ @package_manifest_file ||= T.let(get_original_file("Package.swift"), T.nilable(Dependabot::DependencyFile))
69
75
  end
70
76
 
71
77
  sig { returns(Ecosystem::VersionManager) }
@@ -1,14 +1,27 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "dependabot/file_updaters/base"
5
5
  require "dependabot/shared_helpers"
6
6
  require "dependabot/logger"
7
+ require "sorbet-runtime"
7
8
 
8
9
  module Dependabot
9
10
  module Swift
10
11
  class FileUpdater < Dependabot::FileUpdaters::Base
11
12
  class LockfileUpdater
13
+ extend T::Sig
14
+
15
+ sig do
16
+ params(
17
+ dependency: Dependabot::Dependency,
18
+ manifest: Dependabot::DependencyFile,
19
+ repo_contents_path: String,
20
+ credentials: T::Array[Dependabot::Credential],
21
+ target_version: T.nilable(String)
22
+ )
23
+ .void
24
+ end
12
25
  def initialize(dependency:, manifest:, repo_contents_path:, credentials:, target_version: nil)
13
26
  @dependency = dependency
14
27
  @manifest = manifest
@@ -17,6 +30,7 @@ module Dependabot
17
30
  @target_version = target_version
18
31
  end
19
32
 
33
+ sig { returns(String) }
20
34
  def updated_lockfile_content
21
35
  SharedHelpers.in_a_temporary_repo_directory(manifest.directory, repo_contents_path) do
22
36
  File.write(manifest.name, manifest.content)
@@ -31,6 +45,7 @@ module Dependabot
31
45
 
32
46
  private
33
47
 
48
+ sig { params(dependency_name: String).void }
34
49
  def try_lockfile_update(dependency_name)
35
50
  if target_version
36
51
  SharedHelpers.run_shell_command(
@@ -51,10 +66,19 @@ module Dependabot
51
66
  Dependabot.logger.info("Lockfile failed to be updated due to error:\n#{e.message}")
52
67
  end
53
68
 
69
+ sig { returns(Dependabot::Dependency) }
54
70
  attr_reader :dependency
71
+
72
+ sig { returns(Dependabot::DependencyFile) }
55
73
  attr_reader :manifest
74
+
75
+ sig { returns(String) }
56
76
  attr_reader :repo_contents_path
77
+
78
+ sig { returns(T::Array[Dependabot::Credential]) }
57
79
  attr_reader :credentials
80
+
81
+ sig { returns(T.nilable(String)) }
58
82
  attr_reader :target_version
59
83
  end
60
84
  end
@@ -1,19 +1,30 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "dependabot/file_updaters/base"
5
5
  require "dependabot/swift/file_updater/requirement_replacer"
6
+ require "sorbet-runtime"
6
7
 
7
8
  module Dependabot
8
9
  module Swift
9
10
  class FileUpdater < FileUpdaters::Base
10
11
  class ManifestUpdater
12
+ extend T::Sig
13
+
14
+ sig do
15
+ params(
16
+ content: String, old_requirements: T::Array[T::Hash[Symbol, T.untyped]],
17
+ new_requirements: T::Array[T::Hash[Symbol, T.untyped]]
18
+ )
19
+ .void
20
+ end
11
21
  def initialize(content, old_requirements:, new_requirements:)
12
22
  @content = content
13
23
  @old_requirements = old_requirements
14
24
  @new_requirements = new_requirements
15
25
  end
16
26
 
27
+ sig { returns(String) }
17
28
  def updated_manifest_content
18
29
  updated_content = content
19
30
 
@@ -22,7 +33,7 @@ module Dependabot
22
33
  content: updated_content,
23
34
  declaration: old[:metadata][:declaration_string],
24
35
  old_requirement: old[:metadata][:requirement_string],
25
- new_requirement: new[:metadata][:requirement_string]
36
+ new_requirement: T.must(new)[:metadata][:requirement_string]
26
37
  ).updated_content
27
38
  end
28
39
 
@@ -31,8 +42,13 @@ module Dependabot
31
42
 
32
43
  private
33
44
 
45
+ sig { returns(String) }
34
46
  attr_reader :content
47
+
48
+ sig { returns(T::Array[T::Hash[Symbol, T.untyped]]) }
35
49
  attr_reader :old_requirements
50
+
51
+ sig { returns(T::Array[T::Hash[Symbol, T.untyped]]) }
36
52
  attr_reader :new_requirements
37
53
  end
38
54
  end
@@ -1,12 +1,23 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "dependabot/file_updaters/base"
5
+ require "sorbet-runtime"
5
6
 
6
7
  module Dependabot
7
8
  module Swift
8
9
  class FileUpdater < Dependabot::FileUpdaters::Base
9
10
  class RequirementReplacer
11
+ extend T::Sig
12
+
13
+ sig do
14
+ params(
15
+ content: String,
16
+ declaration: String,
17
+ old_requirement: String,
18
+ new_requirement: String
19
+ ).void
20
+ end
10
21
  def initialize(content:, declaration:, old_requirement:, new_requirement:)
11
22
  @content = content
12
23
  @declaration = declaration
@@ -14,6 +25,7 @@ module Dependabot
14
25
  @new_requirement = new_requirement
15
26
  end
16
27
 
28
+ sig { returns(String) }
17
29
  def updated_content
18
30
  content.gsub(declaration) do |match|
19
31
  match.to_s.sub(old_requirement, new_requirement)
@@ -22,9 +34,16 @@ module Dependabot
22
34
 
23
35
  private
24
36
 
37
+ sig { returns(String) }
25
38
  attr_reader :content
39
+
40
+ sig { returns(String) }
26
41
  attr_reader :declaration
42
+
43
+ sig { returns(String) }
27
44
  attr_reader :old_requirement
45
+
46
+ sig { returns(String) }
28
47
  attr_reader :new_requirement
29
48
  end
30
49
  end
@@ -1,4 +1,4 @@
1
- # typed: true
1
+ # typed: strong
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "dependabot/file_updaters"
@@ -9,6 +9,9 @@ require "dependabot/swift/file_updater/manifest_updater"
9
9
  module Dependabot
10
10
  module Swift
11
11
  class FileUpdater < Dependabot::FileUpdaters::Base
12
+ extend T::Sig
13
+
14
+ sig { override.returns(T::Array[Regexp]) }
12
15
  def self.updated_files_regex
13
16
  [
14
17
  /Package(@swift-\d(\.\d){0,2})?\.swift/,
@@ -16,18 +19,21 @@ module Dependabot
16
19
  ]
17
20
  end
18
21
 
22
+ sig { override.returns(T::Array[Dependabot::DependencyFile]) }
19
23
  def updated_dependency_files
20
- updated_files = []
24
+ updated_files = T.let([], T::Array[Dependabot::DependencyFile])
21
25
 
22
- SharedHelpers.in_a_temporary_repo_directory(manifest.directory, repo_contents_path) do
23
- updated_manifest = nil
26
+ SharedHelpers.in_a_temporary_repo_directory(T.must(manifest).directory, repo_contents_path) do
27
+ updated_manifest = T.let(nil, T.nilable(Dependabot::DependencyFile))
24
28
 
25
- if file_changed?(manifest)
26
- updated_manifest = updated_file(file: manifest, content: updated_manifest_content)
29
+ if file_changed?(T.must(manifest))
30
+ updated_manifest = updated_file(file: T.must(manifest), content: updated_manifest_content)
27
31
  updated_files << updated_manifest
28
32
  end
29
33
 
30
- updated_files << updated_file(file: lockfile, content: updated_lockfile_content(updated_manifest)) if lockfile
34
+ if lockfile
35
+ updated_files << updated_file(file: T.must(lockfile), content: updated_lockfile_content(updated_manifest))
36
+ end
31
37
  end
32
38
 
33
39
  updated_files
@@ -35,42 +41,54 @@ module Dependabot
35
41
 
36
42
  private
37
43
 
44
+ sig { returns(Dependabot::Dependency) }
38
45
  def dependency
39
46
  # For now we will be updating a single dependency.
40
47
  # TODO: Revisit when/if implementing full unlocks
41
- dependencies.first
48
+ T.must(dependencies.first)
42
49
  end
43
50
 
51
+ sig { override.void }
44
52
  def check_required_files
45
53
  raise "A Package.swift file must be provided!" unless manifest
46
54
  end
47
55
 
56
+ sig { returns(String) }
48
57
  def updated_manifest_content
49
58
  ManifestUpdater.new(
50
- manifest.content,
51
- old_requirements: dependency.previous_requirements,
59
+ T.must(T.must(manifest).content),
60
+ old_requirements: T.must(dependency.previous_requirements),
52
61
  new_requirements: dependency.requirements
53
62
  ).updated_manifest_content
54
63
  end
55
64
 
65
+ sig { params(updated_manifest: T.nilable(Dependabot::DependencyFile)).returns(String) }
56
66
  def updated_lockfile_content(updated_manifest)
57
67
  LockfileUpdater.new(
58
68
  dependency: dependency,
59
- manifest: updated_manifest || manifest,
60
- repo_contents_path: repo_contents_path,
69
+ manifest: T.must(updated_manifest || manifest),
70
+ repo_contents_path: T.must(repo_contents_path),
61
71
  credentials: credentials,
62
72
  target_version: dependency.version
63
73
  ).updated_lockfile_content
64
74
  end
65
75
 
76
+ sig { returns(T.nilable(Dependabot::DependencyFile)) }
66
77
  def manifest
67
- @manifest ||= get_original_file("Package.swift")
78
+ @manifest ||= T.let(
79
+ get_original_file("Package.swift"),
80
+ T.nilable(Dependabot::DependencyFile)
81
+ )
68
82
  end
69
83
 
84
+ sig { returns(T.nilable(Dependabot::DependencyFile)) }
70
85
  def lockfile
71
86
  return @lockfile if defined?(@lockfile)
72
87
 
73
- @lockfile = get_original_file("Package.resolved")
88
+ @lockfile = T.let(
89
+ get_original_file("Package.resolved"),
90
+ T.nilable(Dependabot::DependencyFile)
91
+ )
74
92
  end
75
93
  end
76
94
  end
@@ -1,18 +1,30 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "dependabot/utils"
5
5
  require "dependabot/swift/requirement"
6
+ require "sorbet-runtime"
6
7
 
7
8
  module Dependabot
8
9
  module Swift
9
10
  class NativeRequirement
11
+ extend T::Sig
12
+
10
13
  # TODO: Support pinning to specific revisions
11
- REGEXP = /(from.*|\.upToNextMajor.*|\.upToNextMinor.*|".*"\s*\.\.[\.<]\s*".*"|exact.*|\.exact.*)/
14
+ REGEXP = T.let(/(from.*|\.upToNextMajor.*|\.upToNextMinor.*|".*"\s*\.\.[\.<]\s*".*"|exact.*|\.exact.*)/, Regexp)
12
15
 
16
+ sig { returns(String) }
13
17
  attr_reader :declaration
14
18
 
15
- def self.map_requirements(requirements)
19
+ sig do
20
+ type_parameters(:T)
21
+ .params(
22
+ requirements: T::Array[T::Hash[Symbol, T.untyped]],
23
+ _blk: T.proc.params(declaration: NativeRequirement).returns(String)
24
+ )
25
+ .returns(T::Array[T::Hash[Symbol, T.untyped]])
26
+ end
27
+ def self.map_requirements(requirements, &_blk)
16
28
  requirements.map do |requirement|
17
29
  declaration = new(requirement[:metadata][:requirement_string])
18
30
 
@@ -26,6 +38,7 @@ module Dependabot
26
38
  end
27
39
  end
28
40
 
41
+ sig { params(declaration: String).void }
29
42
  def initialize(declaration)
30
43
  @declaration = declaration
31
44
 
@@ -39,21 +52,24 @@ module Dependabot
39
52
  [">= #{min}", "< #{max}"]
40
53
  end
41
54
 
42
- @min = min
43
- @max = max
44
- @requirement = Requirement.new(constraint)
55
+ @min = T.let(min, String)
56
+ @max = T.let(max, String)
57
+ @requirement = T.let(Requirement.new(constraint), Requirement)
45
58
  end
46
59
 
60
+ sig { returns(String) }
47
61
  def to_s
48
62
  requirement.to_s
49
63
  end
50
64
 
65
+ sig { params(version: T.any(String, Gem::Version)).returns(T.nilable(String)) }
51
66
  def update_if_needed(version)
52
67
  return declaration if requirement.satisfied_by?(version)
53
68
 
54
69
  update(version)
55
70
  end
56
71
 
72
+ sig { params(version: T.any(String, Gem::Version)).returns(T.nilable(String)) }
57
73
  def update(version)
58
74
  if single_version_declaration?
59
75
  declaration.sub(min, version.to_s)
@@ -66,6 +82,7 @@ module Dependabot
66
82
 
67
83
  private
68
84
 
85
+ sig { params(declaration: String).returns([String, String]) }
69
86
  def parse_declaration(declaration)
70
87
  if up_to_next_major?
71
88
  min = declaration.gsub(/\Afrom\s*:\s*"(\S+)"\s*\z/, '\1')
@@ -90,24 +107,28 @@ module Dependabot
90
107
  raise "Unsupported constraint: #{declaration}"
91
108
  end
92
109
 
93
- [min, max]
110
+ [T.must(min), T.must(max)]
94
111
  end
95
112
 
113
+ sig { params(separator: String).returns(T::Array[String]) }
96
114
  def parse_range(separator)
97
115
  declaration.split(separator).map { |str| unquote(str.strip) }
98
116
  end
99
117
 
118
+ sig { returns(T::Boolean) }
100
119
  def single_version_declaration?
101
120
  up_to_next_major? || up_to_next_major_deprecated? || up_to_next_minor_deprecated? ||
102
121
  exact_version? || exact_version_deprecated?
103
122
  end
104
123
 
124
+ sig { params(str: String).returns(String) }
105
125
  def bump_major(str)
106
126
  transform_version(str) do |s, i|
107
127
  i.zero? ? s.to_i + 1 : 0
108
128
  end
109
129
  end
110
130
 
131
+ sig { params(str: String).returns(String) }
111
132
  def bump_minor(str)
112
133
  transform_version(str) do |s, i|
113
134
  if i.zero?
@@ -118,44 +139,60 @@ module Dependabot
118
139
  end
119
140
  end
120
141
 
142
+ sig do
143
+ params(str: String, block: T.proc.params(s: String, i: Integer).returns(T.any(String, Integer))).returns(String)
144
+ end
121
145
  def transform_version(str, &block)
122
146
  str.split(".").map.with_index(&block).join(".")
123
147
  end
124
148
 
149
+ sig { returns(T::Boolean) }
125
150
  def up_to_next_major?
126
151
  declaration.start_with?("from")
127
152
  end
128
153
 
154
+ sig { returns(T::Boolean) }
129
155
  def up_to_next_major_deprecated?
130
156
  declaration.start_with?(".upToNextMajor")
131
157
  end
132
158
 
159
+ sig { returns(T::Boolean) }
133
160
  def up_to_next_minor_deprecated?
134
161
  declaration.start_with?(".upToNextMinor")
135
162
  end
136
163
 
164
+ sig { returns(T::Boolean) }
137
165
  def exact_version?
138
166
  declaration.start_with?("exact")
139
167
  end
140
168
 
169
+ sig { returns(T::Boolean) }
141
170
  def exact_version_deprecated?
142
171
  declaration.start_with?(".exact")
143
172
  end
144
173
 
174
+ sig { returns(T::Boolean) }
145
175
  def closed_range?
146
176
  declaration.include?("...")
147
177
  end
148
178
 
179
+ sig { returns(T::Boolean) }
149
180
  def range?
150
181
  declaration.include?("..<")
151
182
  end
152
183
 
184
+ sig { returns(String) }
153
185
  attr_reader :min
186
+
187
+ sig { returns(String) }
154
188
  attr_reader :max
189
+
190
+ sig { returns(Requirement) }
155
191
  attr_reader :requirement
156
192
 
193
+ sig { params(declaration: String).returns(String) }
157
194
  def unquote(declaration)
158
- declaration[1..-2]
195
+ T.must(declaration[1..-2])
159
196
  end
160
197
  end
161
198
  end
@@ -1,4 +1,4 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "sorbet-runtime"
@@ -20,6 +20,7 @@ module Dependabot
20
20
 
21
21
  # Patches Gem::Requirement to make it accept requirement strings like
22
22
  # "~> 4.2.5, >= 4.2.5.1" without first needing to split them.
23
+ sig { params(requirements: T.untyped).void }
23
24
  def initialize(*requirements)
24
25
  requirements = requirements.flatten.flat_map do |req_string|
25
26
  req_string.split(",").map(&:strip)
@@ -1,4 +1,4 @@
1
- # typed: true
1
+ # typed: strong
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "dependabot/update_checkers/base"
@@ -9,23 +9,35 @@ module Dependabot
9
9
  module Swift
10
10
  class UpdateChecker < Dependabot::UpdateCheckers::Base
11
11
  class RequirementsUpdater
12
+ extend T::Sig
13
+
14
+ sig do
15
+ params(
16
+ requirements: T::Array[T::Hash[Symbol, T.untyped]],
17
+ target_version: T.nilable(T.any(String, Gem::Version))
18
+ ).void
19
+ end
12
20
  def initialize(requirements:, target_version:)
13
21
  @requirements = requirements
14
22
 
15
23
  return unless target_version && Version.correct?(target_version)
16
24
 
17
- @target_version = Version.new(target_version)
25
+ @target_version = T.let(Version.new(target_version), Dependabot::Version)
18
26
  end
19
27
 
28
+ sig { returns(T::Array[T::Hash[Symbol, T.untyped]]) }
20
29
  def updated_requirements
21
30
  NativeRequirement.map_requirements(requirements) do |requirement|
22
- requirement.update_if_needed(target_version)
31
+ T.must(requirement.update_if_needed(T.must(target_version)))
23
32
  end
24
33
  end
25
34
 
26
35
  private
27
36
 
37
+ sig { returns(T::Array[T.untyped]) }
28
38
  attr_reader :requirements
39
+
40
+ sig { returns(T.nilable(Gem::Version)) }
29
41
  attr_reader :target_version
30
42
  end
31
43
  end
@@ -1,14 +1,26 @@
1
- # typed: true
1
+ # typed: strong
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "dependabot/update_checkers/base"
5
5
  require "dependabot/swift/file_parser/dependency_parser"
6
6
  require "dependabot/swift/file_updater/lockfile_updater"
7
+ require "sorbet-runtime"
7
8
 
8
9
  module Dependabot
9
10
  module Swift
10
11
  class UpdateChecker < Dependabot::UpdateCheckers::Base
11
12
  class VersionResolver
13
+ extend T::Sig
14
+
15
+ sig do
16
+ params(
17
+ dependency: Dependabot::Dependency,
18
+ manifest: Dependabot::DependencyFile,
19
+ lockfile: T.nilable(Dependabot::DependencyFile),
20
+ repo_contents_path: T.nilable(String),
21
+ credentials: T::Array[Dependabot::Credential]
22
+ ).void
23
+ end
12
24
  def initialize(dependency:, manifest:, lockfile:, repo_contents_path:, credentials:)
13
25
  @dependency = dependency
14
26
  @manifest = manifest
@@ -17,21 +29,26 @@ module Dependabot
17
29
  @repo_contents_path = repo_contents_path
18
30
  end
19
31
 
32
+ sig { returns(T.nilable(String)) }
20
33
  def latest_resolvable_version
21
- @latest_resolvable_version ||= fetch_latest_resolvable_version
34
+ @latest_resolvable_version ||= T.let(
35
+ fetch_latest_resolvable_version,
36
+ T.nilable(String)
37
+ )
22
38
  end
23
39
 
24
40
  private
25
41
 
42
+ sig { returns(T.nilable(String)) }
26
43
  def fetch_latest_resolvable_version
27
44
  updated_lockfile_content = FileUpdater::LockfileUpdater.new(
28
45
  dependency: dependency,
29
46
  manifest: manifest,
30
- repo_contents_path: repo_contents_path,
47
+ repo_contents_path: T.must(repo_contents_path),
31
48
  credentials: credentials
32
49
  ).updated_lockfile_content
33
50
 
34
- return if lockfile && updated_lockfile_content == lockfile.content
51
+ return if lockfile && updated_lockfile_content == T.must(lockfile).content
35
52
 
36
53
  updated_lockfile = DependencyFile.new(
37
54
  name: "Package.resolved",
@@ -41,9 +58,16 @@ module Dependabot
41
58
 
42
59
  dependency_parser(manifest, updated_lockfile).parse.find do |parsed_dep|
43
60
  parsed_dep.name == dependency.name
44
- end.version
61
+ end&.version
45
62
  end
46
63
 
64
+ sig do
65
+ params(
66
+ manifest: Dependabot::DependencyFile,
67
+ lockfile: Dependabot::DependencyFile
68
+ )
69
+ .returns(FileParser::DependencyParser)
70
+ end
47
71
  def dependency_parser(manifest, lockfile)
48
72
  FileParser::DependencyParser.new(
49
73
  dependency_files: [manifest, lockfile].compact,
@@ -52,10 +76,19 @@ module Dependabot
52
76
  )
53
77
  end
54
78
 
79
+ sig { returns(Dependabot::Dependency) }
55
80
  attr_reader :dependency
81
+
82
+ sig { returns(Dependabot::DependencyFile) }
56
83
  attr_reader :manifest
84
+
85
+ sig { returns(T.nilable(Dependabot::DependencyFile)) }
57
86
  attr_reader :lockfile
87
+
88
+ sig { returns(T.nilable(String)) }
58
89
  attr_reader :repo_contents_path
90
+
91
+ sig { returns(T::Array[Dependabot::Credential]) }
59
92
  attr_reader :credentials
60
93
  end
61
94
  end
@@ -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/update_checkers"
5
6
  require "dependabot/update_checkers/base"
6
7
  require "dependabot/update_checkers/version_filters"
@@ -11,58 +12,77 @@ require "dependabot/swift/file_updater/manifest_updater"
11
12
  module Dependabot
12
13
  module Swift
13
14
  class UpdateChecker < Dependabot::UpdateCheckers::Base
15
+ extend T::Sig
16
+
14
17
  require_relative "update_checker/requirements_updater"
15
18
  require_relative "update_checker/version_resolver"
16
19
 
20
+ sig { override.returns(T.nilable(Dependabot::Version)) }
17
21
  def latest_version
18
- @latest_version ||= fetch_latest_version
22
+ @latest_version ||= T.let(fetch_latest_version, T.nilable(Dependabot::Version))
19
23
  end
20
24
 
25
+ sig { override.returns(T.nilable(Dependabot::Version)) }
21
26
  def latest_resolvable_version
22
- @latest_resolvable_version ||= fetch_latest_resolvable_version
27
+ @latest_resolvable_version = T.let(fetch_latest_resolvable_version, T.nilable(Dependabot::Version))
23
28
  end
24
29
 
30
+ sig { override.returns(T.noreturn) }
25
31
  def latest_resolvable_version_with_no_unlock
26
32
  raise NotImplementedError
27
33
  end
28
34
 
35
+ sig { override.returns(T.nilable(Dependabot::Version)) }
29
36
  def lowest_security_fix_version
30
- @lowest_security_fix_version ||= fetch_lowest_security_fix_version
37
+ @lowest_security_fix_version ||= T.let(fetch_lowest_security_fix_version, T.nilable(Dependabot::Version))
31
38
  end
32
39
 
40
+ sig { override.returns(T.nilable(Dependabot::Version)) }
33
41
  def lowest_resolvable_security_fix_version
34
42
  raise "Dependency not vulnerable!" unless vulnerable?
35
43
 
36
- return @lowest_resolvable_security_fix_version if defined?(@lowest_resolvable_security_fix_version)
37
-
38
- @lowest_resolvable_security_fix_version = fetch_lowest_resolvable_security_fix_version
44
+ @lowest_resolvable_security_fix_version = T.let(
45
+ fetch_lowest_resolvable_security_fix_version,
46
+ T.nilable(Dependabot::Version)
47
+ )
39
48
  end
40
49
 
50
+ sig { override.returns(T::Array[T::Hash[Symbol, T.untyped]]) }
41
51
  def updated_requirements
42
52
  RequirementsUpdater.new(
43
53
  requirements: old_requirements,
44
- target_version: preferred_resolvable_version
54
+ target_version: T.must(preferred_resolvable_version)
45
55
  ).updated_requirements
46
56
  end
47
57
 
48
58
  private
49
59
 
60
+ sig { returns(T::Array[T::Hash[Symbol, T.untyped]]) }
50
61
  def old_requirements
51
62
  dependency.requirements
52
63
  end
53
64
 
65
+ sig { returns(T.nilable(Dependabot::Version)) }
54
66
  def fetch_latest_version
55
67
  return unless git_commit_checker.pinned_ref_looks_like_version? && latest_version_tag
56
68
 
57
- latest_version_tag.fetch(:version)
69
+ tag = latest_version_tag
70
+ return unless tag
71
+
72
+ tag.fetch(:version)
58
73
  end
59
74
 
75
+ sig { returns(T.nilable(Dependabot::Version)) }
60
76
  def fetch_lowest_security_fix_version
61
77
  return unless git_commit_checker.pinned_ref_looks_like_version? && latest_version_tag
62
78
 
63
- lowest_security_fix_version_tag.fetch(:version)
79
+ tag = lowest_security_fix_version_tag
80
+ return unless tag
81
+
82
+ tag.fetch(:version)
64
83
  end
65
84
 
85
+ sig { returns(T.nilable(Dependabot::Version)) }
66
86
  def fetch_latest_resolvable_version
67
87
  latest_resolvable_version = version_resolver_for(unlocked_requirements).latest_resolvable_version
68
88
  return current_version unless latest_resolvable_version
@@ -70,6 +90,7 @@ module Dependabot
70
90
  Version.new(latest_resolvable_version)
71
91
  end
72
92
 
93
+ sig { returns(T.nilable(Dependabot::Version)) }
73
94
  def fetch_lowest_resolvable_security_fix_version
74
95
  lowest_resolvable_security_fix_version = version_resolver_for(
75
96
  force_lowest_security_fix_requirements
@@ -79,6 +100,7 @@ module Dependabot
79
100
  Version.new(lowest_resolvable_security_fix_version)
80
101
  end
81
102
 
103
+ sig { params(requirements: T::Array[T::Hash[Symbol, T.untyped]]).returns(VersionResolver) }
82
104
  def version_resolver_for(requirements)
83
105
  VersionResolver.new(
84
106
  dependency: dependency,
@@ -89,66 +111,88 @@ module Dependabot
89
111
  )
90
112
  end
91
113
 
114
+ sig { returns(T::Array[T::Hash[Symbol, T.untyped]]) }
92
115
  def unlocked_requirements
93
116
  NativeRequirement.map_requirements(old_requirements) do |_old_requirement|
94
117
  "\"#{dependency.version}\"...\"#{latest_version}\""
95
118
  end
96
119
  end
97
120
 
121
+ sig { returns(T::Array[T::Hash[Symbol, T.untyped]]) }
98
122
  def force_lowest_security_fix_requirements
99
123
  NativeRequirement.map_requirements(old_requirements) do |_old_requirement|
100
124
  "\"#{lowest_security_fix_version}\"...\"#{lowest_security_fix_version}\""
101
125
  end
102
126
  end
103
127
 
128
+ sig { params(new_requirements: T::Array[T::Hash[Symbol, T.untyped]]).returns(Dependabot::DependencyFile) }
104
129
  def prepare_manifest_for(new_requirements)
130
+ manifest_file = T.must(manifest)
131
+
105
132
  DependencyFile.new(
106
- name: manifest.name,
133
+ name: manifest_file.name,
107
134
  content: FileUpdater::ManifestUpdater.new(
108
- manifest.content,
135
+ T.must(manifest_file.content),
109
136
  old_requirements: old_requirements,
110
137
  new_requirements: new_requirements
111
138
  ).updated_manifest_content,
112
- directory: manifest.directory
139
+ directory: manifest_file.directory
113
140
  )
114
141
  end
115
142
 
143
+ sig { returns(T.nilable(Dependabot::DependencyFile)) }
116
144
  def manifest
117
- @manifest ||= dependency_files.find { |file| file.name == "Package.swift" }
145
+ @manifest ||= T.let(
146
+ dependency_files.find { |file| file.name == "Package.swift" },
147
+ T.nilable(Dependabot::DependencyFile)
148
+ )
118
149
  end
119
150
 
151
+ sig { returns(T.nilable(Dependabot::DependencyFile)) }
120
152
  def lockfile
121
- @lockfile ||= dependency_files.find { |file| file.name == "Package.resolved" }
153
+ @lockfile ||= T.let(
154
+ dependency_files.find { |file| file.name == "Package.resolved" },
155
+ T.nilable(Dependabot::DependencyFile)
156
+ )
122
157
  end
123
158
 
159
+ sig { override.returns(T::Boolean) }
124
160
  def latest_version_resolvable_with_full_unlock?
125
161
  # Full unlock checks aren't implemented for Swift (yet)
126
162
  false
127
163
  end
128
164
 
165
+ sig { override.returns(T.noreturn) }
129
166
  def updated_dependencies_after_full_unlock
130
167
  raise NotImplementedError
131
168
  end
132
169
 
170
+ sig { returns(Dependabot::GitCommitChecker) }
133
171
  def git_commit_checker
134
- @git_commit_checker ||= Dependabot::GitCommitChecker.new(
135
- dependency: dependency,
136
- credentials: credentials,
137
- ignored_versions: ignored_versions,
138
- raise_on_ignored: raise_on_ignored,
139
- consider_version_branches_pinned: true
172
+ @git_commit_checker ||= T.let(
173
+ Dependabot::GitCommitChecker.new(
174
+ dependency: dependency,
175
+ credentials: credentials,
176
+ ignored_versions: ignored_versions,
177
+ raise_on_ignored: raise_on_ignored,
178
+ consider_version_branches_pinned: true
179
+ ),
180
+ T.nilable(Dependabot::GitCommitChecker)
140
181
  )
141
182
  end
142
183
 
184
+ sig { returns(T.nilable(T::Hash[Symbol, T.untyped])) }
143
185
  def latest_version_tag
144
186
  git_commit_checker.local_tag_for_latest_version
145
187
  end
146
188
 
189
+ sig { returns(T.nilable(T::Hash[Symbol, T.untyped])) }
147
190
  def lowest_security_fix_version_tag
148
191
  tags = git_commit_checker.local_tags_for_allowed_versions
149
192
  find_lowest_secure_version(tags)
150
193
  end
151
194
 
195
+ sig { params(tags: T::Array[T::Hash[Symbol, T.untyped]]).returns(T.nilable(T::Hash[Symbol, T.untyped])) }
152
196
  def find_lowest_secure_version(tags)
153
197
  relevant_tags = Dependabot::UpdateCheckers::VersionFilters.filter_vulnerable_versions(tags, security_advisories)
154
198
  relevant_tags = filter_lower_tags(relevant_tags)
@@ -156,6 +200,7 @@ module Dependabot
156
200
  relevant_tags.min_by { |tag| tag.fetch(:version) }
157
201
  end
158
202
 
203
+ sig { params(tags_array: T::Array[T::Hash[Symbol, T.untyped]]).returns(T::Array[T::Hash[Symbol, T.untyped]]) }
159
204
  def filter_lower_tags(tags_array)
160
205
  return tags_array unless current_version
161
206
 
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dependabot-swift
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.309.0
4
+ version: 0.310.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dependabot
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-04-17 00:00:00.000000000 Z
10
+ date: 2025-04-24 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: dependabot-common
@@ -15,14 +15,14 @@ dependencies:
15
15
  requirements:
16
16
  - - '='
17
17
  - !ruby/object:Gem::Version
18
- version: 0.309.0
18
+ version: 0.310.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.309.0
25
+ version: 0.310.0
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: debug
28
28
  requirement: !ruby/object:Gem::Requirement
@@ -264,7 +264,7 @@ licenses:
264
264
  - MIT
265
265
  metadata:
266
266
  bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
267
- changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.309.0
267
+ changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.310.0
268
268
  rdoc_options: []
269
269
  require_paths:
270
270
  - lib