dependabot-composer 0.288.0 → 0.289.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: 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: