diff --git a/common/lib/dependabot/dependency_group.rb b/common/lib/dependabot/dependency_group.rb index c89c752c08..008e98fc2a 100644 --- a/common/lib/dependabot/dependency_group.rb +++ b/common/lib/dependabot/dependency_group.rb @@ -22,15 +22,21 @@ class DependencyGroup sig { returns(T::Array[Dependabot::Dependency]) } attr_reader :dependencies + sig { returns(String) } + attr_reader :applies_to + sig do params( name: String, - rules: T::Hash[String, T.untyped] + rules: T::Hash[String, T.untyped], + applies_to: T.nilable(String) ) .void end - def initialize(name:, rules:) + def initialize(name:, rules:, applies_to: "version-updates") @name = name + # For backwards compatibility, if no applies_to is provided, default to "version-updates" + @applies_to = T.let(applies_to || "version-updates", String) @rules = rules @dependencies = T.let([], T::Array[Dependabot::Dependency]) end diff --git a/silent/tests/testdata/su-group-pattern.txt b/silent/tests/testdata/su-group-pattern.txt index 29379c9a5e..4b05958ad9 100644 --- a/silent/tests/testdata/su-group-pattern.txt +++ b/silent/tests/testdata/su-group-pattern.txt @@ -83,6 +83,7 @@ job: security-updates-only: true dependency-groups: - name: related + applies-to: "security-updates" rules: patterns: - "related-*" diff --git a/silent/tests/testdata/su-group-semver.txt b/silent/tests/testdata/su-group-semver.txt index b429767399..3205109b34 100644 --- a/silent/tests/testdata/su-group-semver.txt +++ b/silent/tests/testdata/su-group-semver.txt @@ -83,6 +83,7 @@ job: security-updates-only: true dependency-groups: - name: dev + applies-to: security-updates rules: update-types: - minor diff --git a/silent/tests/testdata/su-group-type.txt b/silent/tests/testdata/su-group-type.txt index 0bf11c9166..e8109038a5 100644 --- a/silent/tests/testdata/su-group-type.txt +++ b/silent/tests/testdata/su-group-type.txt @@ -85,8 +85,10 @@ job: grouped-update: true dependency-groups: - name: dev + applies-to: security-updates rules: dependency-type: development - name: prod + applies-to: security-updates rules: dependency-type: production diff --git a/updater/lib/dependabot/dependency_group_engine.rb b/updater/lib/dependabot/dependency_group_engine.rb index 5993bac7d8..9cd9fcafee 100644 --- a/updater/lib/dependabot/dependency_group_engine.rb +++ b/updater/lib/dependabot/dependency_group_engine.rb @@ -31,7 +31,8 @@ def self.from_job_config(job:) # Since there are no groups, the default behavior is to group all dependencies, so create a fake group. job.dependency_groups << { "name" => "#{job.package_manager} group", - "rules" => { "patterns" => ["*"] } + "rules" => { "patterns" => ["*"] }, + "applies-to" => "security-updates" } # This ensures refreshes work for these dynamic groups. @@ -41,9 +42,16 @@ def self.from_job_config(job:) end groups = job.dependency_groups.map do |group| - Dependabot::DependencyGroup.new(name: group["name"], rules: group["rules"]) + Dependabot::DependencyGroup.new(name: group["name"], rules: group["rules"], applies_to: group["applies-to"]) end + # Filter out version updates when doing security updates and visa versa + groups = if job.security_updates_only? + groups.select { |group| group.applies_to == "security-updates" } + else + groups.select { |group| group.applies_to == "version-updates" } + end + new(dependency_groups: groups) end diff --git a/updater/spec/dependabot/dependency_group_engine_spec.rb b/updater/spec/dependabot/dependency_group_engine_spec.rb index 034d7f0c6d..c180b6c6cd 100644 --- a/updater/spec/dependabot/dependency_group_engine_spec.rb +++ b/updater/spec/dependabot/dependency_group_engine_spec.rb @@ -13,11 +13,20 @@ include DependencyFileHelpers let(:dependency_group_engine) { described_class.from_job_config(job: job) } - + let(:source) do + Dependabot::Source.new( + provider: "github", + repo: "gocardless/bump", + directory: "/", + branch: "master" + ) + end + let(:security_updates_only) { false } let(:job) do instance_double(Dependabot::Job, dependency_groups: dependency_groups_config, - security_updates_only?: false) + source: source, + security_updates_only?: security_updates_only) end let(:dummy_pkg_a) do @@ -108,6 +117,45 @@ end end + context "when a job has grouped configured, and it's a version update" do + let(:dependency_groups_config) do + [ + { + "name" => "group-a", + "rules" => { + "patterns" => ["dummy-pkg-*"], + "exclude-patterns" => ["dummy-pkg-b"] + } + }, + { + "name" => "group-b", + "applies-to" => "security-updates", + "rules" => { + "patterns" => %w(dummy-pkg-b dummy-pkg-c) + } + } + ] + end + + describe "::from_job_config" do + it "filters out the security update" do + expect(dependency_group_engine.dependency_groups.length).to eql(1) + expect(dependency_group_engine.dependency_groups.map(&:name)).to eql(%w(group-a)) + end + end + + context "when it's a security update" do + let(:security_updates_only) { true } + + describe "::from_job_config" do + it "filters out the version update" do + expect(dependency_group_engine.dependency_groups.length).to eql(1) + expect(dependency_group_engine.dependency_groups.map(&:name)).to eql(%w(group-b)) + end + end + end + end + context "when a job has groups configured" do let(:dependency_groups_config) do [