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,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