dependabot-bundler 0.283.0 → 0.285.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: 3772984b030e3e8ce2c64572c9a790f7842a3429a785837e556ad8963924ed84
4
- data.tar.gz: 35bdd5240c4eb546f8a9919bf5ce4a0b7043f3ce26af25fd6968d5cf35e88c47
3
+ metadata.gz: 46bd8d058b090759dfbdef246960dd68aaf6805eca3e8ed86dcbbe24bae02f05
4
+ data.tar.gz: 0104dce3ac3823fb75626420bf71eabebba6cc6a43a5a01a3ab4475c73f5090f
5
5
  SHA512:
6
- metadata.gz: 3086d857acaf430af46933a16f00de5fdeac7ff80a06593009988e8daa0a2f5cb962857b8ff8c3992fa995b471ae88aaa870a8ccf455ff5b85052ba378a8cc6b
7
- data.tar.gz: c88f11281d9455805ae80db5d3a5ebd16bef0dd9dcebf1cd645f02c00a9826f8e8e67812b7f011cf5057a8f913a6211450ab997c927502c3fac11d2c3ae0e380
6
+ metadata.gz: 29cc464b42b25ae071d77180e16b91e151cc5fb5a5b8fb3375a94908dd6189539b5b23e02d5be93b999fe7e3256671fa4718adc5c63107f18b08332d2f2b0950
7
+ data.tar.gz: a1ca65abcce69cac328b4d99d1e4fe5319abc1c6fc7f8f3ffd5b99f70f1a3887e07434ba8a69521c7fed2c952c3e6cbb745fa55da547148a09c56408cbecac21
@@ -173,4 +173,12 @@ module Functions
173
173
  credentials
174
174
  .select { |cred| cred["type"] == "git_source" }
175
175
  end
176
+
177
+ def self.bundler_raw_version
178
+ Bundler::VERSION
179
+ end
180
+
181
+ def self.ruby_raw_version
182
+ RUBY_VERSION
183
+ end
176
184
  end
@@ -2,6 +2,8 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "parallel"
5
+ require "dependabot/bundler/language"
6
+ require "dependabot/bundler/package_manager"
5
7
  require "dependabot/dependency"
6
8
  require "dependabot/file_parsers"
7
9
  require "dependabot/file_parsers/base"
@@ -32,13 +34,38 @@ module Dependabot
32
34
  dependency_set.dependencies
33
35
  end
34
36
 
35
- sig { returns(PackageManagerBase) }
36
- def package_manager
37
- PackageManager.new(bundler_version)
37
+ sig { returns(Ecosystem) }
38
+ def ecosystem
39
+ @ecosystem ||= T.let(
40
+ Ecosystem.new(
41
+ name: ECOSYSTEM,
42
+ package_manager: package_manager,
43
+ language: language
44
+ ),
45
+ T.nilable(Ecosystem)
46
+ )
38
47
  end
39
48
 
40
49
  private
41
50
 
51
+ sig { returns(Ecosystem::VersionManager) }
52
+ def package_manager
53
+ @package_manager ||= PackageManager.new(bundler_raw_version, package_manager_requirement)
54
+ end
55
+
56
+ def package_manager_requirement
57
+ @package_manager_requirement ||= Helpers.bundler_dependency_requirement(dependency_files)
58
+ end
59
+
60
+ sig { returns(T.nilable(Ecosystem::VersionManager)) }
61
+ def language
62
+ return @language if defined?(@language)
63
+
64
+ return nil if package_manager.unsupported?
65
+
66
+ Language.new(ruby_raw_version)
67
+ end
68
+
42
69
  def check_external_code(dependencies)
43
70
  return unless @reject_external_code
44
71
  return unless git_source?(dependencies)
@@ -309,12 +336,59 @@ module Dependabot
309
336
  .select { |file| file.name.end_with?(".gemspec") }
310
337
  end
311
338
 
339
+ sig { returns(T::Array[Dependabot::DependencyFile]) }
312
340
  def imported_ruby_files
313
341
  dependency_files
314
342
  .select { |f| f.name.end_with?(".rb") }
315
343
  .reject { |f| f.name == "gems.rb" }
316
344
  end
317
345
 
346
+ sig { returns(String) }
347
+ def bundler_raw_version
348
+ return bundler_raw_version if defined?(@bundler_raw_version)
349
+
350
+ package_manager = PackageManager.new(bundler_version)
351
+
352
+ # If the selected version is unsupported, an unsupported error will be raised,
353
+ # so there’s no need to attempt retrieving the raw version.
354
+ return bundler_version if package_manager.unsupported?
355
+
356
+ # read raw version directly from the ecosystem environment
357
+ bundler_raw_version = SharedHelpers.in_a_temporary_repo_directory(
358
+ base_directory,
359
+ repo_contents_path
360
+ ) do
361
+ write_temporary_dependency_files
362
+ NativeHelpers.run_bundler_subprocess(
363
+ function: "bundler_raw_version",
364
+ args: {},
365
+ bundler_version: bundler_version,
366
+ options: { timeout_per_operation_seconds: 10 }
367
+ )
368
+ end
369
+ bundler_raw_version || ::Bundler::VERSION
370
+ end
371
+
372
+ sig { returns(String) }
373
+ def ruby_raw_version
374
+ return @ruby_raw_version if defined?(@ruby_raw_version)
375
+
376
+ ruby_raw_version = SharedHelpers.in_a_temporary_repo_directory(
377
+ base_directory,
378
+ repo_contents_path
379
+ ) do
380
+ write_temporary_dependency_files
381
+ NativeHelpers.run_bundler_subprocess(
382
+ function: "ruby_raw_version",
383
+ args: {},
384
+ bundler_version: bundler_version,
385
+ options: { timeout_per_operation_seconds: 10 }
386
+ )
387
+ end
388
+ ruby_raw_version || RUBY_VERSION
389
+ end
390
+
391
+ sig { returns(String) }
318
392
  def bundler_version
319
393
  @bundler_version ||= Helpers.bundler_version(lockfile)
320
394
  end
@@ -1,6 +1,8 @@
1
1
  # typed: strong
2
2
  # frozen_string_literal: true
3
3
 
4
+ require "dependabot/bundler/requirement"
5
+
4
6
  module Dependabot
5
7
  module Bundler
6
8
  module Helpers
@@ -9,16 +11,18 @@ module Dependabot
9
11
 
10
12
  V1 = "1"
11
13
  V2 = "2"
12
- # If we are updating a project with no Gemfile.lock, we default to the
13
- # newest version we support
14
14
  DEFAULT = V2
15
15
  BUNDLER_MAJOR_VERSION_REGEX = /BUNDLED WITH\s+(?<version>\d+)\./m
16
16
 
17
+ GEMFILE = "Gemfile"
18
+ GEMSPEC_EXTENSION = ".gemspec"
19
+ BUNDLER_GEM_NAME = "bundler"
20
+
17
21
  sig { params(lockfile: T.nilable(Dependabot::DependencyFile)).returns(String) }
18
22
  def self.bundler_version(lockfile)
19
23
  return DEFAULT unless lockfile
20
24
 
21
- if (matches = lockfile.content&.match(BUNDLER_MAJOR_VERSION_REGEX))
25
+ if (matches = T.let(lockfile.content, T.nilable(String))&.match(BUNDLER_MAJOR_VERSION_REGEX))
22
26
  matches[:version].to_i >= 2 ? V2 : V1
23
27
  else
24
28
  DEFAULT
@@ -29,12 +33,75 @@ module Dependabot
29
33
  def self.detected_bundler_version(lockfile)
30
34
  return "unknown" unless lockfile
31
35
 
32
- if (matches = lockfile.content&.match(BUNDLER_MAJOR_VERSION_REGEX))
36
+ if (matches = T.let(lockfile.content, T.nilable(String))&.match(BUNDLER_MAJOR_VERSION_REGEX))
33
37
  matches[:version].to_i.to_s
34
38
  else
35
39
  "unspecified"
36
40
  end
37
41
  end
42
+
43
+ # Method to get the Requirement object for the 'bundler' dependency
44
+ sig do
45
+ params(files: T::Array[Dependabot::DependencyFile]).returns(T.nilable(Dependabot::Bundler::Requirement))
46
+ end
47
+ def self.bundler_dependency_requirement(files)
48
+ constraints = combined_dependency_constraints(files, BUNDLER_GEM_NAME)
49
+ return nil if constraints.empty?
50
+
51
+ combined_constraint = constraints.join(", ")
52
+
53
+ Dependabot::Bundler::Requirement.new(combined_constraint)
54
+ rescue StandardError => e
55
+ Dependabot.logger.error(
56
+ "Failed to create Requirement with constraints '#{constraints&.join(', ')}': #{e.message}"
57
+ )
58
+ nil
59
+ end
60
+
61
+ # Method to gather and combine constraints for a specified dependency from multiple files
62
+ sig do
63
+ params(files: T::Array[Dependabot::DependencyFile], dependency_name: String).returns(T::Array[String])
64
+ end
65
+ def self.combined_dependency_constraints(files, dependency_name)
66
+ files.each_with_object([]) do |file, result|
67
+ content = file.content
68
+ next unless content
69
+
70
+ # Select the appropriate regex based on file type
71
+ regex = if file.name.end_with?(GEMFILE)
72
+ gemfile_dependency_regex(dependency_name)
73
+ elsif file.name.end_with?(GEMSPEC_EXTENSION)
74
+ gemspec_dependency_regex(dependency_name)
75
+ else
76
+ next # Skip unsupported file types
77
+ end
78
+
79
+ # Extract constraints using the chosen regex
80
+ result.concat(extract_constraints_from_file(content, regex))
81
+ end.uniq
82
+ end
83
+
84
+ # Method to generate the regex pattern for a dependency in a Gemfile
85
+ sig { params(dependency_name: String).returns(Regexp) }
86
+ def self.gemfile_dependency_regex(dependency_name)
87
+ /gem\s+['"]#{Regexp.escape(dependency_name)}['"](?:,\s*['"]([^'"]+)['"])?/
88
+ end
89
+
90
+ # Method to generate the regex pattern for a dependency in a gemspec file
91
+ sig { params(dependency_name: String).returns(Regexp) }
92
+ def self.gemspec_dependency_regex(dependency_name)
93
+ /add_(?:runtime_)?dependency\s+['"]#{Regexp.escape(dependency_name)}['"],\s*['"]([^'"]+)['"]/
94
+ end
95
+
96
+ # Extracts constraints from file content based on a dependency regex
97
+ sig { params(content: String, regex: Regexp).returns(T::Array[String]) }
98
+ def self.extract_constraints_from_file(content, regex)
99
+ if content.match(regex)
100
+ content.scan(regex).flatten
101
+ else
102
+ []
103
+ end
104
+ end
38
105
  end
39
106
  end
40
107
  end
@@ -0,0 +1,24 @@
1
+ # typed: strong
2
+ # frozen_string_literal: true
3
+
4
+ require "sorbet-runtime"
5
+ require "dependabot/bundler/version"
6
+ require "dependabot/ecosystem"
7
+
8
+ module Dependabot
9
+ module Bundler
10
+ LANGUAGE = "ruby"
11
+
12
+ class Language < Dependabot::Ecosystem::VersionManager
13
+ extend T::Sig
14
+
15
+ sig { params(raw_version: String).void }
16
+ def initialize(raw_version)
17
+ super(
18
+ LANGUAGE,
19
+ Version.new(raw_version)
20
+ )
21
+ end
22
+ end
23
+ end
24
+ end
@@ -3,10 +3,12 @@
3
3
 
4
4
  require "sorbet-runtime"
5
5
  require "dependabot/bundler/version"
6
- require "dependabot/package_manager"
6
+ require "dependabot/ecosystem"
7
+ require "dependabot/bundler/requirement"
7
8
 
8
9
  module Dependabot
9
10
  module Bundler
11
+ ECOSYSTEM = "bundler"
10
12
  PACKAGE_MANAGER = "bundler"
11
13
 
12
14
  # Keep versions in ascending order
@@ -18,33 +20,23 @@ module Dependabot
18
20
  # DEPRECATED_BUNDLER_VERSIONS = T.let([Version.new("1")].freeze, T::Array[Dependabot::Version])
19
21
  DEPRECATED_BUNDLER_VERSIONS = T.let([].freeze, T::Array[Dependabot::Version])
20
22
 
21
- class PackageManager < PackageManagerBase
23
+ class PackageManager < Dependabot::Ecosystem::VersionManager
22
24
  extend T::Sig
23
25
 
24
- sig { params(version: T.any(String, Dependabot::Version)).void }
25
- def initialize(version)
26
- @version = T.let(Version.new(version), Dependabot::Version)
27
- @name = T.let(PACKAGE_MANAGER, String)
28
- @deprecated_versions = T.let(DEPRECATED_BUNDLER_VERSIONS, T::Array[Dependabot::Version])
29
- @supported_versions = T.let(SUPPORTED_BUNDLER_VERSIONS, T::Array[Dependabot::Version])
26
+ sig do
27
+ params(
28
+ raw_version: String,
29
+ requirement: T.nilable(Requirement)
30
+ ).void
30
31
  end
31
-
32
- sig { override.returns(String) }
33
- attr_reader :name
34
-
35
- sig { override.returns(Dependabot::Version) }
36
- attr_reader :version
37
-
38
- sig { override.returns(T::Array[Dependabot::Version]) }
39
- attr_reader :deprecated_versions
40
-
41
- sig { override.returns(T::Array[Dependabot::Version]) }
42
- attr_reader :supported_versions
43
-
44
- sig { override.returns(T::Boolean) }
45
- def unsupported?
46
- # Check if the version is not supported
47
- supported_versions.all? { |supported| supported > version }
32
+ def initialize(raw_version, requirement = nil)
33
+ super(
34
+ PACKAGE_MANAGER,
35
+ Version.new(raw_version),
36
+ DEPRECATED_BUNDLER_VERSIONS,
37
+ SUPPORTED_BUNDLER_VERSIONS,
38
+ requirement,
39
+ )
48
40
  end
49
41
  end
50
42
  end
@@ -3,6 +3,8 @@
3
3
 
4
4
  # These all need to be required so the various classes can be registered in a
5
5
  # lookup table of package manager names to concrete classes.
6
+ require "dependabot/bundler/language"
7
+ require "dependabot/bundler/package_manager"
6
8
  require "dependabot/bundler/file_fetcher"
7
9
  require "dependabot/bundler/file_parser"
8
10
  require "dependabot/bundler/update_checker"
@@ -10,7 +12,6 @@ require "dependabot/bundler/file_updater"
10
12
  require "dependabot/bundler/metadata_finder"
11
13
  require "dependabot/bundler/requirement"
12
14
  require "dependabot/bundler/version"
13
- require "dependabot/bundler/package_manager"
14
15
 
15
16
  require "dependabot/pull_request_creator/labeler"
16
17
  Dependabot::PullRequestCreator::Labeler
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dependabot-bundler
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.283.0
4
+ version: 0.285.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-10-31 00:00:00.000000000 Z
11
+ date: 2024-11-07 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.283.0
19
+ version: 0.285.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.283.0
26
+ version: 0.285.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: parallel
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -302,6 +302,7 @@ files:
302
302
  - lib/dependabot/bundler/file_updater/requirement_replacer.rb
303
303
  - lib/dependabot/bundler/file_updater/ruby_requirement_setter.rb
304
304
  - lib/dependabot/bundler/helpers.rb
305
+ - lib/dependabot/bundler/language.rb
305
306
  - lib/dependabot/bundler/metadata_finder.rb
306
307
  - lib/dependabot/bundler/native_helpers.rb
307
308
  - lib/dependabot/bundler/package_manager.rb
@@ -321,7 +322,7 @@ licenses:
321
322
  - MIT
322
323
  metadata:
323
324
  bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
324
- changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.283.0
325
+ changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.285.0
325
326
  post_install_message:
326
327
  rdoc_options: []
327
328
  require_paths: