Skip to content
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 hex ecosystem metrics collection #11023

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions hex/lib/dependabot/hex/file_parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,16 @@
require "dependabot/file_parsers/base"
require "dependabot/hex/file_updater/mixfile_sanitizer"
require "dependabot/hex/native_helpers"
require "dependabot/hex/language"
require "dependabot/hex/package_manager"
require "dependabot/hex/requirement"
require "dependabot/shared_helpers"
require "dependabot/errors"

# For docs, see https://hexdocs.pm/mix/Mix.Tasks.Deps.html
module Dependabot
module Hex
extend T::Sig
class FileParser < Dependabot::FileParsers::Base
extend T::Sig
require "dependabot/file_parsers/base/dependency_set"
Expand Down Expand Up @@ -44,6 +48,17 @@ def parse
dependency_set.dependencies.sort_by(&:name)
end

sig { returns(Ecosystem) }
def ecosystem
@ecosystem ||= T.let(begin
Ecosystem.new(
name: ECOSYSTEM,
package_manager: package_manager,
language: language
)
end, T.nilable(Dependabot::Ecosystem))
end

private

sig { returns(T::Array[T.any(T::Hash[String, String], T::Hash[String, T.untyped])]) }
Expand Down Expand Up @@ -137,6 +152,43 @@ def mixfiles
def lockfile
@lockfile ||= T.let(get_original_file("mix.lock"), T.nilable(Dependabot::DependencyFile))
end

sig { returns(Ecosystem::VersionManager) }
def package_manager
@package_manager ||= T.let(
PackageManager.new(hex_version),
T.nilable(Dependabot::Hex::PackageManager)
)
end

sig { returns(T.nilable(Ecosystem::VersionManager)) }
def language
@language ||= T.let(
Language.new(elixir_version),
T.nilable(Dependabot::Hex::Language)
)
end

sig { returns(String) }
def hex_version
T.must(T.must(hex_info).fetch(:hex_version))
end

sig { returns(String) }
def elixir_version
T.must(T.must(hex_info).fetch(:elixir_version))
end

sig { returns(T.nilable(T::Hash[Symbol, T.nilable(String)])) }
def hex_info
@hex_info ||= T.let(begin
version = SharedHelpers.run_shell_command("mix hex.info")
{
hex_version: version.match(/Hex: \s*(\d+\.\d+(.\d+)*)/)&.captures&.first,
elixir_version: version.match(/Elixir: \s*(\d+\.\d+(.\d+)*)/)&.captures&.first
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems to be a pattern, should this be a constant across ecosystems? Tagging @kbukum1 too

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so. It is ecosystem specific and even within the ecosystem the prefixes are different. One starts with hex, the package manager, and the other starts with elixir the language.

}
end, T.nilable(T::Hash[Symbol, T.nilable(String)]))
end
end
end
end
Expand Down
21 changes: 21 additions & 0 deletions hex/lib/dependabot/hex/language.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# typed: strong
# frozen_string_literal: true

require "sorbet-runtime"
require "dependabot/ecosystem"
require "dependabot/hex/version"

module Dependabot
module Hex
LANGUAGE = "elixir"

class Language < Dependabot::Ecosystem::VersionManager
extend T::Sig

sig { params(raw_version: String).void }
def initialize(raw_version)
super(LANGUAGE, Version.new(raw_version))
end
end
end
end
41 changes: 41 additions & 0 deletions hex/lib/dependabot/hex/package_manager.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# typed: strong
# frozen_string_literal: true

require "sorbet-runtime"
require "dependabot/ecosystem"
require "dependabot/hex/version"

module Dependabot
module Hex
ECOSYSTEM = "hex"
PACKAGE_MANAGER = "hex"
SUPPORTED_HEX_VERSIONS = T.let([].freeze, T::Array[Dependabot::Version])

# When a version is going to be unsupported, it will be added here
DEPRECATED_HEX_VERSIONS = T.let([].freeze, T::Array[Dependabot::Version])

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

sig { params(raw_version: String).void }
def initialize(raw_version)
super(
PACKAGE_MANAGER,
Version.new(raw_version),
DEPRECATED_HEX_VERSIONS,
SUPPORTED_HEX_VERSIONS
)
end

sig { returns(T::Boolean) }
def deprecated?
false
end

sig { returns(T::Boolean) }
def unsupported?
false
end
end
end
end
28 changes: 28 additions & 0 deletions hex/spec/dependabot/hex/file_parser_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -452,4 +452,32 @@
end
end
end

describe "#ecosystem" do
subject(:ecosystem) { parser.ecosystem }

it "has the correct name" do
expect(ecosystem.name).to eq "hex"
end

describe "#package_manager" do
subject(:package_manager) { ecosystem.package_manager }

it "returns the correct package manager" do
expect(package_manager.name).to eq "hex"
expect(package_manager.requirement).to be_nil
expect(package_manager.version.to_s).to eq "2.0.6"
end
end

describe "#language" do
subject(:language) { ecosystem.language }

it "returns the correct language" do
expect(language.name).to eq "elixir"
expect(language.requirement).to be_nil
expect(language.version.to_s).to eq "1.14.4"
end
end
end
end
36 changes: 36 additions & 0 deletions hex/spec/dependabot/hex/language_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# typed: false
# frozen_string_literal: true

require "dependabot/hex/language"
require "dependabot/ecosystem"
require "spec_helper"

RSpec.describe Dependabot::Hex::Language do
subject(:language) { described_class.new(version) }

let(:version) { "1.17.3" }

describe "#version" do
it "returns the version" do
expect(language.version).to eq(Dependabot::Hex::Version.new(version))
end
end

describe "#name" do
it "returns the name" do
expect(language.name).to eq(Dependabot::Hex::LANGUAGE)
end
end

describe "#unsupported?" do
it "returns false by default" do
expect(language.unsupported?).to be false
end
end

describe "#deprecated?" do
it "returns false by default" do
expect(language.deprecated?).to be false
end
end
end
36 changes: 36 additions & 0 deletions hex/spec/dependabot/hex/package_manager_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# typed: false
# frozen_string_literal: true

require "dependabot/hex/package_manager"
require "dependabot/ecosystem"
require "spec_helper"

RSpec.describe Dependabot::Hex::PackageManager do
subject(:package_manager) { described_class.new(version) }

let(:version) { "2.1.1" }

describe "#version" do
it "returns the version" do
expect(package_manager.version).to eq(Dependabot::Hex::Version.new(version))
end
end

describe "#name" do
it "returns the name" do
expect(package_manager.name).to eq(Dependabot::Hex::PACKAGE_MANAGER)
end
end

describe "#deprecated_versions" do
it "returns deprecated versions" do
expect(package_manager.deprecated_versions).to eq(Dependabot::Hex::DEPRECATED_HEX_VERSIONS)
end
end

describe "#supported_versions" do
it "returns supported versions" do
expect(package_manager.supported_versions).to eq(Dependabot::Hex::SUPPORTED_HEX_VERSIONS)
end
end
end
Loading