dependabot-go_modules 0.398.0 → 0.399.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: 4c24f81fa270b8d7bf45160f66c0f97ebbf87c28847793b3043b83d5cf00ee9c
4
- data.tar.gz: 4f1403eccfc751c1f0948796a484e3d63cf7e7ded7c5c947f0776066140983dc
3
+ metadata.gz: c542fdbc9273e2bc8287b1763076eabc222f1c53318a298584b6991304edd18f
4
+ data.tar.gz: 06066f37ca5940ee83ee6073e7a8215201577e9da520163eda7b6bf30a6f6a25
5
5
  SHA512:
6
- metadata.gz: a1396231e48e22303ee26a75ddb7d69fcf481691036e0b04c1dc59b069f648fc592c2d39b401055069ea56fa970bd9915670ce5a1df2ae44acd8e8558e10eade
7
- data.tar.gz: 54d6fbb363c517792c0ce1d8bcd5119147d7429fbc29a09c845162bd734c3bfa90b40d5a8679ead205d9e0bc8143320c8d82d401ca8facd43c44ea4698d01afa
6
+ metadata.gz: cfd2c42fe78c12e7f7129afb4c5c066e01195c780fca8a2584766588abaae8a14f1e992506485f4ecc387d54a5dace6b47383f9fd0ebf0cc3f36cd1299f7c62f
7
+ data.tar.gz: 8c16abde1c7c011714160a0f6bb99540356704b7d79ff50321d92d8f280a3fc890ec951342de4748e8609b3638bd384b4c647ddc3777f32b0b0addde94c2f766
@@ -1,4 +1,4 @@
1
- # typed: strict
1
+ # typed: strong
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "sorbet-runtime"
@@ -7,6 +7,7 @@ require "open3"
7
7
  require "dependabot/dependency"
8
8
  require "dependabot/file_parsers/base/dependency_set"
9
9
  require "dependabot/go_modules/go_work_parser"
10
+ require "dependabot/go_modules/go_mod_manifest"
10
11
  require "dependabot/go_modules/path_converter"
11
12
  require "dependabot/go_modules/replace_stubber"
12
13
  require "dependabot/errors"
@@ -291,49 +292,46 @@ module Dependabot
291
292
  stdout, stderr, status = Open3.capture3(command)
292
293
  handle_parser_error(path, stderr, file_path: mod_file.path) unless status.success?
293
294
 
294
- parsed = JSON.parse(stdout)
295
- packages = parsed["Require"] || []
295
+ parsed = GoModManifest.from_json(stdout, file_path: mod_file.path)
296
296
 
297
- packages.filter_map do |hsh|
298
- next if skip_dependency_in_manifest?(hsh, parsed)
297
+ parsed.requirements.filter_map do |entry|
298
+ next if skip_dependency_in_manifest?(entry, parsed)
299
299
 
300
- source = { type: "default", source: hsh["Path"] }
301
- version = hsh["Version"]&.sub(/^v?/, "")
300
+ source = { type: "default", source: entry.path }
301
+ version = entry.version&.sub(/^v?/, "")
302
302
 
303
303
  reqs = [{
304
- requirement: hsh["Version"],
304
+ requirement: entry.version,
305
305
  file: mod_file.name,
306
306
  source: source,
307
307
  groups: []
308
308
  }]
309
309
 
310
310
  Dependency.new(
311
- name: hsh["Path"],
311
+ name: entry.path,
312
312
  version: version,
313
- requirements: hsh["Indirect"] ? [] : reqs,
313
+ requirements: entry.indirect ? [] : reqs,
314
314
  package_manager: "go_modules"
315
315
  )
316
316
  end
317
317
  end
318
318
  end
319
319
 
320
- sig { params(dep: T::Hash[String, T.untyped], mod_manifest: T::Hash[String, T.untyped]).returns(T::Boolean) }
320
+ sig { params(dep: GoModManifest::RequirementEntry, mod_manifest: GoModManifest).returns(T::Boolean) }
321
321
  def skip_dependency_in_manifest?(dep, mod_manifest)
322
322
  return true if dependency_is_replaced_in?(dep, mod_manifest)
323
323
 
324
- path_uri = URI.parse("https://#{dep['Path']}")
324
+ path_uri = URI.parse("https://#{dep.path}")
325
325
  !path_uri.host&.include?(".")
326
326
  rescue URI::InvalidURIError
327
327
  false
328
328
  end
329
329
 
330
- sig { params(details: T::Hash[String, T.untyped], mod_manifest: T::Hash[String, T.untyped]).returns(T::Boolean) }
330
+ sig { params(details: GoModManifest::RequirementEntry, mod_manifest: GoModManifest).returns(T::Boolean) }
331
331
  def dependency_is_replaced_in?(details, mod_manifest)
332
- return false unless mod_manifest["Replace"]
333
-
334
- mod_manifest["Replace"].any? do |replace|
335
- replace["Old"]["Path"] == details["Path"] &&
336
- (!replace["Old"]["Version"] || replace["Old"]["Version"] == details["Version"])
332
+ mod_manifest.replacements.any? do |replacement|
333
+ replacement.old.path == details.path &&
334
+ (replacement.old.version.nil? || replacement.old.version == details.version)
337
335
  end
338
336
  end
339
337
 
@@ -342,32 +340,35 @@ module Dependabot
342
340
  raise "No go.mod or go.work!" unless go_mod || go_work
343
341
  end
344
342
 
345
- sig { params(details: T::Hash[String, T.untyped]).returns(Dependabot::Dependency) }
343
+ sig { params(details: GoModManifest::RequirementEntry).returns(Dependabot::Dependency) }
346
344
  def dependency_from_details(details)
347
- source = { type: "default", source: details["Path"] }
348
- version = details["Version"]&.sub(/^v?/, "")
345
+ source = { type: "default", source: details.path }
346
+ version = details.version&.sub(/^v?/, "")
349
347
 
350
348
  reqs = [{
351
- requirement: details["Version"],
349
+ requirement: details.version,
352
350
  file: go_mod&.name,
353
351
  source: source,
354
352
  groups: []
355
353
  }]
356
354
 
357
355
  Dependency.new(
358
- name: details["Path"],
356
+ name: details.path,
359
357
  version: version,
360
- requirements: details["Indirect"] ? [] : reqs,
358
+ requirements: details.indirect ? [] : reqs,
361
359
  package_manager: "go_modules"
362
360
  )
363
361
  end
364
362
 
365
- sig { returns(T::Array[T::Hash[String, T.untyped]]) }
363
+ sig { returns(T::Array[GoModManifest::RequirementEntry]) }
366
364
  def required_packages
367
365
  @required_packages ||=
368
366
  T.let(
369
- JSON.parse(run_in_parsed_context("go mod edit -json"))["Require"] || [],
370
- T.nilable(T::Array[T::Hash[String, T.untyped]])
367
+ GoModManifest.from_json(
368
+ run_in_parsed_context("go mod edit -json"),
369
+ file_path: T.must(go_mod).path
370
+ ).requirements,
371
+ T.nilable(T::Array[GoModManifest::RequirementEntry])
371
372
  )
372
373
  end
373
374
 
@@ -384,7 +385,7 @@ module Dependabot
384
385
  )
385
386
  end
386
387
 
387
- sig { returns(T::Hash[String, T.untyped]) }
388
+ sig { returns(GoModManifest) }
388
389
  def manifest
389
390
  @manifest ||=
390
391
  T.let(
@@ -398,9 +399,9 @@ module Dependabot
398
399
  stdout, stderr, status = Open3.capture3(command)
399
400
  handle_parser_error(path, stderr) unless status.success?
400
401
 
401
- JSON.parse(stdout)
402
+ GoModManifest.from_json(stdout, file_path: T.must(go_mod).path)
402
403
  end,
403
- T.nilable(T::Hash[String, T.untyped])
404
+ T.nilable(GoModManifest)
404
405
  )
405
406
  end
406
407
 
@@ -418,18 +419,18 @@ module Dependabot
418
419
  raise Dependabot::DependencyFileNotParseable.new(resolved_path, msg)
419
420
  end
420
421
 
421
- sig { params(dep: T::Hash[String, T.untyped]).returns(T::Boolean) }
422
+ sig { params(dep: GoModManifest::RequirementEntry).returns(T::Boolean) }
422
423
  def skip_dependency?(dep)
423
424
  # Updating replaced dependencies is not supported
424
425
  return true if dependency_is_replaced(dep)
425
426
 
426
- path_uri = URI.parse("https://#{dep['Path']}")
427
+ path_uri = URI.parse("https://#{dep.path}")
427
428
  !path_uri.host&.include?(".")
428
429
  rescue URI::InvalidURIError
429
430
  false
430
431
  end
431
432
 
432
- sig { params(details: T::Hash[String, T.untyped]).returns(T::Boolean) }
433
+ sig { params(details: GoModManifest::RequirementEntry).returns(T::Boolean) }
433
434
  def dependency_is_replaced(details)
434
435
  # Mark dependency as replaced if the requested dependency has a
435
436
  # "replace" directive and that either has the same version, or no
@@ -437,15 +438,7 @@ module Dependabot
437
438
  # prevents that we change dependency versions without any impact since
438
439
  # the actual version that is being imported is defined by the replace
439
440
  # directive.
440
- if manifest["Replace"]
441
- dep_replace = manifest["Replace"].find do |replace|
442
- replace["Old"]["Path"] == details["Path"] &&
443
- (!replace["Old"]["Version"] || replace["Old"]["Version"] == details["Version"])
444
- end
445
-
446
- return true if dep_replace
447
- end
448
- false
441
+ dependency_is_replaced_in?(details, manifest)
449
442
  end
450
443
  end
451
444
  end
@@ -8,6 +8,7 @@ require "dependabot/errors"
8
8
  require "dependabot/logger"
9
9
  require "dependabot/go_modules/file_updater"
10
10
  require "dependabot/go_modules/go_work_parser"
11
+ require "dependabot/go_modules/go_mod_manifest"
11
12
  require "dependabot/go_modules/replace_stubber"
12
13
  require "dependabot/go_modules/resolvability_errors"
13
14
 
@@ -386,13 +387,13 @@ module Dependabot
386
387
  FileUtils.rm_f(T.must(tmp_go_file))
387
388
  end
388
389
 
389
- sig { returns(T::Hash[String, T.untyped]) }
390
+ sig { returns(GoModManifest) }
390
391
  def parse_manifest
391
392
  command = "go mod edit -json"
392
393
  stdout, stderr, status = Open3.capture3(command)
393
394
  handle_subprocess_error(stderr) unless status.success?
394
395
 
395
- JSON.parse(stdout) || {}
396
+ GoModManifest.from_json(stdout, file_path: File.join(directory, "go.mod"))
396
397
  end
397
398
 
398
399
  sig do
@@ -426,7 +427,7 @@ module Dependabot
426
427
  # the layout of the filesystem with a structure we can reproduce (i.e.
427
428
  # no paths such as ../../../foo), run the Go tooling, then reverse the
428
429
  # process afterwards.
429
- sig { params(manifest: T::Hash[String, T.untyped]).returns(T::Hash[String, String]) }
430
+ sig { params(manifest: GoModManifest).returns(T::Hash[String, String]) }
430
431
  def replace_directive_substitutions(manifest)
431
432
  @replace_directive_substitutions ||=
432
433
  T.let(
@@ -0,0 +1,165 @@
1
+ # typed: strong
2
+ # frozen_string_literal: true
3
+
4
+ require "json"
5
+ require "sorbet-runtime"
6
+ require "dependabot/shared_helpers"
7
+
8
+ module Dependabot
9
+ module GoModules
10
+ class GoModManifest < T::ImmutableStruct
11
+ extend T::Sig
12
+
13
+ class InvalidOutput < SharedHelpers::HelperSubprocessFailed; end
14
+
15
+ class RequirementEntry < T::ImmutableStruct
16
+ const :path, String
17
+ const :version, T.nilable(String)
18
+ const :indirect, T::Boolean
19
+ end
20
+
21
+ class ModuleReference < T::ImmutableStruct
22
+ const :path, String
23
+ const :version, T.nilable(String)
24
+ end
25
+
26
+ class Replacement < T::ImmutableStruct
27
+ const :old, ModuleReference
28
+ const :new, ModuleReference
29
+ end
30
+
31
+ class Exclusion < T::ImmutableStruct
32
+ const :path, String
33
+ const :version, String
34
+ end
35
+
36
+ ObjectHash = T.type_alias { T::Hash[String, Object] }
37
+
38
+ const :requirements, T::Array[RequirementEntry]
39
+ const :replacements, T::Array[Replacement]
40
+ const :exclusions, T::Array[Exclusion]
41
+
42
+ sig { params(content: String, file_path: String).returns(GoModManifest) }
43
+ def self.from_json(content, file_path:)
44
+ context = "go mod edit -json for #{file_path}"
45
+ fields = object(T.cast(JSON.parse(content), Object), "#{context}: result")
46
+ new(
47
+ requirements: parse_requirements(fields["Require"], "#{context}: Require"),
48
+ replacements: parse_replacements(fields["Replace"], "#{context}: Replace"),
49
+ exclusions: parse_exclusions(fields["Exclude"], "#{context}: Exclude")
50
+ )
51
+ rescue JSON::ParserError
52
+ invalid_output("#{context}: result must be valid JSON")
53
+ end
54
+
55
+ sig { params(value: Object, context: String).returns(T::Array[RequirementEntry]) }
56
+ def self.parse_requirements(value, context)
57
+ array(value, context).each_with_index.map do |entry, index|
58
+ location = "#{context}[#{index}]"
59
+ fields = object(entry, location)
60
+ RequirementEntry.new(
61
+ path: string(fields["Path"], "#{location}.Path"),
62
+ version: optional_string(fields["Version"], "#{location}.Version"),
63
+ indirect: indirect(fields["Indirect"], "#{location}.Indirect")
64
+ )
65
+ end
66
+ end
67
+ private_class_method :parse_requirements
68
+
69
+ sig { params(value: Object, context: String).returns(T::Array[Replacement]) }
70
+ def self.parse_replacements(value, context)
71
+ array(value, context).each_with_index.map do |entry, index|
72
+ location = "#{context}[#{index}]"
73
+ fields = object(entry, location)
74
+ Replacement.new(
75
+ old: module_reference(fields["Old"], "#{location}.Old"),
76
+ new: module_reference(fields["New"], "#{location}.New")
77
+ )
78
+ end
79
+ end
80
+ private_class_method :parse_replacements
81
+
82
+ sig { params(value: Object, context: String).returns(T::Array[Exclusion]) }
83
+ def self.parse_exclusions(value, context)
84
+ array(value, context).each_with_index.map do |entry, index|
85
+ location = "#{context}[#{index}]"
86
+ fields = object(entry, location)
87
+ Exclusion.new(
88
+ path: string(fields["Path"], "#{location}.Path"),
89
+ version: string(fields["Version"], "#{location}.Version")
90
+ )
91
+ end
92
+ end
93
+ private_class_method :parse_exclusions
94
+
95
+ sig { params(value: Object, context: String).returns(ModuleReference) }
96
+ def self.module_reference(value, context)
97
+ fields = object(value, context)
98
+ ModuleReference.new(
99
+ path: string(fields["Path"], "#{context}.Path"),
100
+ version: optional_string(fields["Version"], "#{context}.Version")
101
+ )
102
+ end
103
+ private_class_method :module_reference
104
+
105
+ sig { params(value: Object, context: String).returns(ObjectHash) }
106
+ def self.object(value, context)
107
+ invalid_output("#{context} must be an object") unless value.is_a?(Hash)
108
+
109
+ value.to_h do |raw_key, raw_value|
110
+ key = T.cast(raw_key, Object)
111
+ invalid_output("#{context} keys must be strings") unless key.is_a?(String)
112
+
113
+ [key, T.cast(raw_value, Object)]
114
+ end
115
+ end
116
+ private_class_method :object
117
+
118
+ sig { params(value: Object, context: String).returns(T::Array[Object]) }
119
+ def self.array(value, context)
120
+ return [] if value.nil?
121
+
122
+ invalid_output("#{context} must be an array") unless value.is_a?(Array)
123
+ value.map { |entry| T.cast(entry, Object) }
124
+ end
125
+ private_class_method :array
126
+
127
+ sig { params(value: Object, context: String).returns(String) }
128
+ def self.string(value, context)
129
+ return value if value.is_a?(String)
130
+
131
+ invalid_output("#{context} must be a string")
132
+ end
133
+ private_class_method :string
134
+
135
+ sig { params(value: Object, context: String).returns(T.nilable(String)) }
136
+ def self.optional_string(value, context)
137
+ return if value.nil?
138
+
139
+ string(value, context)
140
+ end
141
+ private_class_method :optional_string
142
+
143
+ sig { params(value: Object, context: String).returns(T::Boolean) }
144
+ def self.indirect(value, context)
145
+ case value
146
+ when nil, false then false
147
+ when true then true
148
+ else invalid_output("#{context} must be a boolean or nil")
149
+ end
150
+ end
151
+ private_class_method :indirect
152
+
153
+ sig { params(message: String).returns(T.noreturn) }
154
+ def self.invalid_output(message)
155
+ raise InvalidOutput.new(
156
+ message: message,
157
+ error_class: "TypeError",
158
+ error_context: { command: "go mod edit -json" }
159
+ ),
160
+ cause: nil
161
+ end
162
+ private_class_method :invalid_output
163
+ end
164
+ end
165
+ end
@@ -0,0 +1,82 @@
1
+ # typed: strong
2
+ # frozen_string_literal: true
3
+
4
+ require "json"
5
+ require "time"
6
+ require "sorbet-runtime"
7
+ require "dependabot/shared_helpers"
8
+
9
+ module Dependabot
10
+ module GoModules
11
+ class ModuleInfo < T::ImmutableStruct
12
+ extend T::Sig
13
+
14
+ class InvalidOutput < SharedHelpers::HelperSubprocessFailed; end
15
+
16
+ ObjectHash = T.type_alias { T::Hash[String, Object] }
17
+
18
+ const :versions, T.nilable(T::Array[String])
19
+ const :released_at, T.nilable(Time)
20
+
21
+ sig { params(content: String, command: String).returns(ModuleInfo) }
22
+ def self.from_json(content, command:)
23
+ fields = object(T.cast(JSON.parse(content), Object), command)
24
+ new(
25
+ versions: parse_versions(fields["Versions"], command),
26
+ released_at: parse_time(fields["Time"], command)
27
+ )
28
+ rescue JSON::ParserError
29
+ invalid_output(command, "result must be valid JSON")
30
+ end
31
+
32
+ sig { params(value: Object, command: String).returns(ObjectHash) }
33
+ def self.object(value, command)
34
+ invalid_output(command, "result must be an object") unless value.is_a?(Hash)
35
+
36
+ value.to_h do |raw_key, raw_value|
37
+ key = T.cast(raw_key, Object)
38
+ invalid_output(command, "result keys must be strings") unless key.is_a?(String)
39
+
40
+ [key, T.cast(raw_value, Object)]
41
+ end
42
+ end
43
+ private_class_method :object
44
+
45
+ sig { params(value: Object, command: String).returns(T.nilable(T::Array[String])) }
46
+ def self.parse_versions(value, command)
47
+ return if value.nil?
48
+
49
+ invalid_output(command, "Versions must be an array or nil") unless value.is_a?(Array)
50
+ value.each_with_index.map do |raw_entry, index|
51
+ entry = T.cast(raw_entry, Object)
52
+ invalid_output(command, "Versions[#{index}] must be a string") unless entry.is_a?(String)
53
+
54
+ entry
55
+ end
56
+ end
57
+ private_class_method :parse_versions
58
+
59
+ sig { params(value: Object, command: String).returns(T.nilable(Time)) }
60
+ def self.parse_time(value, command)
61
+ return if value.nil?
62
+
63
+ invalid_output(command, "Time must be a string or nil") unless value.is_a?(String)
64
+ Time.parse(value)
65
+ rescue ArgumentError
66
+ invalid_output(command, "Time must be a valid timestamp")
67
+ end
68
+ private_class_method :parse_time
69
+
70
+ sig { params(command: String, message: String).returns(T.noreturn) }
71
+ def self.invalid_output(command, message)
72
+ raise InvalidOutput.new(
73
+ message: "#{command}: #{message}",
74
+ error_class: "TypeError",
75
+ error_context: { command: command }
76
+ ),
77
+ cause: nil
78
+ end
79
+ private_class_method :invalid_output
80
+ end
81
+ end
82
+ end
@@ -9,6 +9,8 @@ require "dependabot/update_checkers/version_filters"
9
9
  require "dependabot/shared_helpers"
10
10
  require "dependabot/errors"
11
11
  require "dependabot/go_modules/requirement"
12
+ require "dependabot/go_modules/go_mod_manifest"
13
+ require "dependabot/go_modules/module_info"
12
14
  require "dependabot/go_modules/resolvability_errors"
13
15
  require "dependabot/go_modules/azure_devops_path_normalizer"
14
16
 
@@ -73,17 +75,13 @@ module Dependabot
73
75
  # appears to be a side effect of operating with modules included in GOPRIVATE. We'll
74
76
  # retain any exclude directives to omit those versions.
75
77
  File.write("go.mod", "module dummy\n")
76
- manifest["Exclude"]&.each do |r|
77
- SharedHelpers.run_shell_command("go mod edit -exclude=#{r['Path']}@#{r['Version']}")
78
+ manifest.exclusions.each do |exclusion|
79
+ SharedHelpers.run_shell_command("go mod edit -exclude=#{exclusion.path}@#{exclusion.version}")
78
80
  end
79
81
 
80
82
  # Turn off the module proxy for private dependencies
81
83
  dependency_name = AzureDevopsPathNormalizer.normalize(dependency.name)
82
- versions_json = SharedHelpers.run_shell_command(
83
- "go list -m -versions -json #{dependency_name}",
84
- fingerprint: "go list -m -versions -json <dependency_name>"
85
- )
86
- version_strings = JSON.parse(versions_json)["Versions"]
84
+ version_strings = fetch_module_versions(dependency_name)
87
85
 
88
86
  # If no versions found, the path may be a sub-package rather than a module root.
89
87
  # Try progressively shorter paths to find the actual module.
@@ -106,6 +104,8 @@ module Dependabot
106
104
  end
107
105
  end
108
106
  rescue SharedHelpers::HelperSubprocessFailed => e
107
+ raise if e.is_a?(GoModManifest::InvalidOutput) || e.is_a?(ModuleInfo::InvalidOutput)
108
+
109
109
  retry_count ||= 0
110
110
  retry_count += 1
111
111
  retry if transitory_failure?(e) && retry_count < 2
@@ -150,13 +150,13 @@ module Dependabot
150
150
  )
151
151
  end
152
152
 
153
- sig { returns(T::Hash[String, T.untyped]) }
153
+ sig { returns(GoModManifest) }
154
154
  def parse_manifest
155
155
  SharedHelpers.in_a_temporary_directory do
156
156
  File.write("go.mod", T.must(go_mod).content)
157
157
  json = SharedHelpers.run_shell_command("go mod edit -json")
158
158
 
159
- JSON.parse(json) || {}
159
+ GoModManifest.from_json(json, file_path: T.must(go_mod).path)
160
160
  end
161
161
  end
162
162
 
@@ -171,7 +171,10 @@ module Dependabot
171
171
  "go list -m -versions -json #{module_path}",
172
172
  fingerprint: "go list -m -versions -json <dependency_name>"
173
173
  )
174
- JSON.parse(versions_json)["Versions"]
174
+ ModuleInfo.from_json(
175
+ versions_json,
176
+ command: "go list -m -versions -json <dependency_name>"
177
+ ).versions
175
178
  end
176
179
 
177
180
  # When a full import path (e.g. github.com/owner/repo/cmd/tool) is not a module,
@@ -188,7 +191,9 @@ module Dependabot
188
191
  Dependabot.logger.debug("Trying shorter module path: #{candidate}")
189
192
  versions = fetch_module_versions(candidate)
190
193
  return versions if versions&.any?
191
- rescue SharedHelpers::HelperSubprocessFailed
194
+ rescue SharedHelpers::HelperSubprocessFailed => e
195
+ raise if e.is_a?(ModuleInfo::InvalidOutput)
196
+
192
197
  next
193
198
  end
194
199
 
@@ -1,7 +1,8 @@
1
- # typed: strict
1
+ # typed: strong
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "sorbet-runtime"
5
+ require "dependabot/go_modules/go_mod_manifest"
5
6
 
6
7
  module Dependabot
7
8
  module GoModules
@@ -22,13 +23,13 @@ module Dependabot
22
23
  end
23
24
 
24
25
  sig do
25
- params(manifest: T::Hash[String, T.untyped], directory: T.nilable(String)).returns(T::Hash[String, String])
26
+ params(manifest: GoModManifest, directory: T.nilable(String)).returns(T::Hash[String, String])
26
27
  end
27
28
  def stub_paths(manifest, directory)
28
- (manifest["Replace"] || [])
29
- .filter_map { |r| r["New"]["Path"] }
30
- .select { |p| stub_replace_path?(p, directory) }
31
- .to_h { |p| [p, "./" + Digest::SHA2.hexdigest(p)] }
29
+ manifest.replacements
30
+ .map { |replacement| replacement.new.path }
31
+ .select { |p| stub_replace_path?(p, directory) }
32
+ .to_h { |p| [p, "./" + Digest::SHA2.hexdigest(p)] }
32
33
  end
33
34
 
34
35
  private
@@ -1,4 +1,4 @@
1
- # typed: strict
1
+ # typed: strong
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "excon"
@@ -9,6 +9,7 @@ require "dependabot/update_checkers/version_filters"
9
9
  require "dependabot/shared_helpers"
10
10
  require "dependabot/errors"
11
11
  require "dependabot/go_modules/requirement"
12
+ require "dependabot/go_modules/module_info"
12
13
  require "dependabot/go_modules/resolvability_errors"
13
14
  require "dependabot/go_modules/package/package_details_fetcher"
14
15
  require "dependabot/go_modules/azure_devops_path_normalizer"
@@ -210,9 +211,10 @@ module Dependabot
210
211
  return false
211
212
  end
212
213
 
213
- release.instance_variable_set(
214
- :@released_at, JSON.parse(release_info)["Time"] ? Time.parse(JSON.parse(release_info)["Time"]) : nil
215
- )
214
+ release.released_at = ModuleInfo.from_json(
215
+ release_info,
216
+ command: "go list -m -json <dependency_name>"
217
+ ).released_at
216
218
 
217
219
  return false unless release.released_at
218
220
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dependabot-go_modules
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.398.0
4
+ version: 0.399.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dependabot
@@ -15,14 +15,14 @@ dependencies:
15
15
  requirements:
16
16
  - - '='
17
17
  - !ruby/object:Gem::Version
18
- version: 0.398.0
18
+ version: 0.399.0
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - '='
24
24
  - !ruby/object:Gem::Version
25
- version: 0.398.0
25
+ version: 0.399.0
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: debug
28
28
  requirement: !ruby/object:Gem::Requirement
@@ -256,9 +256,11 @@ files:
256
256
  - lib/dependabot/go_modules/file_parser.rb
257
257
  - lib/dependabot/go_modules/file_updater.rb
258
258
  - lib/dependabot/go_modules/file_updater/go_mod_updater.rb
259
+ - lib/dependabot/go_modules/go_mod_manifest.rb
259
260
  - lib/dependabot/go_modules/go_work_parser.rb
260
261
  - lib/dependabot/go_modules/language.rb
261
262
  - lib/dependabot/go_modules/metadata_finder.rb
263
+ - lib/dependabot/go_modules/module_info.rb
262
264
  - lib/dependabot/go_modules/native_helpers.rb
263
265
  - lib/dependabot/go_modules/package/package_details_fetcher.rb
264
266
  - lib/dependabot/go_modules/package_manager.rb
@@ -275,7 +277,7 @@ licenses:
275
277
  - MIT
276
278
  metadata:
277
279
  bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
278
- changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.398.0
280
+ changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.399.0
279
281
  rdoc_options: []
280
282
  require_paths:
281
283
  - lib