dependabot-common 0.319.0 → 0.320.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: dadae528496bde0e27a338af42b48f57263395c51413da85de8cee747f291588
4
- data.tar.gz: c317409e7dade84ceb6dcb283bfa849c1cff8e3ed017e73bdbb163044592bffc
3
+ metadata.gz: b74b681bdbccdcff5aa8da67d0b700ea41b486357e739ed66c8649bc7232c048
4
+ data.tar.gz: 836bbac6d11db5f90edfe90a233e953a9e40c8ae1aa21c8bb56142dcd84911bb
5
5
  SHA512:
6
- metadata.gz: 91096591c27749bac950a03d207c240013b201f99cfbc15d2d370c091cb5c37c39e14eca34d10d9aa981d2e476ebe29c11e07e72fe780883f504912e0591ef12
7
- data.tar.gz: cf8f0144d3049cee124ec7863637c5e1ec56ee36c775969a86aa0a45a931263734548e5046e80c09eead0104da8aa1b1972fe7b1e1b218e4acd91dd168be7e5f
6
+ metadata.gz: 30dbd2a618772b5b629f11d6a6ef9050734be9c6934d9691567e12889f3446be564581184a1f56dd5f1961fccaaf7ddb72fc86336cd676ab92d373750d959cc9
7
+ data.tar.gz: 434e9960903d572af76a6a1e84d61c194000c313040e5fa61631683eb938557aa668811a1f629de7afe81a39261225abdbe63fcaeb927eea17afdb6f1059c410
@@ -12,12 +12,17 @@ module Dependabot
12
12
 
13
13
  module TIMEOUTS
14
14
  NO_TIME_OUT = -1 # No timeout
15
+ GRARECFULLY_STOP = 5 # 5 seconds for graceful termination
15
16
  LOCAL = 30 # 30 seconds
16
17
  NETWORK = 120 # 2 minutes
17
18
  LONG_RUNNING = 300 # 5 minutes
18
19
  DEFAULT = 900 # 15 minutes
19
20
  end
20
21
 
22
+ OutputObserver = T.type_alias do
23
+ T.nilable(T.proc.params(data: String).returns(T::Hash[Symbol, T.untyped]))
24
+ end
25
+
21
26
  class ProcessStatus
22
27
  extend T::Sig
23
28
 
@@ -70,14 +75,16 @@ module Dependabot
70
75
  env_cmd: T::Array[T.any(T::Hash[String, String], String)],
71
76
  stdin_data: T.nilable(String),
72
77
  stderr_to_stdout: T::Boolean,
73
- timeout: Integer
78
+ timeout: Integer,
79
+ output_observer: OutputObserver
74
80
  ).returns([T.nilable(String), T.nilable(String), T.nilable(ProcessStatus), Float])
75
81
  end
76
82
  def self.capture3_with_timeout(
77
83
  env_cmd,
78
84
  stdin_data: nil,
79
85
  stderr_to_stdout: false,
80
- timeout: TIMEOUTS::DEFAULT
86
+ timeout: TIMEOUTS::DEFAULT,
87
+ output_observer: nil
81
88
  )
82
89
 
83
90
  stdout = T.let("", String)
@@ -142,12 +149,24 @@ module Dependabot
142
149
  stderr += data unless stderr_to_stdout
143
150
  stdout += data if stderr_to_stdout
144
151
  end
145
- rescue EOFError
146
- # Remove the stream when EOF is reached
147
- ios.delete(io)
148
- rescue IO::WaitReadable
149
- # Continue when IO is not ready yet
150
- next
152
+
153
+ # Observe the output if an observer is provided.
154
+ # This allows for custom handling of process output, including early termination.
155
+ observation = output_observer&.call(data)
156
+
157
+ if observation&.dig(:gracefully_stop)
158
+ message = observation[:reason] || "Terminated by output_observer"
159
+ # If the observer indicates a graceful stop, terminate the process
160
+ # by adjusting the remaining timeout 5 seconds
161
+ timeout = [timeout, ((Time.now - last_output_time) + 5).to_i].min
162
+ Dependabot.logger.warn("Terminating process due to observer signal: #{message}")
163
+ end
164
+ rescue EOFError
165
+ # Remove the stream when EOF is reached
166
+ ios.delete(io)
167
+ rescue IO::WaitReadable
168
+ # Continue when IO is not ready yet
169
+ next
151
170
  end
152
171
  end
153
172
 
@@ -78,9 +78,11 @@ module Dependabot
78
78
  "nuget" => "nuget",
79
79
  "pip" => "pip",
80
80
  "pub" => "pub",
81
+ "rust-toolchain" => "rust_toolchain",
81
82
  "swift" => "swift",
82
83
  "terraform" => "terraform",
83
- "uv" => "uv"
84
+ "uv" => "uv",
85
+ "vcpkg" => "vcpkg"
84
86
  }.freeze, T::Hash[String, String])
85
87
 
86
88
  sig { params(cfg: T.nilable(T::Hash[Symbol, T.untyped])).returns(T::Array[IgnoreCondition]) }
@@ -88,8 +88,10 @@ module Dependabot
88
88
  T.must(dependencies.first).package_manager
89
89
  end
90
90
 
91
- sig { returns(String) }
91
+ sig { returns(T.nilable(String)) }
92
92
  def directory
93
+ return if files.empty?
94
+
93
95
  T.must(files.first).directory.tr(" ", "-")
94
96
  end
95
97
  end
@@ -1,4 +1,4 @@
1
- # typed: strong
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "commonmarker"
@@ -30,12 +30,20 @@ module Dependabot
30
30
  MARKDOWN_REGEX = /\[(.+?)\]\(([^)]+)\)|\[(.+?)\]|\A#+\s+([^\s].*)/
31
31
 
32
32
  COMMONMARKER_OPTIONS = T.let(
33
- %i(GITHUB_PRE_LANG FULL_INFO_STRING).freeze,
34
- T::Array[Symbol]
33
+ { escaped_char_spans: false, github_pre_lang: true, full_info_string: true, width: 120 }.freeze,
34
+ T::Hash[Symbol, T.any(T::Boolean, Integer)]
35
35
  )
36
36
  COMMONMARKER_EXTENSIONS = T.let(
37
- %i(table tasklist strikethrough autolink tagfilter).freeze,
38
- T::Array[Symbol]
37
+ {
38
+ autolink: true,
39
+ header_ids: nil,
40
+ shortcodes: false,
41
+ strikethrough: true,
42
+ table: true,
43
+ tagfilter: true,
44
+ tasklist: true
45
+ }.freeze,
46
+ T::Hash[Symbol, T.nilable(T::Boolean)]
39
47
  )
40
48
 
41
49
  sig { returns(T.nilable(String)) }
@@ -48,30 +56,37 @@ module Dependabot
48
56
 
49
57
  sig { params(text: String, unsafe: T::Boolean, format_html: T::Boolean).returns(String) }
50
58
  def sanitize_links_and_mentions(text:, unsafe: false, format_html: true)
51
- doc = CommonMarker.render_doc(
52
- text, :LIBERAL_HTML_TAG, COMMONMARKER_EXTENSIONS
53
- )
59
+ doc = Commonmarker.parse(text, options: { extension: COMMONMARKER_EXTENSIONS, render: COMMONMARKER_OPTIONS })
54
60
 
55
61
  sanitize_team_mentions(doc)
56
62
  sanitize_mentions(doc)
57
63
  sanitize_links(doc)
58
64
  sanitize_nwo_text(doc)
59
65
 
60
- render_options = if text.match?(MARKDOWN_REGEX)
61
- COMMONMARKER_OPTIONS
62
- else
63
- COMMONMARKER_OPTIONS + [:HARDBREAKS]
64
- end
65
-
66
- mode = unsafe ? :UNSAFE : :DEFAULT
67
- return doc.to_commonmark([mode] + render_options) unless format_html
66
+ render_options = COMMONMARKER_OPTIONS.dup
67
+ render_options[:hardbreaks] = false if text.match?(MARKDOWN_REGEX)
68
+ render_options[:unsafe] = true if unsafe
69
+ unless format_html
70
+ return doc.to_commonmark(
71
+ options: {
72
+ extension: COMMONMARKER_EXTENSIONS,
73
+ render: render_options
74
+ }
75
+ )
76
+ end
68
77
 
69
- doc.to_html(([mode] + render_options), COMMONMARKER_EXTENSIONS)
78
+ doc.to_html(
79
+ options: {
80
+ extension: COMMONMARKER_EXTENSIONS,
81
+ render: render_options
82
+ },
83
+ plugins: { syntax_highlighter: nil }
84
+ )
70
85
  end
71
86
 
72
87
  private
73
88
 
74
- sig { params(doc: CommonMarker::Node).void }
89
+ sig { params(doc: Commonmarker::Node).void }
75
90
  def sanitize_mentions(doc)
76
91
  doc.walk do |node|
77
92
  if node.type == :text &&
@@ -96,7 +111,7 @@ module Dependabot
96
111
  # This is because there are ecosystems that have packages that follow the same pattern
97
112
  # (e.g. @angular/angular-cli), and we don't want to create an invalid link, since
98
113
  # team mentions link to `https://github.com/org/:organization_name/teams/:team_name`.
99
- sig { params(doc: CommonMarker::Node).void }
114
+ sig { params(doc: Commonmarker::Node).void }
100
115
  def sanitize_team_mentions(doc)
101
116
  doc.walk do |node|
102
117
  if node.type == :text &&
@@ -112,7 +127,7 @@ module Dependabot
112
127
  end
113
128
  end
114
129
 
115
- sig { params(doc: CommonMarker::Node).void }
130
+ sig { params(doc: Commonmarker::Node).void }
116
131
  def sanitize_links(doc)
117
132
  doc.walk do |node|
118
133
  if node.type == :link && node.url.match?(GITHUB_REF_REGEX)
@@ -122,7 +137,7 @@ module Dependabot
122
137
  next
123
138
  end
124
139
 
125
- last_match = T.must(subnode.string_content.match(GITHUB_REF_REGEX))
140
+ last_match = subnode.string_content.match(GITHUB_REF_REGEX)
126
141
  number = last_match.named_captures.fetch("number")
127
142
  repo = last_match.named_captures.fetch("repo")
128
143
  subnode.string_content = "#{repo}##{number}"
@@ -136,7 +151,7 @@ module Dependabot
136
151
  end
137
152
  end
138
153
 
139
- sig { params(doc: CommonMarker::Node).void }
154
+ sig { params(doc: Commonmarker::Node).void }
140
155
  def sanitize_nwo_text(doc)
141
156
  doc.walk do |node|
142
157
  if node.type == :text &&
@@ -147,9 +162,9 @@ module Dependabot
147
162
  end
148
163
  end
149
164
 
150
- sig { params(node: CommonMarker::Node).void }
165
+ sig { params(node: Commonmarker::Node).void }
151
166
  def replace_nwo_node(node)
152
- match = T.must(node.string_content.match(GITHUB_NWO_REGEX))
167
+ match = node.string_content.match(GITHUB_NWO_REGEX)
153
168
  repo = match.named_captures.fetch("repo")
154
169
  number = match.named_captures.fetch("number")
155
170
  new_node = build_nwo_text_node("#{repo}##{number}")
@@ -166,9 +181,9 @@ module Dependabot
166
181
  )
167
182
  end
168
183
 
169
- sig { params(text: String).returns(T::Array[CommonMarker::Node]) }
184
+ sig { params(text: String).returns(T::Array[Commonmarker::Node]) }
170
185
  def build_mention_nodes(text)
171
- nodes = T.let([], T::Array[CommonMarker::Node])
186
+ nodes = T.let([], T::Array[Commonmarker::Node])
172
187
  scan = StringScanner.new(text)
173
188
 
174
189
  until scan.eos?
@@ -176,7 +191,7 @@ module Dependabot
176
191
  scan.scan_until(EOS_REGEX)
177
192
  line_match = T.must(line).match(MENTION_REGEX)
178
193
  mention = line_match&.to_s
179
- text_node = CommonMarker::Node.new(:text)
194
+ text_node = Commonmarker::Node.new(:text)
180
195
 
181
196
  if mention && !mention.end_with?("/")
182
197
  text_node.string_content = line_match.pre_match
@@ -193,9 +208,9 @@ module Dependabot
193
208
  nodes
194
209
  end
195
210
 
196
- sig { params(text: String).returns(T::Array[CommonMarker::Node]) }
211
+ sig { params(text: String).returns(T::Array[Commonmarker::Node]) }
197
212
  def build_team_mention_nodes(text)
198
- nodes = T.let([], T::Array[CommonMarker::Node])
213
+ nodes = T.let([], T::Array[Commonmarker::Node])
199
214
 
200
215
  scan = StringScanner.new(text)
201
216
  until scan.eos?
@@ -203,7 +218,7 @@ module Dependabot
203
218
  scan.scan_until(EOS_REGEX)
204
219
  line_match = T.must(line).match(TEAM_MENTION_REGEX)
205
220
  mention = line_match&.to_s
206
- text_node = CommonMarker::Node.new(:text)
221
+ text_node = Commonmarker::Node.new(:text)
207
222
 
208
223
  if mention
209
224
  text_node.string_content = line_match.pre_match
@@ -218,25 +233,24 @@ module Dependabot
218
233
  nodes
219
234
  end
220
235
 
221
- sig { params(text: String).returns(T::Array[CommonMarker::Node]) }
236
+ sig { params(text: String).returns(T::Array[Commonmarker::Node]) }
222
237
  def build_mention_link_text_nodes(text)
223
- code_node = CommonMarker::Node.new(:code)
238
+ code_node = Commonmarker::Node.new(:code)
224
239
  code_node.string_content = insert_zero_width_space_in_mention(text)
225
240
  [code_node]
226
241
  end
227
242
 
228
- sig { params(text: String).returns(CommonMarker::Node) }
243
+ sig { params(text: String).returns(Commonmarker::Node) }
229
244
  def build_nwo_text_node(text)
230
- code_node = CommonMarker::Node.new(:code)
245
+ code_node = Commonmarker::Node.new(:code)
231
246
  code_node.string_content = text
232
247
  code_node
233
248
  end
234
249
 
235
- sig { params(url: String, text: String).returns(CommonMarker::Node) }
250
+ sig { params(url: String, text: String).returns(Commonmarker::Node) }
236
251
  def create_link_node(url, text)
237
- link_node = CommonMarker::Node.new(:link)
238
- code_node = CommonMarker::Node.new(:code)
239
- link_node.url = url
252
+ link_node = Commonmarker::Node.new(:link, url: url)
253
+ code_node = Commonmarker::Node.new(:code)
240
254
  code_node.string_content = insert_zero_width_space_in_mention(text)
241
255
  link_node.append_child(code_node)
242
256
  link_node
@@ -251,9 +265,9 @@ module Dependabot
251
265
  mention.sub("@", "@\u200B").encode("utf-8")
252
266
  end
253
267
 
254
- sig { params(node: CommonMarker::Node).returns(T::Boolean) }
268
+ sig { params(node: Commonmarker::Node).returns(T::Boolean) }
255
269
  def parent_node_link?(node)
256
- node.type == :link || (!node.parent.nil? && parent_node_link?(T.must(node.parent)))
270
+ node.type == :link || (!node.parent.nil? && parent_node_link?(node.parent))
257
271
  end
258
272
  end
259
273
  end
@@ -439,7 +439,8 @@ module Dependabot
439
439
  env: T.nilable(T::Hash[String, String]),
440
440
  fingerprint: T.nilable(String),
441
441
  stderr_to_stdout: T::Boolean,
442
- timeout: Integer
442
+ timeout: Integer,
443
+ output_observer: CommandHelpers::OutputObserver
443
444
  ).returns(String)
444
445
  end
445
446
  def self.run_shell_command(command,
@@ -448,7 +449,8 @@ module Dependabot
448
449
  env: {},
449
450
  fingerprint: nil,
450
451
  stderr_to_stdout: true,
451
- timeout: CommandHelpers::TIMEOUTS::DEFAULT)
452
+ timeout: CommandHelpers::TIMEOUTS::DEFAULT,
453
+ output_observer: nil)
452
454
  start = Time.now
453
455
  cmd = allow_unsafe_shell_command ? command : escape_command(command)
454
456
 
@@ -459,10 +461,15 @@ module Dependabot
459
461
 
460
462
  env_cmd = [env || {}, cmd, opts].compact
461
463
  if Experiments.enabled?(:enable_shared_helpers_command_timeout)
462
- stdout, stderr, process = CommandHelpers.capture3_with_timeout(
463
- env_cmd,
464
+ kwargs = {
464
465
  stderr_to_stdout: stderr_to_stdout,
465
466
  timeout: timeout
467
+ }
468
+ kwargs[:output_observer] = output_observer if output_observer
469
+
470
+ stdout, stderr, process = CommandHelpers.capture3_with_timeout(
471
+ env_cmd,
472
+ **kwargs
466
473
  )
467
474
  elsif stderr_to_stdout
468
475
  stdout, process = Open3.capture2e(env || {}, cmd, opts)
@@ -194,7 +194,13 @@ module Dependabot
194
194
 
195
195
  sig { returns(String) }
196
196
  def organization
197
- T.must(repo.split("/").first)
197
+ case provider
198
+ when "azure"
199
+ parts = repo.split("/_git/")
200
+ T.must(T.must(parts.first).split("/").last(2).first)
201
+ else
202
+ T.must(repo.split("/").first)
203
+ end
198
204
  end
199
205
 
200
206
  sig { returns(String) }
@@ -202,7 +208,7 @@ module Dependabot
202
208
  raise "Project is an Azure DevOps concept only" unless provider == "azure"
203
209
 
204
210
  parts = repo.split("/_git/")
205
- return T.must(T.must(parts.first).split("/").last) if parts.first&.split("/")&.count == 2
211
+ return T.must(T.must(parts.first).split("/").last) if parts.first&.split("/")&.count&.>=(2)
206
212
 
207
213
  T.must(parts.last)
208
214
  end
data/lib/dependabot.rb CHANGED
@@ -2,5 +2,5 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Dependabot
5
- VERSION = "0.319.0"
5
+ VERSION = "0.320.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.319.0
4
+ version: 0.320.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dependabot
@@ -63,14 +63,14 @@ dependencies:
63
63
  requirements:
64
64
  - - "~>"
65
65
  - !ruby/object:Gem::Version
66
- version: '0.23'
66
+ version: '2.3'
67
67
  type: :runtime
68
68
  prerelease: false
69
69
  version_requirements: !ruby/object:Gem::Requirement
70
70
  requirements:
71
71
  - - "~>"
72
72
  - !ruby/object:Gem::Version
73
- version: '0.23'
73
+ version: '2.3'
74
74
  - !ruby/object:Gem::Dependency
75
75
  name: docker_registry2
76
76
  requirement: !ruby/object:Gem::Requirement
@@ -625,7 +625,7 @@ licenses:
625
625
  - MIT
626
626
  metadata:
627
627
  bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
628
- changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.319.0
628
+ changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.320.0
629
629
  rdoc_options: []
630
630
  require_paths:
631
631
  - lib