From 521605949a257f674b7eca99f4f77f159c3c8665 Mon Sep 17 00:00:00 2001 From: Mark Allen Date: Fri, 10 Jan 2025 12:27:42 +0000 Subject: [PATCH 1/2] Extract package managers into their own files --- .../lib/dependabot/npm_and_yarn/language.rb | 45 ++++ .../npm_and_yarn/npm_package_manager.rb | 70 +++++++ .../npm_and_yarn/package_manager.rb | 198 +----------------- .../npm_and_yarn/pnpm_package_manager.rb | 55 +++++ .../npm_and_yarn/yarn_package_manager.rb | 56 +++++ 5 files changed, 230 insertions(+), 194 deletions(-) create mode 100644 npm_and_yarn/lib/dependabot/npm_and_yarn/language.rb create mode 100644 npm_and_yarn/lib/dependabot/npm_and_yarn/npm_package_manager.rb create mode 100644 npm_and_yarn/lib/dependabot/npm_and_yarn/pnpm_package_manager.rb create mode 100644 npm_and_yarn/lib/dependabot/npm_and_yarn/yarn_package_manager.rb diff --git a/npm_and_yarn/lib/dependabot/npm_and_yarn/language.rb b/npm_and_yarn/lib/dependabot/npm_and_yarn/language.rb new file mode 100644 index 0000000000..dd1e281f5d --- /dev/null +++ b/npm_and_yarn/lib/dependabot/npm_and_yarn/language.rb @@ -0,0 +1,45 @@ +# typed: strong +# frozen_string_literal: true + +require "dependabot/npm_and_yarn/package_manager" + +module Dependabot + module NpmAndYarn + class Language < Ecosystem::VersionManager + extend T::Sig + NAME = "node" + + SUPPORTED_VERSIONS = T.let([].freeze, T::Array[Dependabot::Version]) + + DEPRECATED_VERSIONS = T.let([].freeze, T::Array[Dependabot::Version]) + + sig do + params( + detected_version: T.nilable(String), + raw_version: T.nilable(String), + requirement: T.nilable(Dependabot::NpmAndYarn::Requirement) + ).void + end + def initialize(detected_version: nil, raw_version: nil, requirement: nil) + super( + name: NAME, + detected_version: detected_version ? Version.new(detected_version) : nil, + version: raw_version ? Version.new(raw_version) : nil, + deprecated_versions: DEPRECATED_VERSIONS, + supported_versions: SUPPORTED_VERSIONS, + requirement: requirement + ) + end + + sig { override.returns(T::Boolean) } + def deprecated? + false + end + + sig { override.returns(T::Boolean) } + def unsupported? + false + end + end + end +end diff --git a/npm_and_yarn/lib/dependabot/npm_and_yarn/npm_package_manager.rb b/npm_and_yarn/lib/dependabot/npm_and_yarn/npm_package_manager.rb new file mode 100644 index 0000000000..e722aec428 --- /dev/null +++ b/npm_and_yarn/lib/dependabot/npm_and_yarn/npm_package_manager.rb @@ -0,0 +1,70 @@ +# typed: strong +# frozen_string_literal: true + +require "dependabot/npm_and_yarn/package_manager" + +module Dependabot + module NpmAndYarn + class NpmPackageManager < Ecosystem::VersionManager + extend T::Sig + NAME = "npm" + RC_FILENAME = ".npmrc" + LOCKFILE_NAME = "package-lock.json" + SHRINKWRAP_LOCKFILE_NAME = "npm-shrinkwrap.json" + + NPM_V6 = "6" + NPM_V7 = "7" + NPM_V8 = "8" + NPM_V9 = "9" + NPM_V10 = "10" + + # Keep versions in ascending order + SUPPORTED_VERSIONS = T.let([ + Version.new(NPM_V7), + Version.new(NPM_V8), + Version.new(NPM_V9), + Version.new(NPM_V10) + ].freeze, T::Array[Dependabot::Version]) + + DEPRECATED_VERSIONS = T.let([Version.new(NPM_V6)].freeze, T::Array[Dependabot::Version]) + + sig do + params( + detected_version: T.nilable(String), + raw_version: T.nilable(String), + requirement: T.nilable(Dependabot::NpmAndYarn::Requirement) + ).void + end + def initialize(detected_version: nil, raw_version: nil, requirement: nil) + super( + name: NAME, + detected_version: detected_version ? Version.new(detected_version) : nil, + version: raw_version ? Version.new(raw_version) : nil, + deprecated_versions: DEPRECATED_VERSIONS, + supported_versions: SUPPORTED_VERSIONS, + requirement: requirement + ) + end + + sig { override.returns(T::Boolean) } + def deprecated? + return false unless detected_version + + return false if unsupported? + + return false unless Dependabot::Experiments.enabled?(:npm_v6_deprecation_warning) + + deprecated_versions.include?(detected_version) + end + + sig { override.returns(T::Boolean) } + def unsupported? + return false unless detected_version + + return false unless Dependabot::Experiments.enabled?(:npm_v6_unsupported_error) + + supported_versions.all? { |supported| supported > detected_version } + end + end + end +end diff --git a/npm_and_yarn/lib/dependabot/npm_and_yarn/package_manager.rb b/npm_and_yarn/lib/dependabot/npm_and_yarn/package_manager.rb index e86198ec9c..013b2c91d4 100644 --- a/npm_and_yarn/lib/dependabot/npm_and_yarn/package_manager.rb +++ b/npm_and_yarn/lib/dependabot/npm_and_yarn/package_manager.rb @@ -6,6 +6,10 @@ require "dependabot/npm_and_yarn/requirement" require "dependabot/npm_and_yarn/version_selector" require "dependabot/npm_and_yarn/registry_helper" +require "dependabot/npm_and_yarn/npm_package_manager" +require "dependabot/npm_and_yarn/yarn_package_manager" +require "dependabot/npm_and_yarn/pnpm_package_manager" +require "dependabot/npm_and_yarn/language" module Dependabot module NpmAndYarn @@ -47,163 +51,6 @@ module NpmAndYarn MANIFEST_PACKAGE_MANAGER_KEY = "packageManager" MANIFEST_ENGINES_KEY = "engines" - class NpmPackageManager < Ecosystem::VersionManager - extend T::Sig - NAME = "npm" - RC_FILENAME = ".npmrc" - LOCKFILE_NAME = "package-lock.json" - SHRINKWRAP_LOCKFILE_NAME = "npm-shrinkwrap.json" - - NPM_V6 = "6" - NPM_V7 = "7" - NPM_V8 = "8" - NPM_V9 = "9" - NPM_V10 = "10" - - # Keep versions in ascending order - SUPPORTED_VERSIONS = T.let([ - Version.new(NPM_V7), - Version.new(NPM_V8), - Version.new(NPM_V9), - Version.new(NPM_V10) - ].freeze, T::Array[Dependabot::Version]) - - DEPRECATED_VERSIONS = T.let([Version.new(NPM_V6)].freeze, T::Array[Dependabot::Version]) - - sig do - params( - detected_version: T.nilable(String), - raw_version: T.nilable(String), - requirement: T.nilable(Dependabot::NpmAndYarn::Requirement) - ).void - end - def initialize(detected_version: nil, raw_version: nil, requirement: nil) - super( - name: NAME, - detected_version: detected_version ? Version.new(detected_version) : nil, - version: raw_version ? Version.new(raw_version) : nil, - deprecated_versions: DEPRECATED_VERSIONS, - supported_versions: SUPPORTED_VERSIONS, - requirement: requirement - ) - end - - sig { override.returns(T::Boolean) } - def deprecated? - return false unless detected_version - - return false if unsupported? - - return false unless Dependabot::Experiments.enabled?(:npm_v6_deprecation_warning) - - deprecated_versions.include?(detected_version) - end - - sig { override.returns(T::Boolean) } - def unsupported? - return false unless detected_version - - return false unless Dependabot::Experiments.enabled?(:npm_v6_unsupported_error) - - supported_versions.all? { |supported| supported > detected_version } - end - end - - class YarnPackageManager < Ecosystem::VersionManager - extend T::Sig - NAME = "yarn" - RC_FILENAME = ".yarnrc" - RC_YML_FILENAME = ".yarnrc.yml" - LOCKFILE_NAME = "yarn.lock" - - YARN_V1 = "1" - YARN_V2 = "2" - YARN_V3 = "3" - - SUPPORTED_VERSIONS = T.let([ - Version.new(YARN_V1), - Version.new(YARN_V2), - Version.new(YARN_V3) - ].freeze, T::Array[Dependabot::Version]) - - DEPRECATED_VERSIONS = T.let([].freeze, T::Array[Dependabot::Version]) - - sig do - params( - detected_version: T.nilable(String), - raw_version: T.nilable(String), - requirement: T.nilable(Dependabot::NpmAndYarn::Requirement) - ).void - end - def initialize(detected_version: nil, raw_version: nil, requirement: nil) - super( - name: NAME, - detected_version: detected_version ? Version.new(detected_version) : nil, - version: raw_version ? Version.new(raw_version) : nil, - deprecated_versions: DEPRECATED_VERSIONS, - supported_versions: SUPPORTED_VERSIONS, - requirement: requirement - ) - end - - sig { override.returns(T::Boolean) } - def deprecated? - false - end - - sig { override.returns(T::Boolean) } - def unsupported? - false - end - end - - class PNPMPackageManager < Ecosystem::VersionManager - extend T::Sig - NAME = "pnpm" - LOCKFILE_NAME = "pnpm-lock.yaml" - PNPM_WS_YML_FILENAME = "pnpm-workspace.yaml" - - PNPM_V7 = "7" - PNPM_V8 = "8" - PNPM_V9 = "9" - - SUPPORTED_VERSIONS = T.let([ - Version.new(PNPM_V7), - Version.new(PNPM_V8), - Version.new(PNPM_V9) - ].freeze, T::Array[Dependabot::Version]) - - DEPRECATED_VERSIONS = T.let([].freeze, T::Array[Dependabot::Version]) - - sig do - params( - detected_version: T.nilable(String), - raw_version: T.nilable(String), - requirement: T.nilable(Dependabot::NpmAndYarn::Requirement) - ).void - end - def initialize(detected_version: nil, raw_version: nil, requirement: nil) - super( - name: NAME, - detected_version: detected_version ? Version.new(detected_version) : nil, - version: raw_version ? Version.new(raw_version) : nil, - deprecated_versions: DEPRECATED_VERSIONS, - supported_versions: SUPPORTED_VERSIONS, - requirement: requirement - ) - end - - sig { override.returns(T::Boolean) } - def deprecated? - false - end - - sig { override.returns(T::Boolean) } - def unsupported? - false - end - end - DEFAULT_PACKAGE_MANAGER = NpmPackageManager::NAME # Define a type alias for the expected class interface @@ -285,43 +132,6 @@ def name_from_engines end end - class Language < Ecosystem::VersionManager - extend T::Sig - NAME = "node" - - SUPPORTED_VERSIONS = T.let([].freeze, T::Array[Dependabot::Version]) - - DEPRECATED_VERSIONS = T.let([].freeze, T::Array[Dependabot::Version]) - - sig do - params( - detected_version: T.nilable(String), - raw_version: T.nilable(String), - requirement: T.nilable(Dependabot::NpmAndYarn::Requirement) - ).void - end - def initialize(detected_version: nil, raw_version: nil, requirement: nil) - super( - name: NAME, - detected_version: detected_version ? Version.new(detected_version) : nil, - version: raw_version ? Version.new(raw_version) : nil, - deprecated_versions: DEPRECATED_VERSIONS, - supported_versions: SUPPORTED_VERSIONS, - requirement: requirement - ) - end - - sig { override.returns(T::Boolean) } - def deprecated? - false - end - - sig { override.returns(T::Boolean) } - def unsupported? - false - end - end - class PackageManagerHelper extend T::Sig extend T::Helpers diff --git a/npm_and_yarn/lib/dependabot/npm_and_yarn/pnpm_package_manager.rb b/npm_and_yarn/lib/dependabot/npm_and_yarn/pnpm_package_manager.rb new file mode 100644 index 0000000000..d8ca5abe5f --- /dev/null +++ b/npm_and_yarn/lib/dependabot/npm_and_yarn/pnpm_package_manager.rb @@ -0,0 +1,55 @@ +# typed: strong +# frozen_string_literal: true + +require "dependabot/npm_and_yarn/package_manager" + +module Dependabot + module NpmAndYarn + class PNPMPackageManager < Ecosystem::VersionManager + extend T::Sig + NAME = "pnpm" + LOCKFILE_NAME = "pnpm-lock.yaml" + PNPM_WS_YML_FILENAME = "pnpm-workspace.yaml" + + PNPM_V7 = "7" + PNPM_V8 = "8" + PNPM_V9 = "9" + + SUPPORTED_VERSIONS = T.let([ + Version.new(PNPM_V7), + Version.new(PNPM_V8), + Version.new(PNPM_V9) + ].freeze, T::Array[Dependabot::Version]) + + DEPRECATED_VERSIONS = T.let([].freeze, T::Array[Dependabot::Version]) + + sig do + params( + detected_version: T.nilable(String), + raw_version: T.nilable(String), + requirement: T.nilable(Dependabot::NpmAndYarn::Requirement) + ).void + end + def initialize(detected_version: nil, raw_version: nil, requirement: nil) + super( + name: NAME, + detected_version: detected_version ? Version.new(detected_version) : nil, + version: raw_version ? Version.new(raw_version) : nil, + deprecated_versions: DEPRECATED_VERSIONS, + supported_versions: SUPPORTED_VERSIONS, + requirement: requirement + ) + end + + sig { override.returns(T::Boolean) } + def deprecated? + false + end + + sig { override.returns(T::Boolean) } + def unsupported? + false + end + end + end +end diff --git a/npm_and_yarn/lib/dependabot/npm_and_yarn/yarn_package_manager.rb b/npm_and_yarn/lib/dependabot/npm_and_yarn/yarn_package_manager.rb new file mode 100644 index 0000000000..40be21474c --- /dev/null +++ b/npm_and_yarn/lib/dependabot/npm_and_yarn/yarn_package_manager.rb @@ -0,0 +1,56 @@ +# typed: strong +# frozen_string_literal: true + +require "dependabot/npm_and_yarn/package_manager" + +module Dependabot + module NpmAndYarn + class YarnPackageManager < Ecosystem::VersionManager + extend T::Sig + NAME = "yarn" + RC_FILENAME = ".yarnrc" + RC_YML_FILENAME = ".yarnrc.yml" + LOCKFILE_NAME = "yarn.lock" + + YARN_V1 = "1" + YARN_V2 = "2" + YARN_V3 = "3" + + SUPPORTED_VERSIONS = T.let([ + Version.new(YARN_V1), + Version.new(YARN_V2), + Version.new(YARN_V3) + ].freeze, T::Array[Dependabot::Version]) + + DEPRECATED_VERSIONS = T.let([].freeze, T::Array[Dependabot::Version]) + + sig do + params( + detected_version: T.nilable(String), + raw_version: T.nilable(String), + requirement: T.nilable(Dependabot::NpmAndYarn::Requirement) + ).void + end + def initialize(detected_version: nil, raw_version: nil, requirement: nil) + super( + name: NAME, + detected_version: detected_version ? Version.new(detected_version) : nil, + version: raw_version ? Version.new(raw_version) : nil, + deprecated_versions: DEPRECATED_VERSIONS, + supported_versions: SUPPORTED_VERSIONS, + requirement: requirement + ) + end + + sig { override.returns(T::Boolean) } + def deprecated? + false + end + + sig { override.returns(T::Boolean) } + def unsupported? + false + end + end + end +end From 71ad8ddd68bb393e33893a09971a588927beaa10 Mon Sep 17 00:00:00 2001 From: Mark Allen Date: Fri, 10 Jan 2025 12:28:39 +0000 Subject: [PATCH 2/2] Add BunPackageManager Co-authored-by: Ashcon Partovi --- .../npm_and_yarn/bun_package_manager.rb | 46 +++++++++++++ .../npm_and_yarn/package_manager.rb | 1 + .../npm_and_yarn/bun_package_manager_spec.rb | 65 +++++++++++++++++++ 3 files changed, 112 insertions(+) create mode 100644 npm_and_yarn/lib/dependabot/npm_and_yarn/bun_package_manager.rb create mode 100644 npm_and_yarn/spec/dependabot/npm_and_yarn/bun_package_manager_spec.rb diff --git a/npm_and_yarn/lib/dependabot/npm_and_yarn/bun_package_manager.rb b/npm_and_yarn/lib/dependabot/npm_and_yarn/bun_package_manager.rb new file mode 100644 index 0000000000..a44150c023 --- /dev/null +++ b/npm_and_yarn/lib/dependabot/npm_and_yarn/bun_package_manager.rb @@ -0,0 +1,46 @@ +# typed: strong +# frozen_string_literal: true + +module Dependabot + module NpmAndYarn + class BunPackageManager < Ecosystem::VersionManager + extend T::Sig + NAME = "bun" + LOCKFILE_NAME = "bun.lock" + + # In Bun 1.1.39, the lockfile format was changed from a binary bun.lockb to a text-based bun.lock. + # https://bun.sh/blog/bun-lock-text-lockfile + MIN_SUPPORTED_VERSION = Version.new("1.1.39") + SUPPORTED_VERSIONS = T.let([MIN_SUPPORTED_VERSION].freeze, T::Array[Dependabot::Version]) + DEPRECATED_VERSIONS = T.let([].freeze, T::Array[Dependabot::Version]) + + sig do + params( + detected_version: T.nilable(String), + raw_version: T.nilable(String), + requirement: T.nilable(Dependabot::NpmAndYarn::Requirement) + ).void + end + def initialize(detected_version: nil, raw_version: nil, requirement: nil) + super( + name: NAME, + detected_version: detected_version ? Version.new(detected_version) : nil, + version: raw_version ? Version.new(raw_version) : nil, + deprecated_versions: DEPRECATED_VERSIONS, + supported_versions: SUPPORTED_VERSIONS, + requirement: requirement + ) + end + + sig { override.returns(T::Boolean) } + def deprecated? + false + end + + sig { override.returns(T::Boolean) } + def unsupported? + supported_versions.all? { |supported| supported > version } + end + end + end +end diff --git a/npm_and_yarn/lib/dependabot/npm_and_yarn/package_manager.rb b/npm_and_yarn/lib/dependabot/npm_and_yarn/package_manager.rb index 013b2c91d4..25ae857dd2 100644 --- a/npm_and_yarn/lib/dependabot/npm_and_yarn/package_manager.rb +++ b/npm_and_yarn/lib/dependabot/npm_and_yarn/package_manager.rb @@ -9,6 +9,7 @@ require "dependabot/npm_and_yarn/npm_package_manager" require "dependabot/npm_and_yarn/yarn_package_manager" require "dependabot/npm_and_yarn/pnpm_package_manager" +require "dependabot/npm_and_yarn/bun_package_manager" require "dependabot/npm_and_yarn/language" module Dependabot diff --git a/npm_and_yarn/spec/dependabot/npm_and_yarn/bun_package_manager_spec.rb b/npm_and_yarn/spec/dependabot/npm_and_yarn/bun_package_manager_spec.rb new file mode 100644 index 0000000000..189bc0f1e2 --- /dev/null +++ b/npm_and_yarn/spec/dependabot/npm_and_yarn/bun_package_manager_spec.rb @@ -0,0 +1,65 @@ +# typed: false +# frozen_string_literal: true + +require "dependabot/npm_and_yarn/package_manager" +require "dependabot/ecosystem" +require "spec_helper" + +RSpec.describe Dependabot::NpmAndYarn::BunPackageManager do + let(:package_manager) do + described_class.new( + detected_version: detected_version, + raw_version: raw_version + ) + end + + let(:detected_version) { "1" } + let(:raw_version) { "1.1.39" } + + describe "#initialize" do + context "when version is a String" do + it "sets the version correctly" do + expect(package_manager.detected_version).to eq(Dependabot::Version.new(detected_version)) + expect(package_manager.version).to eq(Dependabot::Version.new(raw_version)) + end + + it "sets the name correctly" do + expect(package_manager.name).to eq(Dependabot::NpmAndYarn::BunPackageManager::NAME) + end + + it "sets the deprecated_versions correctly" do + expect(package_manager.deprecated_versions).to eq( + Dependabot::NpmAndYarn::BunPackageManager::DEPRECATED_VERSIONS + ) + end + + it "sets the supported_versions correctly" do + expect(package_manager.supported_versions).to eq(Dependabot::NpmAndYarn::BunPackageManager::SUPPORTED_VERSIONS) + end + end + end + + describe "#deprecated?" do + it "returns false" do + expect(package_manager.deprecated?).to be false + end + end + + describe "#unsupported?" do + context "when version is the minimum supported version" do + let(:detected_version) { Dependabot::NpmAndYarn::BunPackageManager::MIN_SUPPORTED_VERSION.to_s } + + it "returns false" do + expect(package_manager.unsupported?).to be false + end + end + + context "when version is unsupported" do + let(:raw_version) { "1.1.38" } + + it "returns true" do + expect(package_manager.unsupported?).to be true + end + end + end +end