Skip to content

Commit

Permalink
Adds error handlers for pnpm exceptions
Browse files Browse the repository at this point in the history
  • Loading branch information
sachin-sandhu committed Jan 16, 2025
1 parent 47316b7 commit 07024df
Show file tree
Hide file tree
Showing 4 changed files with 792 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ def initialize(dependencies:, dependency_files:, repo_contents_path:, credential
@dependency_files = dependency_files
@repo_contents_path = repo_contents_path
@credentials = credentials
@error_handler = PnpmErrorHandler.new(
dependencies: dependencies,
dependency_files: dependency_files
)
end

def updated_pnpm_lock_content(pnpm_lock)
Expand All @@ -36,6 +40,7 @@ def updated_pnpm_lock_content(pnpm_lock)
attr_reader :dependency_files
attr_reader :repo_contents_path
attr_reader :credentials
attr_reader :error_handler

IRRESOLVABLE_PACKAGE = "ERR_PNPM_NO_MATCHING_VERSION"
INVALID_REQUIREMENT = "ERR_PNPM_SPEC_NOT_SUPPORTED_BY_ANY_RESOLVER"
Expand All @@ -46,12 +51,12 @@ def updated_pnpm_lock_content(pnpm_lock)
UNAUTHORIZED_PACKAGE = /ERR_PNPM_FETCH_401[ [^:print:]]+GET (?<dependency_url>.*): Unauthorized - 401/

# ERR_PNPM_FETCH ERROR CODES
ERR_PNPM_FETCH_401 = /ERR_PNPM_FETCH_401.*GET (?<dependency_url>.*): - 401/
ERR_PNPM_FETCH_403 = /ERR_PNPM_FETCH_403.*GET (?<dependency_url>.*): - 403/
ERR_PNPM_FETCH_404 = /ERR_PNPM_FETCH_404.*GET (?<dependency_url>.*): - 404/
ERR_PNPM_FETCH_500 = /ERR_PNPM_FETCH_500.*GET (?<dependency_url>.*): - 500/
ERR_PNPM_FETCH_502 = /ERR_PNPM_FETCH_502.*GET (?<dependency_url>.*): - 502/
ERR_PNPM_FETCH_503 = /ERR_PNPM_FETCH_503.*GET (?<dependency_url>.*): - 503/
ERR_PNPM_FETCH_401 = /ERR_PNPM_FETCH_401.*GET (?<dependency_url>.*):/
ERR_PNPM_FETCH_403 = /ERR_PNPM_FETCH_403.*GET (?<dependency_url>.*):/
ERR_PNPM_FETCH_404 = /ERR_PNPM_FETCH_404.*GET (?<dependency_url>.*):/
ERR_PNPM_FETCH_500 = /ERR_PNPM_FETCH_500.*GET (?<dependency_url>.*):/
ERR_PNPM_FETCH_502 = /ERR_PNPM_FETCH_502.*GET (?<dependency_url>.*):/
ERR_PNPM_FETCH_503 = /ERR_PNPM_FETCH_503.*GET (?<dependency_url>.*):/

# ERR_PNPM_UNSUPPORTED_ENGINE
ERR_PNPM_UNSUPPORTED_ENGINE = /ERR_PNPM_UNSUPPORTED_ENGINE/
Expand Down Expand Up @@ -251,6 +256,8 @@ def handle_pnpm_lock_updater_error(error, pnpm_lock)
pnpm_lock)
end

error_handler.handle_pnpm_error(error)

raise
end
# rubocop:enable Metrics/AbcSize
Expand Down Expand Up @@ -360,5 +367,56 @@ def sanitize_message(message)
end
end
end

class PnpmErrorHandler
extend T::Sig

# remote connection closed
ECONNRESET_ERROR = /ECONNRESET/

# socket hang up error code
SOCKET_HANG_UP = /socket hang up/

# duplicate package error code
DUPLICATE_PACKAGE = /Found duplicates/

ERR_PNPM_NO_VERSIONS = /ERR_PNPM_NO_VERSIONS/

# Initializes the YarnErrorHandler with dependencies and dependency files
sig do
params(
dependencies: T::Array[Dependabot::Dependency],
dependency_files: T::Array[Dependabot::DependencyFile]
).void
end
def initialize(dependencies:, dependency_files:)
@dependencies = dependencies
@dependency_files = dependency_files
end

private

sig { returns(T::Array[Dependabot::Dependency]) }
attr_reader :dependencies

sig { returns(T::Array[Dependabot::DependencyFile]) }
attr_reader :dependency_files

public

# Handles errors with specific to yarn error codes
sig { params(error: SharedHelpers::HelperSubprocessFailed).void }
def handle_pnpm_error(error)
if error.message.match?(DUPLICATE_PACKAGE) || error.message.match?(ERR_PNPM_NO_VERSIONS)

raise DependencyFileNotResolvable, "Error resolving dependency"
end

## Clean error message from ANSI escape codes
return unless error.message.match?(ECONNRESET_ERROR) || error.message.match?(SOCKET_HANG_UP)

raise InconsistentRegistryResponse, "Error resolving dependency"
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# typed: false
# frozen_string_literal: true

require "spec_helper"
require "dependabot/npm_and_yarn/file_updater/pnpm_lockfile_updater"
require "dependabot/npm_and_yarn/dependency_files_filterer"
require "dependabot/dependency"
require "dependabot/dependency_file"
require "dependabot/shared_helpers"
require "dependabot/errors"

RSpec.describe Dependabot::NpmAndYarn::PnpmErrorHandler do
subject(:error_handler) { described_class.new(dependencies: dependencies, dependency_files: dependency_files) }

let(:dependencies) { [dependency] }
let(:error) { instance_double(Dependabot::SharedHelpers::HelperSubprocessFailed, message: error_message) }

let(:dependency) do
Dependabot::Dependency.new(
name: dependency_name,
version: version,
requirements: [],
previous_requirements: [],
package_manager: "npm_and_yarn"
)
end
let(:dependency_files) { project_dependency_files("pnpm/git_dependency_local_file") }

let(:credentials) do
[Dependabot::Credential.new({
"type" => "git_source",
"host" => "github.com"
})]
end

let(:dependency_name) { "@segment/analytics.js-integration-facebook-pixel" }
let(:version) { "github:segmentio/analytics.js-integrations#2.4.1" }
let(:yarn_lock) do
dependency_files.find { |f| f.name == "pnpm.lock" }
end

describe "#initialize" do
it "initializes with dependencies and dependency files" do
expect(error_handler.send(:dependencies)).to eq(dependencies)
expect(error_handler.send(:dependency_files)).to eq(dependency_files)
end
end

describe "#handle_error" do
context "when the error message contains Inconsistent Registry Response" do
let(:error_message) do
"ECONNRESET  request to https://artifactory.schaeffler.com/as.zip failed, reason: socket hang up"
end

it "raises a InconsistentRegistryResponse error with the correct message" do
expect do
error_handler.handle_pnpm_error(error)
end.to raise_error(Dependabot::InconsistentRegistryResponse)
end
end

context "when the error message contains package error" do
let(:error_message) do
"ERR_PNPM_NO_VERSIONS  No versions available for prosemirror-gapcursor. The package may be unpublished."
end

it "raises a DependencyFileNotResolvable error with the correct message" do
expect do
error_handler.handle_pnpm_error(error)
end.to raise_error(Dependabot::DependencyFileNotResolvable)
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"name": "test",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@segment/analytics.js-integration-facebook-pixel": "github:segmentio/analytics.js-integrations#2.4.1"
}
}
Loading

0 comments on commit 07024df

Please sign in to comment.