diff --git a/lib/dependabot/file_parsers/go/modules/go_mod_parser.rb b/lib/dependabot/file_parsers/go/modules/go_mod_parser.rb index decfa82ad4..047eeb144e 100644 --- a/lib/dependabot/file_parsers/go/modules/go_mod_parser.rb +++ b/lib/dependabot/file_parsers/go/modules/go_mod_parser.rb @@ -1,5 +1,6 @@ # frozen_string_literal: true +require "open3" require "dependabot/dependency" require "dependabot/file_parsers/base/dependency_set" require "dependabot/file_parsers/go/modules" @@ -66,16 +67,28 @@ def dependency_from_details(details) def module_info(go_mod) @module_info ||= - SharedHelpers.in_a_temporary_directory do + SharedHelpers.in_a_temporary_directory do |path| SharedHelpers.with_git_configured(credentials: credentials) do File.write("go.mod", go_mod.content) - output = `GO111MODULE=on go list -m -json all` - unless $CHILD_STATUS.success? - raise Dependabot::DependencyFileNotParseable, go_mod.path + command = "GO111MODULE=on go list -m -json all" + stdout, stderr, status = Open3.capture3(command) + next stdout if status.success? + + case stderr + when /go: .*: unknown revision/ + error_msg = stderr.lines.grep(/unknown revision/).first + raise Dependabot::DependencyFileNotResolvable, error_msg + when /go: .*: unrecognized import path/ + error_msg = stderr.lines.grep(/unrecognized import/).first + raise Dependabot::DependencyFileNotResolvable, error_msg + when /go: errors parsing go.mod/ + error_msg = stderr.gsub(path.to_s, "") + raise Dependabot::DependencyFileNotParseable, error_msg + else + error_msg = stderr.gsub(path.to_s, "") + raise Dependabot::DependencyFileNotParseable, error_msg end - - output end end end diff --git a/spec/dependabot/file_parsers/go/modules/go_mod_parser_spec.rb b/spec/dependabot/file_parsers/go/modules/go_mod_parser_spec.rb index 951071502e..f1fe11f139 100644 --- a/spec/dependabot/file_parsers/go/modules/go_mod_parser_spec.rb +++ b/spec/dependabot/file_parsers/go/modules/go_mod_parser_spec.rb @@ -21,9 +21,10 @@ let(:go_mod) do Dependabot::DependencyFile.new( name: "go.mod", - content: fixture("go", "go_mods", go_mod_fixture_name) + content: go_mod_content ) end + let(:go_mod_content) { fixture("go", "go_mods", go_mod_fixture_name) } let(:go_mod_fixture_name) { "go.mod" } describe "dependency_set" do @@ -114,5 +115,38 @@ end end end + + describe "a garbage go.mod" do + let(:go_mod_content) { "not really a go.mod file :-/" } + + it "raises the correct error" do + expect { parser.dependency_set }. + to raise_error(Dependabot::DependencyFileNotParseable) + end + end + + describe "a non-existent dependency" do + let(:go_mod_content) do + go_mod = fixture("go", "go_mods", go_mod_fixture_name) + go_mod.sub("rsc.io/quote", "example.com/not-a-repo") + end + + it "raises the correct error" do + expect { parser.dependency_set }. + to raise_error(Dependabot::DependencyFileNotResolvable) + end + end + + describe "a dependency at a non-existent version" do + let(:go_mod_content) do + go_mod = fixture("go", "go_mods", go_mod_fixture_name) + go_mod.sub("rsc.io/quote v1.4.0", "rsc.io/quote v1.321.0") + end + + it "raises the correct error" do + expect { parser.dependency_set }. + to raise_error(Dependabot::DependencyFileNotResolvable) + end + end end end