mirror of
https://gitee.com/xmz7891/ykxmz.git
synced 2026-10-18 23:00:44 +00:00
按用户定的版本规矩,这一轮既有新内容又有重构,所以升第二位: 1.9.0 -> 2.0.0(最后一位清 0)。 == 一、安装时就能设中转服务器(用户要求)== 安装向导那一页现在是两个输入框:配对码 + 中转服务器。 装的时候是"第一次设置",最该一次把地址填好,不然装完还得去 双击 exe 找设置窗口,很容易漏。 只填域名就行(自动补 https://),留空 = 只走局域网。 批量静默部署同样支持: ykxmz-setup-2.0.0.exe /VERYSILENT /CODE=246810 /RELAY=relay.你的域名 为此新增了一个 --relay-url 参数: --relay 连接一次、打印状态、然后退出(人工排查用) --relay-url 只写进配置,不连接、不退出(安装流程用) 用错那个的话,安装包的命令链会在中间就 return,后面的 --silent 根本跑不到 —— 所以必须分开。 == 二、手表端新增「设置」页(用户要求)== 用户原话:"安卓端加一个设置,各种设置就在这里面调"。 以前设置散在首页(只有一个"中转设置"按钮),现在统一收进设置页: * 中转服务器(填写 / 一键清空) * 记住的配对码(显示 / 清除) * 已配对的电脑(看数量 / 清空,带二次确认) * 关于(版本号从 APK 读,不会和代码对不上) == 三、中转地址默认留空 + 一次性迁移(用户报的问题)== 用户原话:"安卓端为什么还是默认填的我的中转站,以后改成手动填"。 代码里的默认值早就是空的了,但用户看到的还是那个地址 —— 因为**老版本 1.5.0 把作者的域名硬编码成了默认值**,第一次运行就 存进了 SharedPreferences。装新 APK 不会清偏好,所以那个值一直留着。 用户其实从来没"选"过这个地址,是程序硬塞的。 所以加了 migrateLegacyRelay():存的值如果正好等于当时内置的域名, 就当成没设过、清掉。只清完全相等的,用户手填的不会动。 == 四、两个测试自身的毛病 == * test_lan_optimize 那条"没有把旧公网域名当默认值"太粗 —— 它查的是源码里任何位置,于是迁移注释里引用那行老代码就把它判红了。 改成先剥掉注释再查(断言要测的是"有没有把它当默认值")。 * test_image_modes 偶发红:它开真实 Tk 全屏窗口,在全量套件里跑 偶尔起不来(单独跑 19/19 全过)。加了有界重试。 偶发红的测试会让"全量通过"失去意义。 == 五、新增防复发断言 == _tests/test_relay_default_blank.py(15 项,回归阶段 3a3b): * 默认值必须是空串 * 除了迁移清单,源码里不许有写死的中转域名 * 迁移必须真的被调用(不是只定义) * 迁移必须是 remove,不能换成另一个硬编码值 * Windows 端的默认也得是空 理由:用户说过"这个中转站我就自己用,不对外" —— 值得用断言钉死。 == 六、顺手修的 == * release_all.py 崩在 Gitee 那一步:Gitee 的 GET /releases/tags/{tag} 在"标签存在、但还没发行版"时返回的是 **HTTP 200 + JSON null**(不是 404),于是 .get("id") 直接 AttributeError。发 1.9.0 时踩到,已改成容忍 None。 * installer/build_installer.py 里 license-combined.txt 是从 docs/ 三份文档重新生成的,所以光改生成物没用(下次构建又变回去)。 改成在 build_license() 里统一注入当前版本。 * ExE 文件属性里的版本(version_info.txt)从 1.7.1 起就一直没跟上。 全量回归 43 个阶段全部通过。
124 lines
4.2 KiB
Python
124 lines
4.2 KiB
Python
# -*- coding: utf-8 -*-
|
|
r'''把某个版本的成品和官网代码传到中转服务器。
|
|
|
|
用法:
|
|
python _build/deploy_release.py 1.9.0
|
|
python _build/deploy_release.py 1.9.0 --code-only # 只更新官网代码
|
|
python _build/deploy_release.py 1.9.0 --files-only # 只传成品文件
|
|
|
|
== 为什么写成脚本文件而不是 python -c ==
|
|
|
|
这一轮我在 PowerShell 里用 `python -c @"..."@` 写带引号和 $ 的
|
|
Python 代码,失败了四五次(PowerShell 会插值、会吃掉 $、嵌套引号
|
|
转义一层套一层)。凡是超过两行的 Python,一律写成 .py 文件再跑。
|
|
|
|
== 官网上"最新版"是怎么来的 ==
|
|
|
|
relay.py 的 _list_downloads() 按 **mtime 倒序** 返回文件,
|
|
landing.py 的 _version() 取**第一个**能匹配到 x.y.z 的文件名。
|
|
|
|
所以"上传哪个版本,官网就显示哪个版本" —— 不用改任何代码。
|
|
按顺序传 1.9.0、再传 2.0.0,官网就会先显示 1.9.0、再显示 2.0.0。
|
|
'''
|
|
from __future__ import annotations
|
|
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parent.parent
|
|
sys.path.insert(0, str(ROOT / "_build"))
|
|
|
|
from devssh import upload, run # noqa: E402
|
|
|
|
REMOTE_DIR = "/root/lanremote-relay"
|
|
DL_DIR = REMOTE_DIR + "/downloads"
|
|
|
|
# 要传的成品(和 dist/ 里的文件名一致)
|
|
ARTIFACTS = [
|
|
"ykxmz-setup-{v}.exe",
|
|
"ykxmz-watch-{v}.apk",
|
|
"ykxmz-watch-{v}-说明.txt",
|
|
"ykxmz-server-{v}.zip",
|
|
]
|
|
|
|
# 官网/服务端代码
|
|
CODE = ["relay.py", "admin.py", "landing.py", "showcase.py"]
|
|
|
|
|
|
def main() -> int:
|
|
args = [a for a in sys.argv[1:] if a]
|
|
if not args:
|
|
print(__doc__)
|
|
return 1
|
|
version = args[0]
|
|
code_only = "--code-only" in args
|
|
files_only = "--files-only" in args
|
|
|
|
print("=" * 62)
|
|
print(" 部署 %s 到中转服务器" % version)
|
|
print("=" * 62)
|
|
|
|
# ---------------- 成品 ----------------
|
|
if not code_only:
|
|
print()
|
|
print(" ── 1. 上传成品到 downloads/ ──")
|
|
for tpl in ARTIFACTS:
|
|
name = tpl.format(v=version)
|
|
local = ROOT / "dist" / name
|
|
if not local.is_file():
|
|
print(" [跳过] %s 不存在" % name)
|
|
continue
|
|
upload(str(local), "%s/%s" % (DL_DIR, name))
|
|
print(" ✓ %-34s %10d 字节" % (name, local.stat().st_size))
|
|
|
|
# ---------------- 代码 ----------------
|
|
if not files_only:
|
|
print()
|
|
print(" ── 2. 更新官网/服务端代码 ──")
|
|
for name in CODE:
|
|
local = ROOT / "relay" / name
|
|
if not local.is_file():
|
|
print(" [跳过] %s 不存在" % name)
|
|
continue
|
|
upload(str(local), "%s/%s" % (REMOTE_DIR, name))
|
|
print(" ✓ %s" % name)
|
|
|
|
print()
|
|
print(" ── 3. 语法检查 + 重启 ──")
|
|
out = run(
|
|
"cd %s && python3 - <<'PY'\n"
|
|
"import ast\n"
|
|
"for f in %r:\n"
|
|
" ast.parse(open(f, encoding='utf-8').read())\n"
|
|
"print('语法 OK')\n"
|
|
"PY" % (REMOTE_DIR, tuple(CODE)),
|
|
timeout=90)
|
|
print(" " + out[1].strip().splitlines()[-1])
|
|
|
|
out = run("systemctl restart lanremote-relay && sleep 4 && "
|
|
"systemctl is-active lanremote-relay && "
|
|
"grep -m1 '^VERSION' %s/relay.py" % REMOTE_DIR, timeout=120)
|
|
for ln in out[1].strip().splitlines():
|
|
print(" " + ln)
|
|
|
|
# ---------------- 复核 ----------------
|
|
print()
|
|
print(" ── 4. 复核:官网现在显示哪个版本 ──")
|
|
out = run(
|
|
"curl -s -H 'Cache-Control: no-cache' http://127.0.0.1:8080/v1/downloads",
|
|
timeout=60)
|
|
print(" " + out[1].strip()[:400])
|
|
|
|
out = run("curl -s -H 'Cache-Control: no-cache' http://127.0.0.1:8080/ "
|
|
"| grep -o '最新版 [0-9.]*' | head -1", timeout=60)
|
|
print(" 官网首页角标: " + out[1].strip())
|
|
|
|
print()
|
|
print(" 提示:官网 / 走 max-age=60,公网可能需要等一分钟才刷新;")
|
|
print(" 下载链接带 604800 缓存,换版本号正好会换 URL。")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|