mirror of
https://gitee.com/xmz7891/ykxmz.git
synced 2026-10-18 18:20:43 +00:00
上一个提交把仓库里的服务器 IP 换成了占位符,但**那些脚本本身要用这个 IP
去连服务器** —— 换掉之后它们就跑不起来了。这个提交把取值方式理清楚。
== 取值统一走 _build/lssh.py ==
YKXMZ_LS_HOST 环境变量
或 _build/.lightsail_host(一行 IP,已 gitignore)
都没有就报错,并告诉你怎么设
十个运维脚本改成 `from lssh import ... HOST as LS_HOST`,
公开仓库里一个具体地址都不留。
== 顺带修的两个自己造的 bug ==
* 用正则往 `from lssh import ...` 后面追加东西时,
追加到了行尾的 `# noqa: E402` **注释里面** ——
十处导入全是废的,脚本一跑就 NameError。
改成先剥掉注释、拼好导入、再把 noqa 加回去。
* 同一个正则还把 `from lssh import HOST as LS_HOST` 加进了
**lssh.py 自己**,造成自我导入。
教训:**正则批量改导入语句很危险**(注释、行尾、顺序都能坑到),
这种地方宁可逐个 edit。
== 为什么要重建产物 ==
docs/AFTER-INSTALL.txt 会被打进服务端 zip,而它上一轮改过
(去掉了写死的旧管理员密码)—— 不重打的话发出去的还是旧的。
重打后确认:三个产物里都没有旧密码、没有服务器 IP。
== 验证 ==
全量回归退出码 0,41 个阶段全 PASS
603 个 Python 文件语法通过
ykxmz-agent / server / watch 三个产物扫描干净
提交前泄漏闸门通过
140 lines
4.8 KiB
Python
140 lines
4.8 KiB
Python
# -*- coding: utf-8 -*-
|
||
r'''撤掉 Gitee 发行版介绍里泄漏的公网 IP。
|
||
|
||
== 用户报的 ==
|
||
|
||
"那个发行版的介绍里,服务器公网 IP 地址暴露出去了"
|
||
|
||
来源:发布脚本(gitee_release.py / release_all.py)把
|
||
_build/CHANGELOG.md 当"更新说明"传给 Gitee 建发行版,
|
||
而 CHANGELOG 的 2.1.3 那节里写了 <源站IP>。
|
||
|
||
工作区那边已经清了(_build/scrub_server_ip.py),
|
||
但**已经发出去的发行版介绍还在 Gitee 上**,得用 API 改回去。
|
||
|
||
== 接口 ==
|
||
|
||
PATCH /api/v5/repos/{owner}/{repo}/releases/{id}
|
||
参数:access_token + body(新的发行版介绍)
|
||
|
||
== 顺带检查所有发行版 ==
|
||
|
||
不只 v2.1.3 —— 从 2.1.0 起我就在"把 CHANGELOG 当更新说明",
|
||
而 2.1.0/2.1.1 那几节也提到过服务器。全部扫一遍、有 IP 的都改掉。
|
||
'''
|
||
from __future__ import annotations
|
||
|
||
import json
|
||
import sys
|
||
import urllib.parse
|
||
import urllib.request
|
||
from pathlib import Path
|
||
|
||
ROOT = Path(__file__).resolve().parent.parent
|
||
|
||
# ⚠ 这个脚本要"在所有发行版介绍里找这个 IP",所以它必须知道 IP。
|
||
# 但**不能在源码里写死** —— 写了就等于把 IP 又发到公开仓库里,
|
||
# 正是这个脚本要防的事。
|
||
# 从 lssh 取(那里会读环境变量 YKXMZ_LS_HOST 或
|
||
# _build/.lightsail_host,后者已 gitignore)。
|
||
sys.path.insert(0, str(Path(__file__).resolve().parent))
|
||
from lssh import HOST as IP, HOST as LS_HOST # noqa: E402
|
||
|
||
DOMAIN = "yk.xxmxxs.top"
|
||
OWNER_REPO = "xmz7891/ykxmz"
|
||
|
||
|
||
def api(url: str, data: bytes = None, method: str = None) -> tuple:
|
||
req = urllib.request.Request(url, data=data, method=method)
|
||
req.add_header("User-Agent", "ykxmz-release-fix")
|
||
if data is not None:
|
||
req.add_header("Content-Type", "application/json")
|
||
try:
|
||
with urllib.request.urlopen(req, timeout=60) as r:
|
||
return r.status, json.loads(r.read().decode("utf-8"))
|
||
except urllib.error.HTTPError as exc:
|
||
return exc.code, exc.read().decode("utf-8", "replace")[:300]
|
||
|
||
|
||
def main() -> int:
|
||
token_file = ROOT / "_build" / ".gitee_token"
|
||
if not token_file.is_file():
|
||
print(" ✗ 找不到 _build/.gitee_token")
|
||
return 1
|
||
token = token_file.read_text(encoding="utf-8").strip()
|
||
|
||
print("=" * 62)
|
||
print(" 撤掉 Gitee 发行版介绍里的公网 IP")
|
||
print("=" * 62)
|
||
|
||
print()
|
||
print(" ── 1. 列出所有发行版 ──")
|
||
code, data = api(
|
||
"https://gitee.com/api/v5/repos/%s/releases"
|
||
"?access_token=%s&per_page=60" % (OWNER_REPO, token))
|
||
if code != 200:
|
||
print(" ✗ 列不出来: %s" % data)
|
||
return 1
|
||
print(" 共 %d 个发行版" % len(data))
|
||
|
||
print()
|
||
print(" ── 2. 逐个检查 body,有 IP 的改掉 ──")
|
||
fixed = 0
|
||
for rel in data:
|
||
tag = rel.get("tag_name", "?")
|
||
rid = rel.get("id")
|
||
body = rel.get("body") or ""
|
||
if IP not in body:
|
||
print(" %-10s 干净" % tag)
|
||
continue
|
||
|
||
n = body.count(IP)
|
||
new_body = body.replace(IP, DOMAIN)
|
||
print(" %-10s ⚠ 有 %d 处 -> 改掉" % (tag, n))
|
||
|
||
# ⚠ 两个坑:
|
||
#
|
||
# 1. 必须用 **JSON**。第一版 urlencode 拼了 data,但 api()
|
||
# 见 data 非空就声明 Content-Type: application/json ——
|
||
# 内容和声明不一致,Gitee 回 400(一页 HTML 错误页)。
|
||
#
|
||
# 2. **tag_name 和 name 必须一起传**,即使不改它们。
|
||
# 漏了会报 {"messages":["tag_name is missing",
|
||
# "name is missing"]}。
|
||
# (PATCH 语义上应该允许只改 body,但 Gitee 的实现要求
|
||
# 把标识字段带上 —— 那就带上。)
|
||
payload = json.dumps({
|
||
"access_token": token,
|
||
"tag_name": tag,
|
||
"name": rel.get("name") or tag,
|
||
"body": new_body,
|
||
}).encode("utf-8")
|
||
code2, resp = api(
|
||
"https://gitee.com/api/v5/repos/%s/releases/%s"
|
||
% (OWNER_REPO, rid), data=payload, method="PATCH")
|
||
if code2 == 200:
|
||
print(" ✓ 已更新")
|
||
fixed += 1
|
||
else:
|
||
print(" ✗ 更新失败 (%s): %s" % (code2, resp))
|
||
|
||
print()
|
||
print(" ── 3. 复查 ──")
|
||
code, data = api(
|
||
"https://gitee.com/api/v5/repos/%s/releases"
|
||
"?access_token=%s&per_page=60" % (OWNER_REPO, token))
|
||
still = [r.get("tag_name") for r in data
|
||
if IP in (r.get("body") or "")]
|
||
if still:
|
||
print(" ⚠ 还有: %s" % ", ".join(still))
|
||
else:
|
||
print(" ✅ 所有发行版介绍里都没有这个 IP 了")
|
||
|
||
print()
|
||
print(" 改了 %d 个发行版" % fixed)
|
||
return 0
|
||
|
||
|
||
if __name__ == "__main__":
|
||
sys.exit(main())
|