复核 R-d5(dev.sh 读 .env 不全):认 KEY = value(等号两边有空格,和后端的 dotenv 一致);放开发库密码的数据目录也照「环境变量 > backend/.env > .env」读 AGENTLAB_DATA_DIR,相对路径按后端的工作目录 backend/ 算,.postgres-dev 落在后端实际用的数据目录下。单测:等号带空格、export、行尾注释、backend/.env 优先、相对的数据目录

This commit is contained in:
ThearchyHelios
2026-10-19 16:13:35 +08:00
parent 65d35f6c97
commit 49118eeef2
3 changed files with 33 additions and 19 deletions
+2 -1
View File
@@ -53,7 +53,8 @@
# ---- 开发用 PostgreSQL(./scripts/dev.sh --postgres)----
# 这几项只有 dev.sh 读:写成环境变量或写在这个 .env 里都行(环境变量优先)。数据在 docker 数据卷里,
# 密码第一次自动生成在 data/.postgres-dev/,dev.sh 照它设 AGENTLAB_DATABASE_URL(盖过上面写的)
# 密码第一次自动生成在数据目录(和后端一样照 AGENTLAB_DATA_DIR,缺省 data/)的 .postgres-dev/ 里,
# dev.sh 照它设 AGENTLAB_DATABASE_URL(盖过上面写的)
# AGENTLAB_DEV_PG_CONTAINER=agentlab-dev-postgres
# AGENTLAB_DEV_PG_PORT=55432
# AGENTLAB_DEV_PG_VOLUME=agentlab-dev-pgdata
+12 -6
View File
@@ -813,7 +813,7 @@ def test_env_example_lists_every_database_pool_and_multiprocess_setting():
names = {f"AGENTLAB_{name.upper()}" for name in Settings.model_fields if name.startswith(prefixes)}
assert {"AGENTLAB_DATABASE_URL", "AGENTLAB_DATABASE_DIRECT_URL", "AGENTLAB_DB_PGBOUNCER", "AGENTLAB_WORKERS",
"AGENTLAB_WORKER_LEASE_S", "AGENTLAB_DB_STARTUP_TIMEOUT", "AGENTLAB_SCHEDULER_TICK_S"} <= names
dev = set(re.findall(r"dev_pg_setting (AGENTLAB_DEV_PG_[A-Z_]+)", (REPO / "scripts" / "dev.sh").read_text()))
dev = set(re.findall(r"dotenv_setting (AGENTLAB_DEV_PG_[A-Z_]+)", (REPO / "scripts" / "dev.sh").read_text()))
assert len(dev) == 4
example = (REPO / ".env.example").read_text(encoding="utf-8")
listed = set(re.findall(r"^# (AGENTLAB_[A-Z_]+)=", example, re.M))
@@ -827,9 +827,12 @@ def test_dev_script_reads_its_postgres_settings_from_dotenv(tmp_path):
(root / "scripts").mkdir(parents=True)
(root / "frontend" / "node_modules").mkdir(parents=True)
shutil.copy(REPO / "scripts" / "dev.sh", root / "scripts" / "dev.sh")
(root / "backend").symlink_to(REPO / "backend")
(root / ".env").write_text("AGENTLAB_DEV_PG_CONTAINER=from-root-env\nAGENTLAB_DEV_PG_PORT=55491\n"
"AGENTLAB_DEV_PG_VOLUME='quoted-vol' \n")
(root / ".env").write_text("AGENTLAB_DEV_PG_CONTAINER=from-root-env\nAGENTLAB_DEV_PG_PORT = 55491 # 注释\n"
"export AGENTLAB_DEV_PG_VOLUME = 'quoted-vol' \nAGENTLAB_DATA_DIR=from-root\n")
# backend/.env 比 .env 优先(同后端):数据目录写相对路径,按后端的工作目录 backend/ 算
(root / "backend").mkdir()
(root / "backend" / ".env").write_text("AGENTLAB_DATA_DIR = ../devdata\n")
(root / "backend" / "app").symlink_to(REPO / "backend" / "app")
bin_dir = tmp_path / "bin"
bin_dir.mkdir()
log = tmp_path / "docker.log"
@@ -839,7 +842,7 @@ def test_dev_script_reads_its_postgres_settings_from_dotenv(tmp_path):
'container) exit 1 ;; run) exit 1 ;; esac\nexit 0\n')
for f in bin_dir.iterdir():
f.chmod(0o755)
env = {"PATH": f"{bin_dir}:/usr/bin:/bin:/usr/sbin:/sbin", "HOME": str(tmp_path), "AGENTLAB_DATA_DIR": str(tmp_path / "data"),
env = {"PATH": f"{bin_dir}:/usr/bin:/bin:/usr/sbin:/sbin", "HOME": str(tmp_path),
"AGENTLAB_DEV_PG_IMAGE": "postgres:from-env", "AGENTLAB_PORT": "18799", "LANG": "C.UTF-8"}
out = subprocess.run(["bash", str(root / "scripts" / "dev.sh"), "--postgres"], capture_output=True, text=True, env=env,
timeout=60)
@@ -848,7 +851,10 @@ def test_dev_script_reads_its_postgres_settings_from_dotenv(tmp_path):
assert "--name from-root-env" in run and "127.0.0.1:55491:5432" in run, ".env 里的生效"
assert "quoted-vol:/var/lib/postgresql/data" in run, "引号和行尾空白去掉"
assert run.endswith("postgres:from-env"), "环境变量优先"
(root / "backend").unlink()
data = root / "backend" / ".." / "devdata"
assert f"{data}/.postgres-dev/password:/run/agentlab/password:ro" in run, "密码放在后端实际用的数据目录里"
assert (root / "devdata" / ".postgres-dev" / "pgpass").exists()
(root / "backend" / "app").unlink()
def test_dev_script_refuses_unknown_arguments_and_documents_postgres():
+19 -12
View File
@@ -73,19 +73,24 @@ fi
export AGENTLAB_PORT="$API_PORT"
# ---- --postgres:本地开发用的 PostgreSQL ----
# 这几项(AGENTLAB_DEV_PG_*)只有这个脚本用。和后端的配置一样认 .env:环境变量 > backend/.env > .env > 缺省(后端的 settings
# 读这两个文件,后一个优先)。不 source:.env 是给后端按 KEY=VALUE 读的,不是 shell(值里的 $、空格、反引号不该被执行)
# 这几项(AGENTLAB_DEV_PG_*,还有数据目录 AGENTLAB_DATA_DIR)和后端的配置一样认 .env:环境变量 > backend/.env > .env > 缺省
# (后端的 settings 读这两个文件,后一个优先)。写法照后端的 dotenv:KEY=value、KEY = value、export KEY=value、引号、行尾 # 注释。
# 不 source:.env 是给后端按 KEY=VALUE 读的,不是 shell(值里的 $、空格、反引号不该被执行)
dotenv_value() {
local key="$1" file line val="" found=""
local key="$1" file line name val="" found=""
for file in "$ROOT/.env" "$ROOT/backend/.env"; do
[ -f "$file" ] || continue
while IFS= read -r line || [ -n "$line" ]; do
line="${line%$'\r'}"
line="${line#"${line%%[![:space:]]*}"}"
line="${line#export }"
case "$line" in
"$key="*) val="${line#*=}"; found=1 ;;
esac
case "$line" in *=*) ;; *) continue ;; esac
name="${line%%=*}"
name="${name%"${name##*[![:space:]]}"}"
[ "$name" = "$key" ] || continue
val="${line#*=}"
val="${val#"${val%%[![:space:]]*}"}"
found=1
done < "$file"
done
[ -n "$found" ] || return 1
@@ -96,18 +101,20 @@ dotenv_value() {
esac
printf '%s' "$val"
}
dev_pg_setting() {
dotenv_setting() {
local value
value="$(printenv "$1" 2>/dev/null || true)"
[ -n "$value" ] || value="$(dotenv_value "$1" || true)"
printf '%s' "${value:-$2}"
}
if [ -n "$WITH_PG" ]; then
PG_CONTAINER="$(dev_pg_setting AGENTLAB_DEV_PG_CONTAINER agentlab-dev-postgres)"
PG_PORT="$(dev_pg_setting AGENTLAB_DEV_PG_PORT 55432)"
PG_VOLUME="$(dev_pg_setting AGENTLAB_DEV_PG_VOLUME agentlab-dev-pgdata)"
PG_IMAGE="$(dev_pg_setting AGENTLAB_DEV_PG_IMAGE postgres:16)"
DEV_DATA="${AGENTLAB_DATA_DIR:-$ROOT/data}"
PG_CONTAINER="$(dotenv_setting AGENTLAB_DEV_PG_CONTAINER agentlab-dev-postgres)"
PG_PORT="$(dotenv_setting AGENTLAB_DEV_PG_PORT 55432)"
PG_VOLUME="$(dotenv_setting AGENTLAB_DEV_PG_VOLUME agentlab-dev-pgdata)"
PG_IMAGE="$(dotenv_setting AGENTLAB_DEV_PG_IMAGE postgres:16)"
# 密码文件放在后端实际用的数据目录里:和后端一样读 AGENTLAB_DATA_DIR,相对路径按后端的工作目录(backend/)算
DEV_DATA="$(dotenv_setting AGENTLAB_DATA_DIR "$ROOT/data")"
case "$DEV_DATA" in /*) ;; *) DEV_DATA="$ROOT/backend/$DEV_DATA" ;; esac
case "$PG_PORT" in ''|*[!0-9]*) echo "AGENTLAB_DEV_PG_PORT 要是端口号:$PG_PORT"; exit 2 ;; esac
command -v docker >/dev/null || { echo "--postgres 要用 docker,没找到它"; exit 1; }
docker version --format '{{.Server.Version}}' >/dev/null 2>&1 || { echo "连不上 docker 服务,先把 Docker 启动起来"; exit 1; }