dependabot-core 0.88.3 → 0.89.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +6 -0
  3. data/helpers/test/run.rb +3 -0
  4. data/lib/dependabot/file_fetchers.rb +0 -2
  5. data/lib/dependabot/file_parsers.rb +0 -2
  6. data/lib/dependabot/file_updaters.rb +0 -2
  7. data/lib/dependabot/file_updaters/go/dep/lockfile_updater.rb +11 -8
  8. data/lib/dependabot/metadata_finders.rb +0 -2
  9. data/lib/dependabot/shared_helpers.rb +47 -24
  10. data/lib/dependabot/update_checkers.rb +0 -2
  11. data/lib/dependabot/update_checkers/go/dep/version_resolver.rb +11 -7
  12. data/lib/dependabot/utils.rb +0 -4
  13. data/lib/dependabot/version.rb +1 -1
  14. metadata +2 -25
  15. data/helpers/php/.php_cs +0 -34
  16. data/helpers/php/bin/run.php +0 -84
  17. data/helpers/php/composer.json +0 -14
  18. data/helpers/php/composer.lock +0 -1528
  19. data/helpers/php/composer.phar +0 -0
  20. data/helpers/php/setup.sh +0 -4
  21. data/helpers/php/src/DependabotInstallationManager.php +0 -61
  22. data/helpers/php/src/DependabotPluginManager.php +0 -23
  23. data/helpers/php/src/ExceptionIO.php +0 -25
  24. data/helpers/php/src/Hasher.php +0 -21
  25. data/helpers/php/src/UpdateChecker.php +0 -123
  26. data/helpers/php/src/Updater.php +0 -97
  27. data/lib/dependabot/file_fetchers/php/composer.rb +0 -131
  28. data/lib/dependabot/file_parsers/php/composer.rb +0 -177
  29. data/lib/dependabot/file_updaters/php/composer.rb +0 -78
  30. data/lib/dependabot/file_updaters/php/composer/lockfile_updater.rb +0 -269
  31. data/lib/dependabot/file_updaters/php/composer/manifest_updater.rb +0 -70
  32. data/lib/dependabot/metadata_finders/php/composer.rb +0 -66
  33. data/lib/dependabot/update_checkers/php/composer.rb +0 -175
  34. data/lib/dependabot/update_checkers/php/composer/requirements_updater.rb +0 -258
  35. data/lib/dependabot/update_checkers/php/composer/version_resolver.rb +0 -216
  36. data/lib/dependabot/utils/php/requirement.rb +0 -97
  37. data/lib/dependabot/utils/php/version.rb +0 -24
@@ -1,70 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "dependabot/file_updaters/php/composer"
4
-
5
- module Dependabot
6
- module FileUpdaters
7
- module Php
8
- class Composer
9
- class ManifestUpdater
10
- def initialize(dependencies:, manifest:)
11
- @dependencies = dependencies
12
- @manifest = manifest
13
- end
14
-
15
- def updated_manifest_content
16
- dependencies.reduce(manifest.content.dup) do |content, dep|
17
- updated_content = content
18
- updated_requirements(dep).each do |new_req|
19
- old_req = old_requirement(dep, new_req).fetch(:requirement)
20
- updated_req = new_req.fetch(:requirement)
21
-
22
- regex =
23
- /
24
- "#{Regexp.escape(dep.name)}"\s*:\s*
25
- "#{Regexp.escape(old_req)}"
26
- /x
27
-
28
- updated_content = content.gsub(regex) do |declaration|
29
- declaration.gsub(%("#{old_req}"), %("#{updated_req}"))
30
- end
31
-
32
- if content == updated_content
33
- raise "Expected content to change!"
34
- end
35
- end
36
-
37
- updated_content
38
- end
39
- end
40
-
41
- private
42
-
43
- attr_reader :dependencies, :manifest
44
-
45
- def new_requirements(dependency)
46
- dependency.requirements.select { |r| r[:file] == manifest.name }
47
- end
48
-
49
- def old_requirement(dependency, new_requirement)
50
- dependency.previous_requirements.
51
- select { |r| r[:file] == manifest.name }.
52
- find { |r| r[:groups] == new_requirement[:groups] }
53
- end
54
-
55
- def updated_requirements(dependency)
56
- new_requirements(dependency).
57
- reject { |r| dependency.previous_requirements.include?(r) }
58
- end
59
-
60
- def requirement_changed?(file, dependency)
61
- changed_requirements =
62
- dependency.requirements - dependency.previous_requirements
63
-
64
- changed_requirements.any? { |f| f[:file] == file.name }
65
- end
66
- end
67
- end
68
- end
69
- end
70
- end
@@ -1,66 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "excon"
4
- require "dependabot/metadata_finders/base"
5
- require "dependabot/shared_helpers"
6
- require "dependabot/utils"
7
-
8
- module Dependabot
9
- module MetadataFinders
10
- module Php
11
- class Composer < Dependabot::MetadataFinders::Base
12
- private
13
-
14
- def look_up_source
15
- source_from_dependency || look_up_source_from_packagist
16
- end
17
-
18
- def source_from_dependency
19
- source_url =
20
- dependency.requirements.
21
- map { |r| r.fetch(:source) }.compact.
22
- first&.fetch(:url, nil)
23
-
24
- Source.from_url(source_url)
25
- end
26
-
27
- def look_up_source_from_packagist
28
- return nil if packagist_listing&.fetch("packages", nil) == []
29
- unless packagist_listing&.dig("packages", dependency.name.downcase)
30
- return nil
31
- end
32
-
33
- version_listings =
34
- packagist_listing["packages"][dependency.name.downcase].
35
- select { |version, _| Utils::Php::Version.correct?(version) }.
36
- sort_by { |version, _| Utils::Php::Version.new(version) }.
37
- map { |_, listing| listing }.
38
- reverse
39
-
40
- potential_source_urls =
41
- version_listings.
42
- flat_map { |info| [info["homepage"], info.dig("source", "url")] }.
43
- compact
44
-
45
- source_url = potential_source_urls.find { |url| Source.from_url(url) }
46
-
47
- Source.from_url(source_url)
48
- end
49
-
50
- def packagist_listing
51
- return @packagist_listing unless @packagist_listing.nil?
52
-
53
- response = Excon.get(
54
- "https://packagist.org/p/#{dependency.name.downcase}.json",
55
- idempotent: true,
56
- **SharedHelpers.excon_defaults
57
- )
58
-
59
- return nil unless response.status == 200
60
-
61
- @packagist_listing = JSON.parse(response.body)
62
- end
63
- end
64
- end
65
- end
66
- end
@@ -1,175 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "excon"
4
- require "dependabot/update_checkers/base"
5
- require "dependabot/shared_helpers"
6
- require "dependabot/errors"
7
-
8
- require "json"
9
-
10
- module Dependabot
11
- module UpdateCheckers
12
- module Php
13
- class Composer < Dependabot::UpdateCheckers::Base
14
- require_relative "composer/requirements_updater"
15
- require_relative "composer/version_resolver"
16
-
17
- def latest_version
18
- return nil if path_dependency?
19
-
20
- # Fall back to latest_resolvable_version if no listings found
21
- latest_version_from_registry || latest_resolvable_version
22
- end
23
-
24
- def latest_resolvable_version
25
- return nil if path_dependency?
26
-
27
- @latest_resolvable_version ||=
28
- VersionResolver.new(
29
- credentials: credentials,
30
- dependency: dependency,
31
- dependency_files: dependency_files,
32
- latest_allowable_version: latest_version_from_registry,
33
- requirements_to_unlock: :own
34
- ).latest_resolvable_version
35
- end
36
-
37
- def latest_resolvable_version_with_no_unlock
38
- return nil if path_dependency?
39
-
40
- @latest_resolvable_version_with_no_unlock ||=
41
- VersionResolver.new(
42
- credentials: credentials,
43
- dependency: dependency,
44
- dependency_files: dependency_files,
45
- latest_allowable_version: latest_version_from_registry,
46
- requirements_to_unlock: :none
47
- ).latest_resolvable_version
48
- end
49
-
50
- def updated_requirements
51
- RequirementsUpdater.new(
52
- requirements: dependency.requirements,
53
- latest_version: latest_version&.to_s,
54
- latest_resolvable_version: latest_resolvable_version&.to_s,
55
- update_strategy: requirements_update_strategy
56
- ).updated_requirements
57
- end
58
-
59
- def requirements_update_strategy
60
- # If passed in as an option (in the base class) honour that option
61
- if @requirements_update_strategy
62
- return @requirements_update_strategy.to_sym
63
- end
64
-
65
- # Otherwise, widen ranges for libraries and bump versions for apps
66
- library? ? :widen_ranges : :bump_versions_if_necessary
67
- end
68
-
69
- private
70
-
71
- def latest_version_resolvable_with_full_unlock?
72
- # Full unlock checks aren't implemented for Composer (yet)
73
- false
74
- end
75
-
76
- def latest_version_from_registry
77
- versions =
78
- registry_versions.
79
- select { |version| version_class.correct?(version.gsub(/^v/, "")) }.
80
- map { |version| version_class.new(version.gsub(/^v/, "")) }
81
-
82
- versions.reject!(&:prerelease?) unless wants_prerelease?
83
- versions.reject! { |v| ignore_reqs.any? { |r| r.satisfied_by?(v) } }
84
- versions.max
85
- end
86
-
87
- def wants_prerelease?
88
- current_version = dependency.version
89
- if current_version && version_class.new(current_version).prerelease?
90
- return true
91
- end
92
-
93
- dependency.requirements.any? do |req|
94
- req[:requirement].match?(/\d-[A-Za-z]/)
95
- end
96
- end
97
-
98
- def updated_dependencies_after_full_unlock
99
- raise NotImplementedError
100
- end
101
-
102
- def path_dependency?
103
- dependency.requirements.any? { |r| r.dig(:source, :type) == "path" }
104
- end
105
-
106
- def composer_file
107
- composer_file =
108
- dependency_files.find { |f| f.name == "composer.json" }
109
- raise "No composer.json!" unless composer_file
110
-
111
- composer_file
112
- end
113
-
114
- def lockfile
115
- dependency_files.find { |f| f.name == "composer.lock" }
116
- end
117
-
118
- def registry_versions
119
- return @registry_versions unless @registry_versions.nil?
120
-
121
- repositories =
122
- JSON.parse(composer_file.content).
123
- fetch("repositories", []).
124
- select { |r| r.is_a?(Hash) }
125
-
126
- urls = repositories.
127
- select { |h| h["type"] == "composer" }.
128
- map { |h| h["url"] }.compact.
129
- map { |url| url.gsub(%r{\/$}, "") + "/packages.json" }
130
-
131
- unless repositories.any? { |rep| rep["packagist.org"] == false }
132
- urls << "https://packagist.org/p/#{dependency.name.downcase}.json"
133
- end
134
-
135
- @registry_versions = []
136
- urls.each do |url|
137
- @registry_versions += fetch_registry_versions_from_url(url)
138
- end
139
- @registry_versions.uniq
140
- end
141
-
142
- def fetch_registry_versions_from_url(url)
143
- cred = registry_credentials.find { |c| url.include?(c["registry"]) }
144
-
145
- response = Excon.get(
146
- url,
147
- idempotent: true,
148
- user: cred&.fetch("username", nil),
149
- password: cred&.fetch("password", nil),
150
- **SharedHelpers.excon_defaults
151
- )
152
-
153
- return [] unless response.status == 200
154
-
155
- listing = JSON.parse(response.body)
156
- return [] if listing.nil?
157
- return [] if listing.fetch("packages", []) == []
158
- return [] unless listing.dig("packages", dependency.name.downcase)
159
-
160
- listing.dig("packages", dependency.name.downcase).keys
161
- rescue Excon::Error::Socket, Excon::Error::Timeout
162
- []
163
- end
164
-
165
- def library?
166
- JSON.parse(composer_file.content)["type"] == "library"
167
- end
168
-
169
- def registry_credentials
170
- credentials.select { |cred| cred["type"] == "composer_repository" }
171
- end
172
- end
173
- end
174
- end
175
- end
@@ -1,258 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- ################################################################################
4
- # For more details on Composer version constraints, see: #
5
- # https://getcomposer.org/doc/articles/versions.md#writing-version-constraints #
6
- ################################################################################
7
-
8
- require "dependabot/update_checkers/php/composer"
9
- require "dependabot/utils/php/version"
10
- require "dependabot/utils/php/requirement"
11
-
12
- module Dependabot
13
- module UpdateCheckers
14
- module Php
15
- class Composer
16
- class RequirementsUpdater
17
- ALIAS_REGEX = /[a-z0-9\-_\.]*\sas\s+/.freeze
18
- VERSION_REGEX =
19
- /(?:#{ALIAS_REGEX})?[0-9]+(?:\.[a-zA-Z0-9*\-]+)*/.freeze
20
- AND_SEPARATOR =
21
- /(?<=[a-zA-Z0-9*])(?<!\sas)[\s,]+(?![\s,]*[|-]|as)/.freeze
22
- OR_SEPARATOR = /(?<=[a-zA-Z0-9*])[\s,]*\|\|?\s*/.freeze
23
- SEPARATOR = /(?:#{AND_SEPARATOR})|(?:#{OR_SEPARATOR})/.freeze
24
- ALLOWED_UPDATE_STRATEGIES =
25
- %i(widen_ranges bump_versions bump_versions_if_necessary).freeze
26
-
27
- def initialize(requirements:, update_strategy:,
28
- latest_version:, latest_resolvable_version:)
29
- @requirements = requirements
30
- @update_strategy = update_strategy
31
-
32
- check_update_strategy
33
-
34
- if latest_version
35
- @latest_version = version_class.new(latest_version)
36
- end
37
-
38
- return unless latest_resolvable_version
39
-
40
- @latest_resolvable_version =
41
- version_class.new(latest_resolvable_version)
42
- end
43
-
44
- def updated_requirements
45
- return requirements unless latest_resolvable_version
46
-
47
- requirements.map { |req| updated_requirement(req) }
48
- end
49
-
50
- private
51
-
52
- attr_reader :requirements, :update_strategy,
53
- :latest_version, :latest_resolvable_version
54
-
55
- def check_update_strategy
56
- return if ALLOWED_UPDATE_STRATEGIES.include?(update_strategy)
57
-
58
- raise "Unknown update strategy: #{update_strategy}"
59
- end
60
-
61
- # rubocop:disable Metrics/PerceivedComplexity
62
- # rubocop:disable Metrics/CyclomaticComplexity
63
- def updated_requirement(req)
64
- req_string = req[:requirement].strip
65
- or_string_reqs = req_string.split(OR_SEPARATOR)
66
- or_separator = req_string.match(OR_SEPARATOR)&.to_s || " || "
67
- numeric_or_string_reqs = or_string_reqs.
68
- reject { |r| r.start_with?("dev-") }
69
- branch_or_string_reqs = or_string_reqs.
70
- select { |r| r.start_with?("dev-") }
71
-
72
- return req unless req_string.match?(/\d/)
73
- return req if numeric_or_string_reqs.none?
74
- return updated_alias(req) if req_string.match?(ALIAS_REGEX)
75
- return req if req_satisfied_by_latest_resolvable?(req_string) &&
76
- update_strategy != :bump_versions
77
-
78
- new_req =
79
- case update_strategy
80
- when :widen_ranges
81
- widen_requirement(req, or_separator)
82
- when :bump_versions, :bump_versions_if_necessary
83
- update_requirement_version(req, or_separator)
84
- end
85
-
86
- new_req_string =
87
- [new_req[:requirement], *branch_or_string_reqs].join(or_separator)
88
- new_req.merge(requirement: new_req_string)
89
- end
90
- # rubocop:enable Metrics/PerceivedComplexity
91
- # rubocop:enable Metrics/CyclomaticComplexity
92
-
93
- def updated_alias(req)
94
- req_string = req[:requirement]
95
- real_version = req_string.split(/\sas\s/).first.strip
96
-
97
- # If the version we're aliasing isn't a version then we don't know
98
- # how to update it, so we just return the existing requirement.
99
- return req unless version_class.correct?(real_version)
100
-
101
- new_version_string = latest_resolvable_version.to_s
102
- new_req = req_string.sub(real_version, new_version_string)
103
- req.merge(requirement: new_req)
104
- end
105
-
106
- def widen_requirement(req, or_separator)
107
- current_requirement = req[:requirement]
108
- reqs = current_requirement.strip.split(SEPARATOR).map(&:strip)
109
-
110
- updated_requirement =
111
- if reqs.any? { |r| r.start_with?("^") }
112
- update_caret_requirement(current_requirement, or_separator)
113
- elsif reqs.any? { |r| r.start_with?("~") }
114
- update_tilda_requirement(current_requirement, or_separator)
115
- elsif reqs.any? { |r| r.include?("*") }
116
- update_wildcard_requirement(current_requirement, or_separator)
117
- elsif reqs.any? { |r| r.match?(/<|(\s+-\s+)/) }
118
- update_range_requirement(current_requirement, or_separator)
119
- else
120
- update_version_string(current_requirement)
121
- end
122
-
123
- req.merge(requirement: updated_requirement)
124
- end
125
-
126
- def update_requirement_version(req, or_separator)
127
- current_requirement = req[:requirement]
128
- reqs = current_requirement.strip.split(SEPARATOR).map(&:strip)
129
-
130
- updated_requirement =
131
- if reqs.count > 1
132
- "^#{latest_resolvable_version}"
133
- elsif reqs.any? { |r| r.match?(/<|(\s+-\s+)/) }
134
- update_range_requirement(current_requirement, or_separator)
135
- elsif reqs.any? { |r| r.match?(/>[^=]/) }
136
- current_requirement
137
- else
138
- update_version_string(current_requirement)
139
- end
140
-
141
- req.merge(requirement: updated_requirement)
142
- end
143
-
144
- def req_satisfied_by_latest_resolvable?(requirement_string)
145
- ruby_requirements(requirement_string).
146
- any? { |r| r.satisfied_by?(latest_resolvable_version) }
147
- end
148
-
149
- def update_version_string(req_string)
150
- req_string.
151
- sub(VERSION_REGEX) do |old_version|
152
- unless req_string.match?(/[~*\^]/)
153
- next latest_resolvable_version.to_s
154
- end
155
-
156
- old_parts = old_version.split(".")
157
- new_parts = latest_resolvable_version.to_s.split(".").
158
- first(old_parts.count)
159
- new_parts.map.with_index do |part, i|
160
- old_parts[i] == "*" ? "*" : part
161
- end.join(".")
162
- end
163
- end
164
-
165
- def ruby_requirements(requirement_string)
166
- Utils::Php::Requirement.requirements_array(requirement_string)
167
- end
168
-
169
- def update_caret_requirement(req_string, or_separator)
170
- caret_requirements =
171
- req_string.split(SEPARATOR).select { |r| r.start_with?("^") }
172
- version_parts = latest_resolvable_version.segments
173
-
174
- min_existing_precision =
175
- caret_requirements.map { |r| r.split(".").count }.min
176
- first_non_zero_index =
177
- version_parts.count.times.find { |i| version_parts[i] != 0 }
178
-
179
- precision = [min_existing_precision, first_non_zero_index + 1].max
180
- version = version_parts.first(precision).map.with_index do |part, i|
181
- i <= first_non_zero_index ? part : 0
182
- end.join(".")
183
-
184
- req_string + "#{or_separator}^#{version}"
185
- end
186
-
187
- def update_tilda_requirement(req_string, or_separator)
188
- tilda_requirements =
189
- req_string.split(SEPARATOR).select { |r| r.start_with?("~") }
190
- precision = tilda_requirements.map { |r| r.split(".").count }.min
191
-
192
- version_parts = latest_resolvable_version.segments.first(precision)
193
- version_parts[-1] = 0
194
- version = version_parts.join(".")
195
-
196
- req_string + "#{or_separator}~#{version}"
197
- end
198
-
199
- def update_wildcard_requirement(req_string, or_separator)
200
- wildcard_requirements =
201
- req_string.split(SEPARATOR).select { |r| r.include?("*") }
202
- precision = wildcard_requirements.map do |r|
203
- r.split(".").reject { |s| s == "*" }.count
204
- end.min
205
- wildcard_count = wildcard_requirements.map do |r|
206
- r.split(".").select { |s| s == "*" }.count
207
- end.min
208
-
209
- version_parts = latest_resolvable_version.segments.first(precision)
210
- version = version_parts.join(".")
211
-
212
- req_string + "#{or_separator}#{version}#{'.*' * wildcard_count}"
213
- end
214
-
215
- def update_range_requirement(req_string, or_separator)
216
- range_requirements =
217
- req_string.split(SEPARATOR).select { |r| r.match?(/<|(\s+-\s+)/) }
218
-
219
- if range_requirements.count == 1
220
- range_requirement = range_requirements.first
221
- versions = range_requirement.scan(VERSION_REGEX)
222
- upper_bound = versions.map { |v| version_class.new(v) }.max
223
- new_upper_bound = update_greatest_version(
224
- upper_bound,
225
- latest_resolvable_version
226
- )
227
-
228
- req_string.sub(upper_bound.to_s, new_upper_bound.to_s)
229
- else
230
- req_string + "#{or_separator}^#{latest_resolvable_version}"
231
- end
232
- end
233
-
234
- def update_greatest_version(old_version, version_to_be_permitted)
235
- version = version_class.new(old_version)
236
- version = version.release if version.prerelease?
237
-
238
- index_to_update =
239
- version.segments.map.with_index { |seg, i| seg.zero? ? 0 : i }.max
240
-
241
- version.segments.map.with_index do |_, index|
242
- if index < index_to_update
243
- version_to_be_permitted.segments[index]
244
- elsif index == index_to_update
245
- version_to_be_permitted.segments[index] + 1
246
- else 0
247
- end
248
- end.join(".")
249
- end
250
-
251
- def version_class
252
- Utils::Php::Version
253
- end
254
- end
255
- end
256
- end
257
- end
258
- end