dependabot-go_modules 0.117.5 → 0.117.10

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: fceadfcc210c9dc64acc8d92d504afbd0e21e8dbfea0a7109a7dcae163251ed8
4
- data.tar.gz: 04c67017af0b4d2443c8e5dd4800d3b8631eb9cd587afdda7a18f4dfaaefa520
3
+ metadata.gz: 71e2a6e2a03792cf25a5d76d5933b8511805bd589022c553d97d3264c79ced66
4
+ data.tar.gz: 2369ac59c46fbb38b3663ce10c6db8f5a6d7ab250688455eac39196907dd3b34
5
5
  SHA512:
6
- metadata.gz: a5c8da9265bd35b9e3f07af7be78c6187d43cb4da8bea56a8cc0b24bb4f4f9f711f4e0f1c453543314962c5f4901a1b8288fadb5c235e9bef7d6bdfde25fce65
7
- data.tar.gz: 22b5cece236b8040309ee3e9399aea64e87c8cdfc69ba6cda6428a3f3b5beb40d33e20f78cf4415a779dcc0ec134cbf6fc60d70a6234346dbd05075cf32bcdd0
6
+ metadata.gz: 825ea487e046564cdd545df45475000dd86c8cfe2e3aef65feec2f8343b59f9d432dd493db0acb94d951ed0e58d25792d2d373296524c5fb4800053de630e9cf
7
+ data.tar.gz: d01b64ed69bc6494d09c9f967f65c91e7f4dad14bc830bb018e1cb02fd429c99930584991b4c5d3758262e6249c7d5dc3e1b7461c45304b3519b8686a3916079
@@ -36,6 +36,12 @@ func GetUpdatedVersion(args *Args) (interface{}, error) {
36
36
  return nil, errors.New("Expected args.dependency to not be nil")
37
37
  }
38
38
 
39
+ currentVersion := args.Dependency.Version
40
+ currentPrerelease := semver.Prerelease(currentVersion)
41
+ if pseudoVersionRegexp.MatchString(currentPrerelease) {
42
+ return currentVersion, nil
43
+ }
44
+
39
45
  modload.InitMod()
40
46
 
41
47
  repo, err := modfetch.Lookup(args.Dependency.Name)
@@ -53,15 +59,9 @@ func GetUpdatedVersion(args *Args) (interface{}, error) {
53
59
  return nil, err
54
60
  }
55
61
 
56
- currentVersion := args.Dependency.Version
57
62
  currentMajor := semver.Major(currentVersion)
58
- currentPrerelease := semver.Prerelease(currentVersion)
59
63
  latestVersion := args.Dependency.Version
60
64
 
61
- if pseudoVersionRegexp.MatchString(currentPrerelease) {
62
- return latestVersion, nil
63
- }
64
-
65
65
  Outer:
66
66
  for _, v := range versions {
67
67
  if semver.Major(v) != currentMajor {
@@ -135,16 +135,16 @@ module Dependabot
135
135
  end
136
136
  end
137
137
 
138
- GIT_ERROR_REGEX = /go: .*: git fetch .*: exit status 128/.freeze
138
+ GIT_ERROR_REGEX = /go: .*: git fetch .*: exit status 128/m.freeze
139
139
  def handle_parser_error(path, stderr)
140
140
  case stderr
141
- when /go: .*: unknown revision/
141
+ when /go: .*: unknown revision/m
142
142
  line = stderr.lines.grep(/unknown revision/).first
143
143
  raise Dependabot::DependencyFileNotResolvable, line.strip
144
- when /go: .*: unrecognized import path/
144
+ when /go: .*: unrecognized import path/m
145
145
  line = stderr.lines.grep(/unrecognized import/).first
146
146
  raise Dependabot::DependencyFileNotResolvable, line.strip
147
- when /go: errors parsing go.mod/
147
+ when /go: errors parsing go.mod/m
148
148
  msg = stderr.gsub(path.to_s, "").strip
149
149
  raise Dependabot::DependencyFileNotParseable.new(go_mod.path, msg)
150
150
  when GIT_ERROR_REGEX
@@ -9,6 +9,22 @@ module Dependabot
9
9
  module GoModules
10
10
  class FileUpdater
11
11
  class GoModUpdater
12
+ # Turn off the module proxy for now, as it's causing issues with
13
+ # private git dependencies
14
+ ENVIRONMENT = { "GOPRIVATE" => "*" }.freeze
15
+
16
+ RESOLVABILITY_ERROR_REGEXES = [
17
+ /go: .*: git fetch .*: exit status 128/.freeze,
18
+ /verifying .*: checksum mismatch/.freeze,
19
+ /build .*: cannot find module providing package/.freeze
20
+ ].freeze
21
+
22
+ MODULE_PATH_MISMATCH_REGEXES = [
23
+ /go: ([^@\s]+)(?:@[^\s]+)?: .* has non-.* module path "(.*)" at/,
24
+ /go: ([^@\s]+)(?:@[^\s]+)?: .* unexpected module path "(.*)"/,
25
+ /go: ([^@\s]+)(?:@[^\s]+)?: .* declares its path as: ([\S]*)/m
26
+ ].freeze
27
+
12
28
  def initialize(dependencies:, go_mod:, go_sum:, credentials:)
13
29
  @dependencies = dependencies
14
30
  @go_mod = go_mod
@@ -17,96 +33,171 @@ module Dependabot
17
33
  end
18
34
 
19
35
  def updated_go_mod_content
20
- # Turn off the module proxy for now, as it's causing issues with
21
- # private git dependencies
22
- env = { "GOPRIVATE" => "*" }
23
-
24
- @updated_go_mod_content ||=
25
- SharedHelpers.in_a_temporary_directory do
26
- SharedHelpers.with_git_configured(credentials: credentials) do
27
- File.write("go.mod", go_mod.content)
28
-
29
- deps = dependencies.map do |dep|
30
- {
31
- name: dep.name,
32
- version: "v" + dep.version.sub(/^v/i, ""),
33
- indirect: dep.requirements.empty?
34
- }
35
- end
36
-
37
- SharedHelpers.run_helper_subprocess(
38
- command: NativeHelpers.helper_path,
39
- env: env,
40
- function: "updateDependencyFile",
41
- args: { dependencies: deps }
42
- )
43
- end
44
- end
36
+ updated_files[:go_mod]
45
37
  end
46
38
 
47
39
  def updated_go_sum_content
48
- return nil unless go_sum
49
-
50
- # This needs to be run separately so we don't nest subprocess calls
51
- prepared_go_mod_content
52
-
53
- @updated_go_sum_content ||=
54
- SharedHelpers.in_a_temporary_directory do
55
- SharedHelpers.with_git_configured(credentials: credentials) do
56
- # Create a fake empty module for each local module so that
57
- # `go get -d` works, even if some modules have been `replace`d
58
- # with a local module that we don't have access to.
59
- local_replacements.each do |_, stub_path|
60
- Dir.mkdir(stub_path) unless Dir.exist?(stub_path)
61
- FileUtils.touch(File.join(stub_path, "go.mod"))
62
- end
63
-
64
- File.write("go.mod", prepared_go_mod_content)
65
- File.write("go.sum", go_sum.content)
66
- File.write("main.go", dummy_main_go)
67
-
68
- # Turn off the module proxy for now, as it's causing issues
69
- # with private git dependencies
70
- env = { "GOPRIVATE" => "*" }
71
-
72
- _, stderr, status = Open3.capture3(env, "go get -d")
73
- unless status.success?
74
- handle_subprocess_error(go_sum.path, stderr)
75
- end
76
-
77
- File.read("go.sum")
78
- end
79
- end
40
+ updated_files[:go_sum]
80
41
  end
81
42
 
82
43
  private
83
44
 
84
- RESOLVABILITY_ERROR_REGEXES = [
85
- /go: .*: git fetch .*: exit status 128/.freeze,
86
- /verifying .*: checksum mismatch/.freeze,
87
- /build .*: cannot find module providing package/.freeze
88
- ].freeze
89
- MODULE_PATH_MISMATCH_REGEXES = [
90
- /go: ([^@\s]+)(?:@[^\s]+)?: .* has non-.* module path "(.*)" at/,
91
- /go: ([^@\s]+)(?:@[^\s]+)?: .* unexpected module path "(.*)"/,
92
- /go: ([^@\s]+)(?:@[^\s]+)?: .* declares its path as: ([\S]*)/m
93
- ].freeze
45
+ attr_reader :dependencies, :go_mod, :go_sum, :credentials
46
+
47
+ def updated_files
48
+ @updated_files ||= update_files
49
+ end
50
+
51
+ # rubocop:disable Metrics/AbcSize
52
+ def update_files
53
+ # Map paths in local replace directives to path hashes
54
+ substitutions = replace_directive_substitutions(go_mod.content)
55
+ stub_dirs = substitutions.values
56
+
57
+ # Replace full paths with path hashes in the go.mod
58
+ clean_go_mod = substitute_all(go_mod.content, substitutions)
59
+
60
+ # Set the new dependency versions in the go.mod
61
+ updated_go_mod = in_temp_dir(stub_dirs) do
62
+ update_go_mod(clean_go_mod, dependencies)
63
+ end
64
+
65
+ # Then run `go get` to pick up other changes to the file caused by
66
+ # the upgrade
67
+ regenerated_files = in_temp_dir(stub_dirs) do
68
+ run_go_get(updated_go_mod, go_sum)
69
+ end
70
+
71
+ # At this point, the go.mod returned from run_go_get contains the
72
+ # correct set of modules, but running `go get` can change the file in
73
+ # undesirable ways (such as injecting the current Go version), so we
74
+ # need to update the original go.mod with the updated set of
75
+ # requirements rather than using the regenerated file directly
76
+ original_reqs = in_temp_dir(stub_dirs) do
77
+ parse_manifest_requirements(go_mod.content)
78
+ end
79
+ updated_reqs = in_temp_dir(stub_dirs) do
80
+ parse_manifest_requirements(regenerated_files[:go_mod])
81
+ end
82
+
83
+ original_paths = original_reqs.map { |r| r["Path"] }
84
+ updated_paths = updated_reqs.map { |r| r["Path"] }
85
+ req_paths_to_remove = original_paths - updated_paths
94
86
 
95
- def local_replacements
96
- @local_replacements ||=
87
+ output_go_mod = in_temp_dir(stub_dirs) do
88
+ remove_requirements(go_mod.content, req_paths_to_remove)
89
+ end
90
+
91
+ output_go_mod = in_temp_dir(stub_dirs) do
92
+ deps = updated_reqs.map { |r| requirement_to_dependency_obj(r) }
93
+ update_go_mod(output_go_mod, deps)
94
+ end
95
+
96
+ { go_mod: output_go_mod, go_sum: regenerated_files[:go_sum] }
97
+ end
98
+ # rubocop:enable Metrics/AbcSize
99
+
100
+ def update_go_mod(go_mod_content, dependencies)
101
+ File.write("go.mod", go_mod_content)
102
+
103
+ deps = dependencies.map do |dep|
104
+ {
105
+ name: dep.name,
106
+ version: "v" + dep.version.sub(/^v/i, ""),
107
+ indirect: dep.requirements.empty?
108
+ }
109
+ end
110
+
111
+ SharedHelpers.run_helper_subprocess(
112
+ command: NativeHelpers.helper_path,
113
+ env: ENVIRONMENT,
114
+ function: "updateDependencyFile",
115
+ args: { dependencies: deps }
116
+ )
117
+ end
118
+
119
+ def run_go_get(go_mod_content, go_sum)
120
+ File.write("go.mod", go_mod_content)
121
+ File.write("go.sum", go_sum.content) if go_sum
122
+ File.write("main.go", dummy_main_go)
123
+
124
+ _, stderr, status = Open3.capture3(ENVIRONMENT, "go get -d")
125
+ handle_subprocess_error(stderr) unless status.success?
126
+
127
+ updated_go_sum = go_sum ? File.read("go.sum") : nil
128
+ { go_mod: File.read("go.mod"), go_sum: updated_go_sum }
129
+ end
130
+
131
+ def parse_manifest_requirements(go_mod_content)
132
+ File.write("go.mod", go_mod_content)
133
+
134
+ command = "go mod edit -json"
135
+ stdout, stderr, status = Open3.capture3(ENVIRONMENT, command)
136
+ handle_subprocess_error(stderr) unless status.success?
137
+
138
+ JSON.parse(stdout)["Require"] || []
139
+ end
140
+
141
+ def remove_requirements(go_mod_content, requirement_paths)
142
+ File.write("go.mod", go_mod_content)
143
+
144
+ requirement_paths.each do |path|
145
+ escaped_path = Shellwords.escape(path)
146
+ command = "go mod edit -droprequire #{escaped_path}"
147
+ _, stderr, status = Open3.capture3(ENVIRONMENT, command)
148
+ handle_subprocess_error(stderr) unless status.success?
149
+ end
150
+
151
+ File.read("go.mod")
152
+ end
153
+
154
+ def add_requirements(go_mod_content, requirements)
155
+ File.write("go.mod", go_mod_content)
156
+
157
+ requirements.each do |r|
158
+ escaped_req = Shellwords.escape("#{r['Path']}@#{r['Version']}")
159
+ command = "go mod edit -require #{escaped_req}"
160
+ _, stderr, status = Open3.capture3(ENVIRONMENT, command)
161
+ handle_subprocess_error(stderr) unless status.success?
162
+ end
163
+
164
+ File.read("go.mod")
165
+ end
166
+
167
+ def in_temp_dir(stub_paths, &block)
168
+ SharedHelpers.in_a_temporary_directory do
169
+ SharedHelpers.with_git_configured(credentials: credentials) do
170
+ # Create a fake empty module for each local module so that
171
+ # `go get -d` works, even if some modules have been `replace`d
172
+ # with a local module that we don't have access to.
173
+ stub_paths.each do |stub_path|
174
+ Dir.mkdir(stub_path) unless Dir.exist?(stub_path)
175
+ FileUtils.touch(File.join(stub_path, "go.mod"))
176
+ end
177
+
178
+ block.call
179
+ end
180
+ end
181
+ end
182
+
183
+ # Given a go.mod file, find all `replace` directives pointing to a path
184
+ # on the local filesystem, and return an array of pairs mapping the
185
+ # original path to a hash of the path.
186
+ #
187
+ # This lets us substitute all parts of the go.mod that are dependent on
188
+ # the layout of the filesystem with a structure we can reproduce (i.e.
189
+ # no paths such as ../../../foo), run the Go tooling, then reverse the
190
+ # process afterwards.
191
+ def replace_directive_substitutions(go_mod_content)
192
+ @replace_directive_substitutions ||=
97
193
  SharedHelpers.in_a_temporary_directory do |path|
98
- File.write("go.mod", go_mod.content)
194
+ File.write("go.mod", go_mod_content)
99
195
 
100
196
  # Parse the go.mod to get a JSON representation of the replace
101
197
  # directives
102
198
  command = "go mod edit -json"
103
-
104
- # Turn off the module proxy for now, as it's causing issues with
105
- # private git dependencies
106
- env = { "GOPRIVATE" => "*" }
107
-
108
- stdout, stderr, status = Open3.capture3(env, command)
109
- handle_parser_error(path, stderr) unless status.success?
199
+ stdout, stderr, status = Open3.capture3(ENVIRONMENT, command)
200
+ handle_subprocess_error(path, stderr) unless status.success?
110
201
 
111
202
  # Find all the local replacements, and return them with a stub
112
203
  # path we can use in their place. Using generated paths is safer
@@ -116,18 +207,20 @@ module Dependabot
116
207
  map { |r| r["New"]["Path"] }.
117
208
  compact.
118
209
  select { |p| p.start_with?(".") || p.start_with?("/") }.
119
- map { |p| [p, "./" + Digest::SHA2.hexdigest(p)] }
210
+ map { |p| [p, "./" + Digest::SHA2.hexdigest(p)] }.
211
+ to_h
120
212
  end
121
213
  end
122
214
 
123
- def prepared_go_mod_content
124
- content = updated_go_mod_content
125
- local_replacements.reduce(content) do |body, (path, stub_path)|
126
- body.sub(path, stub_path)
215
+ def substitute_all(file, substitutions)
216
+ substitutions.reduce(file) do |text, (a, b)|
217
+ text.sub(a, b)
127
218
  end
128
219
  end
129
220
 
130
- def handle_subprocess_error(path, stderr)
221
+ def handle_subprocess_error(stderr)
222
+ stderr = stderr.gsub(Dir.getwd, "")
223
+
131
224
  error_regex = RESOLVABILITY_ERROR_REGEXES.find { |r| stderr =~ r }
132
225
  if error_regex
133
226
  lines = stderr.lines.drop_while { |l| error_regex !~ l }
@@ -141,7 +234,7 @@ module Dependabot
141
234
  new(go_mod.path, match[1], match[2])
142
235
  end
143
236
 
144
- msg = stderr.gsub(path.to_s, "").lines.last(10).join.strip
237
+ msg = stderr.lines.last(10).join.strip
145
238
  raise Dependabot::DependencyFileNotParseable.new(go_mod.path, msg)
146
239
  end
147
240
 
@@ -156,13 +249,29 @@ module Dependabot
156
249
  # good to switch back to `main` so we can surface more errors.
157
250
  lines = ["package dummypkg", "import ("]
158
251
  dependencies.each do |dep|
159
- lines << "_ \"#{dep.name}\""
252
+ lines << "_ \"#{dep.name}\"" unless dep.requirements.empty?
160
253
  end
161
254
  lines << ")"
162
255
  lines.join("\n")
163
256
  end
164
257
 
165
- attr_reader :dependencies, :go_mod, :go_sum, :credentials
258
+ def requirement_to_dependency_obj(req)
259
+ # This is an approximation - we're not correctly populating `source`
260
+ # for instance, but it's only to plug the requirement into the
261
+ # `update_go_mod` method so this mapping doesn't need to be perfect
262
+ dep_req = {
263
+ file: "go.mod",
264
+ requirement: req["Version"],
265
+ groups: [],
266
+ source: nil
267
+ }
268
+ Dependency.new(
269
+ name: req["Path"],
270
+ version: req["Version"],
271
+ requirements: req["Indirect"] ? [] : [dep_req],
272
+ package_manager: "go_modules"
273
+ )
274
+ end
166
275
  end
167
276
  end
168
277
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dependabot-go_modules
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.117.5
4
+ version: 0.117.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dependabot
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-03-31 00:00:00.000000000 Z
11
+ date: 2020-05-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dependabot-common
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 0.117.5
19
+ version: 0.117.10
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 0.117.5
26
+ version: 0.117.10
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: byebug
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -114,14 +114,14 @@ dependencies:
114
114
  requirements:
115
115
  - - "~>"
116
116
  - !ruby/object:Gem::Version
117
- version: 0.80.1
117
+ version: 0.83.0
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
- version: 0.80.1
124
+ version: 0.83.0
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: vcr
127
127
  requirement: !ruby/object:Gem::Requirement