feat: 服务端集成自动打包流程
This commit is contained in:
+62
-11
@@ -1,6 +1,7 @@
|
||||
"""项目配置 — 从环境变量读取,支持 .env 文件"""
|
||||
import os
|
||||
from pathlib import Path
|
||||
from urllib.parse import quote, urlsplit, urlunsplit
|
||||
|
||||
# 自动加载 .env 文件(如果存在)
|
||||
_env_file = Path(__file__).parent.parent / ".env"
|
||||
@@ -10,16 +11,31 @@ if _env_file.exists():
|
||||
line = line.strip()
|
||||
if line and not line.startswith("#") and "=" in line:
|
||||
key, _, value = line.partition("=")
|
||||
os.environ.setdefault(key.strip(), value.strip())
|
||||
value = value.strip()
|
||||
if len(value) >= 2 and value[0] == value[-1] and value[0] in {'"', "'"}:
|
||||
value = value[1:-1]
|
||||
os.environ.setdefault(key.strip(), value)
|
||||
|
||||
# 项目根目录(iOS 源码,也作为 AutoPacking 脚本来源)
|
||||
PROJECT_ROOT = Path(os.getenv("PROJECT_ROOT", "/Users/shen/Work/Code/Readoor"))
|
||||
# 服务项目根目录
|
||||
SERVER_ROOT = Path(__file__).resolve().parent.parent
|
||||
|
||||
# AutoPacking 目录(打包脚本来源,随分支变化)
|
||||
AUTOPACKING_DIR = PROJECT_ROOT / "AutoPacking"
|
||||
|
||||
def _resolve_server_path(value: str) -> Path:
|
||||
"""将 .env 中的相对目录固定解析到服务项目根目录。"""
|
||||
path = Path(value).expanduser()
|
||||
if not path.is_absolute():
|
||||
path = SERVER_ROOT / path
|
||||
return path.resolve()
|
||||
|
||||
|
||||
# 项目根目录下的初始化配置文件
|
||||
BOOTSTRAP_CONFIG_PATH = SERVER_ROOT / "config.json"
|
||||
|
||||
# 自动打包服务自带的脚本和默认皮肤,不依赖分支源码中的 AutoPacking。
|
||||
AUTOMATION_DIR = Path(__file__).resolve().parent / "automation"
|
||||
|
||||
# 持久化数据目录(不随分支变化,存放运行时配置和皮肤包)
|
||||
DATA_DIR = Path(os.getenv("DATA_DIR", str(Path(__file__).parent / "data")))
|
||||
DATA_DIR = _resolve_server_path(os.getenv("DATA_DIR", str(Path(__file__).parent / "data")))
|
||||
DATA_DIR.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# config.json 路径(持久化,不随分支变化)
|
||||
@@ -29,25 +45,60 @@ CONFIG_JSON_PATH = DATA_DIR / "config.json"
|
||||
SKINS_DIR = DATA_DIR / "skins"
|
||||
|
||||
# 打包基础目录
|
||||
BUILD_BASE_DIR = Path(os.getenv("BUILD_BASE_DIR", "/Users/shen/Documents"))
|
||||
BUILD_BASE_DIR = _resolve_server_path(os.getenv("BUILD_BASE_DIR", str(SERVER_ROOT / "build")))
|
||||
|
||||
# Git 分支源码目录
|
||||
# GIT_SOURCE_BASE: 分支源码的根目录,每个分支一个子目录
|
||||
# GIT_REMOTE_URL: 远程仓库地址,分支目录不存在时自动 clone
|
||||
GIT_SOURCE_BASE = Path(os.getenv("GIT_SOURCE_BASE", str(PROJECT_ROOT.parent / "ReadoorBranches")))
|
||||
GIT_SOURCE_BASE = _resolve_server_path(os.getenv("GIT_SOURCE_BASE", str(SERVER_ROOT / "ReadoorBranches")))
|
||||
GIT_REMOTE_URL = os.getenv("GIT_REMOTE_URL", "")
|
||||
GIT_USERNAME = os.getenv("GIT_USERNAME", "")
|
||||
GIT_PASSWORD = os.getenv("GIT_PASSWORD", "")
|
||||
|
||||
|
||||
def get_git_remote_url(with_credentials: bool = False) -> str:
|
||||
"""获取 Git 远程地址,可选注入用户名密码"""
|
||||
if not with_credentials or not GIT_REMOTE_URL or not GIT_USERNAME:
|
||||
return GIT_REMOTE_URL
|
||||
if "://" not in GIT_REMOTE_URL:
|
||||
return GIT_REMOTE_URL
|
||||
|
||||
parts = urlsplit(GIT_REMOTE_URL)
|
||||
if "@" in parts.netloc:
|
||||
return GIT_REMOTE_URL
|
||||
|
||||
username = quote(GIT_USERNAME, safe="")
|
||||
if GIT_PASSWORD:
|
||||
password = quote(GIT_PASSWORD, safe="")
|
||||
auth = f"{username}:{password}"
|
||||
else:
|
||||
auth = username
|
||||
netloc = f"{auth}@{parts.netloc}"
|
||||
return urlunsplit((parts.scheme, netloc, parts.path, parts.query, parts.fragment))
|
||||
|
||||
|
||||
def mask_git_remote_url(url: str) -> str:
|
||||
"""对 Git 远程地址中的凭证做脱敏"""
|
||||
if not url or "://" not in url:
|
||||
return url
|
||||
parts = urlsplit(url)
|
||||
if "@" not in parts.netloc:
|
||||
return url
|
||||
_, host = parts.netloc.rsplit("@", 1)
|
||||
return urlunsplit((parts.scheme, f"***:***@{host}", parts.path, parts.query, parts.fragment))
|
||||
|
||||
|
||||
def get_source_dir(branch: str) -> Path:
|
||||
"""获取指定分支的源码目录"""
|
||||
return GIT_SOURCE_BASE / branch
|
||||
|
||||
|
||||
# 需要拷贝的目录和文件
|
||||
COPY_ITEMS = [
|
||||
"readoor",
|
||||
"readoor.xcodeproj",
|
||||
"readoorTests",
|
||||
"AutoPacking",
|
||||
"Vendor",
|
||||
"podfile",
|
||||
"Pods",
|
||||
"Podfile.lock",
|
||||
@@ -57,8 +108,8 @@ COPY_ITEMS = [
|
||||
# 服务端口
|
||||
BACKEND_PORT = int(os.getenv("BACKEND_PORT", "8000"))
|
||||
|
||||
# 数据库路径
|
||||
DATABASE_URL = f"sqlite:///{Path(__file__).parent / 'build_server.db'}"
|
||||
# 数据库路径。测试可通过 DATABASE_URL 注入临时 SQLite,避免影响运行库。
|
||||
DATABASE_URL = os.getenv("DATABASE_URL", f"sqlite:///{Path(__file__).parent / 'build_server.db'}")
|
||||
|
||||
# WebSocket 日志队列最大长度
|
||||
LOG_QUEUE_MAX_SIZE = 1000
|
||||
|
||||
Reference in New Issue
Block a user