-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for centralized package manager abstraction for npm_and_yarn
ecosystem
#10862
Changes from all commits
788c271
e686647
875a15c
e8eef8a
adc1457
05643f5
3b9ad7c
e4439e8
cba1cb6
0b3eb23
345ad01
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,7 +19,7 @@ | |
|
||
module Dependabot | ||
module NpmAndYarn | ||
class FileParser < Dependabot::FileParsers::Base | ||
class FileParser < Dependabot::FileParsers::Base # rubocop:disable Metrics/ClassLength | ||
extend T::Sig | ||
|
||
require "dependabot/file_parsers/base/dependency_set" | ||
|
@@ -78,8 +78,82 @@ def parse | |
end | ||
end | ||
|
||
sig { returns(Ecosystem) } | ||
def ecosystem | ||
@ecosystem ||= T.let( | ||
Ecosystem.new( | ||
name: ECOSYSTEM, | ||
package_manager: package_manager_helper.package_manager | ||
), | ||
T.nilable(Ecosystem) | ||
) | ||
end | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This method is used in dependency_snapshot to acquire information related to ecosystem, package manager and in upcoming PRs is going to be language information. That is also used for deprecation and unsupported checks however currently for npm_and_yarn they are disabled. |
||
|
||
private | ||
|
||
sig { returns(PackageManagerHelper) } | ||
def package_manager_helper | ||
@package_manager_helper ||= T.let( | ||
PackageManagerHelper.new( | ||
parsed_package_json, | ||
lockfiles: lockfiles | ||
), T.nilable(PackageManagerHelper) | ||
) | ||
end | ||
|
||
sig { returns(T::Hash[Symbol, T.nilable(Dependabot::DependencyFile)]) } | ||
def lockfiles | ||
{ | ||
npm: package_lock || shrinkwrap, | ||
yarn: yarn_lock, | ||
pnpm: pnpm_lock | ||
} | ||
end | ||
|
||
sig { returns(T.untyped) } | ||
def parsed_package_json | ||
JSON.parse(T.must(package_json.content)) | ||
rescue JSON::ParserError | ||
raise Dependabot::DependencyFileNotParseable, package_json.path | ||
end | ||
|
||
sig { returns(Dependabot::DependencyFile) } | ||
def package_json | ||
# Declare the instance variable with T.let and the correct type | ||
@package_json ||= T.let( | ||
T.must(dependency_files.find { |f| f.name == MANIFEST_FILENAME }), | ||
T.nilable(Dependabot::DependencyFile) | ||
) | ||
end | ||
|
||
sig { returns(T.nilable(Dependabot::DependencyFile)) } | ||
def shrinkwrap | ||
@shrinkwrap ||= T.let(dependency_files.find do |f| | ||
f.name == NpmPackageManager::SHRINKWRAP_LOCKFILE_NAME | ||
end, T.nilable(Dependabot::DependencyFile)) | ||
end | ||
|
||
sig { returns(T.nilable(Dependabot::DependencyFile)) } | ||
def package_lock | ||
@package_lock ||= T.let(dependency_files.find do |f| | ||
f.name == NpmPackageManager::LOCKFILE_NAME | ||
end, T.nilable(Dependabot::DependencyFile)) | ||
end | ||
|
||
sig { returns(T.nilable(Dependabot::DependencyFile)) } | ||
def yarn_lock | ||
@yarn_lock ||= T.let(dependency_files.find do |f| | ||
f.name == YarnPackageManager::LOCKFILE_NAME | ||
end, T.nilable(Dependabot::DependencyFile)) | ||
end | ||
|
||
sig { returns(T.nilable(Dependabot::DependencyFile)) } | ||
def pnpm_lock | ||
@pnpm_lock ||= T.let(dependency_files.find do |f| | ||
f.name == PNPMPackageManager::LOCKFILE_NAME | ||
end, T.nilable(Dependabot::DependencyFile)) | ||
end | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To create an instance from the package manager helper, we require |
||
sig { returns(Dependabot::FileParsers::Base::DependencySet) } | ||
def manifest_dependencies | ||
dependency_set = DependencySet.new | ||
|
@@ -154,7 +228,7 @@ def build_dependency(file:, type:, name:, requirement:) | |
Dependency.new( | ||
name: name, | ||
version: converted_version, | ||
package_manager: "npm_and_yarn", | ||
package_manager: ECOSYSTEM, | ||
requirements: [{ | ||
requirement: requirement_for(requirement), | ||
file: file.name, | ||
|
@@ -166,7 +240,10 @@ def build_dependency(file:, type:, name:, requirement:) | |
|
||
sig { override.void } | ||
def check_required_files | ||
raise DependencyFileNotFound.new(nil, "package.json not found.") unless get_original_file("package.json") | ||
return if get_original_file(MANIFEST_FILENAME) | ||
|
||
raise DependencyFileNotFound.new(nil, | ||
"#{MANIFEST_FILENAME} not found.") | ||
end | ||
|
||
sig { params(requirement: String).returns(T::Boolean) } | ||
|
@@ -186,7 +263,7 @@ def local_path?(requirement) | |
|
||
sig { params(requirement: String).returns(T::Boolean) } | ||
def alias_package?(requirement) | ||
requirement.start_with?("npm:") | ||
requirement.start_with?("#{NpmPackageManager::NAME}:") | ||
end | ||
|
||
sig { params(requirement: String).returns(T::Boolean) } | ||
|
@@ -208,7 +285,7 @@ def git_url_with_semver?(requirement) | |
|
||
sig { params(name: String).returns(T::Boolean) } | ||
def aliased_package_name?(name) | ||
name.include?("@npm:") | ||
name.include?("@#{NpmPackageManager::NAME}:") | ||
end | ||
|
||
sig { returns(T::Array[String]) } | ||
|
@@ -370,8 +447,8 @@ def support_package_files | |
def sub_package_files | ||
return T.must(@sub_package_files) if defined?(@sub_package_files) | ||
|
||
files = dependency_files.select { |f| f.name.end_with?("package.json") } | ||
.reject { |f| f.name == "package.json" } | ||
files = dependency_files.select { |f| f.name.end_with?(MANIFEST_FILENAME) } | ||
.reject { |f| f.name == MANIFEST_FILENAME } | ||
.reject { |f| f.name.include?("node_modules/") } | ||
@sub_package_files ||= T.let(files, T.nilable(T::Array[Dependabot::DependencyFile])) | ||
end | ||
|
@@ -380,7 +457,7 @@ def sub_package_files | |
def package_files | ||
@package_files ||= T.let( | ||
[ | ||
dependency_files.find { |f| f.name == "package.json" }, | ||
dependency_files.find { |f| f.name == MANIFEST_FILENAME }, | ||
*sub_package_files | ||
].compact, T.nilable(T::Array[DependencyFile]) | ||
) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We change the naming as
package_manager_helper
to reduce confusion.package manager
forfile_fetcher
npm
,yarn
andpnpm
and the helper is going to also help to create instance for package manager.