@@ -2533,3 +2533,47 @@ def test_create_version_rejects_cross_package_dependencies(self) -> None:
25332533 created_by = None ,
25342534 dependencies = [entity_in_lp2 .id ],
25352535 )
2536+
2537+ def test_publish_functions_rejected_inside_bulk_draft_changes_for (self ) -> None :
2538+ """
2539+ publish_all_drafts() and publish_from_drafts() must not be callable
2540+ from within a bulk_draft_changes_for() context.
2541+
2542+ bulk_draft_changes_for() opens a DraftChangeLog for accumulating draft
2543+ edits; running a publish inside it mixes draft-change bookkeeping with
2544+ publish bookkeeping in the same atomic block, which corrupts the
2545+ ordering of DraftChangeLog vs. PublishLog records and can leave Drafts
2546+ and Published rows out of sync if the outer context later raises.
2547+ """
2548+ lp1_id = self .learning_package_1 .id
2549+ entity = publishing_api .create_publishable_entity (
2550+ self .learning_package_1 .id ,
2551+ "entity_for_bulk_publish_check" ,
2552+ created = self .now ,
2553+ created_by = None ,
2554+ )
2555+ publishing_api .create_publishable_entity_version (
2556+ entity .id ,
2557+ version_num = 1 ,
2558+ title = "Entity v1" ,
2559+ created = self .now ,
2560+ created_by = None ,
2561+ )
2562+
2563+ with pytest .raises (
2564+ ValidationError ,
2565+ match = f"Cannot publish learning package { lp1_id } while in bulk_draft_changes_for()."
2566+ ):
2567+ with publishing_api .bulk_draft_changes_for (lp1_id ):
2568+ publishing_api .publish_all_drafts (lp1_id )
2569+
2570+ with pytest .raises (
2571+ ValidationError ,
2572+ match = f"Cannot publish learning package { lp1_id } while in bulk_draft_changes_for()."
2573+ ):
2574+ with publishing_api .bulk_draft_changes_for (lp1_id ):
2575+ publishing_api .publish_from_drafts (lp1_id , Draft .objects .filter (entity__learning_package_id = lp1_id ))
2576+
2577+ # But we CAN publish if the bulk_draft_changes_for is a different learning package:
2578+ with publishing_api .bulk_draft_changes_for (self .learning_package_2 .id ):
2579+ publishing_api .publish_all_drafts (lp1_id )
0 commit comments