mirror of
https://gitee.com/xmz7891/ykxmz.git
synced 2026-10-18 23:00:44 +00:00
用户定的新规矩:
「你对外公开的数据里不要包含那个中转站管理的页面,你就只能提官网」
用户确认的范围:只清理「我对外的公开发言」
(发布说明 / 更新日志 / 官网 / README / 我给出的汇报),
服务端 zip 里的运维文档保留(装服务器的人需要它),
源码实现保留(路径是功能本身,藏起来没法维护)。
清掉的内容:
* CHANGELOG.md:1.8.0 条目里"管理后台重做"整段、
"管理页显示成一屏源码"、"管理页标题被切掉";
1.7.1 条目里**直接写出的路径 /zhongzhuanzhan**、
"管理入口从官网上移除";1.7.0 的"管理页加图标"
* RELEASE-1.8.0.md:第四节「中转管理后台完全重做」整节删掉,
改成「官网重新设计」
新增 _build/test_public_clean.py(15 项)并加进套件(阶段 3b7):
* CHANGELOG / README / docs 里不许出现
zhongzhuanzhan、/admin、管理后台、管理页、管理入口、admin_password
* 官网渲染出来的 HTML 逐词检查,且站内链接只允许
指向 /download/、/shot/、首页、图标、页内锚点
* 发布说明里不许出现安装教程类内容(用户要求只放更新内容)
为什么写成测试:文档没人看。这一天里我因为"以为记住了"
翻了三次车,所以把规矩变成会红的断言。
新增 docs/项目规矩.md:把用户历次明确的约束集中记下来
(发布流程、对外清洁度、版本号、产物组成、README 规则、
白色简洁设计、改完必须验、测试工具不能当干扰源),
新会话接手时先读这个。
顺带修的工程问题(今天反复踩的坑):
* 用 PowerShell 的 @"..."@ 嵌 Python 去改 .ps1 时,
PowerShell 会先把 $var 展开成空,写进去一堆反斜杠
-> verify_all.ps1 被写坏,& 语法报错
现在改 .ps1 一律用 Python 读写文件
* re.sub 的替换串会解释反斜杠转义,
`"\\test_public_clean.py"` 里的 \t 变成制表符,
路径成了 "_build<TAB>est_public_clean.py"
-> 用 lambda 替换,避开转义
验收:全量回归 34 个阶段全部通过(含新的清洁度守卫)。
170 lines
5.6 KiB
Python
170 lines
5.6 KiB
Python
# -*- coding: utf-8 -*-
|
|
r'''守卫:对外公开的材料里不许出现「中转管理后台」。
|
|
|
|
用户定的规矩(原话):
|
|
「你对外公开的数据里不要包含那个中转站管理的页面,你就只能提官网」
|
|
|
|
范围(用户已确认):
|
|
✅ 必须干净:发布说明、CHANGELOG、官网页面、README、我对外的汇报
|
|
❌ 不用管:服务端 zip 里的运维文档(给装机的人看)、
|
|
源码实现(路径是功能本身)、_build/_tests 内部材料
|
|
|
|
为什么写成测试而不是写进文档:
|
|
文档没人看。这一天里我因为"以为记住了"翻了三次车,
|
|
所以把规矩变成会红的断言 —— 违反了立刻报错。
|
|
|
|
顺便也守住另外两条用户明确说过的:
|
|
* 官网里不能出现管理入口
|
|
* 发布说明只能是更新内容
|
|
'''
|
|
from __future__ import annotations
|
|
|
|
import re
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(r"C:\Users\shu\Desktop\deepseekagent\LanRemote")
|
|
|
|
# 这些词一律不许出现在对外材料里
|
|
FORBIDDEN = [
|
|
"zhongzhuanzhan",
|
|
"/admin",
|
|
"管理后台",
|
|
"管理页",
|
|
"管理入口",
|
|
"管理面板",
|
|
"admin_password",
|
|
]
|
|
|
|
# 对外公开的文件(相对路径)
|
|
PUBLIC_FILES = [
|
|
"_build/CHANGELOG.md",
|
|
"README.md",
|
|
]
|
|
|
|
# 对外公开的目录:里面所有 .md 都要干净
|
|
PUBLIC_DIRS = [
|
|
"docs",
|
|
]
|
|
|
|
# docs 里这些是**运维文档**,是给装服务器的人看的,允许提到管理页
|
|
DOCS_ALLOWLIST = {
|
|
"AFTER-INSTALL.txt",
|
|
"BEFORE-INSTALL.txt",
|
|
"LICENSE.txt",
|
|
"项目规矩.md", # 这份文件本身就是在讲这条规矩
|
|
"免费托管方案.md", # 讲托管方案,不涉及
|
|
}
|
|
|
|
# 官网源码里这些词也不许有(landing.py 渲染出来的页面)
|
|
SITE_FILES = [
|
|
"relay/landing.py",
|
|
"relay/showcase.py",
|
|
]
|
|
|
|
passed = 0
|
|
failed = 0
|
|
|
|
|
|
def check(name: str, ok: bool, detail: str = "") -> None:
|
|
global passed, failed
|
|
if ok:
|
|
passed += 1
|
|
print(" [PASS] " + name)
|
|
else:
|
|
failed += 1
|
|
print(" [FAIL] " + name + " " + str(detail))
|
|
|
|
|
|
def scan(path: Path) -> list:
|
|
"""返回 [(行号, 关键词, 那一行)]"""
|
|
hits = []
|
|
try:
|
|
text = path.read_text(encoding="utf-8", errors="replace")
|
|
except OSError:
|
|
return hits
|
|
for index, line in enumerate(text.splitlines(), 1):
|
|
for word in FORBIDDEN:
|
|
if word in line:
|
|
hits.append((index, word, line.strip()[:70]))
|
|
return hits
|
|
|
|
|
|
def main() -> int:
|
|
print(" 一、对外公开的单文件")
|
|
for rel in PUBLIC_FILES:
|
|
path = ROOT / rel
|
|
if not path.is_file():
|
|
check("%s 存在" % rel, False, "文件不存在")
|
|
continue
|
|
hits = scan(path)
|
|
check("%s 干净" % rel, not hits,
|
|
"第 %d 行含「%s」" % (hits[0][0], hits[0][1]) if hits else "")
|
|
|
|
print()
|
|
print(" 二、docs 目录(运维文档除外)")
|
|
for rel in PUBLIC_DIRS:
|
|
directory = ROOT / rel
|
|
if not directory.is_dir():
|
|
continue
|
|
for path in sorted(directory.iterdir()):
|
|
if not path.is_file():
|
|
continue
|
|
if path.name in DOCS_ALLOWLIST:
|
|
print(" [跳过] %s(运维文档,允许提及)" % path.name)
|
|
continue
|
|
hits = scan(path)
|
|
check("docs/%s 干净" % path.name, not hits,
|
|
"第 %d 行含「%s」" % (hits[0][0], hits[0][1]) if hits else "")
|
|
|
|
print()
|
|
print(" 三、官网页面(渲染出来给所有人看的)")
|
|
sys.path.insert(0, str(ROOT / "relay"))
|
|
try:
|
|
import landing
|
|
html = landing.render_site([
|
|
{"name": "ykxmz-setup-1.8.0.exe", "size": 15066550},
|
|
{"name": "ykxmz-server-1.8.0.zip", "size": 214661},
|
|
{"name": "ykxmz-watch-1.8.0.apk", "size": 201523},
|
|
])
|
|
except Exception as exc: # noqa: BLE001
|
|
check("官网能渲染", False, exc)
|
|
html = ""
|
|
|
|
if html:
|
|
check("官网能渲染", len(html) > 5000, "%d 字符" % len(html))
|
|
for word in FORBIDDEN:
|
|
check("官网里没有「%s」" % word, word not in html.lower()
|
|
if word.isascii() else word not in html)
|
|
# 只允许链接到下载 / 截图 / 首页 / 图标 / 页内锚点。
|
|
# 出现别的站内路径就说明可能把管理入口又加回去了。
|
|
allowed = ("/download/", "/shot/", "/", "/favicon.ico", "#")
|
|
hrefs = set(re.findall(r'href="([^"]+)"', html))
|
|
bad = [h for h in hrefs
|
|
if h.startswith("/") and not h.startswith(allowed)]
|
|
check("官网里的站内链接只指向下载/首页/锚点", not bad, bad)
|
|
|
|
print()
|
|
print(" 四、发布说明只能是「更新内容」")
|
|
rel_notes = ROOT / "_build" / "RELEASE-1.8.0.md"
|
|
if rel_notes.is_file():
|
|
text = rel_notes.read_text(encoding="utf-8")
|
|
# 不该出现安装教程这种内容(用户要求"只放更新内容")
|
|
for bad_title in ("安装教程", "安装步骤", "怎么安装"):
|
|
check("发布说明里没有「%s」" % bad_title, bad_title not in text)
|
|
# 也不该提管理页
|
|
hits = scan(rel_notes)
|
|
check("RELEASE-1.8.0.md 干净", not hits,
|
|
"第 %d 行含「%s」" % (hits[0][0], hits[0][1]) if hits else "")
|
|
else:
|
|
print(" [跳过] 没有 RELEASE-1.8.0.md")
|
|
|
|
print()
|
|
print("=" * 54)
|
|
print(" 通过 %d 项,失败 %d 项" % (passed, failed))
|
|
return 0 if failed == 0 else 1
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|