diff --git a/updater/lib/dependabot/updater/group_update_creation.rb b/updater/lib/dependabot/updater/group_update_creation.rb index 16b75d3de68..e5bf856c0d4 100644 --- a/updater/lib/dependabot/updater/group_update_creation.rb +++ b/updater/lib/dependabot/updater/group_update_creation.rb @@ -586,8 +586,12 @@ def existing_pr_covers_job_directories?(pull_request) normalized_job_dirs = job_directories.map { |d| Pathname.new(d).cleanpath.to_s }.uniq normalized_pr_dirs = pr_directories.map { |d| Pathname.new(d).cleanpath.to_s }.uniq - # Match only when the PR directories exactly match the job directories - normalized_job_dirs.sort == normalized_pr_dirs.sort + # Match when the PR's directories are a subset of the job's directories. + # A PR only records the directories that actually had updates, so it can + # legitimately cover fewer directories than the job is configured with. + # A PR covering directories outside the job's scope is stale or belongs + # to a different configuration, so it is not a match. + (normalized_pr_dirs - normalized_job_dirs).empty? end sig do diff --git a/updater/spec/dependabot/updater/operations/group_update_all_versions_spec.rb b/updater/spec/dependabot/updater/operations/group_update_all_versions_spec.rb index c05b660af54..f7b20e6d03d 100644 --- a/updater/spec/dependabot/updater/operations/group_update_all_versions_spec.rb +++ b/updater/spec/dependabot/updater/operations/group_update_all_versions_spec.rb @@ -345,6 +345,67 @@ end end + context "when PR covers a subset of the job's directories" do + before do + allow(job).to receive_messages( + existing_group_pull_requests: [ + { + "dependency-group-name" => "dummy-group", + "pr_number" => 123, + "dependencies" => [ + { + "dependency-name" => "rollup", + "dependency-version" => "2.79.2", + "directory" => "/" + } + ] + } + ].map { |pr| Dependabot::Job::ExistingGroupPullRequest.from_hash(pr) }, + source: mock_source_with_multiple_dirs + ) + end + + it "skips creating a new PR" do + expect(mock_create_group_update).not_to receive(:perform) + expect(dependency_snapshot).to receive(:mark_group_handled).with(dependency_group) + perform + end + end + + context "when PR covers directories outside the job's directories" do + before do + allow(job).to receive_messages( + existing_group_pull_requests: [ + { + "dependency-group-name" => "dummy-group", + "pr_number" => 123, + "dependencies" => [ + { + "dependency-name" => "rollup", + "dependency-version" => "2.79.2", + "directory" => "/" + }, + { + "dependency-name" => "rollup", + "dependency-version" => "2.79.2", + "directory" => "/packages/corelib" + } + ] + } + ].map { |pr| Dependabot::Job::ExistingGroupPullRequest.from_hash(pr) }, + source: mock_source + ) + allow(mock_source).to receive(:directory).and_return("/") + end + + it "creates a new PR" do + allow(mock_create_group_update).to receive(:perform).and_return(mock_dependency_change) + expect(mock_create_group_update).to receive(:perform) + expect(dependency_snapshot).not_to receive(:mark_group_handled).with(dependency_group) + perform + end + end + context "when existing PR has no directory info" do before do allow(job).to receive_messages(