Skip to content

Commit

Permalink
Merge pull request #7620 from dependabot/brrygrdn/add-support-for-upd…
Browse files Browse the repository at this point in the history
…ate-types

[Grouped Updates] Add support for grouping by dependency type
  • Loading branch information
brrygrdn authored Jul 25, 2023
2 parents 3e127c2 + e84d54f commit 45e5482
Show file tree
Hide file tree
Showing 11 changed files with 2,866 additions and 12 deletions.
30 changes: 26 additions & 4 deletions common/lib/dependabot/dependency_group.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,9 @@ def initialize(name:, rules:)

def contains?(dependency)
return true if @dependencies.include?(dependency)
return false if matches_excluded_pattern?(dependency.name)

positive_match = rules["patterns"].any? { |rule| WildcardMatcher.match?(rule, dependency.name) }
negative_match = rules["exclude-patterns"]&.any? { |rule| WildcardMatcher.match?(rule, dependency.name) }

positive_match && !negative_match
matches_pattern?(dependency.name) && matches_dependency_type?(dependency)
end

def to_h
Expand All @@ -32,5 +30,29 @@ def to_config_yaml
"groups" => { name => rules }
}.to_yaml.delete_prefix("---\n")
end

private

def matches_pattern?(dependency_name)
return true unless rules.key?("patterns") # If no patterns are defined, we pass this check by default

rules["patterns"].any? { |rule| WildcardMatcher.match?(rule, dependency_name) }
end

def matches_excluded_pattern?(dependency_name)
return false unless rules.key?("exclude-patterns") # If there are no exclusions, fail by default

rules["exclude-patterns"].any? { |rule| WildcardMatcher.match?(rule, dependency_name) }
end

def matches_dependency_type?(dependency)
return true unless rules.key?("dependency-type") # If no dependency-type is set, match by default

rules["dependency-type"] == if dependency.production?
"production"
else
"development"
end
end
end
end
81 changes: 74 additions & 7 deletions common/spec/dependabot/dependency_group_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
{
file: "Gemfile",
requirement: "~> 1.1.0",
groups: [],
groups: ["test"],
source: nil
}
]
Expand All @@ -35,29 +35,44 @@
{
file: "Gemfile",
requirement: "~> 1.1.0",
groups: [],
groups: ["test"],
source: nil
}
]
)
end

let(:another_test_dependency) do
let(:production_dependency) do
Dependabot::Dependency.new(
name: "another-test-dependency",
name: "another-dependency",
package_manager: "bundler",
version: "1.1.0",
requirements: [
{
file: "Gemfile",
requirement: "~> 1.1.0",
groups: [],
groups: ["default"],
source: nil
}
]
)
end

# Mock out the dependency-type == production check for Bundler
let(:production_checker) do
lambda do |gemfile_groups|
return true if gemfile_groups.empty?
return true if gemfile_groups.include?("runtime")
return true if gemfile_groups.include?("default")

gemfile_groups.any? { |g| g.include?("prod") }
end
end

before do
allow(Dependabot::Dependency).to receive(:production_check_for_package_manager).and_return(production_checker)
end

describe "#name" do
it "returns the name" do
expect(dependency_group.name).to eq(name)
Expand Down Expand Up @@ -111,7 +126,7 @@

it "returns false if the dependency does not match any patterns" do
expect(dependency_group.dependencies).to eq([])
expect(dependency_group.contains?(another_test_dependency)).to be_falsey
expect(dependency_group.contains?(production_dependency)).to be_falsey
end
end

Expand All @@ -132,10 +147,62 @@

it "returns false if the dependency is not in the dependency list and does not match a pattern" do
expect(dependency_group.dependencies).to include(test_dependency1)
expect(dependency_group.contains?(another_test_dependency)).to be_falsey
expect(dependency_group.contains?(production_dependency)).to be_falsey
end
end
end

context "when the rules specify a dependency-type" do
let(:rules) do
{
"dependency-type" => "production"
}
end

it "returns true if the dependency matches the specified type" do
expect(dependency_group.contains?(production_dependency)).to be_truthy
end

it "returns false if the dependency does not match the specified type" do
expect(dependency_group.contains?(test_dependency1)).to be_falsey
expect(dependency_group.contains?(test_dependency2)).to be_falsey
end

context "when a dependency is specifically excluded" do
let(:rules) do
{
"dependency-type" => "production",
"exclude-patterns" => [production_dependency.name]
}
end

it "returns false even if the dependency matches the specified type" do
expect(dependency_group.contains?(production_dependency)).to be_falsey
end
end
end

context "when the rules specify a mix of conditions" do
let(:rules) do
{
"patterns" => ["*dependency*"],
"exclude-patterns" => ["*-2"],
"dependency-type" => "development"
}
end

it "returns true if the dependency matches the specified type and a pattern" do
expect(dependency_group.contains?(test_dependency1)).to be_truthy
end

it "returns false if the dependency only matches the pattern" do
expect(dependency_group.contains?(production_dependency)).to be_falsey
end

it "returns false if the dependency matches the specified type and pattern but is excluded" do
expect(dependency_group.contains?(test_dependency2)).to be_falsey
end
end
end

describe "#to_config_yaml" do
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,6 @@
end

let(:dependency_files) do
# Let's use the already up-to-date files
original_bundler_files(fixture: "bundler_vendored", directory: "bundler/")
end

Expand Down Expand Up @@ -416,4 +415,54 @@
group_update_all.perform
end
end

context "when the snapshot is only updating development dependenices", :vcr do
let(:job_definition) do
job_definition_fixture("bundler/version_updates/group_update_all_by_dependency_type")
end

let(:dependency_files) do
original_bundler_files(fixture: "bundler_grouped_by_types")
end

it "creates separate pull requests for development and production dependencies" do
expect(mock_service).to receive(:create_pull_request) do |dependency_change|
expect(dependency_change.dependency_group.name).to eql("dev-dependencies")

# We updated the right dependencies
expect(dependency_change.updated_dependencies.map(&:name)).to eql(%w(rubocop))

# We've updated the gemfiles properly
gemfile = dependency_change.updated_dependency_files.find do |file|
file.path == "/Gemfile"
end
expect(gemfile.content).to eql(fixture("bundler_grouped_by_types/updated_development_deps/Gemfile"))

gemfile_lock = dependency_change.updated_dependency_files.find do |file|
file.path == "/Gemfile.lock"
end
expect(gemfile_lock.content).to eql(fixture("bundler_grouped_by_types/updated_development_deps/Gemfile.lock"))
end

expect(mock_service).to receive(:create_pull_request) do |dependency_change|
expect(dependency_change.dependency_group.name).to eql("production-dependencies")

# We updated the right dependencies
expect(dependency_change.updated_dependencies.map(&:name)).to eql(%w(rack))

# We've updated the gemfiles properly
gemfile = dependency_change.updated_dependency_files.find do |file|
file.path == "/Gemfile"
end
expect(gemfile.content).to eql(fixture("bundler_grouped_by_types/updated_production_deps/Gemfile"))

gemfile_lock = dependency_change.updated_dependency_files.find do |file|
file.path == "/Gemfile.lock"
end
expect(gemfile_lock.content).to eql(fixture("bundler_grouped_by_types/updated_production_deps/Gemfile.lock"))
end

group_update_all.perform
end
end
end
10 changes: 10 additions & 0 deletions updater/spec/fixtures/bundler_grouped_by_types/original/Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# frozen_string_literal: true

source "https://rubygems.org"

gem "rack", "~> 2.1.4"
gem "toml-rb", "~> 2.2.0"

group :development do
gem "rubocop", "~> 0.76.0"
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
GEM
remote: https://rubygems.org/
specs:
ast (2.4.2)
citrus (3.0.2)
jaro_winkler (1.5.6)
parallel (1.23.0)
parser (3.2.2.3)
ast (~> 2.4.1)
racc
racc (1.7.1)
rack (2.1.4.3)
rainbow (3.1.1)
rubocop (0.76.0)
jaro_winkler (~> 1.5.1)
parallel (~> 1.10)
parser (>= 2.6)
rainbow (>= 2.2.2, < 4.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 1.7)
ruby-progressbar (1.13.0)
toml-rb (2.2.0)
citrus (~> 3.0, > 3.0)
unicode-display_width (1.6.1)

PLATFORMS
ruby

DEPENDENCIES
rack (~> 2.1.4)
rubocop (~> 0.76.0)
toml-rb (~> 2.2.0)

BUNDLED WITH
1.14.6
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# frozen_string_literal: true

source "https://rubygems.org"

gem "rack", "~> 2.1.4"
gem "toml-rb", "~> 2.2.0"

group :development do
gem "rubocop", "~> 1.54.1"
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
GEM
remote: https://rubygems.org/
specs:
ast (2.4.2)
citrus (3.0.2)
json (2.6.3)
language_server-protocol (3.17.0.3)
parallel (1.23.0)
parser (3.2.2.3)
ast (~> 2.4.1)
racc
racc (1.7.1)
rack (2.1.4.3)
rainbow (3.1.1)
regexp_parser (2.8.1)
rexml (3.2.5)
rubocop (1.54.1)
json (~> 2.3)
language_server-protocol (>= 3.17.0)
parallel (~> 1.10)
parser (>= 3.2.2.3)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.8, < 3.0)
rexml (>= 3.2.5, < 4.0)
rubocop-ast (>= 1.28.0, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 3.0)
rubocop-ast (1.29.0)
parser (>= 3.2.1.0)
ruby-progressbar (1.13.0)
toml-rb (2.2.0)
citrus (~> 3.0, > 3.0)
unicode-display_width (2.4.2)

PLATFORMS
ruby

DEPENDENCIES
rack (~> 2.1.4)
rubocop (~> 1.54.1)
toml-rb (~> 2.2.0)

BUNDLED WITH
1.14.6
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# frozen_string_literal: true

source "https://rubygems.org"

gem "rack", "~> 3.0.8"
gem "toml-rb", "~> 2.2.0"

group :development do
gem "rubocop", "~> 0.76.0"
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
GEM
remote: https://rubygems.org/
specs:
ast (2.4.2)
citrus (3.0.2)
jaro_winkler (1.5.6)
parallel (1.23.0)
parser (3.2.2.3)
ast (~> 2.4.1)
racc
racc (1.7.1)
rack (3.0.8)
rainbow (3.1.1)
rubocop (0.76.0)
jaro_winkler (~> 1.5.1)
parallel (~> 1.10)
parser (>= 2.6)
rainbow (>= 2.2.2, < 4.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 1.7)
ruby-progressbar (1.13.0)
toml-rb (2.2.0)
citrus (~> 3.0, > 3.0)
unicode-display_width (1.6.1)

PLATFORMS
ruby

DEPENDENCIES
rack (~> 3.0.8)
rubocop (~> 0.76.0)
toml-rb (~> 2.2.0)

BUNDLED WITH
1.14.6
Loading

0 comments on commit 45e5482

Please sign in to comment.