Skip to content

Commit

Permalink
Centralizing Eco-System, and Package Manager Version Information (#10826
Browse files Browse the repository at this point in the history
)

* move package manager into ecosystem wrapper for storing ecosystem related information alongside with package manager information.
* update package manager to use version manager in ecosystem
  • Loading branch information
kbukum1 authored Oct 31, 2024
1 parent 538aa75 commit e34337c
Show file tree
Hide file tree
Showing 27 changed files with 472 additions and 368 deletions.
19 changes: 16 additions & 3 deletions bundler/lib/dependabot/bundler/file_parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,24 @@ def parse
dependency_set.dependencies
end

sig { returns(PackageManagerBase) }
def package_manager
PackageManager.new(bundler_version)
sig { returns(Ecosystem) }
def ecosystem
@ecosystem ||= T.let(
Ecosystem.new(
name: ECOSYSTEM,
package_manager: package_manager
),
T.nilable(Ecosystem)
)
end

private

sig { returns(Ecosystem::VersionManager) }
def package_manager
PackageManager.new(bundler_version)
end

def check_external_code(dependencies)
return unless @reject_external_code
return unless git_source?(dependencies)
Expand Down Expand Up @@ -309,12 +320,14 @@ def gemspecs
.select { |file| file.name.end_with?(".gemspec") }
end

sig { returns(T::Array[Dependabot::DependencyFile]) }
def imported_ruby_files
dependency_files
.select { |f| f.name.end_with?(".rb") }
.reject { |f| f.name == "gems.rb" }
end

sig { returns(String) }
def bundler_version
@bundler_version ||= Helpers.bundler_version(lockfile)
end
Expand Down
37 changes: 11 additions & 26 deletions bundler/lib/dependabot/bundler/package_manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@

require "sorbet-runtime"
require "dependabot/bundler/version"
require "dependabot/package_manager"
require "dependabot/ecosystem"

module Dependabot
module Bundler
ECOSYSTEM = "bundler"
PACKAGE_MANAGER = "bundler"

# Keep versions in ascending order
Expand All @@ -18,33 +19,17 @@ module Bundler
# DEPRECATED_BUNDLER_VERSIONS = T.let([Version.new("1")].freeze, T::Array[Dependabot::Version])
DEPRECATED_BUNDLER_VERSIONS = T.let([].freeze, T::Array[Dependabot::Version])

class PackageManager < PackageManagerBase
class PackageManager < Dependabot::Ecosystem::VersionManager
extend T::Sig

sig { params(version: T.any(String, Dependabot::Version)).void }
def initialize(version)
@version = T.let(Version.new(version), Dependabot::Version)
@name = T.let(PACKAGE_MANAGER, String)
@deprecated_versions = T.let(DEPRECATED_BUNDLER_VERSIONS, T::Array[Dependabot::Version])
@supported_versions = T.let(SUPPORTED_BUNDLER_VERSIONS, T::Array[Dependabot::Version])
end

sig { override.returns(String) }
attr_reader :name

sig { override.returns(Dependabot::Version) }
attr_reader :version

sig { override.returns(T::Array[Dependabot::Version]) }
attr_reader :deprecated_versions

sig { override.returns(T::Array[Dependabot::Version]) }
attr_reader :supported_versions

sig { override.returns(T::Boolean) }
def unsupported?
# Check if the version is not supported
supported_versions.all? { |supported| supported > version }
sig { params(raw_version: String).void }
def initialize(raw_version)
super(
PACKAGE_MANAGER,
Version.new(raw_version),
DEPRECATED_BUNDLER_VERSIONS,
SUPPORTED_BUNDLER_VERSIONS,
)
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion bundler/spec/dependabot/bundler/file_parser_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -734,7 +734,7 @@

describe "#package_manager" do
it "returns the correct package manager" do
expect(parser.package_manager).to be_a(Dependabot::Bundler::PackageManager)
expect(parser.ecosystem.package_manager).to be_a(Dependabot::Bundler::PackageManager)
end
end
end
4 changes: 2 additions & 2 deletions bundler/spec/dependabot/bundler/package_manager_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# frozen_string_literal: true

require "dependabot/bundler/package_manager"
require "dependabot/package_manager"
require "dependabot/ecosystem"
require "spec_helper"

RSpec.describe Dependabot::Bundler::PackageManager do
Expand Down Expand Up @@ -30,7 +30,7 @@
end

context "when version is a Dependabot::Bundler::Version" do
let(:version) { Dependabot::Bundler::Version.new("2") }
let(:version) { "2" }

it "sets the version correctly" do
expect(package_manager.version).to eq(version)
Expand Down
161 changes: 161 additions & 0 deletions common/lib/dependabot/ecosystem.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
# typed: strong
# frozen_string_literal: true

require "sorbet-runtime"

module Dependabot
class Ecosystem
extend T::Sig

class VersionManager
extend T::Sig
extend T::Helpers

abstract!
# Initialize version information with optional requirement
# @param name [String] the name for the package manager (e.g., "bundler", "npm").
# @param version [Dependabot::Version] the parsed current version.
# @param deprecated_versions [Array<Dependabot::Version>] an array of deprecated versions.
# @param supported_versions [Array<Dependabot::Version>] an array of supported versions.
# @example
# VersionManager.new("bundler", "2.1.4", Dependabot::Version.new("2.1.4"), nil)
sig do
params(
name: String,
version: Dependabot::Version,
deprecated_versions: T::Array[Dependabot::Version],
supported_versions: T::Array[Dependabot::Version]
).void
end
def initialize(
name,
version,
deprecated_versions = [],
supported_versions = []
)
@name = T.let(name, String)
@version = T.let(version, Dependabot::Version)

@deprecated_versions = T.let(deprecated_versions, T::Array[Dependabot::Version])
@supported_versions = T.let(supported_versions, T::Array[Dependabot::Version])
end

# The name of the package manager (e.g., "bundler", "npm").
# @example
# name #=> "bundler"
sig { returns(String) }
attr_reader :name

# The current version of the package manager.
# @example
# version #=> Dependabot::Version.new("2.1.4")
sig { returns(Dependabot::Version) }
attr_reader :version

# Returns an array of deprecated versions of the package manager.
# @example
# deprecated_versions #=> [Version.new("1")]
sig { returns(T::Array[Dependabot::Version]) }
attr_reader :deprecated_versions

# Returns an array of supported versions of the package manager.
sig { returns(T::Array[Dependabot::Version]) }
attr_reader :supported_versions

# Checks if the current version is deprecated.
# Returns true if the version is in the deprecated_versions array; false otherwise.
# @example
# deprecated? #=> true
sig { returns(T::Boolean) }
def deprecated?
return false if unsupported?

deprecated_versions.include?(version)
end

# Checks if the current version is unsupported.
# @example
# unsupported? #=> false
sig { returns(T::Boolean) }
def unsupported?
return false if supported_versions.empty?

# Check if the version is not supported
supported_versions.all? { |supported| supported > version }
end

# Raises an error if the current package manager or language version is unsupported.
# If the version is unsupported, it raises a ToolVersionNotSupported error.
sig { void }
def raise_if_unsupported!
return unless unsupported?

# Example: v2.*, v3.*
supported_versions_message = supported_versions.map { |v| "v#{v}.*" }.join(", ")

raise ToolVersionNotSupported.new(
name,
version.to_s,
supported_versions_message
)
end

# Indicates if the package manager supports later versions beyond those listed in supported_versions.
# By default, returns false if not overridden in the subclass.
# @example
# support_later_versions? #=> true
sig { returns(T::Boolean) }
def support_later_versions?
false
end
end

# Initialize with mandatory name and optional language information.
# @param name [String] the name of the ecosystem (e.g., "bundler", "npm_and_yarn").
# @param package_manager [VersionManager] the package manager.
sig do
params(
name: String,
package_manager: VersionManager
).void
end
def initialize(
name:,
package_manager:
)
@name = T.let(name, String)
@package_manager = T.let(package_manager, VersionManager)
end

# The name of the ecosystem (mandatory).
# @example
# name #=> "npm_and_yarn"
sig { returns(String) }
attr_reader :name

# The information related to the package manager (mandatory).
# @example
# package_manager #=> VersionManager.new("bundler", "2.1.4", Version.new("2.1.4"), nil)
sig { returns(VersionManager) }
attr_reader :package_manager

# Checks if the current version is deprecated.
# Returns true if the version is in the deprecated_versions array; false otherwise.
sig { returns(T::Boolean) }
def deprecated?
package_manager.deprecated?
end

# Checks if the current version is unsupported.
sig { returns(T::Boolean) }
def unsupported?
package_manager.unsupported?
end

# Delegate to the package manager to raise ToolVersionNotSupported if the version is unsupported.
sig { void }
def raise_if_unsupported!
package_manager.raise_if_unsupported!
end
end
end
6 changes: 3 additions & 3 deletions common/lib/dependabot/file_parsers/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

require "sorbet-runtime"
require "dependabot/credential"
require "dependabot/package_manager"
require "dependabot/ecosystem"

module Dependabot
module FileParsers
Expand Down Expand Up @@ -54,8 +54,8 @@ def initialize(dependency_files:, source:, repo_contents_path: nil,
sig { abstract.returns(T::Array[Dependabot::Dependency]) }
def parse; end

sig { returns(T.nilable(PackageManagerBase)) }
def package_manager
sig { returns(T.nilable(Ecosystem)) }
def ecosystem
nil
end

Expand Down
6 changes: 3 additions & 3 deletions common/lib/dependabot/notices.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# frozen_string_literal: true

require "sorbet-runtime"
require "dependabot/package_manager"
require "dependabot/ecosystem"

module Dependabot
class Notice
Expand Down Expand Up @@ -95,11 +95,11 @@ def self.generate_supported_versions_description(supported_versions, support_lat
end

# Generates a deprecation notice for the given package manager.
# @param package_manager [PackageManagerBase] The package manager object.
# @param package_manager [VersionManager] The package manager object.
# @return [Notice, nil] The generated deprecation notice or nil if the package manager is not deprecated.
sig do
params(
package_manager: PackageManagerBase
package_manager: Ecosystem::VersionManager
).returns(T.nilable(Notice))
end
def self.generate_pm_deprecation_notice(package_manager)
Expand Down
Loading

0 comments on commit e34337c

Please sign in to comment.