110 lines
3.0 KiB
Python
Raw Normal View History

2025-05-31 03:48:10 +08:00
#!/usr/bin/env python3
"""
本地發布腳本
用法
python scripts/release.py patch # 2.0.0 -> 2.0.1
2025-06-11 03:25:08 +08:00
python scripts/release.py minor # 2.0.0 -> 2.1.0
2025-05-31 03:48:10 +08:00
python scripts/release.py major # 2.0.0 -> 3.0.0
"""
2025-06-11 03:25:08 +08:00
import re
2025-05-31 03:48:10 +08:00
import subprocess
import sys
from pathlib import Path
2025-06-11 03:25:08 +08:00
2025-05-31 03:48:10 +08:00
def run_cmd(cmd, check=True):
"""執行命令並返回結果"""
print(f"🔨 執行: {cmd}")
2025-06-11 03:25:08 +08:00
result = subprocess.run(
cmd, shell=True, capture_output=True, text=True, check=False
)
2025-05-31 03:48:10 +08:00
if check and result.returncode != 0:
print(f"❌ 錯誤: {result.stderr}")
sys.exit(1)
return result
2025-06-11 03:25:08 +08:00
2025-05-31 03:48:10 +08:00
def get_current_version():
"""從 pyproject.toml 獲取當前版本"""
pyproject_path = Path("pyproject.toml")
content = pyproject_path.read_text(encoding="utf-8")
match = re.search(r'version = "([^"]+)"', content)
if match:
return match.group(1)
raise ValueError("無法找到版本號")
2025-06-11 03:25:08 +08:00
2025-05-31 03:48:10 +08:00
def bump_version(version_type):
"""更新版本號"""
2025-06-11 03:25:08 +08:00
if version_type not in ["patch", "minor", "major"]:
2025-05-31 03:48:10 +08:00
print("❌ 版本類型必須是: patch, minor, major")
sys.exit(1)
2025-06-11 03:25:08 +08:00
2025-05-31 03:48:10 +08:00
current = get_current_version()
print(f"📦 當前版本: {current}")
2025-06-11 03:25:08 +08:00
# 使用 bump2version with allow-dirty
run_cmd(f"uv run bump2version --allow-dirty {version_type}")
2025-06-11 03:25:08 +08:00
2025-05-31 03:48:10 +08:00
new_version = get_current_version()
print(f"🎉 新版本: {new_version}")
2025-06-11 03:25:08 +08:00
2025-05-31 03:48:10 +08:00
return current, new_version
2025-06-11 03:25:08 +08:00
2025-05-31 03:48:10 +08:00
def main():
if len(sys.argv) != 2:
print(__doc__)
sys.exit(1)
2025-06-11 03:25:08 +08:00
2025-05-31 03:48:10 +08:00
version_type = sys.argv[1]
2025-06-11 03:25:08 +08:00
2025-05-31 03:48:10 +08:00
print("🚀 開始發布流程...")
2025-06-11 03:25:08 +08:00
# 檢查 Git 狀態(僅提示,不阻止)
2025-05-31 03:48:10 +08:00
result = run_cmd("git status --porcelain", check=False)
if result.stdout.strip():
print("⚠️ 有未提交的變更:")
2025-05-31 03:48:10 +08:00
print(result.stdout)
print("💡 將繼續執行(使用 --allow-dirty 模式)")
2025-06-11 03:25:08 +08:00
2025-05-31 03:48:10 +08:00
# 更新版本
old_version, new_version = bump_version(version_type)
2025-06-11 03:25:08 +08:00
2025-05-31 03:48:10 +08:00
# 建置套件
print("📦 建置套件...")
run_cmd("uv build")
2025-06-11 03:25:08 +08:00
2025-05-31 03:48:10 +08:00
# 檢查套件
print("🔍 檢查套件...")
run_cmd("uv run twine check dist/*")
2025-06-11 03:25:08 +08:00
# 提交所有變更(包括版本更新)
2025-05-31 03:48:10 +08:00
print("💾 提交版本更新...")
run_cmd("git add .")
run_cmd(f'git commit -m "🔖 Release v{new_version}"')
run_cmd(f'git tag "v{new_version}"')
2025-06-11 03:25:08 +08:00
2025-05-31 03:48:10 +08:00
# 詢問是否發布
print(f"\n✅ 準備發布版本 {old_version} -> {new_version}")
choice = input("是否發布到 PyPI (y/N): ")
2025-06-11 03:25:08 +08:00
if choice.lower() == "y":
2025-05-31 03:48:10 +08:00
print("🚀 發布到 PyPI...")
run_cmd("uv run twine upload dist/*")
2025-06-11 03:25:08 +08:00
2025-05-31 03:48:10 +08:00
print("📤 推送到 GitHub...")
run_cmd("git push origin main")
run_cmd(f'git push origin "v{new_version}"')
2025-06-11 03:25:08 +08:00
2025-05-31 03:48:10 +08:00
print(f"🎉 發布完成!版本 v{new_version} 已上線")
2025-06-11 03:25:08 +08:00
print("📦 安裝命令: uvx mcp-feedback-enhanced")
2025-05-31 03:48:10 +08:00
else:
print("⏸️ 發布已取消,版本已更新但未發布")
print("💡 您可以稍後手動發布: uv run twine upload dist/*")
2025-06-11 03:25:08 +08:00
2025-05-31 03:48:10 +08:00
if __name__ == "__main__":
2025-06-11 03:25:08 +08:00
main()