#!/usr/bin/env python3 """ Build and publish script for mcp-mailu package. Usage: python scripts/publish.py --build # Build package python scripts/publish.py --test # Upload to TestPyPI python scripts/publish.py --prod # Upload to PyPI python scripts/publish.py --check # Check package """ import argparse import subprocess import sys from pathlib import Path def run_command(cmd: str, check: bool = True) -> subprocess.CompletedProcess: """Run a shell command and return the result.""" print(f"๐Ÿ”ง Running: {cmd}") result = subprocess.run(cmd, shell=True, capture_output=True, text=True) if check and result.returncode != 0: print(f"โŒ Command failed: {cmd}") print(f"stdout: {result.stdout}") print(f"stderr: {result.stderr}") sys.exit(1) return result def build_package(): """Build the package for distribution.""" print("๐Ÿ“ฆ Building package...") # Clean previous builds run_command("rm -rf dist/ build/ *.egg-info") # Build package run_command("uv build") print("โœ… Package built successfully!") def check_package(): """Check the package for common issues.""" print("๐Ÿ” Checking package...") # Check with twine run_command("uv run twine check dist/*") print("โœ… Package check passed!") def upload_test(): """Upload to TestPyPI for testing.""" print("๐Ÿงช Uploading to TestPyPI...") run_command("uv run twine upload --repository testpypi dist/*") print("โœ… Uploaded to TestPyPI!") print("๐Ÿ“‹ Test installation:") print(" pip install -i https://test.pypi.org/simple/ mcp-mailu") def upload_prod(): """Upload to production PyPI.""" print("๐Ÿš€ Uploading to PyPI...") # Double check first response = input("โš ๏ธ This will upload to production PyPI. Continue? (y/N): ") if response.lower() != 'y': print("โŒ Upload cancelled.") return run_command("uv run twine upload dist/*") print("โœ… Uploaded to PyPI!") print("๐Ÿ“‹ Installation:") print(" pip install mcp-mailu") def main(): """Main script entry point.""" parser = argparse.ArgumentParser(description="Build and publish mcp-mailu package") parser.add_argument("--build", action="store_true", help="Build the package") parser.add_argument("--check", action="store_true", help="Check the package") parser.add_argument("--test", action="store_true", help="Upload to TestPyPI") parser.add_argument("--prod", action="store_true", help="Upload to PyPI") args = parser.parse_args() if not any([args.build, args.check, args.test, args.prod]): parser.print_help() return # Ensure we're in the right directory if not Path("pyproject.toml").exists(): print("โŒ Run this script from the project root directory") sys.exit(1) try: if args.build: build_package() if args.check: check_package() if args.test: build_package() check_package() upload_test() if args.prod: build_package() check_package() upload_prod() except KeyboardInterrupt: print("\nโŒ Operation cancelled by user") sys.exit(1) if __name__ == "__main__": main()