dependabot-common 0.330.0 → 0.331.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: e75354fcd97069450a7897bc3f0c4788fc502b6b7541c7bb1ef01f14779aaec3
4
- data.tar.gz: c71e3cf39d50d4510f12d137e17ba63204aacedce829eb66f48c7da672cece39
3
+ metadata.gz: 368060e7dedf182e8c8b2ddf50b4db02fa3e5376af51f9e67c1463447afd34dc
4
+ data.tar.gz: b803b274fb307a702c06f8b84a97c461c9616c5513c344d75a089f35ceb08af7
5
5
  SHA512:
6
- metadata.gz: 844f8f4ad3fb9b201791b0499fa8c733667ed792701d19fe0791aaad172170b1dfa399244b32477e440ba97d8f2f2862a882c41eb9ab40e029b96affc8c75a9a
7
- data.tar.gz: dd31e1be979b0a984c896be9ba4bc5060175deb1feea9ac0278e03666034dbdc5b711314603c8b56089bd7e2aa93e2e8cbbaa9e552deb75e565d26a3e49129ae
6
+ metadata.gz: 583a5880a5600a7a358971da32c0ec6c50c26221239180daef53139c2d34f9307cc8bb8ef068f13644b01454077708a061a7425d557482e883deacb8c394f8fe
7
+ data.tar.gz: ed79678548ca61683a7f65860b7901ab7af465263e047cec0ffd6b44e74c4bbea7a0f2e1baf404fa530579e57ddc1e9952e40de089658052f98ed2b14df65cb2
@@ -101,6 +101,9 @@ module Dependabot
101
101
  sig { returns(T.nilable(Time)) }
102
102
  attr_accessor :attribution_timestamp
103
103
 
104
+ sig { returns(T::Array[String]) }
105
+ attr_reader :origin_files
106
+
104
107
  # rubocop:disable Metrics/AbcSize
105
108
  # rubocop:disable Metrics/PerceivedComplexity
106
109
  sig do
@@ -116,12 +119,14 @@ module Dependabot
116
119
  subdependency_metadata: T.nilable(T::Array[T::Hash[T.any(Symbol, String), String]]),
117
120
  removed: T::Boolean,
118
121
  metadata: T.nilable(T::Hash[T.any(Symbol, String), String]),
119
- direct_relationship: T::Boolean
122
+ direct_relationship: T::Boolean,
123
+ origin_files: T::Array[String]
120
124
  ).void
121
125
  end
122
126
  def initialize(name:, requirements:, package_manager:, version: nil,
123
127
  previous_version: nil, previous_requirements: nil, directory: nil,
124
- subdependency_metadata: [], removed: false, metadata: {}, direct_relationship: false)
128
+ subdependency_metadata: [], removed: false, metadata: {}, direct_relationship: false,
129
+ origin_files: [])
125
130
  @name = name
126
131
  @version = T.let(
127
132
  case version
@@ -149,7 +154,7 @@ module Dependabot
149
154
  @removed = removed
150
155
  @metadata = T.let(symbolize_keys(metadata || {}), T::Hash[Symbol, T.untyped])
151
156
  @direct_relationship = direct_relationship
152
-
157
+ @origin_files = origin_files
153
158
  check_values
154
159
  end
155
160
  # rubocop:enable Metrics/AbcSize
@@ -462,18 +462,14 @@ module Dependabot
462
462
  params(path: String, fetch_submodules: T::Boolean, raise_errors: T::Boolean)
463
463
  .returns(T::Array[OpenStruct])
464
464
  end
465
- def _fetch_repo_contents(path, fetch_submodules: false, raise_errors: true) # rubocop:disable Metrics/PerceivedComplexity
465
+ def _fetch_repo_contents(path, fetch_submodules: false, raise_errors: true)
466
466
  path = path.gsub(" ", "%20")
467
467
  provider, repo, tmp_path, commit =
468
468
  _full_specification_for(path, fetch_submodules: fetch_submodules)
469
469
  .values_at(:provider, :repo, :path, :commit)
470
470
 
471
471
  entries = _fetch_repo_contents_fully_specified(provider, repo, tmp_path, commit)
472
- if Dependabot::Experiments.enabled?(:enable_exclude_paths_subdirectory_manifest_files)
473
- filter_excluded(entries)
474
- else
475
- entries
476
- end
472
+ entries
477
473
  rescue *CLIENT_NOT_FOUND_ERRORS
478
474
  raise Dependabot::DirectoryNotFound, directory if path == directory.gsub(%r{^/*}, "")
479
475
 
@@ -554,11 +550,7 @@ module Dependabot
554
550
  size: 0 # NOTE: added for parity with github contents API
555
551
  )
556
552
  end
557
- if Dependabot::Experiments.enabled?(:enable_exclude_paths_subdirectory_manifest_files)
558
- filter_excluded(entries)
559
- else
560
- entries
561
- end
553
+ entries
562
554
  end
563
555
 
564
556
  # Filters out any entries whose paths match one of the exclude_paths globs.
@@ -0,0 +1,70 @@
1
+ # typed: strong
2
+ # frozen_string_literal: true
3
+
4
+ module Dependabot
5
+ module FileFiltering
6
+ extend T::Sig
7
+
8
+ # Returns true if the given path matches any of the exclude patterns
9
+ sig { params(path: String, exclude_patterns: T.nilable(T::Array[String])).returns(T::Boolean) }
10
+ def self.exclude_path?(path, exclude_patterns) # rubocop:disable Metrics/PerceivedComplexity
11
+ return false if exclude_patterns.nil? || exclude_patterns.empty?
12
+
13
+ # Normalize the path by removing leading slashes and resolving relative paths
14
+ normalized_path = normalize_path(path)
15
+
16
+ exclude_patterns.any? do |pattern|
17
+ normalized_pattern = normalize_path(pattern.chomp("/"))
18
+
19
+ # case 1: exact match
20
+ exclude_exact = normalized_path == pattern || normalized_path == normalized_pattern
21
+
22
+ # case 2: Directory prefix matching: check if path is inside an excluded directory
23
+ exclude_deeper = normalized_path.start_with?("#{pattern}#{File::SEPARATOR}",
24
+ "#{normalized_pattern}#{File::SEPARATOR}")
25
+
26
+ # case 3: Explicit recursive (patterns that end with /**)
27
+ exclude_recursive = false
28
+ if pattern.end_with?("/**")
29
+ base_pattern_str = pattern[0...-3]
30
+ base_pattern = normalize_path(base_pattern_str) if base_pattern_str
31
+ exclude_recursive = base_pattern && (
32
+ normalized_path == base_pattern ||
33
+ normalized_path.start_with?("#{base_pattern}/") ||
34
+ normalized_path.start_with?("#{base_pattern}#{File::SEPARATOR}")
35
+ )
36
+ end
37
+
38
+ # case 4: Glob pattern matching with enhanced flags
39
+ # Use multiple fnmatch attempts with different flag combinations
40
+ fnmatch_flags = [
41
+ File::FNM_EXTGLOB,
42
+ File::FNM_EXTGLOB | File::FNM_PATHNAME,
43
+ File::FNM_EXTGLOB | File::FNM_PATHNAME | File::FNM_DOTMATCH,
44
+ File::FNM_PATHNAME
45
+ ]
46
+ exclude_fnmatch_paths = fnmatch_flags.any? do |flag|
47
+ File.fnmatch?(pattern, normalized_path, flag) || File.fnmatch?(normalized_pattern, normalized_path, flag)
48
+ end
49
+
50
+ result = exclude_exact || exclude_deeper || exclude_recursive || exclude_fnmatch_paths
51
+ result
52
+ end
53
+ end
54
+
55
+ # Normalize a file path for consistent comparison
56
+ # - Removes leading slashes
57
+ # - Resolves relative path components (., ..)
58
+ sig { params(path: String).returns(String) }
59
+ def self.normalize_path(path)
60
+ return path if path.empty?
61
+
62
+ pathname = Pathname.new(path)
63
+ normalized = pathname.cleanpath.to_s
64
+
65
+ # Remove leading slash for relative comparison
66
+ normalized = normalized.sub(%r{^/+}, "")
67
+ normalized
68
+ end
69
+ end
70
+ end
@@ -150,6 +150,10 @@ module Dependabot
150
150
  (old_dep.subdependency_metadata || []) +
151
151
  (new_dep.subdependency_metadata || [])
152
152
  ).uniq
153
+ origin_files = (
154
+ old_dep.origin_files +
155
+ new_dep.origin_files
156
+ ).uniq
153
157
 
154
158
  Dependency.new(
155
159
  name: old_dep.name,
@@ -157,7 +161,8 @@ module Dependabot
157
161
  requirements: requirements,
158
162
  package_manager: old_dep.package_manager,
159
163
  metadata: old_dep.metadata,
160
- subdependency_metadata: subdependency_metadata
164
+ subdependency_metadata: subdependency_metadata,
165
+ origin_files: origin_files
161
166
  )
162
167
  end
163
168
 
@@ -8,6 +8,7 @@ require "dependabot/requirements_update_strategy"
8
8
  require "dependabot/security_advisory"
9
9
  require "dependabot/utils"
10
10
  require "dependabot/package/release_cooldown_options"
11
+ require "dependabot/file_filtering"
11
12
 
12
13
  module Dependabot
13
14
  module UpdateCheckers
@@ -45,6 +46,9 @@ module Dependabot
45
46
  sig { returns(T.nilable(Dependabot::Package::ReleaseCooldownOptions)) }
46
47
  attr_reader :update_cooldown
47
48
 
49
+ sig { returns(T.nilable(T::Array[String])) }
50
+ attr_reader :exclude_paths
51
+
48
52
  sig { returns(T::Hash[Symbol, T.untyped]) }
49
53
  attr_reader :options
50
54
 
@@ -60,6 +64,7 @@ module Dependabot
60
64
  requirements_update_strategy: T.nilable(Dependabot::RequirementsUpdateStrategy),
61
65
  dependency_group: T.nilable(Dependabot::DependencyGroup),
62
66
  update_cooldown: T.nilable(Dependabot::Package::ReleaseCooldownOptions),
67
+ exclude_paths: T.nilable(T::Array[String]),
63
68
  options: T::Hash[Symbol, T.untyped]
64
69
  )
65
70
  .void
@@ -68,7 +73,7 @@ module Dependabot
68
73
  repo_contents_path: nil, ignored_versions: [],
69
74
  raise_on_ignored: false, security_advisories: [],
70
75
  requirements_update_strategy: nil, dependency_group: nil,
71
- update_cooldown: nil, options: {})
76
+ update_cooldown: nil, exclude_paths: [], options: {})
72
77
  @dependency = dependency
73
78
  @dependency_files = dependency_files
74
79
  @repo_contents_path = repo_contents_path
@@ -79,6 +84,7 @@ module Dependabot
79
84
  @security_advisories = security_advisories
80
85
  @dependency_group = dependency_group
81
86
  @update_cooldown = update_cooldown
87
+ @exclude_paths = exclude_paths
82
88
  @options = options
83
89
  end
84
90
 
@@ -106,6 +112,37 @@ module Dependabot
106
112
  end
107
113
  end
108
114
 
115
+ sig { returns(T::Boolean) }
116
+ def excluded? # rubocop:disable Metrics/PerceivedComplexity
117
+ return false unless Dependabot::Experiments.enabled?(:enable_exclude_paths_subdirectory_manifest_files)
118
+
119
+ return false if exclude_paths.nil? || exclude_paths&.empty?
120
+
121
+ origin_files = @dependency.origin_files
122
+ if origin_files.length.positive?
123
+ excluded_files = []
124
+ non_excluded_files = []
125
+
126
+ origin_files.each do |origin_file|
127
+ if Dependabot::FileFiltering.exclude_path?(origin_file, exclude_paths)
128
+ excluded_files << origin_file
129
+ else
130
+ non_excluded_files << origin_file
131
+ end
132
+ end
133
+
134
+ # Only exclude if the dependency appears ONLY in excluded paths
135
+ # If it appears in any non-excluded path, we should process it
136
+ if non_excluded_files.empty? && excluded_files.any?
137
+ Dependabot.logger.info("Excluding dependency #{dependency.name} - only found in excluded paths " \
138
+ "#{excluded_files.join(', ')}")
139
+ return true
140
+ end
141
+ end
142
+
143
+ false
144
+ end
145
+
109
146
  sig { params(requirements_to_unlock: T.nilable(Symbol)).returns(T::Array[Dependabot::Dependency]) }
110
147
  def updated_dependencies(requirements_to_unlock:)
111
148
  return [] unless can_update?(requirements_to_unlock: requirements_to_unlock)
data/lib/dependabot.rb CHANGED
@@ -2,5 +2,5 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Dependabot
5
- VERSION = "0.330.0"
5
+ VERSION = "0.331.0"
6
6
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dependabot-common
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.330.0
4
+ version: 0.331.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dependabot
@@ -550,6 +550,7 @@ files:
550
550
  - lib/dependabot/file_fetchers.rb
551
551
  - lib/dependabot/file_fetchers/README.md
552
552
  - lib/dependabot/file_fetchers/base.rb
553
+ - lib/dependabot/file_filtering.rb
553
554
  - lib/dependabot/file_parsers.rb
554
555
  - lib/dependabot/file_parsers/README.md
555
556
  - lib/dependabot/file_parsers/base.rb
@@ -625,7 +626,7 @@ licenses:
625
626
  - MIT
626
627
  metadata:
627
628
  bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
628
- changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.330.0
629
+ changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.331.0
629
630
  rdoc_options: []
630
631
  require_paths:
631
632
  - lib