Skip to content

Commit

Permalink
Create separate PRs for any higher semver outside groups
Browse files Browse the repository at this point in the history
  • Loading branch information
brrygrdn committed Jul 31, 2023
1 parent 3e41bfc commit 6871b37
Show file tree
Hide file tree
Showing 10 changed files with 2,711 additions and 46 deletions.
11 changes: 10 additions & 1 deletion common/lib/dependabot/dependency_group.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ 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?

highest_semver_allowed == SEMVER_MAJOR
end

def to_h
{ "name" => name }
end
Expand Down Expand Up @@ -84,10 +90,13 @@ def pattern_rules?
rules.key?("patterns") && rules["patterns"]&.any?
end

def highest_semver_allowed
rules.fetch("highest-semver-allowed", DEFAULT_SEMVER_LEVEL)
end

def generate_ignore_condition!
return NullIgnoreCondition.new unless experimental_rules_enabled?

highest_semver_allowed = rules.fetch("highest-semver-allowed", DEFAULT_SEMVER_LEVEL)
ignored_update_types = case highest_semver_allowed
when SEMVER_MAJOR
[]
Expand Down
19 changes: 19 additions & 0 deletions updater/lib/dependabot/dependency_group_engine.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,25 @@ def assign_to_groups!(dependencies:)
@groups_calculated = true
end

# TODO: Limit the dependency set to those we know have passed-over updates
#
# This will make a second update attempt on every dependency in any groups
# which do not permit highest version avaliable upgrades.
#
# We can be smarter about this since the versions available will need
# to be checked at least once prior to this set being evaluated.
#
# It will require us to start evaluating the DependencyGroup inside the
# UpdaterChecker and expose methods for the highest resolvable version
# both with and without the group's ignore rules.
#
# I'd rather ship this change separately once we've proved this run schema
# works as expected in terms of creating both group and single PRs which do
# not interfere with each other.
def dependencies_with_ungrouped_semvar_levels
dependency_groups.reject(&:targets_highest_versions_possible?).map(&:dependencies).flatten
end

private

def initialize(dependency_groups:)
Expand Down
3 changes: 2 additions & 1 deletion updater/lib/dependabot/dependency_snapshot.rb
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ def ungrouped_dependencies
# If no groups are defined, all dependencies are ungrouped by default.
return allowed_dependencies unless groups.any?

@dependency_group_engine.ungrouped_dependencies
@dependency_group_engine.ungrouped_dependencies +
@dependency_group_engine.dependencies_with_ungrouped_semvar_levels
end

private
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -271,41 +271,52 @@
original_bundler_files(fixture: "bundler_grouped_by_types")
end

it "creates a group PR for minor- and patch-level changes and individual PRs for major-level changes" do
# We should create a group PR with the latest minor versions for rack and rubocop
expect(mock_service).to receive(:create_pull_request) do |dependency_change|
expect(dependency_change.dependency_group.name).to eql("small-bumps")

# We updated the right dependencies
expect(dependency_change.updated_dependencies.map(&:name)).to eql(%w(rack 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_minor_and_patch/Gemfile"))
let(:updated_group_dependency_files) do
bundler_files_for(fixture: "bundler_grouped_by_types", state: "updated_minor_and_patch")
end

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_minor_and_patch/Gemfile.lock"))
end
let(:updated_rack_major_files) do
bundler_files_for(fixture: "bundler_grouped_by_types", state: "updated_rack_major")
end

# We should also create isolated PRs for their major versions
# expect(mock_service).to receive(:create_pull_request) do |dependency_change|
# expect(dependency_change.dependency_group).to be_nil
let(:updated_rubocop_major_files) do
bundler_files_for(fixture: "bundler_grouped_by_types", state: "updated_rubocop_major")
end

# # We updated the right dependencies
# expect(dependency_change.updated_dependencies.map(&:name)).to eql(%w(rack))
# end
it "creates a group PR for minor- and patch-level changes and individual PRs for major-level changes" do
expect(mock_service).to receive(:create_pull_request).with(
an_object_having_attributes(
dependency_group: an_object_having_attributes(name: "small-bumps"),
updated_dependencies: [
an_object_having_attributes(name: "rack", version: "2.2.7", previous_version: "2.1.4.3"),
an_object_having_attributes(name: "rubocop", version: "0.93.1", previous_version: "0.76.0")
],
updated_dependency_files: updated_group_dependency_files
),
"mock-sha"
)

# We should also create isolated PRs for their major versions
# expect(mock_service).to receive(:create_pull_request) do |dependency_change|
# expect(dependency_change.dependency_group).to be_nil
expect(mock_service).to receive(:create_pull_request).with(
an_object_having_attributes(
dependency_group: nil,
updated_dependencies: [
an_object_having_attributes(name: "rack", version: "3.0.8", previous_version: "2.1.4.3")
],
updated_dependency_files: updated_rack_major_files
),
"mock-sha"
)

# # We updated the right dependencies
# expect(dependency_change.updated_dependencies.map(&:name)).to eql(%w(rubocop))
# end
expect(mock_service).to receive(:create_pull_request).with(
an_object_having_attributes(
dependency_group: nil,
updated_dependencies: [
an_object_having_attributes(name: "rubocop", version: "1.54.2", previous_version: "0.76.0")
],
updated_dependency_files: updated_rubocop_major_files
),
"mock-sha"
)

group_update_all.perform
end
Expand Down
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
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.2"
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.2)
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.2)
toml-rb (~> 2.2.0)

BUNDLED WITH
1.14.6
Loading

0 comments on commit 6871b37

Please sign in to comment.