Skip to content
This repository has been archived by the owner on Jun 1, 2023. It is now read-only.

Commit

Permalink
Merge pull request #1661 from Shopify/handle-npm-list-bad-status
Browse files Browse the repository at this point in the history
Handle `npm list` non-zero exit status
  • Loading branch information
lopert authored Oct 20, 2021
2 parents 3fbc4ca + 9d0ab34 commit d8ff0f3
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,31 @@ def metadata

def library_version(library_name)
output = JSON.parse(CommandRunner.new(ctx: ctx).call("npm list --json"))
raise Errors::APILibraryNotFoundError.new(library_name), output unless output["dependencies"][library_name]
output["dependencies"][library_name]["version"]
library_version_from_npm_list(output, library_name)
rescue Errors::SystemCallFailureError => error
library_version_from_npm_list_error_output(error, library_name)
end

private

def library_version_from_npm_list_error_output(error, library_name)
# npm list can return a failure status code, even when returning the correct data.
# This causes the CommandRunner to throw a SystemCallFailure error that contains the data.
# In here, we check that the output contains `npm list`'s structure and extract the version.
output = JSON.parse(error.out)
raise error unless output.key?("dependencies")

library_version_from_npm_list(output, library_name)
rescue JSON::ParserError
raise error
end

def library_version_from_npm_list(output, library_name)
output.dig("dependencies", library_name, "version").tap do |version|
raise Errors::APILibraryNotFoundError, library_name unless version
end
end

def check_node_version!
output, status = @ctx.capture2e("node", "--version")
raise Errors::DependencyInstallError, output unless status.success?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,14 +148,54 @@
end

describe "when CommandRunner raises SystemCallFailureError" do
it "should raise SystemCallFailureError" do
cmd = "npm list --json"
command_runner.any_instance.stubs(:call)
.with(cmd)
.raises(Script::Layers::Infrastructure::Errors::SystemCallFailureError.new(out: "test", cmd: cmd))
describe "when error is not json" do
it "should re-raise SystemCallFailureError" do
cmd = "npm list --json"
command_runner.any_instance.stubs(:call)
.with(cmd)
.raises(Script::Layers::Infrastructure::Errors::SystemCallFailureError.new(
out: "some non-json parsable error output", cmd: cmd
))

assert_raises Script::Layers::Infrastructure::Errors::SystemCallFailureError do
subject
end
end
end

assert_raises Script::Layers::Infrastructure::Errors::SystemCallFailureError do
subject
describe "when error is json, but doesn't contain the expected structure" do
it "should re-raise SystemCallFailureError" do
cmd = "npm list --json"
command_runner.any_instance.stubs(:call)
.with(cmd)
.raises(Script::Layers::Infrastructure::Errors::SystemCallFailureError.new(
out: {
"not what we expected" => {},
}.to_json,
cmd: cmd
))
assert_raises Script::Layers::Infrastructure::Errors::SystemCallFailureError do
subject
end
end
end

describe "when error contains expected versioning data" do
it "should rescue SystemCallFailureError if the library version is present" do
cmd = "npm list --json"
command_runner.any_instance.stubs(:call)
.with(cmd)
.raises(Script::Layers::Infrastructure::Errors::SystemCallFailureError.new(
out: {
"dependencies" => {
extension_point_config["assemblyscript"][:package] => {
"version" => "1.3.7",
},
},
}.to_json,
cmd: cmd
))
assert_equal "1.3.7", subject
end
end
end
Expand Down

0 comments on commit d8ff0f3

Please sign in to comment.