Files
ykxmz/_build/release.py
T
xmz7891 4c88ca901f 1.6.2:常规发布
- 版本号 1.6.2 -> 1.6.2
- 重建三端并打包
- 关键测试全过
2026-10-06 23:08:07 +08:00

186 lines
6.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- coding: utf-8 -*-
r"""一条命令完成发布。
用法:
python _build/release.py 1.7.0 # 升版本 + 构建 + 打包 + 推送 + 建发行版
python _build/release.py 1.7.0 --no-readme # 明说这版没改 README
它干这些事:
1. 升版本号(三端 + 文档 + 测试断言)
2. 重建 EXE 和 APK
3. 打三个成品
4. 跑一遍关键测试
5. git 提交 + 推送
6. 在 Gitee 建发行版,把三个文件传上去
7. 覆盖仓库简介(只在第一次需要,重复设成一样也无害)
令牌从 _build/.gitee_token 读(那个文件在 .gitignore 里,不会进仓库)。
第一次用:把令牌写进去就行。
"""
from __future__ import annotations
import os
import subprocess
import time
import sys
from pathlib import Path
ROOT = Path(r"C:\Users\shu\Desktop\deepseekagent\LanRemote")
TOKEN_FILE = ROOT / "_build" / ".gitee_token"
GIT = r"C:\Program Files\Git\bin\git.exe"
GIT_SSH = r"C:\Program Files\Git\usr\bin\ssh.exe"
def sh(args, cwd=ROOT, check=False, timeout=1800, env=None):
merged = dict(os.environ)
if env:
merged.update(env)
proc = subprocess.run(args, cwd=cwd, capture_output=True, text=True,
encoding="utf-8", errors="replace", timeout=timeout,
env=merged)
if check and proc.returncode != 0:
raise RuntimeError(f"{args[0]} 失败:{proc.stdout}\n{proc.stderr}")
return proc
def step(n, title):
print()
print(f" {'=' * 56}")
print(f" {n}. {title}")
print(f" {'=' * 56}")
def read_current_version() -> str:
text = (ROOT / "_build" / "package_remote.py").read_text(encoding="utf-8")
for line in text.splitlines():
if line.startswith("VERSION = "):
return line.split('"')[1]
return "0.0.0"
def main() -> int:
if len(sys.argv) < 2:
print(" 用法: python _build/release.py <新版本号>")
print(f" 当前版本: {read_current_version()}")
return 1
new_version = sys.argv[1]
old_version = read_current_version()
note_readme = "--no-readme" in sys.argv
if not TOKEN_FILE.is_file():
print(f" [失败] 找不到令牌文件 {TOKEN_FILE}")
print(" 把 Gitee 令牌写进那个文件(一行,别加引号)")
return 1
token = TOKEN_FILE.read_text(encoding="utf-8").strip()
if len(token) < 20:
print(f" [失败] 令牌看起来不对(长度 {len(token)})")
return 1
print(f" 发布 {old_version} -> {new_version}")
print(f" README: {'这次改了' if note_readme else '没改'}")
# ---- 1. 升版本 ----
step(1, "升版本号")
proc = sh([sys.executable, "_build/bump_version_generic.py",
old_version, new_version])
print(proc.stdout[-1200:])
if proc.returncode != 0:
print(proc.stderr[-500:])
return 1
# ---- 2. 重建 ----
step(2, "重建 EXE 和 APK")
sh([GIT, "--version"]) # 探活,无关紧要
for args in (["powershell", "-NoProfile", "-ExecutionPolicy", "Bypass",
"-File", "android\\build_apk.ps1"],
["powershell", "-NoProfile", "-ExecutionPolicy", "Bypass",
"-File", "windows\\build_exe.ps1"]):
proc = sh(args, timeout=2400)
tail = (proc.stdout or "").strip().splitlines()[-2:]
for line in tail:
print(f" {line}")
if proc.returncode != 0:
print(f" [失败] {args[-1]}")
print((proc.stderr or "")[-600:])
return 1
# ---- 3. 打包 ----
step(3, "打三个成品")
proc = sh([sys.executable, "_build/package_remote.py"])
print(proc.stdout[-1400:])
if proc.returncode != 0:
return 1
# ---- 4. 关键测试 ----
step(4, "跑关键测试")
for test in ("audit_encoding.py", "test_net_tune.py", "test_chunked_body.py",
"test_admin_js.py"):
proc = sh([sys.executable, "-u", f"_tests/{test}"], timeout=900)
# 用退出码判断 —— 各测试的输出格式不一样
# (有的打"失败 0 项",有的打"结论:JS 合法",字符串匹配会误判)
bad = proc.returncode != 0
print(f" {test:28} {'✗' if bad else '✓'}")
if bad:
print((proc.stdout or "")[-800:])
print((proc.stderr or "")[-400:])
return 1
# 打包测试要起真的中转 + agent,前面刚跑过几个测试,
# 偶尔会撞上端口/隧道还没恢复 —— 重试一次就好
ok_pkg = False
for attempt in range(2):
proc = sh([sys.executable, "-u", "_tests/test_package_remote.py"],
timeout=1800)
out = proc.stdout or ""
last = [ln for ln in out.splitlines() if "通过" in ln or "失败" in ln]
ok_pkg = proc.returncode == 0
tag = "✓" if ok_pkg else ("重试" if attempt == 0 else "✗")
print(f" {'test_package_remote.py':28} {tag} "
f"{last[-1] if last else ''}")
if ok_pkg:
break
print(" (失败,清一下残留再试)")
sh(["powershell", "-NoProfile", "-Command",
"Get-CimInstance Win32_Process -Filter \"Name='python.exe'\" | "
"Where-Object { $_.CommandLine -match 'run_agent' -or "
"$_.CommandLine -match '_tests' -or "
"$_.CommandLine -match 'relay.py' } | "
"ForEach-Object { Stop-Process -Id $_.ProcessId -Force "
"-ErrorAction SilentlyContinue }"], timeout=120)
time.sleep(4)
if not ok_pkg:
return 1
# ---- 5. 提交推送 ----
step(5, "提交并推送")
env = {"GIT_SSH_COMMAND": f'"{GIT_SSH}"'}
sh([GIT, "add", "-A"])
msg = (f"{new_version}:{'README 与' if note_readme else ''}常规发布\n\n"
f"- 版本号 {old_version} -> {new_version}\n"
f"- 重建三端并打包\n"
f"- 关键测试全过\n")
sh([GIT, "commit", "-q", "-m", msg])
proc = sh([GIT, "push", "origin", "main"], env=env, timeout=1800)
print(f" {proc.stdout.strip()[-300:]}")
if proc.returncode != 0:
print(proc.stderr[-600:])
return 1
# ---- 6. 发行版 ----
step(6, "建 Gitee 发行版")
proc = sh([sys.executable, "_build/gitee_release.py", token, new_version],
timeout=2400)
print(proc.stdout[-1200:])
if proc.returncode != 0:
print(proc.stderr[-600:])
return 1
print()
print(f" ✓ {new_version} 发布完成")
print(f" https://gitee.com/xmz7891/ykxmz/releases/tag/v{new_version}")
return 0
if __name__ == "__main__":
sys.exit(main())