mirror of
https://gitee.com/xmz7891/ykxmz.git
synced 2026-10-18 13:40:45 +00:00
195 lines
7.0 KiB
Python
195 lines
7.0 KiB
Python
# -*- 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, "打成品(安装包 + 服务器 zip + APK)")
|
||
proc = sh([sys.executable, "_build/package_remote.py"])
|
||
print(proc.stdout[-1200:])
|
||
if proc.returncode != 0:
|
||
return 1
|
||
|
||
# 电脑端对外发的是**安装包**,不是 zip
|
||
proc = sh([sys.executable, "installer/build_installer.py"], timeout=1800)
|
||
for line in (proc.stdout or "").splitlines():
|
||
if "安装包" in line or "失败" in line:
|
||
print(f" {line.strip()}")
|
||
if proc.returncode != 0:
|
||
print((proc.stdout or "")[-1200:])
|
||
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(3):
|
||
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(8)
|
||
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())
|