dependabot-swift 0.223.0 → 0.225.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: b9c4d7a75751290497fd09eb0dc26f82ca32b29246bf0d07fabe6c71a9af64f2
4
- data.tar.gz: b84e6a5b45b30892f35e2033dc4b57cbb172b3f3f006f2b71f17c7fa4d7463f3
3
+ metadata.gz: ece4598e2b52cc65a287a39c06f315c6971c62162bb5f571f8b35b8a7dcd95ca
4
+ data.tar.gz: a2e0c834bb02b3e8ee6cc0fac896083700ea4423154827ddee9b3ab9af9fc8d6
5
5
  SHA512:
6
- metadata.gz: a7fb390b84f5159787be751f8b30815918a76f86a3433961811c6647d2ede4bb1cce2ec201665dce979eafb35b06646c884d4400a313817f18a4a2855fc459b7
7
- data.tar.gz: c47f6f424a89188321c59fa5e9401cab4a821c3c80418e5bc7ae7f9b3ec555b1d11e8f525487516659791513fc10e381aee15663baf6b70f731fd849a3c2b5ef
6
+ metadata.gz: 1b53549f3e23982d335b6d8ab2e0e7bfb540fd708b22f1f220625a3aed3524af77586d097f8cc700af0839b31ded7fec9876643ee32413a76f81282c216efa8c
7
+ data.tar.gz: 284f0ee7c59cfe1854b77b23ba1ace37cbe3629512a67d4fa519ef148fc1276fd0a9530802878ebdc0295335bb2983c7c6978786ab5cd45c3aaa94b3186345e0
@@ -4,6 +4,7 @@ require "dependabot/file_parsers/base"
4
4
  require "dependabot/shared_helpers"
5
5
  require "dependabot/dependency"
6
6
  require "json"
7
+ require "uri"
7
8
 
8
9
  module Dependabot
9
10
  module Swift
@@ -47,12 +48,14 @@ module Dependabot
47
48
  end
48
49
 
49
50
  def all_dependencies(data, level: 0)
50
- name = data["identity"]
51
+ identity = data["identity"]
51
52
  url = data["url"]
53
+ name = normalize(url)
52
54
  version = data["version"]
53
55
 
54
56
  source = { type: "git", url: url, ref: version, branch: nil }
55
- args = { name: name, version: version, package_manager: "swift", requirements: [] }
57
+ metadata = { identity: identity }
58
+ args = { name: name, version: version, package_manager: "swift", requirements: [], metadata: metadata }
56
59
 
57
60
  if level.zero?
58
61
  args[:requirements] << { requirement: nil, groups: ["dependencies"], file: nil, source: source }
@@ -65,6 +68,12 @@ module Dependabot
65
68
  [dep, *subdependencies(data, level: level + 1)].compact
66
69
  end
67
70
 
71
+ def normalize(source)
72
+ uri = URI.parse(source.downcase)
73
+
74
+ "#{uri.host}#{uri.path}".delete_prefix("www.").delete_suffix(".git")
75
+ end
76
+
68
77
  attr_reader :dependency_files, :repo_contents_path, :credentials
69
78
  end
70
79
  end
@@ -7,7 +7,8 @@ module Dependabot
7
7
  module Swift
8
8
  class FileParser < Dependabot::FileParsers::Base
9
9
  class ManifestParser
10
- DEPENDENCY = /(?<declaration>\.package\(\s*(?:name: "[^"]+",\s*)?url: "(?<url>[^"]+)",\s*(?<requirement>.*)\))/
10
+ DEPENDENCY =
11
+ /(?<declaration>\.package\(\s*(?:name: "[^"]+",\s*)?url: "(?<url>[^"]+)",\s*(?<requirement>.*)\s*\))/
11
12
 
12
13
  def initialize(manifest, source:)
13
14
  @manifest = manifest
@@ -24,7 +24,8 @@ module Dependabot
24
24
  name: dep.name,
25
25
  version: dep.version,
26
26
  package_manager: dep.package_manager,
27
- requirements: requirements
27
+ requirements: requirements,
28
+ metadata: dep.metadata
28
29
  )
29
30
  else
30
31
  dependency_set << dep
@@ -2,16 +2,18 @@
2
2
 
3
3
  require "dependabot/file_updaters/base"
4
4
  require "dependabot/shared_helpers"
5
+ require "dependabot/logger"
5
6
 
6
7
  module Dependabot
7
8
  module Swift
8
9
  class FileUpdater < Dependabot::FileUpdaters::Base
9
10
  class LockfileUpdater
10
- def initialize(dependencies:, manifest:, repo_contents_path:, credentials:)
11
- @dependencies = dependencies
11
+ def initialize(dependency:, manifest:, repo_contents_path:, credentials:, target_version: nil)
12
+ @dependency = dependency
12
13
  @manifest = manifest
13
14
  @repo_contents_path = repo_contents_path
14
15
  @credentials = credentials
16
+ @target_version = target_version
15
17
  end
16
18
 
17
19
  def updated_lockfile_content
@@ -19,10 +21,7 @@ module Dependabot
19
21
  File.write(manifest.name, manifest.content)
20
22
 
21
23
  SharedHelpers.with_git_configured(credentials: credentials) do
22
- SharedHelpers.run_shell_command(
23
- "swift package update #{dependencies.map(&:name).join(' ')}",
24
- fingerprint: "swift package update <dependency_name>"
25
- )
24
+ try_lockfile_update(dependency.metadata[:identity])
26
25
 
27
26
  File.read("Package.resolved")
28
27
  end
@@ -31,7 +30,27 @@ module Dependabot
31
30
 
32
31
  private
33
32
 
34
- attr_reader :dependencies, :manifest, :repo_contents_path, :credentials
33
+ def try_lockfile_update(dependency_name)
34
+ if target_version
35
+ SharedHelpers.run_shell_command(
36
+ "swift package resolve #{dependency_name} --version #{target_version}",
37
+ fingerprint: "swift package resolve <dependency_name> --version <target_version>"
38
+ )
39
+ else
40
+ SharedHelpers.run_shell_command(
41
+ "swift package update #{dependency_name}",
42
+ fingerprint: "swift package update <dependency_name>"
43
+ )
44
+ end
45
+ rescue SharedHelpers::HelperSubprocessFailed => e
46
+ # This class is not only used for final lockfile updates, but for
47
+ # checking resolvability. So resolvability errors here are expected in
48
+ # certain situations and will result in `no_update_possible` outcomes.
49
+ # That said, since we're swallowing all errors we at least log them to ease debugging.
50
+ Dependabot.logger.info("Lockfile failed to be updated due to error:\n#{e.message}")
51
+ end
52
+
53
+ attr_reader :dependency, :manifest, :repo_contents_path, :credentials, :target_version
35
54
  end
36
55
  end
37
56
  end
@@ -54,10 +54,11 @@ module Dependabot
54
54
 
55
55
  def updated_lockfile_content(updated_manifest)
56
56
  LockfileUpdater.new(
57
- dependencies: dependencies,
57
+ dependency: dependency,
58
58
  manifest: updated_manifest || manifest,
59
59
  repo_contents_path: repo_contents_path,
60
- credentials: credentials
60
+ credentials: credentials,
61
+ target_version: dependency.version
61
62
  ).updated_lockfile_content
62
63
  end
63
64
 
@@ -90,7 +90,7 @@ module Dependabot
90
90
  end
91
91
 
92
92
  def parse_range(separator)
93
- declaration.split(separator).map { |str| unquote(str) }
93
+ declaration.split(separator).map { |str| unquote(str.strip) }
94
94
  end
95
95
 
96
96
  def single_version_declaration?
@@ -8,9 +8,10 @@ module Dependabot
8
8
  module Swift
9
9
  class UpdateChecker < Dependabot::UpdateCheckers::Base
10
10
  class VersionResolver
11
- def initialize(dependency:, manifest:, repo_contents_path:, credentials:)
11
+ def initialize(dependency:, manifest:, lockfile:, repo_contents_path:, credentials:)
12
12
  @dependency = dependency
13
13
  @manifest = manifest
14
+ @lockfile = lockfile
14
15
  @credentials = credentials
15
16
  @repo_contents_path = repo_contents_path
16
17
  end
@@ -23,18 +24,21 @@ module Dependabot
23
24
 
24
25
  def fetch_latest_resolvable_version
25
26
  updated_lockfile_content = FileUpdater::LockfileUpdater.new(
26
- dependencies: [dependency],
27
+ dependency: dependency,
27
28
  manifest: manifest,
28
29
  repo_contents_path: repo_contents_path,
29
30
  credentials: credentials
30
31
  ).updated_lockfile_content
31
32
 
32
- lockfile = DependencyFile.new(
33
+ return if updated_lockfile_content == lockfile.content
34
+
35
+ updated_lockfile = DependencyFile.new(
33
36
  name: "Package.resolved",
34
- content: updated_lockfile_content
37
+ content: updated_lockfile_content,
38
+ directory: manifest.directory
35
39
  )
36
40
 
37
- dependency_parser(manifest, lockfile).parse.find do |parsed_dep|
41
+ dependency_parser(manifest, updated_lockfile).parse.find do |parsed_dep|
38
42
  parsed_dep.name == dependency.name
39
43
  end.version
40
44
  end
@@ -47,7 +51,7 @@ module Dependabot
47
51
  )
48
52
  end
49
53
 
50
- attr_reader :dependency, :manifest, :repo_contents_path, :credentials
54
+ attr_reader :dependency, :manifest, :lockfile, :repo_contents_path, :credentials
51
55
  end
52
56
  end
53
57
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  require "dependabot/update_checkers"
4
4
  require "dependabot/update_checkers/base"
5
+ require "dependabot/update_checkers/version_filters"
5
6
  require "dependabot/git_commit_checker"
6
7
  require "dependabot/swift/native_requirement"
7
8
  require "dependabot/swift/file_updater/manifest_updater"
@@ -24,6 +25,18 @@ module Dependabot
24
25
  raise NotImplementedError
25
26
  end
26
27
 
28
+ def lowest_security_fix_version
29
+ @lowest_security_fix_version ||= fetch_lowest_security_fix_version
30
+ end
31
+
32
+ def lowest_resolvable_security_fix_version
33
+ raise "Dependency not vulnerable!" unless vulnerable?
34
+
35
+ return @lowest_resolvable_security_fix_version if defined?(@lowest_resolvable_security_fix_version)
36
+
37
+ @lowest_resolvable_security_fix_version = fetch_lowest_resolvable_security_fix_version
38
+ end
39
+
27
40
  def updated_requirements
28
41
  RequirementsUpdater.new(
29
42
  requirements: old_requirements,
@@ -43,14 +56,33 @@ module Dependabot
43
56
  latest_version_tag.fetch(:version)
44
57
  end
45
58
 
59
+ def fetch_lowest_security_fix_version
60
+ return unless git_commit_checker.pinned_ref_looks_like_version? && latest_version_tag
61
+
62
+ lowest_security_fix_version_tag.fetch(:version)
63
+ end
64
+
46
65
  def fetch_latest_resolvable_version
47
- Version.new(version_resolver.latest_resolvable_version)
66
+ latest_resolvable_version = version_resolver_for(unlocked_requirements).latest_resolvable_version
67
+ return current_version unless latest_resolvable_version
68
+
69
+ Version.new(latest_resolvable_version)
70
+ end
71
+
72
+ def fetch_lowest_resolvable_security_fix_version
73
+ lowest_resolvable_security_fix_version = version_resolver_for(
74
+ force_lowest_security_fix_requirements
75
+ ).latest_resolvable_version
76
+ return unless lowest_resolvable_security_fix_version
77
+
78
+ Version.new(lowest_resolvable_security_fix_version)
48
79
  end
49
80
 
50
- def version_resolver
81
+ def version_resolver_for(requirements)
51
82
  VersionResolver.new(
52
83
  dependency: dependency,
53
- manifest: prepared_manifest,
84
+ manifest: prepare_manifest_for(requirements),
85
+ lockfile: lockfile,
54
86
  repo_contents_path: repo_contents_path,
55
87
  credentials: credentials
56
88
  )
@@ -62,19 +94,30 @@ module Dependabot
62
94
  end
63
95
  end
64
96
 
65
- def prepared_manifest
97
+ def force_lowest_security_fix_requirements
98
+ NativeRequirement.map_requirements(old_requirements) do |_old_requirement|
99
+ "\"#{lowest_security_fix_version}\"...\"#{lowest_security_fix_version}\""
100
+ end
101
+ end
102
+
103
+ def prepare_manifest_for(new_requirements)
66
104
  DependencyFile.new(
67
105
  name: manifest.name,
68
106
  content: FileUpdater::ManifestUpdater.new(
69
107
  manifest.content,
70
108
  old_requirements: old_requirements,
71
- new_requirements: unlocked_requirements
72
- ).updated_manifest_content
109
+ new_requirements: new_requirements
110
+ ).updated_manifest_content,
111
+ directory: manifest.directory
73
112
  )
74
113
  end
75
114
 
76
115
  def manifest
77
- dependency_files.find { |file| file.name == "Package.swift" }
116
+ @manifest ||= dependency_files.find { |file| file.name == "Package.swift" }
117
+ end
118
+
119
+ def lockfile
120
+ @lockfile ||= dependency_files.find { |file| file.name == "Package.resolved" }
78
121
  end
79
122
 
80
123
  def latest_version_resolvable_with_full_unlock?
@@ -99,6 +142,25 @@ module Dependabot
99
142
  def latest_version_tag
100
143
  git_commit_checker.local_tag_for_latest_version
101
144
  end
145
+
146
+ def lowest_security_fix_version_tag
147
+ tags = git_commit_checker.local_tags_for_allowed_versions
148
+ find_lowest_secure_version(tags)
149
+ end
150
+
151
+ def find_lowest_secure_version(tags)
152
+ relevant_tags = Dependabot::UpdateCheckers::VersionFilters.filter_vulnerable_versions(tags, security_advisories)
153
+ relevant_tags = filter_lower_tags(relevant_tags)
154
+
155
+ relevant_tags.min_by { |tag| tag.fetch(:version) }
156
+ end
157
+
158
+ def filter_lower_tags(tags_array)
159
+ return tags_array unless current_version
160
+
161
+ tags_array.
162
+ select { |tag| tag.fetch(:version) > current_version }
163
+ end
102
164
  end
103
165
  end
104
166
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dependabot-swift
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.223.0
4
+ version: 0.225.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dependabot
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-07-25 00:00:00.000000000 Z
11
+ date: 2023-07-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dependabot-common
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 0.223.0
19
+ version: 0.225.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 0.223.0
26
+ version: 0.225.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: debug
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -207,7 +207,7 @@ licenses:
207
207
  - Nonstandard
208
208
  metadata:
209
209
  bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
210
- changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.223.0
210
+ changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.225.0
211
211
  post_install_message:
212
212
  rdoc_options: []
213
213
  require_paths: