Skip to content

Commit e7e2518

Browse files
authored
Ignore root .env in deployment scripts (#3318)
Co-authored-by: hhhhsc <name>
1 parent a038699 commit e7e2518

15 files changed

Lines changed: 89 additions & 83 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ bash deploy.sh docker
5252

5353
The root `deploy.sh` only forwards to the target deploy script; the native Docker implementation is `bash deploy/docker/deploy.sh`. The Docker and Kubernetes deploy scripts share the same deployment configuration model. Interactive runs show Bash TUI menus for component selection, port policy, and image source. `infrastructure` is required; `application`, `data-process`, and `supabase` are selected by default and can be disabled when you want a smaller deployment. Use `b`/Backspace to return to the previous TUI step and `q` to quit. Non-interactive runs can pass the same choices with `--version`, `--components`, `--port-policy development|production`, and `--image-source general|mainland|local-latest`. Successful deployments save non-sensitive choices to each deploy directory's `deploy.options` for reuse on the next run.
5454

55-
Docker and Kubernetes both use `deploy/env/.env` as the runtime configuration file. Existing `deploy/env/.env` is kept as-is. If it does not exist, the deploy scripts first reuse an existing legacy root `.env` or `docker/.env`, then fall back to `deploy/env/.env.example` or legacy templates.
55+
Docker and Kubernetes both use `deploy/env/.env` as the runtime configuration file. Existing `deploy/env/.env` is kept as-is. If it does not exist, the deploy scripts first reuse `docker/.env`, then fall back to `deploy/env/.env.example`.
5656

5757
Docker uninstall is handled by `bash uninstall.sh docker`. It can preserve or delete data volumes: run it interactively, pass `--delete-volumes true|false`, or use `bash uninstall.sh docker delete-all` to remove containers and persistent data.
5858

README_CN.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ bash deploy.sh docker
5252

5353
根目录 `deploy.sh` 只负责转发到目标部署脚本;Docker 真实实现为 `bash deploy/docker/deploy.sh`。Docker 和 Kubernetes 使用同一套部署配置模型;交互式运行会通过 Bash TUI 选择组件、端口策略和镜像源。`infrastructure` 必选,`application``data-process``supabase` 默认选中,也可以取消以部署更小的组合。非交互部署可传入 `--version``--components``--port-policy development|production``--image-source general|mainland|local-latest`
5454

55-
Docker 与 Kubernetes 统一使用 `deploy/env/.env` 作为运行配置文件;已有 `deploy/env/.env` 会原样保留。如果`deploy/env/.env` 不存在,部署脚本会优先复用已有的 `docker/.env`,再回退到 `deploy/env/.env.example``docker/.env.example`
55+
Docker 与 Kubernetes 统一使用 `deploy/env/.env` 作为运行配置文件;已有 `deploy/env/.env` 会原样保留。如果 `deploy/env/.env` 不存在,部署脚本会优先复用已有的 `docker/.env`,再回退到 `deploy/env/.env.example`
5656

5757
Docker 卸载入口为 `bash uninstall.sh docker`,默认交互确认是否删除持久化数据;也可以通过 `--delete-volumes true|false` 控制,或使用 `bash uninstall.sh docker delete-all` 同时删除容器和持久化数据。
5858

deploy/common/common.sh

Lines changed: 5 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,7 @@ deployment_ensure_root_env() {
9191
local env_dir="$project_root/deploy/env"
9292
local root_env="$env_dir/.env"
9393
local root_example="$env_dir/.env.example"
94-
local legacy_root_env="$project_root/.env"
95-
local legacy_root_example="$project_root/.env.example"
96-
local legacy_docker_env="$docker_dir/.env"
97-
local legacy_docker_example="$docker_dir/.env.example"
94+
local docker_env="$docker_dir/.env"
9895

9996
mkdir -p "$env_dir"
10097
DEPLOYMENT_ROOT_ENV="$root_env"
@@ -104,15 +101,9 @@ deployment_ensure_root_env() {
104101
return 0
105102
fi
106103

107-
if [ -f "$legacy_root_env" ]; then
108-
cp "$legacy_root_env" "$root_env"
109-
deployment_log "✅ Created deploy/env/.env from legacy root .env"
110-
return 0
111-
fi
112-
113-
if [ -f "$legacy_docker_env" ]; then
114-
cp "$legacy_docker_env" "$root_env"
115-
deployment_log "✅ Created deploy/env/.env from legacy docker/.env"
104+
if [ -f "$docker_env" ]; then
105+
cp "$docker_env" "$root_env"
106+
deployment_log "✅ Created deploy/env/.env from docker/.env"
116107
return 0
117108
fi
118109

@@ -122,19 +113,7 @@ deployment_ensure_root_env() {
122113
return 0
123114
fi
124115

125-
if [ -f "$legacy_root_example" ]; then
126-
cp "$legacy_root_example" "$root_env"
127-
deployment_log "✅ Created deploy/env/.env from legacy root .env.example"
128-
return 0
129-
fi
130-
131-
if [ -f "$legacy_docker_example" ]; then
132-
cp "$legacy_docker_example" "$root_env"
133-
deployment_log "✅ Created deploy/env/.env from legacy docker/.env.example"
134-
return 0
135-
fi
136-
137-
deployment_error "deploy/env/.env not found and no .env.example template is available"
116+
deployment_error "deploy/env/.env not found and no docker/.env or deploy/env/.env.example template is available"
138117
return 1
139118
}
140119

deploy/docker/assets/scripts/sync_skill_directory.py

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -51,19 +51,9 @@ def get_env(key: str, default: str = "") -> str:
5151
def load_environment_from_host():
5252
"""
5353
Load environment variables from host .env file.
54-
Looks for deploy/env/.env first, with legacy .env locations as fallbacks.
54+
Looks for DEPLOYMENT_ROOT_ENV, deploy/env/.env, then docker/.env.
5555
"""
56-
script_dir = Path(__file__).resolve().parent
57-
candidates = []
58-
explicit_env = os.environ.get("DEPLOYMENT_ROOT_ENV")
59-
if explicit_env:
60-
candidates.append(Path(explicit_env))
61-
candidates.extend([
62-
script_dir.parent.parent.parent / "env" / ".env", # deploy/env/.env
63-
script_dir.parent.parent.parent / ".env",
64-
script_dir.parent.parent / ".env",
65-
script_dir.parent / ".env",
66-
])
56+
candidates = get_host_env_candidates()
6757
env_file = next((candidate for candidate in candidates if candidate.is_file()), candidates[0])
6858

6959
if env_file.is_file():
@@ -88,17 +78,7 @@ def get_root_dir() -> str:
8878
"""Get ROOT_DIR from environment, normalized for the current OS."""
8979
root_dir = get_env("ROOT_DIR")
9080
if not root_dir:
91-
script_dir = Path(__file__).resolve().parent
92-
candidates = []
93-
explicit_env = os.environ.get("DEPLOYMENT_ROOT_ENV")
94-
if explicit_env:
95-
candidates.append(Path(explicit_env))
96-
candidates.extend([
97-
script_dir.parent.parent.parent / "env" / ".env",
98-
script_dir.parent.parent.parent / ".env",
99-
script_dir.parent.parent / ".env",
100-
script_dir.parent / ".env",
101-
])
81+
candidates = get_host_env_candidates()
10282
env_file = next((candidate for candidate in candidates if candidate.is_file()), candidates[0])
10383
if env_file.is_file():
10484
with open(env_file, 'r') as f:
@@ -113,6 +93,27 @@ def get_root_dir() -> str:
11393
return root_dir
11494

11595

96+
def get_host_env_candidates():
97+
"""Return allowed host env files without consulting the project root .env."""
98+
script_dir = Path(__file__).resolve().parent
99+
candidates = []
100+
explicit_env = os.environ.get("DEPLOYMENT_ROOT_ENV")
101+
if explicit_env:
102+
candidates.append(Path(explicit_env))
103+
104+
if len(script_dir.parents) >= 4:
105+
deploy_root = script_dir.parents[2]
106+
project_root = script_dir.parents[3]
107+
candidates.extend([
108+
deploy_root / "env" / ".env",
109+
project_root / "docker" / ".env",
110+
])
111+
112+
if not candidates:
113+
candidates.append(script_dir / "deploy" / "env" / ".env")
114+
return candidates
115+
116+
116117
def check_container_running():
117118
"""Check if nexent-config container is running."""
118119
try:

deploy/docker/assets/scripts/v220_sync_skill_directory.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ fi
6060
# deploy/docker/assets/scripts or from the copied ROOT_DIR/scripts directory.
6161
ENV_FILE="${DEPLOYMENT_ROOT_ENV:-}"
6262
if [ -z "$ENV_FILE" ]; then
63-
for candidate in "${SCRIPT_DIR}/../../../env/.env" "${SCRIPT_DIR}/../../../../.env" "${SCRIPT_DIR}/../../../.env" "${SCRIPT_DIR}/../../.env"; do
63+
for candidate in "${SCRIPT_DIR}/../../../env/.env" "${SCRIPT_DIR}/../../../../docker/.env"; do
6464
if [ -f "$candidate" ]; then
6565
ENV_FILE="$candidate"
6666
break

deploy/docker/generate_env.sh

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,7 @@ DEPLOY_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
88
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
99
ENV_FILE="${DEPLOYMENT_ROOT_ENV:-$DEPLOY_ROOT/env/.env}"
1010
ENV_EXAMPLE="$DEPLOY_ROOT/env/.env.example"
11-
LEGACY_ROOT_ENV="$PROJECT_ROOT/.env"
12-
LEGACY_ROOT_EXAMPLE="$PROJECT_ROOT/.env.example"
13-
LEGACY_ENV="$PROJECT_ROOT/docker/.env"
14-
LEGACY_ENV_EXAMPLE="$PROJECT_ROOT/docker/.env.example"
11+
DOCKER_ENV="$PROJECT_ROOT/docker/.env"
1512

1613
if [ "${NEXENT_GENERATE_ENV_SKIP_MAIN:-false}" != "true" ]; then
1714
echo " 📁 Target .env location: $ENV_FILE"
@@ -47,28 +44,16 @@ prepare_env_file() {
4744

4845
if [ -f "$ENV_FILE" ]; then
4946
echo " ✅ Using existing deploy/env/.env"
50-
elif [ -f "$LEGACY_ROOT_ENV" ]; then
51-
echo " deploy/env/.env not found, copying legacy root .env..."
52-
cp "$LEGACY_ROOT_ENV" "$ENV_FILE"
53-
echo " Created deploy/env/.env from legacy root .env"
54-
elif [ -f "$LEGACY_ENV" ]; then
47+
elif [ -f "$DOCKER_ENV" ]; then
5548
echo " deploy/env/.env not found, copying docker/.env..."
56-
cp "$LEGACY_ENV" "$ENV_FILE"
49+
cp "$DOCKER_ENV" "$ENV_FILE"
5750
echo " Created deploy/env/.env from docker/.env"
5851
elif [ -f "$ENV_EXAMPLE" ]; then
5952
echo " 📋 deploy/env/.env not found, copying .env.example..."
6053
cp "$ENV_EXAMPLE" "$ENV_FILE"
6154
echo " ✅ Created deploy/env/.env from .env.example"
62-
elif [ -f "$LEGACY_ROOT_EXAMPLE" ]; then
63-
echo " 📋 deploy/env/.env not found, copying legacy root .env.example..."
64-
cp "$LEGACY_ROOT_EXAMPLE" "$ENV_FILE"
65-
echo " ✅ Created deploy/env/.env from legacy root .env.example"
66-
elif [ -f "$LEGACY_ENV_EXAMPLE" ]; then
67-
echo " 📋 deploy/env/.env not found, copying docker/.env.example..."
68-
cp "$LEGACY_ENV_EXAMPLE" "$ENV_FILE"
69-
echo " ✅ Created deploy/env/.env from docker/.env.example"
7055
else
71-
echo " ERROR Neither deploy/env/.env nor deploy/env/.env.example nor legacy .env files exist"
56+
echo " ERROR Neither deploy/env/.env nor docker/.env nor deploy/env/.env.example exists"
7257
ERROR_OCCURRED=1
7358
return 1
7459
fi

deploy/k8s/helm/nexent/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ bash uninstall.sh k8s delete-all
6969
bash uninstall.sh k8s delete-all --keep-local-data
7070
```
7171

72-
K8s deployments read runtime configuration from `deploy/env/.env`, the same file used by Docker. Existing `deploy/env/.env` is kept as-is. If it is missing, the deploy script first reuses an existing legacy root `.env` or `docker/.env`, then falls back to `deploy/env/.env.example` or legacy templates. Do not edit generated Helm values by hand; they are recreated from `deploy/env/.env` and deployment options.
72+
K8s deployments read runtime configuration from `deploy/env/.env`, the same file used by Docker. Existing `deploy/env/.env` is kept as-is. If it is missing, the deploy script first reuses `docker/.env`, then falls back to `deploy/env/.env.example`. Do not edit generated Helm values by hand; they are recreated from `deploy/env/.env` and deployment options.
7373

7474
When `--persistence-mode local` is used, Nexent renders static PVs with `hostPath` and `DirectoryOrCreate`; node affinity is not required. Shared workspace data uses `/var/lib/nexent`, shared skills use `/var/lib/nexent-data/skills`, and service data uses `/var/lib/nexent-data/nexent-*` by default.
7575

deploy/tests/test_common.sh

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -202,10 +202,28 @@ fi
202202

203203
ENV_TEST_ROOT="$TMP_DIR/env-root"
204204
mkdir -p "$ENV_TEST_ROOT/docker" "$ENV_TEST_ROOT/deploy/env"
205+
printf 'FROM_ROOT_SHOULD_NOT_COPY=yes\n' > "$ENV_TEST_ROOT/.env"
206+
printf 'FROM_ROOT_EXAMPLE_SHOULD_NOT_COPY=yes\n' > "$ENV_TEST_ROOT/.env.example"
205207
printf 'FROM_DOCKER=yes\n' > "$ENV_TEST_ROOT/docker/.env"
206208
printf 'FROM_EXAMPLE=yes\n' > "$ENV_TEST_ROOT/deploy/env/.env.example"
207209
deployment_ensure_root_env "$ENV_TEST_ROOT" "$ENV_TEST_ROOT/docker"
208210
assert_contains "$(cat "$ENV_TEST_ROOT/deploy/env/.env")" "FROM_DOCKER=yes" "deploy/env/.env should migrate from docker/.env first"
211+
if grep -q "FROM_ROOT_SHOULD_NOT_COPY" "$ENV_TEST_ROOT/deploy/env/.env"; then
212+
echo "FAIL: deploy/env/.env should not migrate from root .env"
213+
exit 1
214+
fi
215+
216+
DOCKER_EXAMPLE_ONLY_ROOT="$TMP_DIR/docker-example-only-root"
217+
mkdir -p "$DOCKER_EXAMPLE_ONLY_ROOT/docker" "$DOCKER_EXAMPLE_ONLY_ROOT/deploy/env"
218+
printf 'FROM_DOCKER_EXAMPLE_SHOULD_NOT_COPY=yes\n' > "$DOCKER_EXAMPLE_ONLY_ROOT/docker/.env.example"
219+
if deployment_ensure_root_env "$DOCKER_EXAMPLE_ONLY_ROOT" "$DOCKER_EXAMPLE_ONLY_ROOT/docker" 2>/dev/null; then
220+
echo "FAIL: deploy/env/.env should not migrate from docker/.env.example"
221+
exit 1
222+
fi
223+
if [ -f "$DOCKER_EXAMPLE_ONLY_ROOT/deploy/env/.env" ]; then
224+
echo "FAIL: docker/.env.example should not create deploy/env/.env"
225+
exit 1
226+
fi
209227

210228
printf 'ROOT_ONLY=yes\n' > "$ENV_TEST_ROOT/deploy/env/.env"
211229
deployment_ensure_root_env "$ENV_TEST_ROOT" "$ENV_TEST_ROOT/docker"
@@ -228,6 +246,8 @@ assert_eq "false" "$DEPLOYMENT_LAST_ENV_WRITE_CHANGED" "env updater should norma
228246

229247
GENERATE_ENV_TEST_ROOT="$TMP_DIR/generate-env-root"
230248
mkdir -p "$GENERATE_ENV_TEST_ROOT/docker" "$GENERATE_ENV_TEST_ROOT/deploy/env"
249+
printf 'FROM_GENERATE_ROOT_SHOULD_NOT_COPY=yes\n' > "$GENERATE_ENV_TEST_ROOT/.env"
250+
printf 'FROM_GENERATE_ROOT_EXAMPLE_SHOULD_NOT_COPY=yes\n' > "$GENERATE_ENV_TEST_ROOT/.env.example"
231251
printf 'FROM_GENERATE_DOCKER=yes\n' > "$GENERATE_ENV_TEST_ROOT/docker/.env"
232252
printf 'FROM_GENERATE_EXAMPLE=yes\n' > "$GENERATE_ENV_TEST_ROOT/deploy/env/.env.example"
233253
(
@@ -236,11 +256,32 @@ printf 'FROM_GENERATE_EXAMPLE=yes\n' > "$GENERATE_ENV_TEST_ROOT/deploy/env/.env.
236256
source "$SCRIPT_DIR/../docker/generate_env.sh"
237257
ENV_FILE="$GENERATE_ENV_TEST_ROOT/deploy/env/.env"
238258
ENV_EXAMPLE="$GENERATE_ENV_TEST_ROOT/deploy/env/.env.example"
239-
LEGACY_ROOT_ENV="$GENERATE_ENV_TEST_ROOT/.env"
240-
LEGACY_ROOT_EXAMPLE="$GENERATE_ENV_TEST_ROOT/.env.example"
241-
LEGACY_ENV="$GENERATE_ENV_TEST_ROOT/docker/.env"
242-
LEGACY_ENV_EXAMPLE="$GENERATE_ENV_TEST_ROOT/docker/.env.example"
259+
DOCKER_ENV="$GENERATE_ENV_TEST_ROOT/docker/.env"
243260
prepare_env_file >/dev/null
244261
)
245262
assert_contains "$(cat "$GENERATE_ENV_TEST_ROOT/deploy/env/.env")" "FROM_GENERATE_DOCKER=yes" "generate_env should migrate docker/.env before deploy/env/.env.example"
263+
if grep -q "FROM_GENERATE_ROOT_SHOULD_NOT_COPY" "$GENERATE_ENV_TEST_ROOT/deploy/env/.env"; then
264+
echo "FAIL: generate_env should not migrate from root .env"
265+
exit 1
266+
fi
267+
268+
GENERATE_DOCKER_EXAMPLE_ONLY_ROOT="$TMP_DIR/generate-docker-example-only-root"
269+
mkdir -p "$GENERATE_DOCKER_EXAMPLE_ONLY_ROOT/docker" "$GENERATE_DOCKER_EXAMPLE_ONLY_ROOT/deploy/env"
270+
printf 'FROM_GENERATE_DOCKER_EXAMPLE_SHOULD_NOT_COPY=yes\n' > "$GENERATE_DOCKER_EXAMPLE_ONLY_ROOT/docker/.env.example"
271+
if (
272+
NEXENT_GENERATE_ENV_SKIP_MAIN=true
273+
# shellcheck source=/dev/null
274+
source "$SCRIPT_DIR/../docker/generate_env.sh"
275+
ENV_FILE="$GENERATE_DOCKER_EXAMPLE_ONLY_ROOT/deploy/env/.env"
276+
ENV_EXAMPLE="$GENERATE_DOCKER_EXAMPLE_ONLY_ROOT/deploy/env/.env.example"
277+
DOCKER_ENV="$GENERATE_DOCKER_EXAMPLE_ONLY_ROOT/docker/.env"
278+
prepare_env_file >/dev/null 2>&1
279+
); then
280+
echo "FAIL: generate_env should not migrate from docker/.env.example"
281+
exit 1
282+
fi
283+
if [ -f "$GENERATE_DOCKER_EXAMPLE_ONLY_ROOT/deploy/env/.env" ]; then
284+
echo "FAIL: generate_env should not create deploy/env/.env from docker/.env.example"
285+
exit 1
286+
fi
246287
echo "All deployment common tests passed."

doc/docs/en/developer-guide/environment-setup.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ bash deploy.sh docker --components infrastructure --port-policy development
2626
```
2727

2828
:::: info Important Notes
29-
Infrastructure mode launches PostgreSQL, Redis, Elasticsearch, and MinIO. The script generates required credentials and saves them in the project root `.env`. URLs are configured as localhost endpoints for easy local development.
29+
Infrastructure mode launches PostgreSQL, Redis, Elasticsearch, and MinIO. The script generates required credentials and saves them in `deploy/env/.env`. URLs are configured as localhost endpoints for easy local development.
3030
::::
3131

3232
### 2. Backend Setup

doc/docs/en/quick-start/installation.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ git clone https://github.com/ModelEngine-Group/nexent.git
2121
cd nexent
2222
```
2323

24-
> **Tip**: Docker and Kubernetes use `deploy/env/.env`. Existing `deploy/env/.env` is kept as-is. If it does not exist, the deploy scripts first reuse an existing legacy root `.env` or `docker/.env`, then fall back to `deploy/env/.env.example` or legacy templates. If you need to configure voice models (STT/TTS), update the related values in `deploy/env/.env` before or after deployment.
24+
> **Tip**: Docker and Kubernetes use `deploy/env/.env`. Existing `deploy/env/.env` is kept as-is. If it does not exist, the deploy scripts first reuse `docker/.env`, then fall back to `deploy/env/.env.example`. If you need to configure voice models (STT/TTS), update the related values in `deploy/env/.env` before or after deployment.
2525
2626
### 2. Deployment Options
2727

0 commit comments

Comments
 (0)