File size: 3,085 Bytes
b8361f0
46319d0
a5bcb12
46319d0
 
 
a5bcb12
46319d0
 
 
 
b8361f0
46319d0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b8361f0
46319d0
 
 
b8361f0
46319d0
b8361f0
 
46319d0
 
b8361f0
46319d0
 
 
a5bcb12
46319d0
 
b8361f0
a5bcb12
46319d0
a5bcb12
46319d0
b8361f0
 
 
 
a5bcb12
46319d0
b8361f0
 
46319d0
b8361f0
46319d0
 
 
 
 
 
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
72
73
74
75
76
77
78
79
80
81
82
83
# startup.py
import os, pathlib, json, shutil

BASE = pathlib.Path(__file__).parent          # 通常是 /app
# 可选显式指定源码目录(绝对路径),若不设会自动发现:
APP_SOURCE_DIR = os.getenv("APP_SOURCE_DIR")

# 入口文件候选名(可覆盖)
ENTRY_HINTS = [s.strip() for s in os.getenv(
    "APP_ENTRY_HINTS", "script.py,app.py,main.py,server.py"
).split(",") if s.strip()]

def find_source_dir() -> pathlib.Path | None:
    # 1) 环境变量优先
    if APP_SOURCE_DIR:
        p = pathlib.Path(APP_SOURCE_DIR)
        if p.is_dir(): return p
    # 2) 常见候选根
    candidates = [BASE, BASE / "src"]
    for d in BASE.iterdir():
        if d.is_dir():
            candidates.append(d)
            if (d / "src").is_dir():
                candidates.append(d / "src")
    # 3) 在候选根里按入口名搜索
    for root in candidates:
        for entry in ENTRY_HINTS:
            for path in root.rglob(entry):
                if "site-packages" in str(path): 
                    continue
                return path.parent
    return None

SRC_READONLY = find_source_dir()
if not SRC_READONLY:
    # 打印部分目录树帮助定位
    listing = "\n".join([str(p) for p in BASE.rglob("*")][:200])
    raise FileNotFoundError(
        f"找不到源码目录,请设置 APP_SOURCE_DIR。已尝试在 {BASE} 下自动发现。\n"
        f"以下为部分目录树(截断):\n{listing}"
    )

# 选择可写运行目录(优先 /data,失败回退 /tmp)
pref = pathlib.Path(os.getenv("APP_RUNTIME_DIR", "/data/grade_query_app"))
RUNTIME = pref
try:
    RUNTIME.mkdir(parents=True, exist_ok=True)
    (RUNTIME / ".probe").write_text("ok", encoding="utf-8")
    (RUNTIME / ".probe").unlink(missing_ok=True)
except Exception:
    RUNTIME = pathlib.Path("/tmp/grade_query_app")
    RUNTIME.mkdir(parents=True, exist_ok=True)

# 把源码复制到可写目录,保持相对路径语义(templates 等)
shutil.copytree(SRC_READONLY, RUNTIME, dirs_exist_ok=True)

# 把 Secrets 写成运行期文件
cookies_txt = os.getenv("COOKIES_TXT", "").strip()
students_json = os.getenv("STUDENTS_JSON", "").strip()

if cookies_txt:
    (RUNTIME / "cookies.txt").write_text(cookies_txt, encoding="utf-8")
    print(f"✅ cookies.txt -> {RUNTIME/'cookies.txt'}")

if students_json:
    try:
        data = json.loads(students_json)
        (RUNTIME / "students.json").write_text(
            json.dumps(data, ensure_ascii=False, indent=2), encoding="utf-8"
        )
        print(f"✅ students.json (parsed JSON) -> {RUNTIME/'students.json'}")
    except Exception:
        (RUNTIME / "students.json").write_text(students_json, encoding="utf-8")
        print(f"✅ students.json (raw text) -> {RUNTIME/'students.json'}")

# 暴露给 wsgi.py 使用
os.environ["APP_RUNTIME_DIR_RESOLVED"] = str(RUNTIME)
for hint in ENTRY_HINTS:
    if (RUNTIME / hint).exists():
        os.environ["APP_ENTRY_FILE_RESOLVED"] = hint
        break

print(f"ℹ️  Using runtime dir: {RUNTIME}, entry: {os.environ.get('APP_ENTRY_FILE_RESOLVED','(auto)')}")