修正CEO报销财务兜底与部署护栏(07-28-ceo-finance-fallback)
这个提交包含在:
@@ -16,7 +16,7 @@
|
||||
- [ ] 已将 OA `Caddyfile` 站点块配置到 `/etc/caddy/Caddyfile`
|
||||
- [ ] 已确认 Caddy 反代到 `.env` 中 `APP_HOST_PORT` 对应的宿主回环端口,并用 `header_up X-Forwarded-For {remote_host}` 覆盖客户端 XFF
|
||||
- [ ] 已执行 `systemctl reload caddy`
|
||||
- [ ] 已显式提供 `DEPLOY_SERVER`、`REMOTE_DIR`、绝对 `POSTGRES_DATA_DIR`、绝对 `STORAGE_HOST_DIR` 和 `DEPLOY_DATA_MODE`,并从本地执行发布入口
|
||||
- [ ] 已显式提供 `DEPLOY_SERVER`、`REMOTE_DIR`、绝对 `POSTGRES_DATA_DIR`、绝对 `STORAGE_HOST_DIR` 和 `DEPLOY_DATA_MODE`,并确认源码同步根目录与两个数据目录任一方向均不嵌套,再从本地执行发布入口
|
||||
- [ ] 已通过 `https://<oa-domain>/ready` 或首页登录完成最小探活
|
||||
- [ ] 首次上线先执行系统初始化(migration + seed),不要直接导入旧库整库备份
|
||||
- [ ] 若要导数据,仅准备最小主数据:部门、员工、角色、在用资产、活跃项目、合同元数据
|
||||
|
||||
+30
-3
@@ -22,6 +22,7 @@ RUNTIME_SMOKE_SCRIPT="server/src/scripts/smoke-trialrun-runtime.js"
|
||||
EXTERNAL_DEPS_SMOKE_SCRIPT="server/src/scripts/smoke-external-deps.js"
|
||||
PROVENANCE_SCRIPT="deploy/trialrun/check-source-provenance.mjs"
|
||||
STAGING_DIR=""
|
||||
RSYNC_PROTECT_ARGS=()
|
||||
|
||||
cleanup() {
|
||||
if [[ -n "$STAGING_DIR" && -d "$STAGING_DIR" ]]; then
|
||||
@@ -56,7 +57,7 @@ if [[ ! "$COMPOSE_PROJECT_NAME" =~ ^[a-z0-9][a-z0-9_-]*$ ]]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
validate_data_path() {
|
||||
validate_absolute_path() {
|
||||
local name="$1"
|
||||
local value="$2"
|
||||
if [[ -z "$value" || "$value" != /* || ! "$value" =~ ^/[A-Za-z0-9._/-]+$ ]]; then
|
||||
@@ -70,8 +71,16 @@ validate_data_path() {
|
||||
fi
|
||||
}
|
||||
|
||||
validate_data_path POSTGRES_DATA_DIR "$POSTGRES_DATA_DIR"
|
||||
validate_data_path STORAGE_HOST_DIR "$STORAGE_HOST_DIR"
|
||||
paths_overlap() {
|
||||
local first="$1"
|
||||
local second="$2"
|
||||
[[ "$first" == "$second" || "$first" == "$second"/* || "$second" == "$first"/* ]]
|
||||
}
|
||||
|
||||
validate_absolute_path REMOTE_DIR "$REMOTE_DIR"
|
||||
validate_absolute_path REMOTE_ENV_FILE "$REMOTE_ENV_FILE"
|
||||
validate_absolute_path POSTGRES_DATA_DIR "$POSTGRES_DATA_DIR"
|
||||
validate_absolute_path STORAGE_HOST_DIR "$STORAGE_HOST_DIR"
|
||||
if [[ "$POSTGRES_DATA_DIR" == "$STORAGE_HOST_DIR" \
|
||||
|| "$POSTGRES_DATA_DIR" == "$STORAGE_HOST_DIR"/* \
|
||||
|| "$STORAGE_HOST_DIR" == "$POSTGRES_DATA_DIR"/* ]]; then
|
||||
@@ -82,6 +91,23 @@ if [[ "$DEPLOY_DATA_MODE" != "existing" && "$DEPLOY_DATA_MODE" != "initialize" ]
|
||||
echo "[ERROR] DEPLOY_DATA_MODE 必须显式设为 existing 或 initialize" >&2
|
||||
exit 1
|
||||
fi
|
||||
if paths_overlap "$REMOTE_DIR" "$POSTGRES_DATA_DIR"; then
|
||||
echo "[ERROR] POSTGRES_DATA_DIR 不得与 REMOTE_DIR 同目录或相互嵌套,避免源码同步触碰数据库" >&2
|
||||
exit 1
|
||||
fi
|
||||
if paths_overlap "$REMOTE_DIR" "$STORAGE_HOST_DIR"; then
|
||||
echo "[ERROR] STORAGE_HOST_DIR 不得与 REMOTE_DIR 同目录或相互嵌套,避免源码同步触碰附件" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ "$REMOTE_ENV_FILE" == "$REMOTE_DIR" ]]; then
|
||||
echo "[ERROR] REMOTE_ENV_FILE 不得等于 REMOTE_DIR" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ "$REMOTE_ENV_FILE" == "$REMOTE_DIR"/* ]]; then
|
||||
REMOTE_ENV_RELATIVE="${REMOTE_ENV_FILE#"$REMOTE_DIR"/}"
|
||||
RSYNC_PROTECT_ARGS+=(--filter="protect /${REMOTE_ENV_RELATIVE}")
|
||||
RSYNC_PROTECT_ARGS+=(--exclude="/${REMOTE_ENV_RELATIVE}")
|
||||
fi
|
||||
|
||||
if [[ ! -f "${ROOT_DIR}/${PROVENANCE_SCRIPT}" ]]; then
|
||||
echo "[ERROR] 缺少 ${PROVENANCE_SCRIPT}" >&2
|
||||
@@ -139,6 +165,7 @@ ssh "${DEPLOY_SERVER}" "mkdir -p '${REMOTE_DIR}'"
|
||||
|
||||
echo ">>> 4. 同步已验证提交到服务器"
|
||||
rsync -az --delete \
|
||||
"${RSYNC_PROTECT_ARGS[@]}" \
|
||||
--exclude '.git' \
|
||||
--exclude '.github' \
|
||||
--exclude '.agent' \
|
||||
|
||||
@@ -119,7 +119,7 @@ docker-compose -p "$COMPOSE_PROJECT_NAME" -f deploy/trialrun/docker-compose.yml
|
||||
```
|
||||
|
||||
说明:
|
||||
- `init` 是一次性任务:`migrate:deploy + seed:config + seed:trialrun`。
|
||||
- `init` 是一次性任务:`migrate:deploy + seed:config + seed:trialrun`。`seed:config` 仅在审批规则表为空时创建默认三档;已有任意审批规则时必须全部保留,生产规则变更另走获批的原子事务。
|
||||
- 初始化必须发生在依赖新增列的新 server 切换之前;正式部署脚本会先用新 init 镜像校验生产配置并执行迁移,再替换 server。
|
||||
- 若 `TRIALRUN_ADMIN_PASSWORD` 为空,seed 会生成一次性口令并输出到控制台(请立刻保存)。
|
||||
- 正式启用前,推荐先保持“空基线 + 默认种子”,不要直接导入开发库、测试库或旧 OA 整库备份。
|
||||
@@ -392,7 +392,7 @@ systemctl status hyb-oa-public-app-health.service --no-pager
|
||||
|
||||
步骤:
|
||||
1) 先做备份(见 E14 脚本)
|
||||
2) 从本地仓库执行 `DEPLOY_SERVER=<ssh-target> REMOTE_DIR=<remote-dir> COMPOSE_PROJECT_NAME=<approved-compose-project> POSTGRES_DATA_DIR=<absolute-pgdata> STORAGE_HOST_DIR=<absolute-storage> DEPLOY_DATA_MODE=existing bash deploy/trialrun/deploy.sh`(推荐);脚本只同步已验证提交的 Git archive,不依赖远端 `git pull`,也不会把本地 ignored 文件带入发布。
|
||||
2) 从本地仓库执行 `DEPLOY_SERVER=<ssh-target> REMOTE_DIR=<remote-dir> COMPOSE_PROJECT_NAME=<approved-compose-project> POSTGRES_DATA_DIR=<absolute-pgdata> STORAGE_HOST_DIR=<absolute-storage> DEPLOY_DATA_MODE=existing bash deploy/trialrun/deploy.sh`(推荐);脚本只同步已验证提交的 Git archive,不依赖远端 `git pull`,也不会把本地 ignored 文件带入发布。`REMOTE_DIR` 必须与 PostgreSQL、附件宿主目录完全分离;任一方向嵌套都会在 SSH 和 `rsync --delete` 前阻断。位于同步树内的 `REMOTE_ENV_FILE` 按实际相对路径动态保护。
|
||||
- 在现网目录统一任务中,新的 `COMPOSE_PROJECT_NAME`、`POSTGRES_DATA_DIR`、`STORAGE_HOST_DIR` 必须与活动数据目录复制在同一停机窗口启用;本地提交本身不授权切换。
|
||||
- 旧栈停止命令必须使用冻结阶段由 `docker compose ls` 实测的旧 project;不得拿新 project 名去停止旧容器。
|
||||
- `artifacts/` 和 `output/` 是运行期证据/截图目录,不作为源码发布输入,也不由 `rsync --delete` 清理远端历史证据。
|
||||
|
||||
@@ -428,8 +428,14 @@ for (const requiredFragment of [
|
||||
}
|
||||
|
||||
for (const requiredFragment of [
|
||||
'validate_data_path POSTGRES_DATA_DIR "$POSTGRES_DATA_DIR"',
|
||||
'validate_data_path STORAGE_HOST_DIR "$STORAGE_HOST_DIR"',
|
||||
'validate_absolute_path REMOTE_DIR "$REMOTE_DIR"',
|
||||
'validate_absolute_path REMOTE_ENV_FILE "$REMOTE_ENV_FILE"',
|
||||
'validate_absolute_path POSTGRES_DATA_DIR "$POSTGRES_DATA_DIR"',
|
||||
'validate_absolute_path STORAGE_HOST_DIR "$STORAGE_HOST_DIR"',
|
||||
'paths_overlap "$REMOTE_DIR" "$POSTGRES_DATA_DIR"',
|
||||
'paths_overlap "$REMOTE_DIR" "$STORAGE_HOST_DIR"',
|
||||
'RSYNC_PROTECT_ARGS+=(--filter="protect /${REMOTE_ENV_RELATIVE}")',
|
||||
'RSYNC_PROTECT_ARGS+=(--exclude="/${REMOTE_ENV_RELATIVE}")',
|
||||
'DEPLOY_DATA_MODE" != "existing"',
|
||||
'DEPLOY_DATA_MODE" != "initialize"',
|
||||
'"$POSTGRES_DATA_DIR/PG_VERSION"',
|
||||
|
||||
在新工单中引用
屏蔽一个用户