File size: 2,648 Bytes
3b1ab70 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | """A14 backup.py:暫存路徑 → 確認 tar.gz 產出且內容齊全。"""
from __future__ import annotations
import importlib.util
import tarfile
from pathlib import Path
SCRIPT = Path(__file__).resolve().parents[2] / "scripts" / "backup.py"
def _load_module():
spec = importlib.util.spec_from_file_location("backup_script", SCRIPT)
assert spec and spec.loader
mod = importlib.util.module_from_spec(spec)
spec.loader.exec_module(mod)
return mod
def test_backup_produces_tar_with_db_and_vault(tmp_path, monkeypatch):
db = tmp_path / "kbv5.db"
db.write_bytes(b"SQLite format 3\x00") # 假 SQLite header
vault = tmp_path / "vault"
(vault / "知識" / "筆記").mkdir(parents=True)
(vault / "知識" / "筆記" / "demo-1.md").write_text("# demo", encoding="utf-8")
history = tmp_path / "history"
history.mkdir()
(history / "v1.md").write_text("# v1", encoding="utf-8")
monkeypatch.setenv("KBV5_DB", str(db))
monkeypatch.setenv("KBV5_VAULT_DIR", str(vault))
monkeypatch.setenv("KBV5_HISTORY_DIR", str(history))
out_dir = tmp_path / "out"
mod = _load_module()
rc = mod.main([str(out_dir)])
assert rc == 0
backups = list(out_dir.glob("kbv5-*.tar.gz"))
assert len(backups) == 1
with tarfile.open(backups[0], "r:gz") as tar:
names = tar.getnames()
# 三項都應在 tar 內(檔名透過 arcname 處理)
assert any(n.endswith("kbv5.db") for n in names)
assert any("demo-1.md" in n for n in names)
assert any("v1.md" in n for n in names)
def test_backup_missing_all_returns_error(tmp_path, monkeypatch):
monkeypatch.setenv("KBV5_DB", str(tmp_path / "nope.db"))
monkeypatch.setenv("KBV5_VAULT_DIR", str(tmp_path / "nope_vault"))
monkeypatch.setenv("KBV5_HISTORY_DIR", str(tmp_path / "nope_history"))
mod = _load_module()
rc = mod.main([str(tmp_path / "out")])
assert rc == 1
def test_dockerfile_and_compose_exist():
"""A14 必要部署檔存在。"""
root = Path(__file__).resolve().parents[2]
for f in ("Dockerfile", "docker-compose.yml", ".env.example", ".dockerignore"):
assert (root / f).exists(), f"missing {f}"
def test_env_example_lists_critical_vars():
""".env.example 必含關鍵 env 提示,避免新人漏設。"""
root = Path(__file__).resolve().parents[2]
text = (root / ".env.example").read_text(encoding="utf-8")
for var in ("JWT_SECRET", "KBV5_DB", "KBV5_VAULT_DIR",
"ALLOWED_EMAIL_DOMAINS", "ANTHROPIC_API_KEY",
"OPENAI_API_KEY", "GEMINI_API_KEY"):
assert var in text, f".env.example missing {var}"
|