dependabot-core 0.88.3 → 0.89.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.
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,177 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "dependabot/dependency"
4
- require "dependabot/file_parsers/base"
5
- require "dependabot/shared_helpers"
6
- require "dependabot/errors"
7
-
8
- module Dependabot
9
- module FileParsers
10
- module Php
11
- class Composer < Dependabot::FileParsers::Base
12
- require "dependabot/file_parsers/base/dependency_set"
13
-
14
- DEPENDENCY_GROUP_KEYS = [
15
- {
16
- manifest: "require",
17
- lockfile: "packages",
18
- group: "runtime"
19
- },
20
- {
21
- manifest: "require-dev",
22
- lockfile: "packages-dev",
23
- group: "development"
24
- }
25
- ].freeze
26
-
27
- def parse
28
- dependency_set = DependencySet.new
29
- dependency_set += manifest_dependencies
30
- dependency_set += lockfile_dependencies
31
- dependency_set.dependencies
32
- end
33
-
34
- private
35
-
36
- def manifest_dependencies
37
- dependencies = DependencySet.new
38
-
39
- DEPENDENCY_GROUP_KEYS.each do |keys|
40
- next unless parsed_composer_json[keys[:manifest]]
41
-
42
- parsed_composer_json[keys[:manifest]].each do |name, req|
43
- next unless package?(name)
44
-
45
- if lockfile
46
- version = dependency_version(name: name, type: keys[:group])
47
-
48
- # Ignore dependencies which appear in the composer.json but not
49
- # the composer.lock.
50
- next if version.nil?
51
-
52
- # Ignore dependency versions which are non-numeric, since they
53
- # can't be compared later in the process.
54
- next unless version.match?(/^\d/)
55
- end
56
-
57
- dependencies <<
58
- Dependency.new(
59
- name: name,
60
- version: dependency_version(name: name, type: keys[:group]),
61
- requirements: [{
62
- requirement: req,
63
- file: "composer.json",
64
- source: dependency_source(name: name, type: keys[:group]),
65
- groups: [keys[:group]]
66
- }],
67
- package_manager: "composer"
68
- )
69
- end
70
- end
71
-
72
- dependencies
73
- end
74
-
75
- def lockfile_dependencies
76
- dependencies = DependencySet.new
77
-
78
- return dependencies unless lockfile
79
-
80
- DEPENDENCY_GROUP_KEYS.map { |h| h.fetch(:lockfile) }.each do |key|
81
- next unless parsed_lockfile[key]
82
-
83
- parsed_lockfile[key].each do |details|
84
- name = details["name"]
85
- next unless package?(name)
86
-
87
- version = details["version"]&.sub(/^v?/, "")
88
- next if version.nil?
89
- next unless version.match?(/^\d/)
90
-
91
- dependencies <<
92
- Dependency.new(
93
- name: name,
94
- version: version,
95
- requirements: [],
96
- package_manager: "composer"
97
- )
98
- end
99
- end
100
-
101
- dependencies
102
- end
103
-
104
- def dependency_version(name:, type:)
105
- return unless lockfile
106
-
107
- key = lockfile_key(type)
108
-
109
- parsed_lockfile.
110
- fetch(key, []).
111
- find { |d| d["name"] == name }&.
112
- fetch("version")&.sub(/^v?/, "")
113
- end
114
-
115
- def dependency_source(name:, type:)
116
- return unless lockfile
117
-
118
- key = lockfile_key(type)
119
- package = parsed_lockfile.fetch(key).find { |d| d["name"] == name }
120
-
121
- return unless package
122
-
123
- if package["source"].nil? && package.dig("dist", "type") == "path"
124
- return { type: "path" }
125
- end
126
-
127
- return unless package.dig("source", "type") == "git"
128
-
129
- {
130
- type: "git",
131
- url: package.dig("source", "url")
132
- }
133
- end
134
-
135
- def lockfile_key(type)
136
- case type
137
- when "runtime" then "packages"
138
- when "development" then "packages-dev"
139
- else raise "unknown type #{type}"
140
- end
141
- end
142
-
143
- def package?(name)
144
- # Filter out php, ext-, composer-plugin-api, and other special
145
- # packages which don't behave as normal
146
- name.split("/").count == 2
147
- end
148
-
149
- def check_required_files
150
- raise "No composer.json!" unless get_original_file("composer.json")
151
- end
152
-
153
- def parsed_lockfile
154
- return unless lockfile
155
-
156
- @parsed_lockfile ||= JSON.parse(lockfile.content)
157
- rescue JSON::ParserError
158
- raise Dependabot::DependencyFileNotParseable, lockfile.path
159
- end
160
-
161
- def parsed_composer_json
162
- @parsed_composer_json ||= JSON.parse(composer_json.content)
163
- rescue JSON::ParserError
164
- raise Dependabot::DependencyFileNotParseable, composer_json.path
165
- end
166
-
167
- def composer_json
168
- @composer_json ||= get_original_file("composer.json")
169
- end
170
-
171
- def lockfile
172
- @lockfile ||= get_original_file("composer.lock")
173
- end
174
- end
175
- end
176
- end
177
- end
@@ -1,78 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "dependabot/file_updaters/base"
4
- require "dependabot/utils/php/version"
5
- require "dependabot/shared_helpers"
6
- require "dependabot/errors"
7
-
8
- module Dependabot
9
- module FileUpdaters
10
- module Php
11
- class Composer < Base
12
- require_relative "composer/manifest_updater"
13
- require_relative "composer/lockfile_updater"
14
-
15
- def self.updated_files_regex
16
- [
17
- /^composer\.json$/,
18
- /^composer\.lock$/
19
- ]
20
- end
21
-
22
- def updated_dependency_files
23
- updated_files = []
24
-
25
- if file_changed?(composer_json)
26
- updated_files <<
27
- updated_file(
28
- file: composer_json,
29
- content: updated_composer_json_content
30
- )
31
- end
32
-
33
- if lockfile
34
- updated_files <<
35
- updated_file(file: lockfile, content: updated_lockfile_content)
36
- end
37
-
38
- if updated_files.none? ||
39
- updated_files.sort_by(&:name) == dependency_files.sort_by(&:name)
40
- raise "No files have changed!"
41
- end
42
-
43
- updated_files
44
- end
45
-
46
- private
47
-
48
- def check_required_files
49
- raise "No composer.json!" unless get_original_file("composer.json")
50
- end
51
-
52
- def updated_composer_json_content
53
- ManifestUpdater.new(
54
- dependencies: dependencies,
55
- manifest: composer_json
56
- ).updated_manifest_content
57
- end
58
-
59
- def updated_lockfile_content
60
- @updated_lockfile_content ||=
61
- LockfileUpdater.new(
62
- dependencies: dependencies,
63
- dependency_files: dependency_files,
64
- credentials: credentials
65
- ).updated_lockfile_content
66
- end
67
-
68
- def composer_json
69
- @composer_json ||= get_original_file("composer.json")
70
- end
71
-
72
- def lockfile
73
- @lockfile ||= get_original_file("composer.lock")
74
- end
75
- end
76
- end
77
- end
78
- end
@@ -1,269 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "dependabot/file_updaters/php/composer"
4
- require "dependabot/utils/php/version"
5
- require "dependabot/shared_helpers"
6
- require "dependabot/errors"
7
-
8
- module Dependabot
9
- module FileUpdaters
10
- module Php
11
- class Composer
12
- class LockfileUpdater
13
- require_relative "manifest_updater"
14
-
15
- def initialize(dependencies:, dependency_files:, credentials:)
16
- @dependencies = dependencies
17
- @dependency_files = dependency_files
18
- @credentials = credentials
19
- end
20
-
21
- def updated_lockfile_content
22
- base_directory = dependency_files.first.directory
23
- @updated_lockfile_content ||=
24
- SharedHelpers.in_a_temporary_directory(base_directory) do
25
- write_temporary_dependency_files
26
-
27
- updated_content = run_update_helper.fetch("composer.lock")
28
-
29
- updated_content = post_process_lockfile(updated_content)
30
- if lockfile.content == updated_content
31
- raise "Expected content to change!"
32
- end
33
-
34
- updated_content
35
- end
36
- rescue SharedHelpers::HelperSubprocessFailed => error
37
- handle_composer_errors(error)
38
- end
39
-
40
- private
41
-
42
- attr_reader :dependencies, :dependency_files, :credentials
43
-
44
- def dependency
45
- # For now, we'll only ever be updating a single dependency for PHP
46
- dependencies.first
47
- end
48
-
49
- def run_update_helper
50
- SharedHelpers.with_git_configured(credentials: credentials) do
51
- SharedHelpers.run_helper_subprocess(
52
- command: "php #{php_helper_path}",
53
- function: "update",
54
- env: credentials_env,
55
- args: [
56
- Dir.pwd,
57
- dependency.name,
58
- dependency.version,
59
- git_credentials,
60
- registry_credentials
61
- ]
62
- )
63
- end
64
- end
65
-
66
- def updated_composer_json_content
67
- ManifestUpdater.new(
68
- dependencies: dependencies,
69
- manifest: composer_json
70
- ).updated_manifest_content
71
- end
72
-
73
- # rubocop:disable Metrics/PerceivedComplexity
74
- # rubocop:disable Metrics/AbcSize
75
- # rubocop:disable Metrics/CyclomaticComplexity
76
- # rubocop:disable Metrics/MethodLength
77
- def handle_composer_errors(error)
78
- if error.message.start_with?("Failed to execute git checkout")
79
- raise git_dependency_reference_error(error)
80
- end
81
-
82
- if error.message.start_with?("Failed to execute git clone")
83
- dependency_url =
84
- error.message.match(/(?:mirror|checkout) '(?<url>.*?)'/).
85
- named_captures.fetch("url")
86
- raise GitDependenciesNotReachable, dependency_url
87
- end
88
-
89
- if error.message.start_with?("Failed to clone")
90
- dependency_url =
91
- error.message.match(/Failed to clone (?<url>.*?) via/).
92
- named_captures.fetch("url")
93
- raise GitDependenciesNotReachable, dependency_url
94
- end
95
-
96
- if error.message.start_with?("Could not find a key for ACF PRO")
97
- raise MissingEnvironmentVariable, "ACF_PRO_KEY"
98
- end
99
-
100
- if error.message.start_with?("Unknown downloader type: npm-sign") ||
101
- error.message.include?("file could not be downloaded") ||
102
- error.message.include?("configuration does not allow connect")
103
- raise DependencyFileNotResolvable, error.message
104
- end
105
-
106
- if error.message.start_with?("Allowed memory size")
107
- raise Dependabot::OutOfMemory
108
- end
109
-
110
- if error.message.include?("403 Forbidden")
111
- source = error.message.match(%r{https?://(?<source>[^/]+)/}).
112
- named_captures.fetch("source")
113
- raise PrivateSourceAuthenticationFailure, source
114
- end
115
-
116
- if error.message.include?("Argument 1 passed to Composer")
117
- msg = "One of your Composer plugins is not compatible with the "\
118
- "latest version of Composer. Please update Composer and "\
119
- "try running `composer update` to debug further."
120
- raise DependencyFileNotResolvable, msg
121
- end
122
-
123
- raise error
124
- end
125
- # rubocop:enable Metrics/PerceivedComplexity
126
- # rubocop:enable Metrics/AbcSize
127
- # rubocop:enable Metrics/CyclomaticComplexity
128
- # rubocop:enable Metrics/MethodLength
129
-
130
- def write_temporary_dependency_files
131
- path_dependencies.each do |file|
132
- path = file.name
133
- FileUtils.mkdir_p(Pathname.new(path).dirname)
134
- File.write(file.name, file.content)
135
- end
136
-
137
- File.write("composer.json", locked_composer_json_content)
138
- File.write("composer.lock", lockfile.content)
139
- end
140
-
141
- def locked_composer_json_content
142
- dependencies.
143
- reduce(updated_composer_json_content) do |content, dep|
144
- updated_req = dep.version
145
- next content unless Utils::Php::Version.correct?(updated_req)
146
-
147
- old_req =
148
- dep.requirements.find { |r| r[:file] == "composer.json" }&.
149
- fetch(:requirement)
150
-
151
- # When updating a subdep there won't be an old requirement
152
- next content unless old_req
153
-
154
- regex =
155
- /
156
- "#{Regexp.escape(dep.name)}"\s*:\s*
157
- "#{Regexp.escape(old_req)}"
158
- /x
159
-
160
- content.gsub(regex) do |declaration|
161
- declaration.gsub(%("#{old_req}"), %("#{updated_req}"))
162
- end
163
- end
164
- end
165
-
166
- def git_dependency_reference_error(error)
167
- ref = error.message.match(/checkout '(?<ref>.*?)'/).
168
- named_captures.fetch("ref")
169
- dependency_name =
170
- JSON.parse(lockfile.content).
171
- values_at("packages", "packages-dev").flatten(1).
172
- find { |dep| dep.dig("source", "reference") == ref }&.
173
- fetch("name")
174
-
175
- raise unless dependency_name
176
-
177
- raise GitDependencyReferenceNotFound, dependency_name
178
- end
179
-
180
- def post_process_lockfile(content)
181
- content = replace_patches(content)
182
- replace_content_hash(content)
183
- end
184
-
185
- def replace_patches(updated_content)
186
- content = updated_content
187
- %w(packages packages-dev).each do |package_type|
188
- JSON.parse(lockfile.content).fetch(package_type).each do |details|
189
- next unless details["extra"].is_a?(Hash)
190
- next unless (patches = details.dig("extra", "patches_applied"))
191
-
192
- updated_object = JSON.parse(content)
193
- updated_object_package =
194
- updated_object.
195
- fetch(package_type).
196
- find { |d| d["name"] == details["name"] }
197
-
198
- next unless updated_object_package
199
-
200
- updated_object_package["extra"] ||= {}
201
- updated_object_package["extra"]["patches_applied"] = patches
202
-
203
- content =
204
- JSON.pretty_generate(updated_object, indent: " ").
205
- gsub(/\[\n\n\s*\]/, "[]").
206
- gsub(/\}\z/, "}\n")
207
- end
208
- end
209
- content
210
- end
211
-
212
- def replace_content_hash(content)
213
- existing_hash = JSON.parse(content).fetch("content-hash")
214
- SharedHelpers.in_a_temporary_directory do
215
- File.write("composer.json", updated_composer_json_content)
216
-
217
- content_hash =
218
- SharedHelpers.run_helper_subprocess(
219
- command: "php #{php_helper_path}",
220
- function: "get_content_hash",
221
- env: credentials_env,
222
- args: [Dir.pwd]
223
- )
224
-
225
- content.gsub(existing_hash, content_hash)
226
- end
227
- end
228
-
229
- def php_helper_path
230
- project_root = File.join(File.dirname(__FILE__), "../../../../..")
231
- File.join(project_root, "helpers/php/bin/run.php")
232
- end
233
-
234
- def credentials_env
235
- credentials.
236
- select { |c| c.fetch("type") == "php_environment_variable" }.
237
- map { |cred| [cred["env-key"], cred["env-value"]] }.
238
- to_h
239
- end
240
-
241
- def git_credentials
242
- credentials.
243
- select { |cred| cred.fetch("type") == "git_source" }
244
- end
245
-
246
- def registry_credentials
247
- credentials.
248
- select { |cred| cred.fetch("type") == "composer_repository" }
249
- end
250
-
251
- def composer_json
252
- @composer_json ||=
253
- dependency_files.find { |f| f.name == "composer.json" }
254
- end
255
-
256
- def lockfile
257
- @lockfile ||=
258
- dependency_files.find { |f| f.name == "composer.lock" }
259
- end
260
-
261
- def path_dependencies
262
- @path_dependencies ||=
263
- dependency_files.select { |f| f.name.end_with?("/composer.json") }
264
- end
265
- end
266
- end
267
- end
268
- end
269
- end