Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions app/lib/actions/katello/content_view/incremental_updates.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ def version_environments_by_cv_id(version_environments)
def plan(version_environments, composite_version_environments, content, dep_solve, hosts, description)
old_new_version_map = {}
output_for_version_ids = []
# Extract composite CV IDs that will be updated via propagate to prevent duplicate auto-publish
propagated_composite_cv_ids = composite_version_environments.map { |cve| cve[:content_view_version].content_view_id }.compact.uniq

sequence do
concurrence do
Expand All @@ -33,8 +35,9 @@ def plan(version_environments, composite_version_environments, content, dep_solv
{:name => version.content_view.name, :version => version.version}
end

action = plan_action(ContentViewVersion::IncrementalUpdate, version,
version_environment[:environments], :resolve_dependencies => dep_solve, :content => content, :description => description)
action = plan_action(ContentViewVersion::IncrementalUpdate, version, version_environment[:environments],
:resolve_dependencies => dep_solve, :content => content, :description => description,
:propagated_composite_cv_ids => propagated_composite_cv_ids)
old_new_version_map[version] = action.new_content_view_version
output_for_version_ids << {:version_id => action.new_content_view_version.id, :output => action.output}
end
Expand Down
16 changes: 12 additions & 4 deletions app/lib/actions/katello/content_view_version/incremental_update.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ def plan(old_version, environments, options = {})
description = options.fetch(:description, '')
content = options.fetch(:content, {})
new_components = options.fetch(:new_components, [])
propagated_composite_cv_ids = options.fetch(:propagated_composite_cv_ids, [])

is_composite = old_version.content_view.composite?
all_components = is_composite ? calculate_components(old_version, new_components) : []
Expand All @@ -46,7 +47,8 @@ def plan(old_version, environments, options = {})
:new_content_view_version_id => publish_action.content_view_version_id,
:environment_ids => environments.map(&:id), :user_id => ::User.current.id,
:history_id => publish_action.history_id,
:old_version => old_version.id)
:old_version => old_version.id,
:propagated_composite_cv_ids => propagated_composite_cv_ids)

if old_version.environments.present?
plan_action(::Actions::Katello::ContentView::Promote, publish_action.version,
Expand Down Expand Up @@ -120,7 +122,8 @@ def plan(old_version, environments, options = {})
:new_content_view_version_id => self.new_content_view_version.id,
:environment_ids => environments.map(&:id), :user_id => ::User.current.id,
:history_id => history.id, :copy_action_outputs => copy_action_outputs,
:old_version => old_version.id)
:old_version => old_version.id,
:propagated_composite_cv_ids => propagated_composite_cv_ids)
promote(new_content_view_version, environments)
end
end
Expand Down Expand Up @@ -223,8 +226,13 @@ def components_repo_instances(old_version_repo, new_component_versions)
def run
version = ::Katello::ContentViewVersion.find(input[:new_content_view_version_id])
if version.latest? && !version.content_view.composite?
output[:auto_publish_content_view_ids] = version.content_view.auto_publish_composites.pluck(:id)
output[:auto_publish_content_view_version_id] = version.id
# Exclude composites that are already being updated via propagate to prevent duplicate publishes
propagated_composite_cv_ids = input[:propagated_composite_cv_ids] || []
auto_publish_ids = version.content_view.auto_publish_composites.pluck(:id) - propagated_composite_cv_ids
unless auto_publish_ids.empty?
output[:auto_publish_content_view_ids] = auto_publish_ids
output[:auto_publish_content_view_version_id] = version.id
end
end

content = { ::Katello::Erratum::CONTENT_TYPE => [],
Expand Down
6 changes: 4 additions & 2 deletions test/actions/katello/content_view_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -951,7 +951,8 @@ class IncrementalUpdatesTest < TestBase
plan_action(action, [{:content_view_version => content_view.version(library), :environments => [library]}], [],
{:errata_ids => ["FOO"]}, true, [], "BadDescription")
assert_action_planned_with(action, ::Actions::Katello::ContentViewVersion::IncrementalUpdate, content_view.version(library), [library],
:content => {:errata_ids => ["FOO"]}, :resolve_dependencies => true, :description => "BadDescription")
:resolve_dependencies => true, :content => {:errata_ids => ["FOO"]}, :description => "BadDescription",
:propagated_composite_cv_ids => [])
end

it 'plans with composite' do
Expand All @@ -966,7 +967,8 @@ class IncrementalUpdatesTest < TestBase
plan_action(action, [{:content_view_version => component, :environments => []}], [{:content_view_version => composite_version, :environments => [library]}],
{:errata_ids => ["FOO"]}, true, [], "BadDescription")
assert_action_planned_with(action, ::Actions::Katello::ContentViewVersion::IncrementalUpdate, component, [],
:content => {:errata_ids => ["FOO"]}, :resolve_dependencies => true, :description => "BadDescription")
:resolve_dependencies => true, :content => {:errata_ids => ["FOO"]}, :description => "BadDescription",
:propagated_composite_cv_ids => [composite_version.content_view_id])
assert_action_planned_with(action, ::Actions::Katello::ContentViewVersion::IncrementalUpdate, composite_version, [library],
:new_components => [new_version],
:description => "BadDescription")
Expand Down
174 changes: 174 additions & 0 deletions test/actions/katello/content_view_version/incremental_update_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
require 'katello_test_helper'

module Actions::Katello::ContentViewVersion
class IncrementalUpdateAutoPropagateTest < ActiveSupport::TestCase
include Dynflow::Testing
include Support::Actions::Fixtures
include FactoryBot::Syntax::Methods

before do
User.current = users(:admin)
end

let(:action_class) { ::Actions::Katello::ContentViewVersion::IncrementalUpdate }
let(:action) { create_action action_class }

describe 'Auto Publish with Propagate' do
let(:component_cv) { katello_content_views(:library_dev_view) }
let(:component_version) { component_cv.versions.first }
let(:composite_cv) { katello_content_views(:composite_view) }
let(:mock_output) { {} }

before do
# Set up composite to have auto_publish enabled
composite_cv.update!(auto_publish: true)

# Ensure component has the composite in its relationships
unless component_version.composites.include?(composite_cv.versions.first)
::Katello::ContentViewComponent.create!(
composite_content_view: composite_cv,
content_view: component_cv,
latest: true
)
end

# Stub the output to be writable
action.stubs(:output).returns(mock_output)
end

it 'excludes propagated composites from auto-publish list' do
# Set input as if plan_self was called with propagated composite IDs
action.input.update(
new_content_view_version_id: component_version.id,
old_version: component_version.id,
propagated_composite_cv_ids: [composite_cv.id]
)

::Katello::ContentViewVersion.stubs(:find).with(component_version.id).returns(component_version)
component_version.stubs(:repositories).returns([])
component_version.stubs(:latest?).returns(true)
component_cv.stubs(:composite?).returns(false)
mock_relation = mock('auto_publish_composites')
mock_relation.expects(:pluck).with(:id).returns([composite_cv.id])
component_cv.stubs(:auto_publish_composites).returns(mock_relation)

action.run
assert_nil mock_output[:auto_publish_content_view_ids], "Expected auto_publish_content_view_ids to be nil when all composites are propagated"
assert_nil mock_output[:auto_publish_content_view_version_id]
end

it 'includes composites in auto-publish list when not propagated' do
# Set input without propagated composites
action.input.update(
new_content_view_version_id: component_version.id,
old_version: component_version.id,
propagated_composite_cv_ids: []
)

::Katello::ContentViewVersion.stubs(:find).with(component_version.id).returns(component_version)
component_version.stubs(:repositories).returns([])
component_version.stubs(:latest?).returns(true)
component_cv.stubs(:composite?).returns(false)
mock_relation = mock('auto_publish_composites')
mock_relation.expects(:pluck).with(:id).returns([composite_cv.id])
component_cv.stubs(:auto_publish_composites).returns(mock_relation)

action.run
auto_publish_ids = mock_output[:auto_publish_content_view_ids]
assert_equal [composite_cv.id], auto_publish_ids, "Expected composite to be in auto-publish list when not propagated"
assert_equal component_version.id, mock_output[:auto_publish_content_view_version_id]
end

it 'handles partial propagation with multiple composites' do
composite_cv2 = create(:katello_content_view, :composite,
organization: composite_cv.organization,
auto_publish: true)
::Katello::ContentViewComponent.create!(
composite_content_view: composite_cv2,
content_view: component_cv,
latest: true
)

action.input.update(
new_content_view_version_id: component_version.id,
old_version: component_version.id,
propagated_composite_cv_ids: [composite_cv.id] # Only first is propagated
)

::Katello::ContentViewVersion.stubs(:find).with(component_version.id).returns(component_version)
component_version.stubs(:repositories).returns([])
component_version.stubs(:latest?).returns(true)
component_cv.stubs(:composite?).returns(false)
mock_relation = mock('auto_publish_composites')
mock_relation.expects(:pluck).with(:id).returns([composite_cv.id, composite_cv2.id])
component_cv.stubs(:auto_publish_composites).returns(mock_relation)

action.run
auto_publish_ids = mock_output[:auto_publish_content_view_ids]

refute_includes auto_publish_ids, composite_cv.id, "Propagated composite should be excluded"
assert_includes auto_publish_ids, composite_cv2.id, "Non-propagated composite should be included"
assert_equal [composite_cv2.id], auto_publish_ids, "Only non-propagated composite should be in list"
assert_equal component_version.id, mock_output[:auto_publish_content_view_version_id]
end

it 'handles nil propagated_composite_cv_ids for backward compatibility' do
# Don't set propagated_composite_cv_ids at all (backward compatibility)
action.input.update(
new_content_view_version_id: component_version.id,
old_version: component_version.id
)

::Katello::ContentViewVersion.stubs(:find).with(component_version.id).returns(component_version)
component_version.stubs(:repositories).returns([])
component_version.stubs(:latest?).returns(true)
component_cv.stubs(:composite?).returns(false)

mock_relation = mock('auto_publish_composites')
mock_relation.expects(:pluck).with(:id).returns([composite_cv.id])
component_cv.stubs(:auto_publish_composites).returns(mock_relation)

action.run
auto_publish_ids = mock_output[:auto_publish_content_view_ids]
assert_equal [composite_cv.id], auto_publish_ids, "Should include composite when propagated_composite_cv_ids is nil"
assert_equal component_version.id, mock_output[:auto_publish_content_view_version_id]
end

it 'does not auto-publish for composite content views' do
composite_version = composite_cv.versions.first

action.input.update(
new_content_view_version_id: composite_version.id,
old_version: composite_version.id,
propagated_composite_cv_ids: []
)

::Katello::ContentViewVersion.stubs(:find).with(composite_version.id).returns(composite_version)
composite_version.stubs(:latest?).returns(true)
composite_version.stubs(:repositories).returns([])
composite_cv.stubs(:composite?).returns(true)

action.run
assert_nil mock_output[:auto_publish_content_view_ids], "Composite CVs should not set auto_publish_content_view_ids"
assert_nil mock_output[:auto_publish_content_view_version_id]
end

it 'does not auto-publish for non-latest versions' do
action.input.update(
new_content_view_version_id: component_version.id,
old_version: component_version.id,
propagated_composite_cv_ids: []
)

::Katello::ContentViewVersion.stubs(:find).with(component_version.id).returns(component_version)
component_version.stubs(:repositories).returns([])
component_version.stubs(:latest?).returns(false)
component_cv.stubs(:composite?).returns(false)

action.run
assert_nil mock_output[:auto_publish_content_view_ids], "Non-latest versions should not set auto_publish_content_view_ids"
assert_nil mock_output[:auto_publish_content_view_version_id]
end
end
end
end