chore(observability): add CSS mirror sync helper
All checks were successful
CD Pipeline / deploy (push) Successful in 1m33s
All checks were successful
CD Pipeline / deploy (push) Successful in 1m33s
This commit is contained in:
@@ -50,7 +50,13 @@ scripts/check_observability_suite.sh
|
||||
python3 scripts/check_observability_ui.py
|
||||
```
|
||||
|
||||
或透過既有 quick review 選單執行第 8 項完整 QA 套件、第 6 項靜態 UI guard:
|
||||
如果修改了 `static/css/observability-system.css`,先同步 Flask 實際服務用的 mirror:
|
||||
|
||||
```bash
|
||||
python3 scripts/sync_observability_css.py
|
||||
```
|
||||
|
||||
或透過既有 quick review 選單執行第 8 項完整 QA 套件、第 6 項靜態 UI guard、第 9 項 CSS mirror sync:
|
||||
|
||||
```bash
|
||||
./scripts/quick_review.sh
|
||||
|
||||
@@ -202,7 +202,7 @@ def scan_css() -> list[str]:
|
||||
web_text = web_path.read_text(encoding="utf-8")
|
||||
if web_text != text:
|
||||
findings.append(
|
||||
f"{WEB_CSS_PATH}: must match {CSS_PATH} so production /static CSS is in sync"
|
||||
f"{WEB_CSS_PATH}: must match {CSS_PATH} so production /static CSS is in sync; run `python3 scripts/sync_observability_css.py`"
|
||||
)
|
||||
|
||||
return findings
|
||||
|
||||
@@ -18,6 +18,7 @@ CODE_REVIEW_SCRIPT="$PROJECT_ROOT/scripts/code_review.py"
|
||||
OBSERVABILITY_UI_GUARD="$PROJECT_ROOT/scripts/check_observability_ui.py"
|
||||
OBSERVABILITY_PAGE_SMOKE="$PROJECT_ROOT/scripts/check_observability_pages.py"
|
||||
OBSERVABILITY_QA_SUITE="$PROJECT_ROOT/scripts/check_observability_suite.sh"
|
||||
OBSERVABILITY_CSS_SYNC="$PROJECT_ROOT/scripts/sync_observability_css.py"
|
||||
|
||||
# 顯示標題
|
||||
echo -e "${BLUE}========================================${NC}"
|
||||
@@ -75,6 +76,16 @@ run_observability_qa_suite() {
|
||||
bash "$OBSERVABILITY_QA_SUITE"
|
||||
}
|
||||
|
||||
run_observability_css_sync() {
|
||||
if [ ! -f "$OBSERVABILITY_CSS_SYNC" ]; then
|
||||
echo -e "${RED}❌ AI觀測台 CSS 同步腳本不存在: $OBSERVABILITY_CSS_SYNC${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "${GREEN}🎨 同步 AI觀測台 CSS 到 Flask static path...${NC}"
|
||||
python3 "$OBSERVABILITY_CSS_SYNC"
|
||||
}
|
||||
|
||||
# 顯示選單
|
||||
if [ $# -eq 0 ]; then
|
||||
echo -e "${YELLOW}請選擇操作:${NC}"
|
||||
@@ -86,8 +97,9 @@ if [ $# -eq 0 ]; then
|
||||
echo "6) AI觀測台 UI/UX 防回歸檢查"
|
||||
echo "7) AI觀測台 10頁線上巡檢"
|
||||
echo "8) AI觀測台完整 QA 套件"
|
||||
echo "9) 同步 AI觀測台 CSS static mirror"
|
||||
echo ""
|
||||
read -p "請輸入選項 (1-8): " choice
|
||||
read -p "請輸入選項 (1-9): " choice
|
||||
|
||||
case $choice in
|
||||
1)
|
||||
@@ -126,6 +138,9 @@ if [ $# -eq 0 ]; then
|
||||
8)
|
||||
run_observability_qa_suite
|
||||
;;
|
||||
9)
|
||||
run_observability_css_sync
|
||||
;;
|
||||
*)
|
||||
echo -e "${RED}❌ 無效選項${NC}"
|
||||
exit 1
|
||||
|
||||
49
scripts/sync_observability_css.py
Normal file
49
scripts/sync_observability_css.py
Normal file
@@ -0,0 +1,49 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Sync the canonical observability CSS to the Flask-served static path.
|
||||
|
||||
The project keeps the design-system source at:
|
||||
static/css/observability-system.css
|
||||
|
||||
Production Flask static serving currently exposes:
|
||||
web/static/css/observability-system.css
|
||||
|
||||
This helper keeps the two files byte-identical so deploys do not regress into
|
||||
"HTML links the CSS but /static/css/observability-system.css is 404/stale".
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
SOURCE = ROOT / "static/css/observability-system.css"
|
||||
TARGET = ROOT / "web/static/css/observability-system.css"
|
||||
|
||||
|
||||
def main() -> int:
|
||||
if not SOURCE.exists():
|
||||
print(f"ERROR: missing source CSS: {SOURCE.relative_to(ROOT)}")
|
||||
return 1
|
||||
|
||||
TARGET.parent.mkdir(parents=True, exist_ok=True)
|
||||
source_bytes = SOURCE.read_bytes()
|
||||
target_bytes = TARGET.read_bytes() if TARGET.exists() else b""
|
||||
|
||||
if source_bytes == target_bytes:
|
||||
print("Observability CSS sync: already in sync")
|
||||
print(f"- source: {SOURCE.relative_to(ROOT)}")
|
||||
print(f"- target: {TARGET.relative_to(ROOT)}")
|
||||
return 0
|
||||
|
||||
shutil.copyfile(SOURCE, TARGET)
|
||||
print("Observability CSS sync: synced")
|
||||
print(f"- source: {SOURCE.relative_to(ROOT)}")
|
||||
print(f"- target: {TARGET.relative_to(ROOT)}")
|
||||
print(f"- bytes: {len(source_bytes)}")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user