From a40c5ce4392f24f93dff8bae280748528f6faec5 Mon Sep 17 00:00:00 2001 From: wkc <978997012@qq.com> Date: Mon, 23 Mar 2026 14:45:35 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9ENAS=E9=83=A8=E7=BD=B2?= =?UTF-8?q?=E8=84=9A=E6=9C=AC=E5=B9=B6=E8=A1=A5=E9=BD=90Mock=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E5=BA=93=E7=8E=AF=E5=A2=83=E5=8F=98=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .DS_Store | Bin 14340 -> 14340 bytes .env.example | 7 ++ deploy/deploy-to-nas.sh | 117 ++++++++++++++++++ docker-compose.yml | 5 + ...6-03-23-deploy-to-nas-sh-implementation.md | 26 ++++ ...-23-lsfx-mock-db-env-fix-implementation.md | 33 +++++ .../src/main/resources/application-nas.yml | 6 + tests/deploy/test_deploy_to_nas.py | 45 +++++++ tests/deploy/test_lsfx_mock_deploy_config.py | 15 +++ 9 files changed, 254 insertions(+) create mode 100755 deploy/deploy-to-nas.sh create mode 100644 docs/reports/implementation/2026-03-23-deploy-to-nas-sh-implementation.md create mode 100644 docs/reports/implementation/2026-03-23-lsfx-mock-db-env-fix-implementation.md create mode 100644 tests/deploy/test_deploy_to_nas.py create mode 100644 tests/deploy/test_lsfx_mock_deploy_config.py diff --git a/.DS_Store b/.DS_Store index 183ecf64d336dccce1c12f6af471abbfe8b94132..d467ef556817a2cef91c1ff46bb6e9551145d8b2 100644 GIT binary patch delta 717 zcmdtfKP=pF9LDj_`zso9Cp3tE!KuGN8s{p}w8S8dlpE?U2sV!XNPfRdi57zhO|||E zzS^k?O&QxrPPI#=Ww2;M`e!hxgaL!eqCxu0H8FPR*k^c#XM5!t4UPsEU%H~oZhDGc zp7Ihs@9K3po12U_%k&uo0evsIUk7s%qqD0@B%IJ{Rv+3*O&jVq%=YMnKkH>9QIals zQZ7~EmkzOHSSDmvmgJ+X$QSt`JF+jwaw@;%TrP;fNg_!klfpH!$t4dDx2d3#yZG?a zKqIXL=-@sECJ%YU0E2jkdB!-CO!0zQ=6KCKZ&>C%A6RFTExz)NpB!+=5oan=#i}@U zRi&ylm98?BTa~I?s#&v!@~OpvSPx%TNCcS_HoVpBt;# delta 627 zcmd7PKS1JI$t)l#YPuGVeDBy&X-Th2*-&hfmCeRF~}sJ0-T(uj0!5b zhKoBi&`1-lJiv#ac0%;R#{`6ZFcyb#jYHa zBuSHWIU`x(kQ~XCQn@TwrAlh$ws>?}cAZ?0+0Pzk*G6HscI50Gq9v*$Hrw5cT(Jx{ zsHTRS)LITVEqG#/dev/null 2>&1; then + echo "缺少命令: ${command_name}" >&2 + exit 1 + fi +} + +reset_directory() { + local target_dir="$1" + rm -rf "${target_dir}" + mkdir -p "${target_dir}" +} + +copy_path() { + local source_path="$1" + local destination_path="$2" + cp -R "${source_path}" "${destination_path}" +} + +ensure_paramiko() { + if python3 - <<'PY' +import importlib.util +import sys + +sys.exit(0 if importlib.util.find_spec("paramiko") else 1) +PY + then + return + fi + + python3 -m pip install --user paramiko +} + +POSITION=0 +for arg in "$@"; do + if [[ "${arg}" == "--dry-run" ]]; then + DRY_RUN="true" + continue + fi + + POSITION=$((POSITION + 1)) + case "${POSITION}" in + 1) SERVER_HOST="${arg}" ;; + 2) SERVER_PORT="${arg}" ;; + 3) SERVER_USERNAME="${arg}" ;; + 4) SERVER_PASSWORD="${arg}" ;; + 5) REMOTE_ROOT="${arg}" ;; + *) + echo "仅支持 [host] [port] [username] [password] [remoteRoot] [--dry-run]" >&2 + exit 1 + ;; + esac +done + +if [[ "${DRY_RUN}" == "true" ]]; then + echo "[DryRun] 一键部署参数预览" + echo "Host: ${SERVER_HOST}" + echo "Port: ${SERVER_PORT}" + echo "Username: ${SERVER_USERNAME}" + echo "RemoteRoot: ${REMOTE_ROOT}" + exit 0 +fi + +echo "[1/5] 检查本地环境" +ensure_command "mvn" +ensure_command "npm" +ensure_command "python3" + +echo "[2/5] 打包后端" +( + cd "${REPO_ROOT}" + mvn clean package -DskipTests +) + +echo "[3/5] 打包前端" +( + cd "${REPO_ROOT}/ruoyi-ui" + npm run build:prod +) + +echo "[4/5] 组装部署目录" +reset_directory "${STAGE_ROOT}" +mkdir -p "${STAGE_ROOT}/backend" "${STAGE_ROOT}/frontend" + +copy_path "${REPO_ROOT}/docker" "${STAGE_ROOT}/docker" +copy_path "${REPO_ROOT}/lsfx-mock-server" "${STAGE_ROOT}/lsfx-mock-server" +copy_path "${REPO_ROOT}/ruoyi-ui/dist" "${STAGE_ROOT}/frontend/dist" +copy_path "${REPO_ROOT}/docker-compose.yml" "${STAGE_ROOT}/docker-compose.yml" +copy_path "${REPO_ROOT}/.env.example" "${STAGE_ROOT}/.env.example" +copy_path "${REPO_ROOT}/ruoyi-admin/target/ruoyi-admin.jar" "${STAGE_ROOT}/backend/ruoyi-admin.jar" + +echo "[5/5] 上传并远端部署" +ensure_paramiko + +python3 "${SCRIPT_DIR}/remote-deploy.py" \ + --host "${SERVER_HOST}" \ + --port "${SERVER_PORT}" \ + --username "${SERVER_USERNAME}" \ + --password "${SERVER_PASSWORD}" \ + --local-root "${STAGE_ROOT}" \ + --remote-root "${REMOTE_ROOT}" diff --git a/docker-compose.yml b/docker-compose.yml index 35b2d36a..b5ea0ec7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -32,6 +32,11 @@ services: HOST: 0.0.0.0 PORT: 8000 PARSE_DELAY_SECONDS: 4 + CCDI_DB_HOST: ${CCDI_DB_HOST:-192.168.0.111} + CCDI_DB_PORT: ${CCDI_DB_PORT:-40627} + CCDI_DB_NAME: ${CCDI_DB_NAME:-ccdi} + CCDI_DB_USERNAME: ${CCDI_DB_USERNAME:-root} + CCDI_DB_PASSWORD: ${CCDI_DB_PASSWORD:-Kfcx@1234} frontend: build: diff --git a/docs/reports/implementation/2026-03-23-deploy-to-nas-sh-implementation.md b/docs/reports/implementation/2026-03-23-deploy-to-nas-sh-implementation.md new file mode 100644 index 00000000..b3f55736 --- /dev/null +++ b/docs/reports/implementation/2026-03-23-deploy-to-nas-sh-implementation.md @@ -0,0 +1,26 @@ +# Deploy To NAS Shell 入口实施记录 + +## 本次改动 + +- 新增 `deploy/deploy-to-nas.sh`,提供适用于当前 Unix 环境的 NAS 部署入口。 +- 保留原有默认参数:`host`、`port`、`username`、`password`、`remoteRoot`。 +- 保持与原 BAT 一致的位置参数协议,并继续支持 `--dry-run` 快速校验。 +- 在 Shell 入口内完成本地环境检查、后端打包、前端打包、部署目录组装、`paramiko` 依赖检查与远端部署调用。 +- 复用现有 `deploy/remote-deploy.py`,不改动 NAS 端上传与 Docker Compose 执行逻辑。 +- 新增 `tests/deploy/test_deploy_to_nas.py`,覆盖默认参数和覆盖参数两类 `dry-run` 行为。 + +## 变更文件 + +- `deploy/deploy-to-nas.sh` +- `tests/deploy/test_deploy_to_nas.py` + +## 验证结果 + +- `python3 -m pytest tests/deploy/test_deploy_to_nas.py -q` +- `bash -n deploy/deploy-to-nas.sh` +- `bash deploy/deploy-to-nas.sh --dry-run` + +## 说明 + +- 当前环境未预装 `paramiko`,脚本会在真实部署前自动执行 `python3 -m pip install --user paramiko`。 +- 本次未执行真实 NAS 部署,只完成了脚本级与 `dry-run` 级验证,避免在未明确要求下直接触发线上构建上传。 diff --git a/docs/reports/implementation/2026-03-23-lsfx-mock-db-env-fix-implementation.md b/docs/reports/implementation/2026-03-23-lsfx-mock-db-env-fix-implementation.md new file mode 100644 index 00000000..7e91d455 --- /dev/null +++ b/docs/reports/implementation/2026-03-23-lsfx-mock-db-env-fix-implementation.md @@ -0,0 +1,33 @@ +# LSFX Mock 数据库环境变量修复记录 + +## 本次改动 + +- 修复 NAS 部署后 `lsfx-mock-server` 未注入员工库连接参数的问题。 +- 在根目录 `docker-compose.yml` 的 `lsfx-mock-server` 服务中补充: + - `CCDI_DB_HOST` + - `CCDI_DB_PORT` + - `CCDI_DB_NAME` + - `CCDI_DB_USERNAME` + - `CCDI_DB_PASSWORD` +- 在根目录 `.env.example` 中补充对应示例值,便于后续按环境覆盖。 +- 新增部署配置测试,保证 Mock 容器必须携带上述数据库参数默认值。 + +## 根因说明 + +- `lsfx-mock-server` 在容器内启动时没有 `CCDI_DB_*` 环境变量。 +- `config/settings.py` 在容器内无法从主项目配置路径解析出数据库默认值,最终得到空字符串主机名。 +- `PyMySQL` 在主机名为空时退化为按 `localhost` 建连,容器内没有本地 MySQL,因此上传接口调用员工库时报 `Can't connect to MySQL server on 'localhost'`。 + +## 变更文件 + +- `docker-compose.yml` +- `.env.example` +- `tests/deploy/test_lsfx_mock_deploy_config.py` + +## 验证结果 + +- `python3 -m pytest tests/deploy -q` +- 重新执行 `bash deploy/deploy-to-nas.sh` +- 容器内读取 `settings.CCDI_DB_HOST`,结果为 `192.168.0.111` +- 容器内执行数据库 `SELECT 1` 成功 +- 调用 `POST /watson/api/project/remoteUploadSplitFile` 返回 `200 OK` diff --git a/ruoyi-admin/src/main/resources/application-nas.yml b/ruoyi-admin/src/main/resources/application-nas.yml index 2786b24c..0c03d334 100644 --- a/ruoyi-admin/src/main/resources/application-nas.yml +++ b/ruoyi-admin/src/main/resources/application-nas.yml @@ -1,3 +1,9 @@ +# 开发环境配置 +ruoyi: + # 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath) + profile: backend/uploadPath + + # 开发环境配置 server: # 服务器的HTTP端口,默认为8080 diff --git a/tests/deploy/test_deploy_to_nas.py b/tests/deploy/test_deploy_to_nas.py new file mode 100644 index 00000000..fb4d7112 --- /dev/null +++ b/tests/deploy/test_deploy_to_nas.py @@ -0,0 +1,45 @@ +from pathlib import Path +import subprocess + + +REPO_ROOT = Path(__file__).resolve().parents[2] +SCRIPT_PATH = REPO_ROOT / "deploy" / "deploy-to-nas.sh" + + +def test_sh_dry_run_uses_default_nas_target(): + result = subprocess.run( + ["bash", str(SCRIPT_PATH), "--dry-run"], + cwd=REPO_ROOT, + capture_output=True, + text=True, + ) + + assert result.returncode == 0 + assert "Host: 116.62.17.81" in result.stdout + assert "Port: 9444" in result.stdout + assert "Username: wkc" in result.stdout + assert "RemoteRoot: /volume1/webapp/ccdi" in result.stdout + + +def test_sh_dry_run_accepts_override_arguments(): + result = subprocess.run( + [ + "bash", + str(SCRIPT_PATH), + "10.0.0.8", + "2222", + "deploy-user", + "secret", + "/volume2/custom/app", + "--dry-run", + ], + cwd=REPO_ROOT, + capture_output=True, + text=True, + ) + + assert result.returncode == 0 + assert "Host: 10.0.0.8" in result.stdout + assert "Port: 2222" in result.stdout + assert "Username: deploy-user" in result.stdout + assert "RemoteRoot: /volume2/custom/app" in result.stdout diff --git a/tests/deploy/test_lsfx_mock_deploy_config.py b/tests/deploy/test_lsfx_mock_deploy_config.py new file mode 100644 index 00000000..2fe0b710 --- /dev/null +++ b/tests/deploy/test_lsfx_mock_deploy_config.py @@ -0,0 +1,15 @@ +from pathlib import Path + + +REPO_ROOT = Path(__file__).resolve().parents[2] +DOCKER_COMPOSE = REPO_ROOT / "docker-compose.yml" + + +def test_lsfx_mock_service_receives_ccdi_db_defaults(): + compose_text = DOCKER_COMPOSE.read_text(encoding="utf-8") + + assert 'CCDI_DB_HOST: ${CCDI_DB_HOST:-192.168.0.111}' in compose_text + assert 'CCDI_DB_PORT: ${CCDI_DB_PORT:-40627}' in compose_text + assert 'CCDI_DB_NAME: ${CCDI_DB_NAME:-ccdi}' in compose_text + assert 'CCDI_DB_USERNAME: ${CCDI_DB_USERNAME:-root}' in compose_text + assert 'CCDI_DB_PASSWORD: ${CCDI_DB_PASSWORD:-Kfcx@1234}' in compose_text