dependabot-swift 0.223.0 → 0.225.0

Sign up to get free protection for your applications and to get access to all the features.
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: