dependabot-composer 0.288.0 → 0.289.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: bd0752795e58781bcfdde294a2839ec30d86cc3494808574fd640abaa6bcdbbc
4
- data.tar.gz: db40e334568d71890aaa5b921b7d54cd9495c4166c56fa3042dce1d87b99caa5
3
+ metadata.gz: 90fd9742e112bda23efcab031a487985c2bc19431d081a25e53f23a915edbdc0
4
+ data.tar.gz: 18902e7c4b755fac1bd12fd6ba60a1b2e7baeb97355156120b9591d3b031cb41
5
5
  SHA512:
6
- metadata.gz: 7b720d76e4a8730515a66e7ea94a2486174c77ccbd15dd0163b60b2c58a21d2a3759a952ff61fd5c9dabf9bc0df0204a89d3af736786604c61cd8ea274a3ebe9
7
- data.tar.gz: e77480ca0704e49366911e390cc3b9c99132109c7f32ed021035b6990c27b2e3fb0c60212b9e318ca688556952fa78aa644866ff12fda88c66b5a95a53a70dd3
6
+ metadata.gz: fcbf0ae77a0f37ae82e66a5fbfe6b040b881c3de3ac0b4be70ff8964bf2d7c0d1883ef4bf239548febec2d457a5d083bc01bb764a3a9cd0b23731c56dec17254
7
+ data.tar.gz: e799650f569f04c2ffb674199bba37a1eb9f2e121183ebd353701ae2b6df948080c45661b3ff7af830a090c771ea9fc60410d90cf94a05991ba60f545c29667d
@@ -17,7 +17,7 @@ module Dependabot
17
17
  end
18
18
 
19
19
  def dependency_file
20
- filename = File.join(path, "composer.json")
20
+ filename = File.join(path, PackageManager::MANIFEST_FILENAME)
21
21
 
22
22
  # Current we just return `nil` if a path dependency can't be built.
23
23
  # In future we may wish to change that to a raise. (We'll get errors
@@ -16,17 +16,17 @@ module Dependabot
16
16
  require_relative "helpers"
17
17
 
18
18
  def self.required_files_in?(filenames)
19
- filenames.include?("composer.json")
19
+ filenames.include?(PackageManager::MANIFEST_FILENAME)
20
20
  end
21
21
 
22
22
  def self.required_files_message
23
- "Repo must contain a composer.json."
23
+ "Repo must contain a #{PackageManager::MANIFEST_FILENAME}."
24
24
  end
25
25
 
26
26
  def ecosystem_versions
27
27
  {
28
28
  package_managers: {
29
- "composer" => Helpers.composer_version(parsed_composer_json, parsed_lockfile)
29
+ PackageManager::NAME => Helpers.composer_version(parsed_composer_json, parsed_lockfile)
30
30
  }
31
31
  }
32
32
  end
@@ -45,20 +45,20 @@ module Dependabot
45
45
  private
46
46
 
47
47
  def composer_json
48
- @composer_json ||= fetch_file_from_host("composer.json")
48
+ @composer_json ||= fetch_file_from_host(PackageManager::MANIFEST_FILENAME)
49
49
  end
50
50
 
51
51
  def composer_lock
52
52
  return @composer_lock if defined?(@composer_lock)
53
53
 
54
- @composer_lock = fetch_file_if_present("composer.lock")
54
+ @composer_lock = fetch_file_if_present(PackageManager::LOCKFILE_FILENAME)
55
55
  end
56
56
 
57
57
  # NOTE: This is fetched but currently unused
58
58
  def auth_json
59
59
  return @auth_json if defined?(@auth_json)
60
60
 
61
- @auth_json = fetch_support_file("auth.json")
61
+ @auth_json = fetch_support_file(PackageManager::AUTH_FILENAME)
62
62
  end
63
63
 
64
64
  def artifact_dependencies
@@ -106,7 +106,7 @@ module Dependabot
106
106
  directories = path.end_with?("*") ? expand_path(path) : [path]
107
107
 
108
108
  directories.each do |dir|
109
- file = File.join(dir, "composer.json")
109
+ file = File.join(dir, PackageManager::MANIFEST_FILENAME)
110
110
 
111
111
  begin
112
112
  composer_json_files << fetch_file_with_root_fallback(file)
@@ -11,6 +11,12 @@ require "dependabot/errors"
11
11
 
12
12
  module Dependabot
13
13
  module Composer
14
+ REQUIREMENT_SEPARATOR = /
15
+ (?<=\S|^) # Positive lookbehind for a non-whitespace character or start of string
16
+ (?:[ \t,]*\|\|?[ \t]*) # Match optional whitespace, a pipe (|| or |), and optional whitespace
17
+ (?=\S|$) # Positive lookahead for a non-whitespace character or end of string
18
+ /x
19
+
14
20
  class FileParser < Dependabot::FileParsers::Base
15
21
  require "dependabot/file_parsers/base/dependency_set"
16
22
 
@@ -40,7 +46,8 @@ module Dependabot
40
46
  @ecosystem ||= T.let(
41
47
  Ecosystem.new(
42
48
  name: ECOSYSTEM,
43
- package_manager: package_manager
49
+ package_manager: package_manager,
50
+ language: language
44
51
  ),
45
52
  T.nilable(Ecosystem)
46
53
  )
@@ -50,7 +57,48 @@ module Dependabot
50
57
 
51
58
  sig { returns(Ecosystem::VersionManager) }
52
59
  def package_manager
53
- PackageManager.new(composer_version)
60
+ raw_composer_version = env_versions[:composer] || composer_version
61
+ PackageManager.new(
62
+ raw_composer_version
63
+ )
64
+ end
65
+
66
+ sig { returns(T.nilable(Ecosystem::VersionManager)) }
67
+ def language
68
+ php_version = env_versions[:php]
69
+
70
+ return unless php_version
71
+
72
+ Language.new(
73
+ php_version,
74
+ requirement: php_requirement
75
+ )
76
+ end
77
+
78
+ sig { returns(T::Hash[Symbol, T.nilable(String)]) }
79
+ def env_versions
80
+ @env_versions ||= T.let(
81
+ Helpers.fetch_composer_and_php_versions,
82
+ T.nilable(T::Hash[Symbol, T.nilable(String)])
83
+ )
84
+ end
85
+
86
+ # Capture PHP requirement from the composer.json
87
+ sig { returns(T.nilable(Requirement)) }
88
+ def php_requirement
89
+ requirement_string = Helpers.php_constraint(parsed_composer_json)
90
+
91
+ return nil unless requirement_string
92
+
93
+ requirements = requirement_string
94
+ .strip
95
+ .split(REQUIREMENT_SEPARATOR)
96
+ .map(&:strip)
97
+ .reject(&:empty?)
98
+
99
+ return nil unless requirements.any?
100
+
101
+ Requirement.new(requirements)
54
102
  end
55
103
 
56
104
  sig { returns(DependencySet) }
@@ -95,7 +143,7 @@ module Dependabot
95
143
  version: dependency_version(name: name, type: group),
96
144
  requirements: [{
97
145
  requirement: req,
98
- file: "composer.json",
146
+ file: PackageManager::MANIFEST_FILENAME,
99
147
  source: dependency_source(
100
148
  name: name,
101
149
  type: group,
@@ -103,7 +151,7 @@ module Dependabot
103
151
  ),
104
152
  groups: [group]
105
153
  }],
106
- package_manager: "composer"
154
+ package_manager: PackageManager::NAME
107
155
  )
108
156
  end
109
157
 
@@ -141,7 +189,7 @@ module Dependabot
141
189
  name: name,
142
190
  version: version,
143
191
  requirements: [],
144
- package_manager: "composer",
192
+ package_manager: PackageManager::NAME,
145
193
  subdependency_metadata: [{
146
194
  production: keys.fetch(:group) != "development"
147
195
  }]
@@ -162,7 +210,8 @@ module Dependabot
162
210
  end
163
211
 
164
212
  sig do
165
- params(name: String, type: String, requirement: String).returns(T.nilable(T::Hash[Symbol, T.nilable(String)]))
213
+ params(name: String, type: String,
214
+ requirement: String).returns(T.nilable(T::Hash[Symbol, T.nilable(String)]))
166
215
  end
167
216
  def dependency_source(name:, type:, requirement:)
168
217
  return unless lockfile
@@ -223,7 +272,7 @@ module Dependabot
223
272
 
224
273
  sig { override.void }
225
274
  def check_required_files
226
- raise "No composer.json!" unless get_original_file("composer.json")
275
+ raise "No #{PackageManager::MANIFEST_FILENAME}!" unless get_original_file(PackageManager::MANIFEST_FILENAME)
227
276
  end
228
277
 
229
278
  sig { returns(T.nilable(T::Hash[String, T.untyped])) }
@@ -243,7 +292,10 @@ module Dependabot
243
292
  def parsed_composer_json
244
293
  content = composer_json&.content
245
294
 
246
- raise Dependabot::DependencyFileNotParseable, composer_json&.path || "" if content.nil? || content.strip.empty?
295
+ if content.nil? || content.strip.empty?
296
+ raise Dependabot::DependencyFileNotParseable,
297
+ composer_json&.path || ""
298
+ end
247
299
 
248
300
  @parsed_composer_json ||= T.let(JSON.parse(content), T.nilable(T::Hash[String, T.untyped]))
249
301
  rescue JSON::ParserError
@@ -252,17 +304,24 @@ module Dependabot
252
304
 
253
305
  sig { returns(T.nilable(Dependabot::DependencyFile)) }
254
306
  def composer_json
255
- @composer_json ||= T.let(get_original_file("composer.json"), T.nilable(Dependabot::DependencyFile))
307
+ @composer_json ||= T.let(
308
+ get_original_file(PackageManager::MANIFEST_FILENAME),
309
+ T.nilable(Dependabot::DependencyFile)
310
+ )
256
311
  end
257
312
 
258
313
  sig { returns(T.nilable(Dependabot::DependencyFile)) }
259
314
  def lockfile
260
- @lockfile ||= T.let(get_original_file("composer.lock"), T.nilable(Dependabot::DependencyFile))
315
+ @lockfile ||= T.let(
316
+ get_original_file(PackageManager::LOCKFILE_FILENAME),
317
+ T.nilable(Dependabot::DependencyFile)
318
+ )
261
319
  end
262
320
 
263
321
  sig { returns(String) }
264
322
  def composer_version
265
- @composer_version ||= T.let(Helpers.composer_version(parsed_composer_json, parsed_lockfile), T.nilable(String))
323
+ @composer_version ||= T.let(Helpers.composer_version(parsed_composer_json, parsed_lockfile),
324
+ T.nilable(String))
266
325
  end
267
326
  end
268
327
  end
@@ -68,7 +68,7 @@ module Dependabot
68
68
  SharedHelpers.in_a_temporary_directory(base_directory) do
69
69
  write_temporary_dependency_files
70
70
 
71
- updated_content = run_update_helper.fetch("composer.lock")
71
+ updated_content = run_update_helper.fetch(PackageManager::LOCKFILE_FILENAME)
72
72
 
73
73
  updated_content = post_process_lockfile(updated_content)
74
74
  raise "Expected content to change!" if lockfile.content == updated_content
@@ -256,9 +256,9 @@ module Dependabot
256
256
  File.write(file.name, file.content)
257
257
  end
258
258
 
259
- File.write("composer.json", locked_composer_json_content)
260
- File.write("composer.lock", lockfile.content)
261
- File.write("auth.json", auth_json.content) if auth_json
259
+ File.write(PackageManager::MANIFEST_FILENAME, locked_composer_json_content)
260
+ File.write(PackageManager::LOCKFILE_FILENAME, lockfile.content)
261
+ File.write(PackageManager::AUTH_FILENAME, auth_json.content) if auth_json
262
262
  end
263
263
 
264
264
  def locked_composer_json_content
@@ -288,7 +288,7 @@ module Dependabot
288
288
  next content unless Composer::Version.correct?(updated_req)
289
289
 
290
290
  old_req =
291
- dep.requirements.find { |r| r[:file] == "composer.json" }
291
+ dep.requirements.find { |r| r[:file] == PackageManager::MANIFEST_FILENAME }
292
292
  &.fetch(:requirement)
293
293
 
294
294
  # When updating a subdep there won't be an old requirement
@@ -379,11 +379,11 @@ module Dependabot
379
379
  def replace_content_hash(content)
380
380
  existing_hash = JSON.parse(content).fetch("content-hash")
381
381
  SharedHelpers.in_a_temporary_directory do
382
- File.write("composer.json", updated_composer_json_content)
382
+ File.write(PackageManager::MANIFEST_FILENAME, updated_composer_json_content)
383
383
 
384
384
  content_hash =
385
385
  SharedHelpers.run_helper_subprocess(
386
- command: "php #{php_helper_path}",
386
+ command: "#{Language::NAME} #{php_helper_path}",
387
387
  function: "get_content_hash",
388
388
  env: credentials_env,
389
389
  args: [Dir.pwd]
@@ -466,25 +466,25 @@ module Dependabot
466
466
 
467
467
  def registry_credentials
468
468
  credentials
469
- .select { |cred| cred.fetch("type") == "composer_repository" }
469
+ .select { |cred| cred.fetch("type") == PackageManager::REPOSITORY_KEY }
470
470
  .select { |cred| cred["password"] }
471
471
  end
472
472
 
473
473
  def initial_platform
474
- platform_php = parsed_composer_json.dig("config", "platform", "php")
474
+ platform_php = Helpers.capture_platform_php(parsed_composer_json)
475
475
 
476
476
  platform = {}
477
- platform["php"] = [platform_php] if platform_php.is_a?(String) && requirement_valid?(platform_php)
477
+ platform[Language::NAME] = [platform_php] if platform_php.is_a?(String) && requirement_valid?(platform_php)
478
478
 
479
479
  # NOTE: We *don't* include the require-dev PHP version in our initial
480
480
  # platform. If we fail to resolve with the PHP version specified in
481
481
  # `require` then it will be picked up in a subsequent iteration.
482
- requirement_php = parsed_composer_json.dig("require", "php")
482
+ requirement_php = Helpers.php_constraint(parsed_composer_json)
483
483
  return platform unless requirement_php.is_a?(String)
484
484
  return platform unless requirement_valid?(requirement_php)
485
485
 
486
- platform["php"] ||= []
487
- platform["php"] << requirement_php
486
+ platform[Language::NAME] ||= []
487
+ platform[Language::NAME] << requirement_php
488
488
  platform
489
489
  end
490
490
 
@@ -505,16 +505,16 @@ module Dependabot
505
505
 
506
506
  def composer_json
507
507
  @composer_json ||=
508
- dependency_files.find { |f| f.name == "composer.json" }
508
+ dependency_files.find { |f| f.name == PackageManager::MANIFEST_FILENAME }
509
509
  end
510
510
 
511
511
  def lockfile
512
512
  @lockfile ||=
513
- dependency_files.find { |f| f.name == "composer.lock" }
513
+ dependency_files.find { |f| f.name == PackageManager::LOCKFILE_FILENAME }
514
514
  end
515
515
 
516
516
  def auth_json
517
- @auth_json ||= dependency_files.find { |f| f.name == "auth.json" }
517
+ @auth_json ||= dependency_files.find { |f| f.name == PackageManager::AUTH_FILENAME }
518
518
  end
519
519
 
520
520
  def artifact_dependencies
@@ -524,7 +524,7 @@ module Dependabot
524
524
 
525
525
  def path_dependencies
526
526
  @path_dependencies ||=
527
- dependency_files.select { |f| f.name.end_with?("/composer.json") }
527
+ dependency_files.select { |f| f.name.end_with?("/#{PackageManager::MANIFEST_FILENAME}") }
528
528
  end
529
529
  end
530
530
  end
@@ -46,7 +46,7 @@ module Dependabot
46
46
  private
47
47
 
48
48
  def check_required_files
49
- raise "No composer.json!" unless get_original_file("composer.json")
49
+ raise "No #{PackageManager::MANIFEST_FILENAME}!" unless get_original_file(PackageManager::MANIFEST_FILENAME)
50
50
  end
51
51
 
52
52
  def updated_composer_json_content
@@ -66,11 +66,11 @@ module Dependabot
66
66
  end
67
67
 
68
68
  def composer_json
69
- @composer_json ||= get_original_file("composer.json")
69
+ @composer_json ||= get_original_file(PackageManager::MANIFEST_FILENAME)
70
70
  end
71
71
 
72
72
  def lockfile
73
- @lockfile ||= get_original_file("composer.lock")
73
+ @lockfile ||= get_original_file(PackageManager::LOCKFILE_FILENAME)
74
74
  end
75
75
  end
76
76
  end
@@ -45,8 +45,8 @@ module Dependabot
45
45
  def self.composer_version(composer_json, parsed_lockfile = nil)
46
46
  # If the parsed lockfile has a plugin API version, we return either V1 or V2
47
47
  # based on the major version of the lockfile.
48
- if parsed_lockfile && parsed_lockfile["plugin-api-version"]
49
- version = Composer::Version.new(parsed_lockfile["plugin-api-version"])
48
+ if parsed_lockfile && parsed_lockfile[PackageManager::PLUGIN_API_VERSION_KEY]
49
+ version = Composer::Version.new(parsed_lockfile[PackageManager::PLUGIN_API_VERSION_KEY])
50
50
  major_version = version.canonical_segments.first
51
51
 
52
52
  return major_version.nil? || major_version > 1 ? V2 : V1
@@ -89,11 +89,84 @@ module Dependabot
89
89
  nil
90
90
  end
91
91
 
92
+ # Run single composer command returning stdout/stderr
93
+ sig { params(command: String, fingerprint: T.nilable(String)).returns(String) }
94
+ def self.package_manager_run_command(command, fingerprint: nil)
95
+ full_command = "composer #{command}"
96
+
97
+ Dependabot.logger.info("Running composer command: #{full_command}")
98
+
99
+ result = Dependabot::SharedHelpers.run_shell_command(
100
+ full_command,
101
+ fingerprint: "composer #{fingerprint || command}"
102
+ ).strip
103
+
104
+ Dependabot.logger.info("Command executed successfully: #{full_command}")
105
+ result
106
+ rescue StandardError => e
107
+ Dependabot.logger.error("Error running composer command: #{full_command}, Error: #{e.message}")
108
+ raise
109
+ end
110
+
111
+ # Example output:
112
+ # [dependabot] ~ $ composer --version
113
+ # Composer version 2.7.7 2024-06-10 22:11:12
114
+ # PHP version 7.4.33 (/usr/bin/php7.4)
115
+ # Run the "diagnose" command to get more detailed diagnostics output.
116
+ # Get the version of the composer and php form the command output
117
+ # @return [Hash] with the composer and php version
118
+ # => { composer: "2.7.7", php: "7.4.33" }
119
+ sig { returns(T::Hash[Symbol, T.nilable(String)]) }
120
+ def self.fetch_composer_and_php_versions
121
+ output = package_manager_run_command("--version").strip
122
+
123
+ composer_version = capture_version(output, /Composer version (?<version>\d+\.\d+\.\d+)/)
124
+ php_version = capture_version(output, /PHP version (?<version>\d+\.\d+\.\d+)/)
125
+
126
+ Dependabot.logger.info("Dependabot running with Composer version: #{composer_version}")
127
+ Dependabot.logger.info("Dependabot running with PHP version: #{php_version}")
128
+
129
+ { composer: composer_version, php: php_version }
130
+ rescue StandardError => e
131
+ Dependabot.logger.error("Error fetching versions for package manager and language #{name}: #{e.message}")
132
+ {}
133
+ end
134
+
135
+ sig { params(output: String, regex: Regexp).returns(T.nilable(String)) }
136
+ def self.capture_version(output, regex)
137
+ match = output.match(regex)
138
+ match&.named_captures&.fetch("version", nil)
139
+ end
140
+
141
+ # Capture the platform PHP version from composer.json
142
+ sig { params(parsed_composer_json: T::Hash[String, T.untyped]).returns(T.nilable(String)) }
143
+ def self.capture_platform_php(parsed_composer_json)
144
+ capture_platform(parsed_composer_json, Language::NAME)
145
+ end
146
+
147
+ # Capture the platform extension from composer.json
148
+ sig { params(parsed_composer_json: T::Hash[String, T.untyped], name: String).returns(T.nilable(String)) }
149
+ def self.capture_platform(parsed_composer_json, name)
150
+ parsed_composer_json.dig(PackageManager::CONFIG_KEY, PackageManager::PLATFORM_KEY, name)
151
+ end
152
+
153
+ # Capture PHP version constraint from composer.json
154
+ sig { params(parsed_composer_json: T::Hash[String, T.untyped]).returns(T.nilable(String)) }
155
+ def self.php_constraint(parsed_composer_json)
156
+ dependency_constraint(parsed_composer_json, Language::NAME)
157
+ end
158
+
159
+ # Capture extension version constraint from composer.json
160
+ sig { params(parsed_composer_json: T::Hash[String, T.untyped], name: String).returns(T.nilable(String)) }
161
+ def self.dependency_constraint(parsed_composer_json, name)
162
+ parsed_composer_json.dig(PackageManager::REQUIRE_KEY, name)
163
+ end
164
+
92
165
  sig { params(composer_json: T::Hash[String, T.untyped]).returns(T::Boolean) }
93
166
  def self.invalid_v2_requirement?(composer_json)
94
- return false unless composer_json.key?("require")
167
+ return false unless composer_json.key?(PackageManager::REQUIRE_KEY)
95
168
 
96
- composer_json["require"].keys.any? do |key|
169
+ composer_json[PackageManager::REQUIRE_KEY].keys.any? do |key|
97
170
  key !~ PLATFORM_PACKAGE_REGEX && key !~ COMPOSER_V2_NAME_REGEX
98
171
  end
99
172
  end
@@ -0,0 +1,38 @@
1
+ # typed: strong
2
+ # frozen_string_literal: true
3
+
4
+ require "sorbet-runtime"
5
+ require "dependabot/ecosystem"
6
+ require "dependabot/composer/requirement"
7
+ require "dependabot/composer/version"
8
+
9
+ module Dependabot
10
+ module Composer
11
+ class Language < Dependabot::Ecosystem::VersionManager
12
+ extend T::Sig
13
+
14
+ NAME = "php"
15
+
16
+ sig { params(raw_version: String, requirement: T.nilable(Requirement)).void }
17
+ def initialize(raw_version, requirement: nil)
18
+ super(
19
+ NAME,
20
+ Version.new(raw_version),
21
+ [],
22
+ [],
23
+ requirement
24
+ )
25
+ end
26
+
27
+ sig { returns(T::Boolean) }
28
+ def deprecated?
29
+ false
30
+ end
31
+
32
+ sig { returns(T::Boolean) }
33
+ def unsupported?
34
+ false
35
+ end
36
+ end
37
+ end
38
+ end
@@ -8,22 +8,35 @@ require "dependabot/composer/version"
8
8
  module Dependabot
9
9
  module Composer
10
10
  ECOSYSTEM = "composer"
11
- PACKAGE_MANAGER = "composer"
12
-
13
- # Keep versions in ascending order
14
- SUPPORTED_COMPOSER_VERSIONS = T.let([Version.new("2")].freeze, T::Array[Dependabot::Version])
15
-
16
- DEPRECATED_COMPOSER_VERSIONS = T.let([
17
- Version.new("1")
18
- ].freeze, T::Array[Dependabot::Version])
19
11
 
20
12
  class PackageManager < Dependabot::Ecosystem::VersionManager
21
13
  extend T::Sig
22
14
 
15
+ NAME = "composer"
16
+ MANIFEST_FILENAME = "composer.json"
17
+ LOCKFILE_FILENAME = "composer.lock"
18
+ AUTH_FILENAME = "auth.json"
19
+ DEPENDENCY_NAME = "composer/composer"
20
+
21
+ REQUIRE_KEY = "require"
22
+ CONFIG_KEY = "config"
23
+ PLATFORM_KEY = "platform"
24
+ PLUGIN_API_VERSION_KEY = "plugin-api-version"
25
+ REPOSITORY_KEY = "composer_repository"
26
+
27
+ # Keep versions in ascending order
28
+ SUPPORTED_COMPOSER_VERSIONS = T.let([Version.new("2")].freeze, T::Array[Dependabot::Version])
29
+
30
+ # Currently, we don't support any deprecated versions of Composer
31
+ # When a version is going to be unsupported, it will be added here for a while to give users time to upgrade
32
+ # Example for deprecation:
33
+ # DEPRECATED_COMPOSER_VERSIONS = T.let([Version.new("1")].freeze, T::Array[Dependabot::Version])
34
+ DEPRECATED_COMPOSER_VERSIONS = T.let([].freeze, T::Array[Dependabot::Version])
35
+
23
36
  sig { params(raw_version: String).void }
24
37
  def initialize(raw_version)
25
38
  super(
26
- PACKAGE_MANAGER,
39
+ NAME,
27
40
  Version.new(raw_version),
28
41
  DEPRECATED_COMPOSER_VERSIONS,
29
42
  SUPPORTED_COMPOSER_VERSIONS,
@@ -107,7 +107,7 @@ module Dependabot
107
107
  .select { |r| r.is_a?(Hash) }
108
108
 
109
109
  urls = repositories
110
- .select { |h| h["type"] == "composer" }
110
+ .select { |h| h["type"] == PackageManager::NAME }
111
111
  .filter_map { |h| h["url"] }
112
112
  .map { |url| url.gsub(%r{\/$}, "") + "/packages.json" }
113
113
 
@@ -170,7 +170,7 @@ module Dependabot
170
170
  end
171
171
 
172
172
  def registry_credentials
173
- credentials.select { |cred| cred["type"] == "composer_repository" } +
173
+ credentials.select { |cred| cred["type"] == PackageManager::REPOSITORY_KEY } +
174
174
  auth_json_credentials
175
175
  end
176
176
 
@@ -191,14 +191,16 @@ module Dependabot
191
191
 
192
192
  def composer_file
193
193
  composer_file =
194
- dependency_files.find { |f| f.name == "composer.json" }
195
- raise "No composer.json!" unless composer_file
194
+ dependency_files.find do |f|
195
+ f.name == PackageManager::MANIFEST_FILENAME
196
+ end
197
+ raise "No #{PackageManager::MANIFEST_FILENAME}!" unless composer_file
196
198
 
197
199
  composer_file
198
200
  end
199
201
 
200
202
  def auth_json
201
- dependency_files.find { |f| f.name == "auth.json" }
203
+ dependency_files.find { |f| f.name == PackageManager::AUTH_FILENAME }
202
204
  end
203
205
 
204
206
  def ignore_requirements
@@ -108,7 +108,7 @@ module Dependabot
108
108
 
109
109
  def write_dependency_file(unlock_requirement:)
110
110
  File.write(
111
- "composer.json",
111
+ PackageManager::MANIFEST_FILENAME,
112
112
  prepared_composer_json_content(
113
113
  unlock_requirement: unlock_requirement
114
114
  )
@@ -123,11 +123,11 @@ module Dependabot
123
123
  end
124
124
 
125
125
  def write_lockfile
126
- File.write("composer.lock", lockfile.content) if lockfile
126
+ File.write(PackageManager::LOCKFILE_FILENAME, lockfile.content) if lockfile
127
127
  end
128
128
 
129
129
  def write_auth_file
130
- File.write("auth.json", auth_json.content) if auth_json
130
+ File.write(PackageManager::AUTH_FILENAME, auth_json.content) if auth_json
131
131
  end
132
132
 
133
133
  def transitory_failure?(error)
@@ -175,9 +175,9 @@ module Dependabot
175
175
  composer_platform_extensions.each do |extension, requirements|
176
176
  next unless version_for_reqs(requirements)
177
177
 
178
- json["config"] ||= {}
179
- json["config"]["platform"] ||= {}
180
- json["config"]["platform"][extension] =
178
+ json[PackageManager::CONFIG_KEY] ||= {}
179
+ json[PackageManager::CONFIG_KEY][PackageManager::PLATFORM_KEY] ||= {}
180
+ json[PackageManager::CONFIG_KEY][PackageManager::PLATFORM_KEY][extension] =
181
181
  version_for_reqs(requirements)
182
182
  end
183
183
 
@@ -338,8 +338,10 @@ module Dependabot
338
338
  # composer.json. In this case we just ignore the dependency.
339
339
  nil
340
340
  elsif error.message.include?("does not match the expected JSON schema")
341
- msg = "Composer failed to parse your composer.json as it does not match the expected JSON schema.\n" \
342
- "Run `composer validate` to check your composer.json and composer.lock files.\n\n" \
341
+ msg = "Composer failed to parse your #{PackageManager::MANIFEST_FILENAME}" \
342
+ "as it does not match the expected JSON schema.\n" \
343
+ "Run `composer validate` to check your #{PackageManager::MANIFEST_FILENAME} " \
344
+ "and #{PackageManager::LOCKFILE_FILENAME} files.\n\n" \
343
345
  "See https://getcomposer.org/doc/04-schema.md for details on the schema."
344
346
  raise Dependabot::DependencyFileNotParseable, msg
345
347
  else
@@ -452,20 +454,22 @@ module Dependabot
452
454
  end
453
455
 
454
456
  def initial_platform
455
- platform_php = parsed_composer_file.dig("config", "platform", "php")
457
+ platform_php = Helpers.capture_platform_php(parsed_composer_file)
456
458
 
457
459
  platform = {}
458
- platform["php"] = [platform_php] if platform_php.is_a?(String) && requirement_valid?(platform_php)
460
+ if platform_php.is_a?(String) && requirement_valid?(platform_php)
461
+ platform[Dependabot::Composer::Language::NAME] = [platform_php]
462
+ end
459
463
 
460
464
  # NOTE: We *don't* include the require-dev PHP version in our initial
461
465
  # platform. If we fail to resolve with the PHP version specified in
462
466
  # `require` then it will be picked up in a subsequent iteration.
463
- requirement_php = parsed_composer_file.dig("require", "php")
467
+ requirement_php = Helpers.php_constraint(parsed_composer_file)
464
468
  return platform unless requirement_php.is_a?(String)
465
469
  return platform unless requirement_valid?(requirement_php)
466
470
 
467
- platform["php"] ||= []
468
- platform["php"] << requirement_php
471
+ platform[Dependabot::Composer::Language::NAME] ||= []
472
+ platform[Dependabot::Composer::Language::NAME] << requirement_php
469
473
  platform
470
474
  end
471
475
 
@@ -479,12 +483,12 @@ module Dependabot
479
483
 
480
484
  def composer_file
481
485
  @composer_file ||=
482
- dependency_files.find { |f| f.name == "composer.json" }
486
+ dependency_files.find { |f| f.name == PackageManager::MANIFEST_FILENAME }
483
487
  end
484
488
 
485
489
  def path_dependency_files
486
490
  @path_dependency_files ||=
487
- dependency_files.select { |f| f.name.end_with?("/composer.json") }
491
+ dependency_files.select { |f| f.name.end_with?("/#{PackageManager::MANIFEST_FILENAME}") }
488
492
  end
489
493
 
490
494
  def zipped_path_dependency_files
@@ -494,11 +498,11 @@ module Dependabot
494
498
 
495
499
  def lockfile
496
500
  @lockfile ||=
497
- dependency_files.find { |f| f.name == "composer.lock" }
501
+ dependency_files.find { |f| f.name == PackageManager::LOCKFILE_FILENAME }
498
502
  end
499
503
 
500
504
  def auth_json
501
- @auth_json ||= dependency_files.find { |f| f.name == "auth.json" }
505
+ @auth_json ||= dependency_files.find { |f| f.name == PackageManager::AUTH_FILENAME }
502
506
  end
503
507
 
504
508
  def requirement_valid?(req_string)
@@ -516,7 +520,7 @@ module Dependabot
516
520
 
517
521
  def registry_credentials
518
522
  credentials
519
- .select { |cred| cred["type"] == "composer_repository" }
523
+ .select { |cred| cred["type"] == PackageManager::REPOSITORY_KEY }
520
524
  .select { |cred| cred["password"] }
521
525
  end
522
526
  end
@@ -139,8 +139,8 @@ module Dependabot
139
139
 
140
140
  def composer_file
141
141
  composer_file =
142
- dependency_files.find { |f| f.name == "composer.json" }
143
- raise "No composer.json!" unless composer_file
142
+ dependency_files.find { |f| f.name == PackageManager::MANIFEST_FILENAME }
143
+ raise "No #{PackageManager::MANIFEST_FILENAME}!" unless composer_file
144
144
 
145
145
  composer_file
146
146
  end
@@ -12,6 +12,7 @@ require "dependabot/composer/requirement"
12
12
  require "dependabot/composer/version"
13
13
  require "dependabot/composer/helpers"
14
14
  require "dependabot/composer/package_manager"
15
+ require "dependabot/composer/language"
15
16
 
16
17
  require "dependabot/pull_request_creator/labeler"
17
18
  Dependabot::PullRequestCreator::Labeler
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dependabot-composer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.288.0
4
+ version: 0.289.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dependabot
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-11-21 00:00:00.000000000 Z
11
+ date: 2024-12-05 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.288.0
19
+ version: 0.289.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.288.0
26
+ version: 0.289.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: debug
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -261,6 +261,7 @@ files:
261
261
  - lib/dependabot/composer/file_updater/lockfile_updater.rb
262
262
  - lib/dependabot/composer/file_updater/manifest_updater.rb
263
263
  - lib/dependabot/composer/helpers.rb
264
+ - lib/dependabot/composer/language.rb
264
265
  - lib/dependabot/composer/metadata_finder.rb
265
266
  - lib/dependabot/composer/native_helpers.rb
266
267
  - lib/dependabot/composer/package_manager.rb
@@ -275,7 +276,7 @@ licenses:
275
276
  - MIT
276
277
  metadata:
277
278
  bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
278
- changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.288.0
279
+ changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.289.0
279
280
  post_install_message:
280
281
  rdoc_options: []
281
282
  require_paths: