#!/usr/bin/env python3 """ Shared utilities for Modal deployment and run scripts. """ import re import subprocess from pathlib import Path DEPLOYMENT_UTILS_PATH = Path("suno_utils") / "worker" / "deployment_utils.py" def find_app_name_prefix(content: str) -> str | None: """Find the app name prefix from APP_NAME = get_app_name("prefix") pattern.""" get_app_name_pattern = r'APP_NAME\s*=\s*get_app_name\(["\']([^"\']+)["\']\)' match = re.search(get_app_name_pattern, content) if match: return match.group(1) return None def uses_deployment_utils(content: str) -> bool: """Check if file uses the centralized deployment system.""" return "from suno_utils.worker.deployment_utils import" in content def update_deployment_utils(repo_root: Path, deployment_type: str) -> str: """Update the deployment_utils.py file with the static deployment type.""" deployment_utils_path = repo_root / DEPLOYMENT_UTILS_PATH # Read current content content = deployment_utils_path.read_text() # Store original content for rollback original_content = content # Replace the _STATIC_DEPLOYMENT_TYPE value pattern = r'_STATIC_DEPLOYMENT_TYPE = "[^"]*"' replacement = f'_STATIC_DEPLOYMENT_TYPE = "{deployment_type}"' updated_content = re.sub(pattern, replacement, content) # Validate that the replacement actually occurred if updated_content == content: raise RuntimeError( f"Failed to update deployment type in {deployment_utils_path}. " f"Could not find _STATIC_DEPLOYMENT_TYPE pattern to replace." ) # Validate that the new deployment type is present in the updated content if f'_STATIC_DEPLOYMENT_TYPE = "{deployment_type}"' not in updated_content: raise RuntimeError( f"Failed to properly set deployment type to '{deployment_type}' in {deployment_utils_path}. " f"Update may have failed." ) # Write updated content deployment_utils_path.write_text(updated_content) return original_content def restore_deployment_utils(repo_root: Path, original_content: str) -> None: """Restore the original deployment_utils.py content.""" deployment_utils_path = repo_root / DEPLOYMENT_UTILS_PATH deployment_utils_path.write_text(original_content) def find_repo_root() -> Path: """Find the repository root (directory containing suno_utils package).""" repo_root = Path.cwd() if not (repo_root / "suno_utils").exists(): # Try parent directories for parent in Path.cwd().parents: if (parent / "suno_utils").exists(): repo_root = parent break else: raise RuntimeError("Error: Could not find suno_utils package directory") return repo_root def run_modal_command( command: str, file_path: Path, repo_root: Path, additional_args: list[str] | None = None, ) -> int: """ Run a modal command with streaming output. Args: command: The modal command to run (e.g., "deploy" or "run") file_path: Path to the modal file repo_root: Repository root path additional_args: Additional arguments to pass to the command Returns: Return code from the modal command """ # Use relative path from repo root relative_path = file_path.relative_to(repo_root) # Build command cmd = ["uv", "run", "modal", command, str(relative_path)] if additional_args: cmd.extend(additional_args) # Run with inherited stdout/stderr to preserve rich formatting process = subprocess.Popen( cmd, cwd=repo_root, ) # Wait for process to complete return process.wait()