dependabot-bundler 0.284.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: 48a9435c67c8a6b58134c7a80486d74ab609273e937c10eed74191426d6cded8
4
- data.tar.gz: a139d9cc839fddffc0e0ca6ef3b8a7ab87d9a1ae2d82e5404e16b1823502cf2e
3
+ metadata.gz: 46bd8d058b090759dfbdef246960dd68aaf6805eca3e8ed86dcbbe24bae02f05
4
+ data.tar.gz: 0104dce3ac3823fb75626420bf71eabebba6cc6a43a5a01a3ab4475c73f5090f
5
5
  SHA512:
6
- metadata.gz: 9612d984f30f3e0cfa5079a1c34be49112fe4de0e93aabca848a70f5438ae722acd958746950f7ff94404f66ce14bc50ec8604014e933e7877d7fb0cdf013bdc
7
- data.tar.gz: c2edeee8f3df7b37c19b747b4e54a6d34846efde4ab76a26d14302124432b77901c57afedc3cad21a95695c619f445b7d08e10dfa72e882fe8fc7688367b5e9c
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"
@@ -37,7 +39,8 @@ module Dependabot
37
39
  @ecosystem ||= T.let(
38
40
  Ecosystem.new(
39
41
  name: ECOSYSTEM,
40
- package_manager: package_manager
42
+ package_manager: package_manager,
43
+ language: language
41
44
  ),
42
45
  T.nilable(Ecosystem)
43
46
  )
@@ -47,7 +50,20 @@ module Dependabot
47
50
 
48
51
  sig { returns(Ecosystem::VersionManager) }
49
52
  def package_manager
50
- PackageManager.new(bundler_version)
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)
51
67
  end
52
68
 
53
69
  def check_external_code(dependencies)
@@ -327,6 +343,51 @@ module Dependabot
327
343
  .reject { |f| f.name == "gems.rb" }
328
344
  end
329
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
+
330
391
  sig { returns(String) }
331
392
  def bundler_version
332
393
  @bundler_version ||= Helpers.bundler_version(lockfile)
@@ -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
@@ -4,6 +4,7 @@
4
4
  require "sorbet-runtime"
5
5
  require "dependabot/bundler/version"
6
6
  require "dependabot/ecosystem"
7
+ require "dependabot/bundler/requirement"
7
8
 
8
9
  module Dependabot
9
10
  module Bundler
@@ -22,13 +23,19 @@ module Dependabot
22
23
  class PackageManager < Dependabot::Ecosystem::VersionManager
23
24
  extend T::Sig
24
25
 
25
- sig { params(raw_version: String).void }
26
- def initialize(raw_version)
26
+ sig do
27
+ params(
28
+ raw_version: String,
29
+ requirement: T.nilable(Requirement)
30
+ ).void
31
+ end
32
+ def initialize(raw_version, requirement = nil)
27
33
  super(
28
34
  PACKAGE_MANAGER,
29
35
  Version.new(raw_version),
30
36
  DEPRECATED_BUNDLER_VERSIONS,
31
37
  SUPPORTED_BUNDLER_VERSIONS,
38
+ requirement,
32
39
  )
33
40
  end
34
41
  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.284.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-11-05 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.284.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.284.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.284.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: