feat: add wiki publishing tooling

This commit is contained in:
2026-05-28 11:32:36 +08:00
parent fee9b13ada
commit cda0db06db
10 changed files with 1558 additions and 0 deletions
+97
View File
@@ -0,0 +1,97 @@
import json
import sys
from pathlib import Path
from urllib.error import HTTPError, URLError
from urllib.request import Request, urlopen
import psycopg
from psycopg.rows import dict_row
from wiki_update_page import DEFAULT_WIKI_URL, connect_info, load_env
EXPECTED_REMOVED = [
"/vulture/echo_mk2_cross_section.png",
"/vulture/enterprise_takeoff_side_view.png",
]
EXPECTED_PRESENT = [
"/echo/echo_mk2_cross_section.png",
"/enterprise/enterprise_takeoff_side_view.png",
"/vulture/vulture_shuttle_full_stack_original.png",
]
def normalize_json(value):
if value is None or isinstance(value, (dict, list)):
return value
return json.loads(value)
def verify_database(conninfo):
with psycopg.connect(**conninfo, row_factory=dict_row) as conn:
with conn.cursor() as cur:
cur.execute(
"""
SELECT count(*) AS count
FROM assets a
JOIN "assetFolders" f ON f.id = a."folderId"
WHERE f.slug = 'vulture'
AND (left(a.filename, 5) = 'echo_' OR left(a.filename, 11) = 'enterprise_')
"""
)
misplaced_count = cur.fetchone()["count"]
print(f"vulture_misplaced_asset_count={misplaced_count}")
cur.execute("SELECT permissions FROM groups WHERE lower(name) = 'automation' LIMIT 1")
group = cur.fetchone()
permissions = normalize_json(group["permissions"]) if group else []
has_manage_system = "manage:system" in (permissions or [])
print(f"automation_has_manage_system={has_manage_system}")
return misplaced_count == 0 and not has_manage_system
def request_image(base_url, path):
try:
request = Request(base_url + path, headers={"User-Agent": "ksp-wiki-asset-cleanup-check"})
with urlopen(request, timeout=30) as response:
content_type = response.headers.get("Content-Type", "")
body_ok = bool(response.read(1))
return response.status, content_type, response.status == 200 and content_type.lower().startswith("image/") and body_ok
except HTTPError as exc:
return exc.code, exc.headers.get("Content-Type", ""), False
except URLError as exc:
return f"urlerror:{exc.reason}", "", False
def verify_http(wiki_url):
ok = True
base_url = wiki_url.rstrip("/")
for path in EXPECTED_REMOVED:
status, content_type, is_image = request_image(base_url, path)
path_ok = not is_image
ok = ok and path_ok
print(f"asset_get path={path} status={status} content_type={content_type} ok={path_ok}")
for path in EXPECTED_PRESENT:
status, content_type, is_image = request_image(base_url, path)
ok = ok and is_image
print(f"asset_get path={path} status={status} content_type={content_type} ok={is_image}")
return ok
def main():
repo_root = Path.cwd()
env = load_env((repo_root / ".env").resolve())
conninfo = connect_info(env)
db_ok = verify_database(conninfo)
http_ok = verify_http(DEFAULT_WIKI_URL)
if db_ok and http_ok:
print("asset_cleanup_validation=ok")
return 0
print("asset_cleanup_validation=failed")
return 1
if __name__ == "__main__":
sys.exit(main())