Skip to content

Commit

Permalink
implement semver grouping and individual PRs (#7776)
Browse files Browse the repository at this point in the history
  • Loading branch information
jakecoffman authored Aug 10, 2023
1 parent 6f7ac3a commit a3e2c09
Show file tree
Hide file tree
Showing 14 changed files with 4,377 additions and 4,050 deletions.
74 changes: 0 additions & 74 deletions common/lib/dependabot/dependency_group.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,34 +9,12 @@

module Dependabot
class DependencyGroup
ANY_DEPENDENCY_NAME = "*"
SECURITY_UPDATES_ONLY = false

DEFAULT_UPDATE_TYPES = [
SEMVER_MAJOR = "major",
SEMVER_MINOR = "minor",
SEMVER_PATCH = "patch"
].freeze

IGNORE_CONDITION_TYPES = {
SEMVER_MAJOR => Dependabot::Config::IgnoreCondition::MAJOR_VERSION_TYPE,
SEMVER_MINOR => Dependabot::Config::IgnoreCondition::MINOR_VERSION_TYPE,
SEMVER_PATCH => Dependabot::Config::IgnoreCondition::PATCH_VERSION_TYPE
}.freeze

class NullIgnoreCondition
def ignored_versions(_dependency, _security_updates_only)
[]
end
end

attr_reader :name, :rules, :dependencies

def initialize(name:, rules:)
@name = name
@rules = rules
@dependencies = []
@ignore_condition = generate_ignore_condition!
end

def contains?(dependency)
Expand All @@ -46,18 +24,6 @@ def contains?(dependency)
matches_pattern?(dependency.name) && matches_dependency_type?(dependency)
end

# This method generates ignored versions for the given Dependency based on
# the any update-types we have defined.
def ignored_versions_for(dependency)
@ignore_condition.ignored_versions(dependency, SECURITY_UPDATES_ONLY)
end

def targets_highest_versions_possible?
return true unless experimental_rules_enabled?

update_types.include?(SEMVER_MAJOR)
end

def to_h
{ "name" => name }
end
Expand Down Expand Up @@ -93,46 +59,6 @@ def matches_dependency_type?(dependency)
end
end

def pattern_rules?
rules.key?("patterns") && rules["patterns"]&.any?
end

def update_types
rules.fetch("update-types", DEFAULT_UPDATE_TYPES)
end

def generate_ignore_condition!
return NullIgnoreCondition.new unless experimental_rules_enabled?

ignored_update_types = ignored_update_types_for_rules

return NullIgnoreCondition.new unless ignored_update_types.any?

Dependabot.logger.debug("The #{name} group has set ignores for update-type(s): #{ignored_update_types}")

Dependabot::Config::IgnoreCondition.new(
dependency_name: ANY_DEPENDENCY_NAME,
update_types: ignored_update_types
)
end

def ignored_update_types_for_rules
unless update_types.is_a?(Array)
raise ArgumentError,
"The #{name} group has an unexpected value for update-types: '#{update_types}'"
end

unless update_types.any?
raise ArgumentError,
"The #{name} group has specified an empty array for update-types."
end

ignored_update_types = DEFAULT_UPDATE_TYPES - update_types
return [] if ignored_update_types.empty?

IGNORE_CONDITION_TYPES.fetch_values(*ignored_update_types)
end

def experimental_rules_enabled?
Dependabot::Experiments.enabled?(:grouped_updates_experimental_rules)
end
Expand Down
223 changes: 0 additions & 223 deletions common/spec/dependabot/dependency_group_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -205,229 +205,6 @@
end
end

describe "#ignored_versions_for with experimental rules enabled" do
let(:dependency) do
Dependabot::Dependency.new(
name: "business",
package_manager: "bundler",
version: "1.8.0",
requirements: [
{ file: "Gemfile", requirement: "~> 1.8.0", groups: [], source: nil }
]
)
end

before do
Dependabot::Experiments.register(:grouped_updates_experimental_rules, true)
end

after do
Dependabot::Experiments.reset!
end

context "the group has not defined an update-types rule" do
it "returns an empty array as nothing should be ignored" do
expect(dependency_group.ignored_versions_for(dependency)).to be_empty
end
end

context "the group permits all update-types" do
let(:rules) do
{
"update-types" => %w(major minor patch)
}
end

it "returns an empty array as nothing should be ignored" do
expect(dependency_group.ignored_versions_for(dependency)).to be_empty
end
end

context "the group permits minor or lower" do
let(:rules) do
{
"update-types" => %w(minor patch)
}
end

it "returns a range which ignores major versions" do
expect(dependency_group.ignored_versions_for(dependency)).to eql([
">= 2.a"
])
end
end

context "when the group only permits patch versions" do
let(:rules) do
{
"update-types" => ["patch"]
}
end

it "returns ranges which ignore major and minor updates" do
expect(dependency_group.ignored_versions_for(dependency)).to eql([
">= 2.a",
">= 1.9.a, < 2"
])
end
end

context "when the group has empty update-types" do
let(:rules) do
{
"update-types" => []
}
end

it "raises an exception when created" do
expect { dependency_group }.
to raise_error(
ArgumentError,
starting_with("The #{name} group has specified an empty array for update-types.")
)
end
end

context "when the group has garbage update-types" do
let(:rules) do
{
"update-types" => "revision"
}
end

it "raises an exception when created" do
expect { dependency_group }.
to raise_error(
ArgumentError,
starting_with("The #{name} group has an unexpected value for update-types:")
)
end
end
end

describe "#ignored_versions_for with experimental rules disabled" do
let(:dependency) do
Dependabot::Dependency.new(
name: "business",
package_manager: "bundler",
version: "1.8.0",
requirements: [
{ file: "Gemfile", requirement: "~> 1.8.0", groups: [], source: nil }
]
)
end

context "the group has not defined an update-types rule" do
it "returns an empty array as nothing should be ignored" do
expect(dependency_group.ignored_versions_for(dependency)).to be_empty
end
end

context "the group has defined an update-types rule" do
let(:rules) do
{
"update-types" => "patch"
}
end

it "returns an empty array as nothing should be ignored" do
expect(dependency_group.ignored_versions_for(dependency)).to be_empty
end
end
end

describe "#targets_highest_versions_possible with experimental rules enabled" do
before do
Dependabot::Experiments.register(:grouped_updates_experimental_rules, true)
end

after do
Dependabot::Experiments.reset!
end

it "is true by default" do
expect(dependency_group).to be_targets_highest_versions_possible
end

context "when the highest level is major" do
let(:rules) do
{
"update-types" => %w(major minor patch)
}
end

it "is true" do
expect(dependency_group).to be_targets_highest_versions_possible
end
end

context "when the highest level is minor" do
let(:rules) do
{
"update-types" => %w(minor)
}
end

it "is false" do
expect(dependency_group).not_to be_targets_highest_versions_possible
end
end

context "when the highest level is patch" do
let(:rules) do
{
"update-types" => %w(patch)
}
end

it "is false" do
expect(dependency_group).not_to be_targets_highest_versions_possible
end
end
end

describe "#targets_highest_versions_possible with experimental rules enabled" do
it "is true by default" do
expect(dependency_group).to be_targets_highest_versions_possible
end

context "when the highest level is major" do
let(:rules) do
{
"update-types" => %w(major minor patch)
}
end

it "is true" do
expect(dependency_group).to be_targets_highest_versions_possible
end
end

context "when the highest level is minor" do
let(:rules) do
{
"update-types" => %w(minor)
}
end

it "is true" do
expect(dependency_group).to be_targets_highest_versions_possible
end
end

context "when the highest level is patch" do
let(:rules) do
{
"update-types" => %w(patch)
}
end

it "is true" do
expect(dependency_group).to be_targets_highest_versions_possible
end
end
end

describe "#to_config_yaml" do
let(:rules) do
{
Expand Down
7 changes: 7 additions & 0 deletions updater/lib/dependabot/dependency_snapshot.rb
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,16 @@ def groups
@dependency_group_engine.dependency_groups
end

def calculate_ungrouped_dependencies(all_grouped_changes)
@ungrouped_dependencies = allowed_dependencies.select do |dep|
all_grouped_changes.none? { |change| change.name == dep.name }
end
end

def ungrouped_dependencies
# If no groups are defined, all dependencies are ungrouped by default.
return allowed_dependencies unless groups.any?
return @ungrouped_dependencies if defined?(@ungrouped_dependencies)

@dependency_group_engine.ungrouped_dependencies
end
Expand Down
Loading

0 comments on commit a3e2c09

Please sign in to comment.