dependabot-common 0.236.0 → 0.238.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/lib/dependabot/clients/azure.rb +3 -3
  3. data/lib/dependabot/clients/codecommit.rb +1 -0
  4. data/lib/dependabot/config/file.rb +17 -6
  5. data/lib/dependabot/config/update_config.rb +23 -5
  6. data/lib/dependabot/dependency.rb +137 -27
  7. data/lib/dependabot/dependency_file.rb +84 -14
  8. data/lib/dependabot/dependency_group.rb +29 -5
  9. data/lib/dependabot/errors.rb +335 -13
  10. data/lib/dependabot/file_fetchers/base.rb +227 -93
  11. data/lib/dependabot/file_updaters/base.rb +1 -1
  12. data/lib/dependabot/git_commit_checker.rb +6 -0
  13. data/lib/dependabot/git_metadata_fetcher.rb +58 -20
  14. data/lib/dependabot/git_ref.rb +71 -0
  15. data/lib/dependabot/metadata_finders/base/changelog_finder.rb +13 -6
  16. data/lib/dependabot/pull_request_creator/github.rb +11 -8
  17. data/lib/dependabot/pull_request_creator/message.rb +21 -2
  18. data/lib/dependabot/pull_request_creator/message_builder/link_and_mention_sanitizer.rb +37 -16
  19. data/lib/dependabot/pull_request_creator/message_builder/metadata_presenter.rb +4 -2
  20. data/lib/dependabot/pull_request_creator/message_builder.rb +54 -4
  21. data/lib/dependabot/pull_request_creator/pr_name_prefixer.rb +10 -4
  22. data/lib/dependabot/shared_helpers.rb +117 -33
  23. data/lib/dependabot/simple_instrumentor.rb +22 -3
  24. data/lib/dependabot/source.rb +65 -17
  25. data/lib/dependabot/update_checkers/version_filters.rb +12 -1
  26. data/lib/dependabot/utils.rb +21 -2
  27. data/lib/dependabot/workspace/base.rb +42 -7
  28. data/lib/dependabot/workspace/change_attempt.rb +31 -3
  29. data/lib/dependabot/workspace/git.rb +34 -4
  30. data/lib/dependabot/workspace.rb +16 -2
  31. data/lib/dependabot.rb +1 -1
  32. metadata +38 -9
@@ -1,13 +1,47 @@
1
- # typed: true
1
+ # typed: strong
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "pathname"
5
+ require "sorbet-runtime"
5
6
 
6
7
  module Dependabot
7
8
  class DependencyFile
8
- attr_accessor :name, :content, :directory, :type, :support_file,
9
- :vendored_file, :symlink_target, :content_encoding,
10
- :operation, :mode
9
+ extend T::Sig
10
+
11
+ sig { returns(String) }
12
+ attr_accessor :name
13
+
14
+ sig { returns(T.nilable(String)) }
15
+ attr_accessor :content
16
+
17
+ sig { returns(String) }
18
+ attr_accessor :directory
19
+
20
+ sig { returns(String) }
21
+ attr_accessor :type
22
+
23
+ sig { returns(T::Boolean) }
24
+ attr_accessor :support_file
25
+
26
+ sig { returns(T::Boolean) }
27
+ attr_accessor :vendored_file
28
+
29
+ sig { returns(T.nilable(String)) }
30
+ attr_accessor :symlink_target
31
+
32
+ sig { returns(String) }
33
+ attr_accessor :content_encoding
34
+
35
+ sig { returns(String) }
36
+ attr_accessor :operation
37
+
38
+ sig { returns(T.nilable(String)) }
39
+ attr_accessor :mode
40
+
41
+ # The directory that this file was fetched for. This is useful for multi-directory
42
+ # updates, where a set of files that are related to each other are updated together.
43
+ sig { returns(T.nilable(String)) }
44
+ attr_accessor :job_directory
11
45
 
12
46
  class ContentEncoding
13
47
  UTF_8 = "utf-8"
@@ -25,18 +59,36 @@ module Dependabot
25
59
  SUBMODULE = "160000"
26
60
  end
27
61
 
62
+ sig do
63
+ params(
64
+ name: String,
65
+ content: T.nilable(String),
66
+ directory: String,
67
+ type: String,
68
+ support_file: T::Boolean,
69
+ vendored_file: T::Boolean,
70
+ symlink_target: T.nilable(String),
71
+ content_encoding: String,
72
+ deleted: T::Boolean,
73
+ operation: String,
74
+ mode: T.nilable(String),
75
+ job_directory: T.nilable(String)
76
+ )
77
+ .void
78
+ end
28
79
  def initialize(name:, content:, directory: "/", type: "file",
29
80
  support_file: false, vendored_file: false, symlink_target: nil,
30
81
  content_encoding: ContentEncoding::UTF_8, deleted: false,
31
- operation: Operation::UPDATE, mode: nil)
82
+ operation: Operation::UPDATE, mode: nil, job_directory: nil)
32
83
  @name = name
33
84
  @content = content
34
- @directory = clean_directory(directory)
85
+ @directory = T.let(clean_directory(directory), String)
35
86
  @symlink_target = symlink_target
36
87
  @support_file = support_file
37
88
  @vendored_file = vendored_file
38
89
  @content_encoding = content_encoding
39
90
  @operation = operation
91
+ @job_directory = job_directory
40
92
 
41
93
  # Make deleted override the operation. Deleted is kept when operation
42
94
  # was introduced to keep compatibility with downstream dependants.
@@ -50,7 +102,7 @@ module Dependabot
50
102
  @type = type
51
103
 
52
104
  begin
53
- @mode = File.stat(realpath).mode.to_s(8)
105
+ @mode = T.let(File.stat(realpath).mode.to_s(8), T.nilable(String))
54
106
  rescue StandardError
55
107
  @mode = mode
56
108
  end
@@ -61,6 +113,7 @@ module Dependabot
61
113
  raise "Only symlinked files must specify a target!" if symlink_target
62
114
  end
63
115
 
116
+ sig { returns(T::Hash[String, T.untyped]) }
64
117
  def to_h
65
118
  details = {
66
119
  "name" => name,
@@ -74,66 +127,83 @@ module Dependabot
74
127
  "mode" => mode
75
128
  }
76
129
 
130
+ details["job_directory"] = job_directory if job_directory
77
131
  details["symlink_target"] = symlink_target if symlink_target
78
132
  details
79
133
  end
80
134
 
135
+ sig { returns(String) }
81
136
  def path
82
137
  Pathname.new(File.join(directory, name)).cleanpath.to_path
83
138
  end
84
139
 
140
+ sig { returns(String) }
85
141
  def realpath
86
142
  (symlink_target || path).sub(%r{^/}, "")
87
143
  end
88
144
 
145
+ sig { params(other: BasicObject).returns(T::Boolean) }
89
146
  def ==(other)
90
- return false unless other.instance_of?(self.class)
91
-
92
- my_hash = to_h.reject { |k| k == "support_file" }
93
- their_hash = other.to_h.reject { |k| k == "support_file" }
94
- my_hash == their_hash
147
+ case other
148
+ when DependencyFile
149
+ my_hash = to_h.reject { |k| k == "support_file" }
150
+ their_hash = other.to_h.reject { |k| k == "support_file" }
151
+ my_hash == their_hash
152
+ else
153
+ false
154
+ end
95
155
  end
96
156
 
157
+ sig { returns(Integer) }
97
158
  def hash
98
159
  to_h.hash
99
160
  end
100
161
 
162
+ sig { params(other: BasicObject).returns(T::Boolean) }
101
163
  def eql?(other)
102
164
  self == other
103
165
  end
104
166
 
167
+ sig { returns(T::Boolean) }
105
168
  def support_file?
106
169
  @support_file
107
170
  end
108
171
 
172
+ sig { returns(T::Boolean) }
109
173
  def vendored_file?
110
174
  @vendored_file
111
175
  end
112
176
 
177
+ sig { returns(T::Boolean) }
113
178
  def deleted
114
179
  @operation == Operation::DELETE
115
180
  end
116
181
 
182
+ sig { params(deleted: T::Boolean).void }
117
183
  def deleted=(deleted)
118
184
  @operation = deleted ? Operation::DELETE : Operation::UPDATE
119
185
  end
120
186
 
187
+ sig { returns(T::Boolean) }
121
188
  def deleted?
122
189
  deleted
123
190
  end
124
191
 
192
+ sig { returns(T::Boolean) }
125
193
  def binary?
126
194
  content_encoding == ContentEncoding::BASE64
127
195
  end
128
196
 
197
+ sig { returns(String) }
129
198
  def decoded_content
130
- return Base64.decode64(content) if binary?
199
+ return Base64.decode64(T.must(content)) if binary?
131
200
 
132
- content
201
+ T.must(content)
133
202
  end
134
203
 
135
204
  private
136
205
 
206
+ sig { params(directory: String).returns(String) }
137
207
  def clean_directory(directory)
138
208
  # Directory should always start with a `/`
139
209
  directory.sub(%r{^/*}, "/")
@@ -1,23 +1,41 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "dependabot/experiments"
5
5
  require "dependabot/config/ignore_condition"
6
6
  require "dependabot/logger"
7
7
 
8
+ require "sorbet-runtime"
8
9
  require "wildcard_matcher"
9
10
  require "yaml"
10
11
 
11
12
  module Dependabot
12
13
  class DependencyGroup
13
- attr_reader :name, :rules, :dependencies
14
+ extend T::Sig
14
15
 
16
+ sig { returns(String) }
17
+ attr_reader :name
18
+
19
+ sig { returns(T::Hash[String, T.any(String, T::Array[String])]) }
20
+ attr_reader :rules
21
+
22
+ sig { returns(T::Array[Dependabot::Dependency]) }
23
+ attr_reader :dependencies
24
+
25
+ sig do
26
+ params(
27
+ name: String,
28
+ rules: T::Hash[String, T.untyped]
29
+ )
30
+ .void
31
+ end
15
32
  def initialize(name:, rules:)
16
33
  @name = name
17
34
  @rules = rules
18
- @dependencies = []
35
+ @dependencies = T.let([], T::Array[Dependabot::Dependency])
19
36
  end
20
37
 
38
+ sig { params(dependency: Dependabot::Dependency).returns(T::Boolean) }
21
39
  def contains?(dependency)
22
40
  return true if @dependencies.include?(dependency)
23
41
  return false if matches_excluded_pattern?(dependency.name)
@@ -25,11 +43,13 @@ module Dependabot
25
43
  matches_pattern?(dependency.name) && matches_dependency_type?(dependency)
26
44
  end
27
45
 
46
+ sig { returns(T::Hash[String, String]) }
28
47
  def to_h
29
48
  { "name" => name }
30
49
  end
31
50
 
32
51
  # Provides a debug utility to view the group as it appears in the config file.
52
+ sig { returns(String) }
33
53
  def to_config_yaml
34
54
  {
35
55
  "groups" => { name => rules }
@@ -38,18 +58,21 @@ module Dependabot
38
58
 
39
59
  private
40
60
 
61
+ sig { params(dependency_name: String).returns(T::Boolean) }
41
62
  def matches_pattern?(dependency_name)
42
63
  return true unless rules.key?("patterns") # If no patterns are defined, we pass this check by default
43
64
 
44
- rules["patterns"].any? { |rule| WildcardMatcher.match?(rule, dependency_name) }
65
+ T.unsafe(rules["patterns"]).any? { |rule| WildcardMatcher.match?(rule, dependency_name) }
45
66
  end
46
67
 
68
+ sig { params(dependency_name: String).returns(T::Boolean) }
47
69
  def matches_excluded_pattern?(dependency_name)
48
70
  return false unless rules.key?("exclude-patterns") # If there are no exclusions, fail by default
49
71
 
50
- rules["exclude-patterns"].any? { |rule| WildcardMatcher.match?(rule, dependency_name) }
72
+ T.unsafe(rules["exclude-patterns"]).any? { |rule| WildcardMatcher.match?(rule, dependency_name) }
51
73
  end
52
74
 
75
+ sig { params(dependency: Dependabot::Dependency).returns(T::Boolean) }
53
76
  def matches_dependency_type?(dependency)
54
77
  return true unless rules.key?("dependency-type") # If no dependency-type is set, match by default
55
78
 
@@ -60,6 +83,7 @@ module Dependabot
60
83
  end
61
84
  end
62
85
 
86
+ sig { returns(T::Boolean) }
63
87
  def experimental_rules_enabled?
64
88
  Dependabot::Experiments.enabled?(:grouped_updates_experimental_rules)
65
89
  end