Skip to content

Commit 4489865

Browse files
committed
Refs #38856 - address rubocop concerns again.
1 parent 30b3b75 commit 4489865

File tree

3 files changed

+78
-65
lines changed

3 files changed

+78
-65
lines changed

app/models/katello/content_view_version.rb

Lines changed: 52 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,57 @@ def auto_publish_composites!(component_task_id)
385385
end
386386
end
387387

388+
class << self
389+
# Trigger a composite publish with coordination for sibling tasks.
390+
# Checks for running component CV publishes and chains if necessary.
391+
def trigger_composite_publish_with_coordination(composite_cv, description, triggered_by_version_id, calling_task_id: nil)
392+
# Find currently running component CV publish tasks
393+
component_cv_ids = composite_cv.components.pluck(:content_view_id)
394+
running_tasks = ForemanTasks::Task::DynflowTask
395+
.for_action(::Actions::Katello::ContentView::Publish)
396+
.where(state: ['planning', 'planned', 'running'])
397+
.select do |task|
398+
task_input = task.input
399+
task_input && component_cv_ids.include?(task_input.dig('content_view', 'id'))
400+
end
401+
402+
sibling_task_ids = running_tasks.map(&:external_id)
403+
# Exclude the calling component task to avoid self-dependency
404+
sibling_task_ids.reject! { |id| id == calling_task_id } if calling_task_id
405+
406+
trigger_publish_with_sibling_tasks(composite_cv, sibling_task_ids, description, triggered_by_version_id)
407+
rescue ForemanTasks::Lock::LockConflict => e
408+
Rails.logger.info("Composite CV #{composite_cv.name} publish lock conflict: #{e.class} - #{e.message}")
409+
::Katello::UINotifications::ContentView::AutoPublishFailure.deliver!(composite_cv)
410+
raise
411+
rescue StandardError => e
412+
Rails.logger.error("Failed to auto-publish composite CV #{composite_cv.name}: #{e.class} - #{e.message}")
413+
Rails.logger.debug(e.backtrace.join("\n")) if e.backtrace
414+
::Katello::UINotifications::ContentView::AutoPublishFailure.deliver!(composite_cv)
415+
raise
416+
end
417+
418+
# Trigger a composite publish, chaining to sibling tasks if any exist
419+
def trigger_publish_with_sibling_tasks(composite_cv, sibling_task_ids, description, triggered_by_version_id)
420+
if sibling_task_ids.any?
421+
ForemanTasks.dynflow.world.chain(
422+
sibling_task_ids,
423+
::Actions::Katello::ContentView::Publish,
424+
composite_cv,
425+
description,
426+
triggered_by_id: triggered_by_version_id
427+
)
428+
else
429+
ForemanTasks.async_task(
430+
::Actions::Katello::ContentView::Publish,
431+
composite_cv,
432+
description,
433+
triggered_by_id: triggered_by_version_id
434+
)
435+
end
436+
end
437+
end
438+
388439
private
389440

390441
# Returns :scheduled, :running, or nil based on composite CV publish task status
@@ -420,61 +471,11 @@ def scheduled_task_for_composite?(task, composite_cv)
420471

421472
args = delayed_plan.args
422473
args.first.is_a?(::Katello::ContentView) && args.first.id == composite_cv.id
423-
rescue NoMethodError, TypeError, Dynflow::Error
474+
rescue NoMethodError, TypeError, Dynflow::Error => e
424475
Rails.logger.error("Failed to check scheduled task for composite CV #{composite_cv.name}: #{e.message}")
425476
false
426477
end
427478

428-
# Trigger a composite publish with coordination for sibling tasks.
429-
# Checks for running component CV publishes and chains if necessary.
430-
def self.trigger_composite_publish_with_coordination(composite_cv, description, triggered_by_version_id, calling_task_id: nil)
431-
# Find currently running component CV publish tasks
432-
component_cv_ids = composite_cv.components.pluck(:content_view_id)
433-
running_tasks = ForemanTasks::Task::DynflowTask
434-
.for_action(::Actions::Katello::ContentView::Publish)
435-
.where(state: ['planning', 'planned', 'running'])
436-
.select do |task|
437-
task_input = task.input
438-
task_input && component_cv_ids.include?(task_input.dig('content_view', 'id'))
439-
end
440-
441-
sibling_task_ids = running_tasks.map(&:external_id)
442-
# Exclude the calling component task to avoid self-dependency
443-
sibling_task_ids.reject! { |id| id == calling_task_id } if calling_task_id
444-
445-
trigger_publish_with_sibling_tasks(composite_cv, sibling_task_ids, description, triggered_by_version_id)
446-
rescue ForemanTasks::Lock::LockConflict => e
447-
Rails.logger.info("Composite CV #{composite_cv.name} publish lock conflict: #{e.class} - #{e.message}")
448-
::Katello::UINotifications::ContentView::AutoPublishFailure.deliver!(composite_cv)
449-
raise
450-
rescue StandardError => e
451-
Rails.logger.error("Failed to auto-publish composite CV #{composite_cv.name}: #{e.class} - #{e.message}")
452-
Rails.logger.debug(e.backtrace.join("\n")) if e.backtrace
453-
::Katello::UINotifications::ContentView::AutoPublishFailure.deliver!(composite_cv)
454-
raise
455-
end
456-
457-
# Trigger a composite publish, chaining to sibling tasks if any exist
458-
def self.trigger_publish_with_sibling_tasks(composite_cv, sibling_task_ids, description, triggered_by_version_id)
459-
if sibling_task_ids.any?
460-
ForemanTasks.dynflow.world.chain(
461-
sibling_task_ids,
462-
::Actions::Katello::ContentView::Publish,
463-
composite_cv,
464-
description,
465-
triggered_by_id: triggered_by_version_id
466-
)
467-
else
468-
ForemanTasks.async_task(
469-
::Actions::Katello::ContentView::Publish,
470-
composite_cv,
471-
description,
472-
triggered_by_id: triggered_by_version_id
473-
)
474-
end
475-
end
476-
477-
478479
# Find active (planning/planned/running) composite publish tasks (does NOT check scheduled tasks)
479480
def find_active_composite_publish_tasks(composite_cv)
480481
relevant_tasks = ForemanTasks::Task::DynflowTask

test/actions/katello/content_view_test.rb

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ class PublishTest < TestBase
249249
end
250250

251251
context 'run phase' do
252-
it 'triggers auto-publish for composite views' do
252+
it 'schedules event for composite views' do
253253
composite_view = katello_content_views(:composite_view)
254254
action.stubs(:task).returns(success_task)
255255

@@ -258,18 +258,15 @@ class PublishTest < TestBase
258258
composite_content_view: composite_view,
259259
content_view: content_view)
260260

261-
# Mock the task relations to simulate no scheduled, no running composite, no sibling tasks
261+
# Mock the task relations to simulate no scheduled composite
262262
ForemanTasks::Task::DynflowTask.stubs(:for_action)
263263
.returns(stub(where: stub(any?: false))) # Scheduled check: no scheduled tasks
264264
.then.returns(stub(where: stub(select: []))) # Running composite check: none
265-
.then.returns(stub(where: stub(select: []))) # Sibling check: none
266-
267-
# Expect async_task to be called (no siblings, so no chaining)
268-
ForemanTasks.expects(:async_task).with(
269-
::Actions::Katello::ContentView::Publish,
270-
composite_view,
271-
anything,
272-
triggered_by_id: anything
265+
266+
# Expect event to be scheduled
267+
::Katello::EventQueue.expects(:push_event).with(
268+
::Katello::Events::AutoPublishCompositeView::EVENT_TYPE,
269+
composite_view.id
273270
)
274271

275272
plan_action action, content_view
@@ -279,9 +276,8 @@ class PublishTest < TestBase
279276
it 'does nothing for non-composite view' do
280277
action.stubs(:task).returns(success_task)
281278

282-
# Should not trigger any auto-publish tasks
283-
ForemanTasks.expects(:async_task).never
284-
ForemanTasks.dynflow.world.expects(:chain).never
279+
# Should not trigger any auto-publish events
280+
::Katello::EventQueue.expects(:push_event).never
285281

286282
plan_action action, katello_content_views(:no_environment_view)
287283
run_action action

test/models/content_view_version_auto_publish_test.rb

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ def test_auto_publish_schedules_event_when_no_composite_activity
4545
# Stub to return no scheduled, no running composite
4646
ForemanTasks::Task::DynflowTask.stubs(:for_action)
4747
.returns(stub(where: stub(any?: false))) # Scheduled check: no scheduled tasks
48-
.then.returns(stub(where: stub(select: []))) # Running composite check: none
48+
.then.returns(stub(where: stub(select: []))) # Running composite check: none
4949

5050
::Katello::EventQueue.expects(:push_event).with(
5151
::Katello::Events::AutoPublishCompositeView::EVENT_TYPE,
@@ -99,5 +99,21 @@ def test_auto_publish_skips_when_composite_already_scheduled
9999
@component1_version.auto_publish_composites!(task_id)
100100
end
101101

102+
def test_scheduled_task_for_composite_handles_errors_gracefully
103+
task_id = SecureRandom.uuid
104+
composite_task = stub(external_id: task_id)
105+
106+
# Mock dynflow world to raise an error when loading delayed plan
107+
world_stub = ForemanTasks.dynflow.world
108+
persistence_stub = stub
109+
persistence_stub.stubs(:load_delayed_plan).raises(Dynflow::Error, "Delayed plan not found")
110+
world_stub.stubs(:persistence).returns(persistence_stub)
111+
112+
# Should log error and return false instead of raising
113+
Rails.logger.expects(:error).with(regexp_matches(/Failed to check scheduled task/))
114+
115+
result = @component1_version.send(:scheduled_task_for_composite?, composite_task, @composite_cv)
116+
refute result
117+
end
102118
end
103119
end

0 commit comments

Comments
 (0)