""" Plugin Distribution System Signals Handles automatic ZIP creation when plugin versions are released. """ import logging from django.db.models.signals import pre_save, post_save from django.dispatch import receiver from django.utils import timezone from .models import PluginVersion from .utils import create_plugin_zip logger = logging.getLogger(__name__) @receiver(pre_save, sender=PluginVersion) def auto_build_plugin_on_release(sender, instance, **kwargs): """ Automatically build ZIP package when a version is marked as released. This ensures: 1. ZIP file is always up-to-date with source code 2. File size and checksum are auto-calculated 3. No manual intervention needed for releases Triggers on: - New version created with status 'released' - Existing version status changed to 'released' Note: Only 'released' status makes the version available for download. """ # Only build ZIP when status is 'released' should_build = False if not instance.pk: # New instance - build if status is released if instance.status == 'released': should_build = True logger.info(f"New plugin version {instance.plugin.slug} v{instance.version} created with status 'released' - building ZIP") else: # Existing instance - check if status changed to released try: old_instance = PluginVersion.objects.get(pk=instance.pk) old_status = old_instance.status new_status = instance.status # Build if moving to released from any other status if new_status == 'released' and old_status != 'released': should_build = True logger.info(f"Building plugin ZIP for {instance.plugin.slug} v{instance.version} (status: {old_status} -> released)") elif old_status == 'released' and new_status == 'released': # No status change, already released - no rebuild return except PluginVersion.DoesNotExist: return if not should_build: return # Build the ZIP try: file_path, checksum, file_size = create_plugin_zip( platform=instance.plugin.platform, plugin_slug=instance.plugin.slug, version=instance.version, update_version=True ) if not file_path: logger.error(f"Failed to build ZIP for {instance.plugin.slug} v{instance.version}") return # Update the instance with new file info instance.file_path = file_path instance.checksum = checksum instance.file_size = file_size # Set released_at if not already set if not instance.released_at: instance.released_at = timezone.now() logger.info(f"Built plugin ZIP: {file_path} ({file_size} bytes, checksum: {checksum[:16]}...)") except Exception as e: logger.error(f"Error building ZIP for {instance.plugin.slug} v{instance.version}: {e}")