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 +4 -4
- data/lib/dependabot/go_modules/file_parser.rb +35 -42
- data/lib/dependabot/go_modules/file_updater/go_mod_updater.rb +4 -3
- data/lib/dependabot/go_modules/go_mod_manifest.rb +165 -0
- data/lib/dependabot/go_modules/module_info.rb +82 -0
- data/lib/dependabot/go_modules/package/package_details_fetcher.rb +16 -11
- data/lib/dependabot/go_modules/replace_stubber.rb +7 -6
- data/lib/dependabot/go_modules/update_checker/latest_version_finder.rb +6 -4
- metadata +6 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c542fdbc9273e2bc8287b1763076eabc222f1c53318a298584b6991304edd18f
|
|
4
|
+
data.tar.gz: 06066f37ca5940ee83ee6073e7a8215201577e9da520163eda7b6bf30a6f6a25
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: cfd2c42fe78c12e7f7129afb4c5c066e01195c780fca8a2584766588abaae8a14f1e992506485f4ecc387d54a5dace6b47383f9fd0ebf0cc3f36cd1299f7c62f
|
|
7
|
+
data.tar.gz: 8c16abde1c7c011714160a0f6bb99540356704b7d79ff50321d92d8f280a3fc890ec951342de4748e8609b3638bd384b4c647ddc3777f32b0b0addde94c2f766
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# typed:
|
|
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 =
|
|
295
|
-
packages = parsed["Require"] || []
|
|
295
|
+
parsed = GoModManifest.from_json(stdout, file_path: mod_file.path)
|
|
296
296
|
|
|
297
|
-
|
|
298
|
-
next if skip_dependency_in_manifest?(
|
|
297
|
+
parsed.requirements.filter_map do |entry|
|
|
298
|
+
next if skip_dependency_in_manifest?(entry, parsed)
|
|
299
299
|
|
|
300
|
-
source = { type: "default", source:
|
|
301
|
-
version =
|
|
300
|
+
source = { type: "default", source: entry.path }
|
|
301
|
+
version = entry.version&.sub(/^v?/, "")
|
|
302
302
|
|
|
303
303
|
reqs = [{
|
|
304
|
-
requirement:
|
|
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:
|
|
311
|
+
name: entry.path,
|
|
312
312
|
version: version,
|
|
313
|
-
requirements:
|
|
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:
|
|
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
|
|
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:
|
|
330
|
+
sig { params(details: GoModManifest::RequirementEntry, mod_manifest: GoModManifest).returns(T::Boolean) }
|
|
331
331
|
def dependency_is_replaced_in?(details, mod_manifest)
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
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:
|
|
343
|
+
sig { params(details: GoModManifest::RequirementEntry).returns(Dependabot::Dependency) }
|
|
346
344
|
def dependency_from_details(details)
|
|
347
|
-
source = { type: "default", source: details
|
|
348
|
-
version = details
|
|
345
|
+
source = { type: "default", source: details.path }
|
|
346
|
+
version = details.version&.sub(/^v?/, "")
|
|
349
347
|
|
|
350
348
|
reqs = [{
|
|
351
|
-
requirement: details
|
|
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
|
|
356
|
+
name: details.path,
|
|
359
357
|
version: version,
|
|
360
|
-
requirements: details
|
|
358
|
+
requirements: details.indirect ? [] : reqs,
|
|
361
359
|
package_manager: "go_modules"
|
|
362
360
|
)
|
|
363
361
|
end
|
|
364
362
|
|
|
365
|
-
sig { returns(T::Array[
|
|
363
|
+
sig { returns(T::Array[GoModManifest::RequirementEntry]) }
|
|
366
364
|
def required_packages
|
|
367
365
|
@required_packages ||=
|
|
368
366
|
T.let(
|
|
369
|
-
|
|
370
|
-
|
|
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(
|
|
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
|
-
|
|
402
|
+
GoModManifest.from_json(stdout, file_path: T.must(go_mod).path)
|
|
402
403
|
end,
|
|
403
|
-
T.nilable(
|
|
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:
|
|
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
|
|
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:
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
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:
|
|
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
|
|
77
|
-
SharedHelpers.run_shell_command("go mod edit -exclude=#{
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
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:
|
|
26
|
+
params(manifest: GoModManifest, directory: T.nilable(String)).returns(T::Hash[String, String])
|
|
26
27
|
end
|
|
27
28
|
def stub_paths(manifest, directory)
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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:
|
|
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.
|
|
214
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|