#!/usr/bin/env python3 """ Script to help with publishing to TestPyPI and PyPI. This script provides an interactive way to build and publish the package. """ import subprocess import sys import argparse from pathlib import Path def run_command(cmd: list[str], description: str) -> bool: """Run a command and return success status.""" print(f"\nšŸ”„ {description}") print(f"Command: {' '.join(cmd)}") try: result = subprocess.run(cmd, check=True, cwd=Path(__file__).parent.parent) print(f"āœ… {description} - Success") return True except subprocess.CalledProcessError as e: print(f"āŒ {description} - Failed with exit code {e.returncode}") return False def main(): """Main publishing script.""" parser = argparse.ArgumentParser(description="Publish MCP Name Cheap package") parser.add_argument( "--target", choices=["testpypi", "pypi"], default="testpypi", help="Publishing target (default: testpypi)" ) parser.add_argument( "--skip-tests", action="store_true", help="Skip running tests before publishing" ) parser.add_argument( "--skip-build", action="store_true", help="Skip building (use existing dist/)" ) args = parser.parse_args() print("šŸš€ MCP Name Cheap Publishing Script") print(f"Target: {args.target}") success = True # Run tests unless skipped if not args.skip_tests: print("\n" + "="*60) print("šŸ“‹ Running tests...") success &= run_command( ["python", "run_tests.py", "--all"], "Running all tests and quality checks" ) if not success: print("\nāŒ Tests failed. Fix issues before publishing.") return 1 # Clean and build if not args.skip_build: print("\n" + "="*60) print("šŸ—ļø Building package...") # Clean old builds success &= run_command( ["rm", "-rf", "dist/", "build/"], "Cleaning old build artifacts" ) # Build package success &= run_command( ["python", "-m", "build"], "Building source and wheel distributions" ) if not success: print("\nāŒ Build failed.") return 1 # Check package print("\n" + "="*60) print("šŸ” Checking package...") success &= run_command( ["python", "-m", "twine", "check", "dist/*"], "Checking package with twine" ) if not success: print("\nāŒ Package check failed.") return 1 # Publish print("\n" + "="*60) print(f"šŸ“¦ Publishing to {args.target}...") if args.target == "testpypi": repository_url = "https://test.pypi.org/legacy/" print("\nāš ļø Publishing to TestPyPI") print("You can install the test package with:") print("pip install -i https://test.pypi.org/simple/ mcp-namecheap") else: repository_url = "https://upload.pypi.org/legacy/" print("\n🚨 Publishing to PRODUCTION PyPI") confirm = input("Are you sure you want to publish to production PyPI? (yes/no): ") if confirm.lower() != "yes": print("āŒ Publishing cancelled.") return 1 # Build twine command twine_cmd = ["python", "-m", "twine", "upload"] if args.target == "testpypi": twine_cmd.extend(["--repository-url", repository_url]) twine_cmd.append("dist/*") success &= run_command( twine_cmd, f"Publishing to {args.target}" ) if success: print(f"\nšŸŽ‰ Successfully published to {args.target}!") if args.target == "testpypi": print("\nšŸ“‹ Next steps:") print("1. Test the package: pip install -i https://test.pypi.org/simple/ mcp-namecheap") print("2. If everything works, publish to PyPI: python scripts/publish.py --target pypi") else: print("\n🌟 Package is now live on PyPI!") print("Users can install with: pip install mcp-namecheap") else: print(f"\nāŒ Publishing to {args.target} failed.") return 1 return 0 if __name__ == "__main__": sys.exit(main())