""" 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 or update_ready. 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 """ # Skip if this is a new instance (no pk yet) if not instance.pk: return try: # Get the old instance to check for status change old_instance = PluginVersion.objects.get(pk=instance.pk) except PluginVersion.DoesNotExist: return # Check if status is changing TO 'released' or 'update_ready' release_statuses = ['released', 'update_ready'] old_status = old_instance.status new_status = instance.status # Only trigger build if: # 1. Status is changing # 2. New status is a release status # 3. Old status was not a release status (avoid rebuilding on every save) if old_status == new_status: return if new_status not in release_statuses: return # If moving from one release status to another, don't rebuild if old_status in release_statuses: logger.info(f"Plugin {instance.plugin.slug} v{instance.version}: Status changing from {old_status} to {new_status}, no rebuild needed") return logger.info(f"Building plugin ZIP for {instance.plugin.slug} v{instance.version} (status: {old_status} -> {new_status})") # Build the ZIP 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 moving to released status and not already set if new_status in release_statuses and not instance.released_at: instance.released_at = timezone.now() logger.info(f"Built plugin ZIP: {file_path} ({file_size} bytes, checksum: {checksum[:16]}...)")