Initial commit: reorganized source tree

- backend/: 13 Maven modules (cw-elevator-application, cloudwalk-cloud, intelligent-cwoscomponent, ninca-crk, etc.)
- frontend/: 4 Vue projects (elevator-front, cwos-portal, alarm-front, front_acs) + decompiled + scripts
- scripts/: build, test-env, tools (Docker Compose, service templates, API parity)
- docs/: AGENTS.md, superpowers specs, architecture docs
- .gitignore: standard Java/Maven exclusions

Moved from legacy maven-*/ root layout to backend/ organized structure.
This commit is contained in:
hpd840321
2026-05-09 09:00:12 +08:00
commit 7b2bd307f1
7260 changed files with 612980 additions and 0 deletions
+335
View File
@@ -0,0 +1,335 @@
#!/usr/bin/env bash
# 仅编译本仓库(maven-cw-elevator-application),依赖从 Nexus 拉取,避免使用全局 ~/.m2 里
# 其它反编译工程 mvn install 产生的同坐标覆盖。
#
# 方案要点:
# - 使用独立 maven.repo.local(默认:仓库根目录下 .m2-elevator-nexus-only),与 ~/.m2 隔离。
# - Nexus 常缺聚合父 POM cloudwalk-cloud-common:脚本会(1)尝试从全局 ~/.m2 复制该目录;
# (2)若仍缺,且存在相邻仓库 maven-cloudwalk-legacy-public/cloudwalk-cloud-common,则自动
# mvn -N install 到隔离库(仅父 POM,不编其它反编译模块)。
# - 私服上 cloudwalk-common-web 等 POM 若传递依赖不完整,隔离构建会缺 spring-boot / commons-lang
# 等编译包。可选(3)从全局 ~/.m2 复制 cloudwalk-common-* 同版本目录(与 Nexus 二选一:先复制则优先用本地该目录)。
# - Nexus 常缺 SNAPSHOT 父 POMcwos / davinci)及 cloudwalk-device-sdk 父 POM:若相邻仓库存在对应 pom.xml,则自动 mvn -N install
# 到隔离库:maven-cwos-resource 的 cwos-component-resource、cwos-portalmaven-cloudwalk-intelligent-davinci-manager 根 POM
# maven-cloudwalk-device-sdk 根 POM(供 intelligent-cwoscomponent-interface 解析 protocol-entity)。
# ELEVATOR_AUTO_INSTALL_LEGACY_SNAPSHOT_PARENTS=0 跳过上述「相邻父 POM install」整段。
# - intelligent-cwoscomponent 固定为 2.9.2-xinghewan(与 cw_lib 一致,禁止 3.0.0):可先 ELEVATOR_BOOTSTRAP_INTELLIGENT_CWOSCOMPONENT_FROM_GLOBAL
# 从 ~/.m2 复制 parentartifactId intelligent-cwoscomponent/ interface / rest;若仍缺 JAR,则对
# cw-elevator-application-V1.0.0.20211103/cw_lib 内同名 jar+pom 执行 install-file,并先安装 scripts/legacy-poms 下父 POM 桩。
# ELEVATOR_AUTO_INSTALL_INTELLIGENT_CWOSCOMPONENT=0 跳过 installELEVATOR_CW_LIB_DIR 覆盖 cw_lib 路径。
# - cwos-sdk-event(默认 1.5.0-SNAPSHOT):ELEVATOR_BOOTSTRAP_CWOS_SDK_EVENT_FROM_GLOBAL 从 ~/.m2 复制;缺 JAR 时对
# maven-cloudwalk-legacy-public/cwos-sdk-event mvn install。ELEVATOR_AUTO_INSTALL_CWOS_SDK_EVENT=0 跳过 install。
# - ELEVATOR_BOOTSTRAP_FROM_GLOBAL_M2=0 跳过(1);ELEVATOR_AUTO_INSTALL_LEGACY_PARENT=0 跳过(2);
# ELEVATOR_BOOTSTRAP_CLOUDWALK_MODULES_FROM_GLOBAL=0 跳过(3)(坚持纯 Nexus 时用)。
#
# 用法:
# ./scripts/build_nexus_only.sh
# ELEVATOR_M2_REPO=/path/to/custom-repo ./scripts/build_nexus_only.sh
# ELEVATOR_SYNC_DEPLOY=1 ./scripts/build_nexus_only.sh # 另同步 V1/V2 到 deploy/v1-legacy 与 deploy/v2-maven
# - 编译成功后默认将 starter fat jar 安装到 deploy/v2-maven/(覆盖 cw-elevator-application-2.0.0.jar)。
# ELEVATOR_DEPLOY_V2_MAVEN=0 跳过;ELEVATOR_DEPLOY_V2_DIR=/path 覆盖目标目录(默认同 deploy/v2-maven)。
set -euo pipefail
REPO="$(cd "$(dirname "$0")/.." && pwd)"
cd "$REPO"
if [[ -z "${JAVA_8:-}" ]]; then
for d in /usr/lib/jvm/java-8-openjdk-amd64 /usr/lib/jvm/java-1.8.0-openjdk; do
if [[ -x "$d/bin/java" ]]; then
export JAVA_8="$d"
break
fi
done
fi
: "${JAVA_8:=/usr/lib/jvm/java-8-openjdk-amd64}"
export JAVA_HOME="$JAVA_8"
export PATH="$JAVA_HOME/bin:$PATH"
if [[ ! -x "${JAVA_HOME}/bin/java" ]]; then
echo "ERROR: 未找到 JDK 8,请设置 JAVA_8 或安装 openjdk-8-jdk。" >&2
exit 1
fi
M2_LOCAL="${ELEVATOR_M2_REPO:-$REPO/.m2-elevator-nexus-only}"
mkdir -p "$M2_LOCAL"
LEGACY_VER="${CLOUDWALK_LEGACY_VERSION:-3.7.2-Brussels-SRX}"
ICOMP_VER="${ELEVATOR_INTELLIGENT_CWOSCOMPONENT_VERSION:-2.9.2-xinghewan}"
CWOS_EVENT_VER="${ELEVATOR_CWOS_SDK_EVENT_VERSION:-1.5.0-SNAPSHOT}"
GLOBAL_M2="${ELEVATOR_GLOBAL_M2:-$HOME/.m2/repository}"
parent_marker_file() {
echo "$M2_LOCAL/cn/cloudwalk/cloud/cloudwalk-cloud-common/${LEGACY_VER}/cloudwalk-cloud-common-${LEGACY_VER}.pom"
}
bootstrap_from_global_m2() {
local rel="cn/cloudwalk/cloud/cloudwalk-cloud-common/${LEGACY_VER}"
local src="$GLOBAL_M2/$rel"
if [[ ! -d "$src" ]]; then
echo "WARN: 全局仓库中无父 POM 目录: $src(将尝试相邻 legacy 自动 install" >&2
return 0
fi
mkdir -p "$M2_LOCAL/$rel"
cp -a "$src/." "$M2_LOCAL/$rel/"
echo "==> 已从全局 ~/.m2 预置父 POM(仅该目录): $rel"
}
purge_last_updated_under() {
local base="$1"
[[ -d "$base" ]] || return 0
find "$base" -name '*.lastUpdated' -type f -print -delete 2>/dev/null || true
}
# 参数: marker_pom_path pom_file human_desc
install_one_snapshot_parent_to_local_repo() {
local marker="$1"
local pom="$2"
local desc="$3"
if [[ -f "$marker" ]]; then
echo "==> 隔离库已有: $desc"
return 0
fi
if [[ ! -f "$pom" ]]; then
echo "ERROR: 隔离库缺少 $desc,且未找到 POM: $pom" >&2
echo " 请将对应父 POM 发布到 Nexus,或设置 ELEVATOR_LEGACY_CWOS_RESOURCE_DIR / ELEVATOR_LEGACY_DAVINCI_MANAGER_POM。" >&2
exit 1
fi
echo "==> 向隔离库安装(mvn -N install: $desc -> $pom"
mvn -Dmaven.repo.local="$M2_LOCAL" -f "$pom" -N install -DskipTests
if [[ ! -f "$marker" ]]; then
echo "ERROR: install 后仍缺少: $marker" >&2
exit 1
fi
}
install_legacy_cloudwalk_parent_to_local_repo() {
local marker
marker="$(parent_marker_file)"
if [[ -f "$marker" ]]; then
echo "==> 隔离库已有父 POM: $marker"
return 0
fi
if [[ "${ELEVATOR_AUTO_INSTALL_LEGACY_PARENT:-1}" != "1" ]]; then
echo "ERROR: 隔离库缺少父 POM 且 ELEVATOR_AUTO_INSTALL_LEGACY_PARENT=0$marker" >&2
exit 1
fi
local def_pom
def_pom="$(cd "$REPO/.." && pwd)/maven-cloudwalk-legacy-public/cloudwalk-cloud-common/pom.xml"
local legacy_pom="${ELEVATOR_LEGACY_CLOUDWALK_COMMON_POM:-$def_pom}"
if [[ ! -f "$legacy_pom" ]]; then
echo "ERROR: 隔离库无 cloudwalk-cloud-common POM,且未找到:$legacy_pom" >&2
echo " 请设置 ELEVATOR_LEGACY_CLOUDWALK_COMMON_POM,或将该父 POM 发布到 Nexus。" >&2
exit 1
fi
echo "==> 向隔离库安装父 POMmvn -N install: $legacy_pom"
mvn -Dmaven.repo.local="$M2_LOCAL" -f "$legacy_pom" -N install -DskipTests
if [[ ! -f "$marker" ]]; then
echo "ERROR: install 后仍缺少: $marker" >&2
exit 1
fi
}
if [[ "${ELEVATOR_BOOTSTRAP_FROM_GLOBAL_M2:-1}" == "1" ]]; then
echo "==> 尝试从全局 ~/.m2 预置 cloudwalk-cloud-common${LEGACY_VER}"
bootstrap_from_global_m2
fi
install_legacy_cloudwalk_parent_to_local_repo
# 私服缺 cwos-portal / cwos-component-resource / cloudwalk-intelligent-davinci-manager 等父 POM 时,用相邻反应堆根 POM 闭合描述符。
install_legacy_snapshot_parents_to_local_repo() {
if [[ "${ELEVATOR_AUTO_INSTALL_LEGACY_SNAPSHOT_PARENTS:-1}" != "1" ]]; then
return 0
fi
local root
root="$(cd "$REPO/.." && pwd)"
local def_cwos="$root/maven-cwos-resource"
local def_davinci="$root/maven-cloudwalk-intelligent-davinci-manager/pom.xml"
local cwos_base="${ELEVATOR_LEGACY_CWOS_RESOURCE_DIR:-$def_cwos}"
install_one_snapshot_parent_to_local_repo \
"$M2_LOCAL/cn/cloudwalk/cloud/cwos-component-resource/1.0.0-SNAPSHOT/cwos-component-resource-1.0.0-SNAPSHOT.pom" \
"$cwos_base/cwos-component-resource/pom.xml" \
"cwos-component-resource 1.0.0-SNAPSHOT"
install_one_snapshot_parent_to_local_repo \
"$M2_LOCAL/cn/cloudwalk/cwos-portal/1.0.0-SNAPSHOT/cwos-portal-1.0.0-SNAPSHOT.pom" \
"$cwos_base/cwos-portal/pom.xml" \
"cwos-portal 1.0.0-SNAPSHOT"
install_one_snapshot_parent_to_local_repo \
"$M2_LOCAL/cn/cloudwalk/intelligent/cloudwalk-intelligent-davinci-manager/1.1.7-SNAPSHOT/cloudwalk-intelligent-davinci-manager-1.1.7-SNAPSHOT.pom" \
"${ELEVATOR_LEGACY_DAVINCI_MANAGER_POM:-$def_davinci}" \
"cloudwalk-intelligent-davinci-manager 1.1.7-SNAPSHOT"
install_one_snapshot_parent_to_local_repo \
"$M2_LOCAL/cn/cloudwalk/cloudwalk-device-sdk/2.2.0/cloudwalk-device-sdk-2.2.0.pom" \
"${ELEVATOR_LEGACY_DEVICE_SDK_POM:-$root/maven-cloudwalk-device-sdk/pom.xml}" \
"cloudwalk-device-sdk 2.2.0"
}
install_legacy_snapshot_parents_to_local_repo
bootstrap_intelligent_cwoscomponent_from_global() {
if [[ "${ELEVATOR_BOOTSTRAP_INTELLIGENT_CWOSCOMPONENT_FROM_GLOBAL:-1}" != "1" ]]; then
return 0
fi
local copied=0
# 2.9.2 线:父 artifactId 为 intelligent-cwoscomponent(非 reactor/parent 3.x 命名)
for art in intelligent-cwoscomponent intelligent-cwoscomponent-interface intelligent-cwoscomponent-rest; do
local rel="cn/cloudwalk/intelligent/${art}/${ICOMP_VER}"
if [[ -d "$GLOBAL_M2/$rel" ]]; then
mkdir -p "$M2_LOCAL/$rel"
cp -a "$GLOBAL_M2/$rel/." "$M2_LOCAL/$rel/"
echo "==> 已从 ~/.m2 预置 intelligent-cwoscomponent: $rel"
copied=1
fi
done
if [[ "$copied" -eq 0 ]]; then
echo "WARN: ~/.m2 中未找到 intelligent-cwoscomponent-*${ICOMP_VER}),将视情况从 cw_lib install-file。" >&2
fi
}
install_intelligent_cwoscomponent_from_cw_lib_if_missing() {
if [[ "${ELEVATOR_AUTO_INSTALL_INTELLIGENT_CWOSCOMPONENT:-1}" != "1" ]]; then
return 0
fi
if [[ "$ICOMP_VER" == "3.0.0-xinghewan" ]]; then
echo "ERROR: 本产品线禁止使用 intelligent-cwoscomponent 3.0.0-xinghewan;请使用 2.9.2-xinghewancw_lib)。" >&2
exit 1
fi
local marker="$M2_LOCAL/cn/cloudwalk/intelligent/intelligent-cwoscomponent-rest/${ICOMP_VER}/intelligent-cwoscomponent-rest-${ICOMP_VER}.jar"
if [[ -f "$marker" ]]; then
echo "==> 隔离库已有 intelligent-cwoscomponent-rest${ICOMP_VER}"
return 0
fi
local root cw_lib
root="$(cd "$REPO/.." && pwd)"
cw_lib="${ELEVATOR_CW_LIB_DIR:-$root/cw-elevator-application-V1.0.0.20211103/cw_lib}"
local stub="$REPO/scripts/legacy-poms/intelligent-cwoscomponent-2.9.2-xinghewan-parent.pom"
local ij="$cw_lib/intelligent-cwoscomponent-interface-${ICOMP_VER}.jar"
local ip="$cw_lib/intelligent-cwoscomponent-interface-${ICOMP_VER}.pom"
local rj="$cw_lib/intelligent-cwoscomponent-rest-${ICOMP_VER}.jar"
local rp="$cw_lib/intelligent-cwoscomponent-rest-${ICOMP_VER}.pom"
if [[ ! -f "$stub" ]]; then
echo "ERROR: 缺少父 POM 桩: $stub" >&2
exit 1
fi
if [[ ! -f "$ij" || ! -f "$ip" || ! -f "$rj" || ! -f "$rp" ]]; then
echo "ERROR: cw_lib 缺少 intelligent-cwoscomponent 2.9.2 构件,无法安装到隔离库。" >&2
echo " 期望目录: $cw_lib(设 ELEVATOR_CW_LIB_DIR 可覆盖)" >&2
echo " 需要: intelligent-cwoscomponent-interface/rest 的 .jar 与 .pom" >&2
exit 1
fi
echo "==> 向隔离库安装 intelligent-cwoscomponent 父 POM(桩): $stub"
mvn -Dmaven.repo.local="$M2_LOCAL" -f "$stub" -N install -DskipTests
echo "==> install-file intelligent-cwoscomponent-interface${ICOMP_VER}"
mvn -Dmaven.repo.local="$M2_LOCAL" org.apache.maven.plugins:maven-install-plugin:3.1.1:install-file \
-DpomFile="$ip" -Dfile="$ij" -Dpackaging=jar
echo "==> install-file intelligent-cwoscomponent-rest${ICOMP_VER}"
mvn -Dmaven.repo.local="$M2_LOCAL" org.apache.maven.plugins:maven-install-plugin:3.1.1:install-file \
-DpomFile="$rp" -Dfile="$rj" -Dpackaging=jar
if [[ ! -f "$marker" ]]; then
echo "ERROR: install 后仍缺少: $marker" >&2
exit 1
fi
}
bootstrap_intelligent_cwoscomponent_from_global
install_intelligent_cwoscomponent_from_cw_lib_if_missing
bootstrap_cwos_sdk_event_from_global() {
if [[ "${ELEVATOR_BOOTSTRAP_CWOS_SDK_EVENT_FROM_GLOBAL:-1}" != "1" ]]; then
return 0
fi
local rel="cn/cloudwalk/cloud/cwos-sdk-event/${CWOS_EVENT_VER}"
if [[ -d "$GLOBAL_M2/$rel" ]]; then
mkdir -p "$M2_LOCAL/$rel"
cp -a "$GLOBAL_M2/$rel/." "$M2_LOCAL/$rel/"
echo "==> 已从 ~/.m2 预置 cwos-sdk-event: $rel"
else
echo "WARN: ~/.m2 中无 cwos-sdk-event${CWOS_EVENT_VER}),将视情况 mvn install legacy 模块。" >&2
fi
}
install_cwos_sdk_event_if_missing() {
if [[ "${ELEVATOR_AUTO_INSTALL_CWOS_SDK_EVENT:-1}" != "1" ]]; then
return 0
fi
local marker="$M2_LOCAL/cn/cloudwalk/cloud/cwos-sdk-event/${CWOS_EVENT_VER}/cwos-sdk-event-${CWOS_EVENT_VER}.jar"
if [[ -f "$marker" ]]; then
echo "==> 隔离库已有 cwos-sdk-event${CWOS_EVENT_VER}"
return 0
fi
local root def_pom
root="$(cd "$REPO/.." && pwd)"
def_pom="$root/maven-cloudwalk-legacy-public/cwos-sdk-event/pom.xml"
local ev_pom="${ELEVATOR_LEGACY_CWOS_SDK_EVENT_POM:-$def_pom}"
if [[ ! -f "$ev_pom" ]]; then
echo "ERROR: 私服缺少 cwos-sdk-event:${CWOS_EVENT_VER},且未找到: $ev_pom" >&2
exit 1
fi
echo "==> 向隔离库 install cwos-sdk-event: $ev_pom"
mvn -Dmaven.repo.local="$M2_LOCAL" -f "$ev_pom" install -DskipTests
if [[ ! -f "$marker" ]]; then
echo "ERROR: install 后仍缺少: $marker" >&2
exit 1
fi
}
bootstrap_cwos_sdk_event_from_global
install_cwos_sdk_event_if_missing
bootstrap_cloudwalk_modules_from_global() {
if [[ "${ELEVATOR_BOOTSTRAP_CLOUDWALK_MODULES_FROM_GLOBAL:-1}" != "1" ]]; then
return 0
fi
local _arts="${ELEVATOR_CLOUDWALK_BOOTSTRAP_ARTIFACTS:-cloudwalk-common-result cloudwalk-common-web cloudwalk-common-serial cloudwalk-common-service}"
local copied=0
for a in $_arts; do
[[ -n "$a" ]] || continue
local rel="cn/cloudwalk/cloud/${a}/${LEGACY_VER}"
if [[ -d "$GLOBAL_M2/$rel" ]]; then
mkdir -p "$M2_LOCAL/$rel"
cp -a "$GLOBAL_M2/$rel/." "$M2_LOCAL/$rel/"
echo "==> 已从 ~/.m2 预置 cloudwalk 构件目录: $rel"
copied=1
fi
done
if [[ "$copied" -eq 0 ]]; then
echo "WARN: ~/.m2 中未找到上述 cloudwalk-common-* 目录(${LEGACY_VER}),将完全依赖 Nexus 传递依赖。" >&2
fi
}
bootstrap_cloudwalk_modules_from_global
echo "==> 清理 cn/cloudwalk 下失败缓存 (*.lastUpdated)"
purge_last_updated_under "$M2_LOCAL/cn/cloudwalk"
MVN_GOALS="${ELEVATOR_MVN_GOALS:-clean package}"
echo "==> 使用隔离本地仓库: $M2_LOCAL"
echo "==> mvn -Dmaven.repo.local=... $MVN_GOALS -DskipTests -U"
mvn -Dmaven.repo.local="$M2_LOCAL" -U $MVN_GOALS -DskipTests
JAR="$REPO/cw-elevator-application-starter/target/cw-elevator-application-2.0.0.jar"
echo "==> 产物: $JAR"
test -f "$JAR" && ls -la "$JAR"
if [[ -f "$JAR" && "${ELEVATOR_DEPLOY_V2_MAVEN:-1}" == "1" ]]; then
V2_DEPLOY_DIR="${ELEVATOR_DEPLOY_V2_DIR:-$REPO/deploy/v2-maven}"
mkdir -p "$V2_DEPLOY_DIR"
install -m0644 "$JAR" "$V2_DEPLOY_DIR/cw-elevator-application-2.0.0.jar"
echo "==> 已发布到 deploy/v2-maven(替换 JAR: $V2_DEPLOY_DIR/cw-elevator-application-2.0.0.jar"
ls -la "$V2_DEPLOY_DIR/cw-elevator-application-2.0.0.jar"
fi
if [[ "${ELEVATOR_SYNC_DEPLOY:-0}" == "1" ]]; then
SYNC="$REPO/deploy/sync-jars.sh"
if [[ -x "$SYNC" ]] || chmod +x "$SYNC" 2>/dev/null; then
echo "==> ELEVATOR_SYNC_DEPLOY=1 -> $SYNC"
bash "$SYNC"
else
echo "WARN: 未找到可执行的 deploy/sync-jars.sh,跳过同步。" >&2
fi
fi
@@ -0,0 +1,80 @@
#!/usr/bin/env bash
# 将 V1 运行包 cw_lib 中的电梯四模块 jar 用 CFR 反编译到本仓库 tools/v1-decompiled/ 下,
# 供与 maven-cw-elevator-application 源码逐类比对(不依赖历史 artifacts 手工目录)。
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
MV_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
REPO_ROOT="$(cd "$MV_ROOT/.." && pwd)"
# V1 解压目录(含 cw_lib
: "${V1_RUN_DIR:=${REPO_ROOT}/cw-elevator-application-V1.0.0.20211103}"
CW_LIB="${V1_RUN_DIR}/cw_lib"
# CFR:优先环境变量,其次仓库 artifacts
: "${CFR_JAR:=${REPO_ROOT}/artifacts/decompiled/v1-cfr-compare-20211103/cfr-0.152.jar}"
if [[ ! -f "$CFR_JAR" ]]; then
echo "ERROR: CFR not found: $CFR_JAR" >&2
echo "Set CFR_JAR to a local cfr-*.jar path." >&2
exit 1
fi
# 输出根目录(可用环境变量覆盖)
: "${V1_DECOMP_OUT:=${MV_ROOT}/tools/v1-decompiled/cfr-from-cw-lib}"
TIMESTAMP="$(date +%Y%m%d-%H%M%S)"
OUT="${V1_DECOMP_OUT}-${TIMESTAMP}"
FINAL_LINK="${MV_ROOT}/tools/v1-decompiled/cfr-from-cw-lib-current"
MODULES=(
"cw-elevator-application-common-1.0-SNAPSHOT.jar"
"cw-elevator-application-data-1.0-SNAPSHOT.jar"
"cw-elevator-application-service-1.0-SNAPSHOT.jar"
"cw-elevator-application-web-1.0-SNAPSHOT.jar"
)
echo "V1 cw_lib: $CW_LIB"
echo "CFR: $CFR_JAR"
echo "Output: $OUT"
mkdir -p "$OUT"
for j in "${MODULES[@]}"; do
jar_path="${CW_LIB}/${j}"
if [[ ! -f "$jar_path" ]]; then
echo "WARNING: missing $jar_path — skip"
continue
fi
mod="${j%.jar}"
dest="${OUT}/${mod}"
mkdir -p "$dest"
echo ">>> Decompiling $j -> $dest"
java -jar "$CFR_JAR" "$jar_path" \
--outputdir "$dest" \
--silent true
done
# 可选:V1 fat jar(体积大,默认关闭)
if [[ "${DECOMPILE_V1_FAT_JAR:-0}" == "1" ]]; then
FAT="${V1_RUN_DIR}/cw-elevator-application-V1.0.0.20211103.jar"
if [[ -f "$FAT" ]]; then
echo ">>> Decompiling fat jar (may take several minutes)..."
java -jar "$CFR_JAR" "$FAT" \
--outputdir "${OUT}/cw-elevator-application-V1.0.0.20211103-fat" \
--silent true
else
echo "WARNING: fat jar not found: $FAT"
fi
fi
# 写元数据
{
echo "generated_utc: $(date -u +%Y-%m-%dT%H:%M:%SZ)"
echo "v1_run_dir: $V1_RUN_DIR"
echo "cfr_jar: $CFR_JAR"
echo "modules:"
for j in "${MODULES[@]}"; do echo " - $j"; done
} > "${OUT}/MANIFEST.txt"
ln -sfn "$OUT" "$FINAL_LINK"
echo ""
echo "Done. Latest symlink: $FINAL_LINK -> $OUT"
echo "Manifest: ${OUT}/MANIFEST.txt"
@@ -0,0 +1,115 @@
#!/usr/bin/env bash
# 将 cw_lib 中的 intelligent-cwoscomponent(父 POM 桩 + interface + rest)部署到 Nexus
# 与 docs/operations/deploy_cw_elevator_v1_lib_to_nexus.py 使用同一 server id / 仓库 URL 约定。
#
# 需要 ~/.m2/settings.xml 中配置 server idnexus-releases(密码等)。
#
# 环境变量(可选):
# NEXUS_RELEASES_URL 默认 http://192.168.3.12:8081/repository/maven-releases/
# NEXUS_RELEASES_ID 默认 nexus-releases
# ELEVATOR_CW_LIB_DIR 默认 反编译根下 cw-elevator-application-V1.0.0.20211103/cw_lib
# ELEVATOR_ICOMP_VER 默认 2.9.2-xinghewan
# DRY_RUN=1 仅打印命令
# ELEVATOR_INSTALL_LOCAL_M2=1(默认)部署后再把 cw_lib 安装到 ~/.m2(与 build_nexus_only
# 一致;因私服上子 POM 缺版本段时 dependency:get 可能无效模型,本地以桩父 POM+install-file 为准)
# ELEVATOR_INSTALL_LOCAL_M2=0 跳过本机安装
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
REPO_ROOT="${ELEVATOR_REPO_ROOT_OVERRIDE:-$REPO_ROOT}"
NEXUS_RELEASES_URL="${NEXUS_RELEASES_URL:-http://192.168.3.12:8081/repository/maven-releases/}"
NEXUS_RELEASES_ID="${NEXUS_RELEASES_ID:-nexus-releases}"
ICOMP_VER="${ELEVATOR_ICOMP_VER:-2.9.2-xinghewan}"
CW_LIB="${ELEVATOR_CW_LIB_DIR:-$REPO_ROOT/cw-elevator-application-V1.0.0.20211103/cw_lib}"
PARENT_STUB="$SCRIPT_DIR/legacy-poms/intelligent-cwoscomponent-2.9.2-xinghewan-parent.pom"
die() { echo "ERROR: $*" >&2; exit 1; }
[[ -f "$PARENT_STUB" ]] || die "缺少父 POM 桩: $PARENT_STUB"
[[ -d "$CW_LIB" ]] || die "cw_lib 目录不存在: $CW_LIB"
IJ="$CW_LIB/intelligent-cwoscomponent-interface-${ICOMP_VER}.jar"
IP="$CW_LIB/intelligent-cwoscomponent-interface-${ICOMP_VER}.pom"
RJ="$CW_LIB/intelligent-cwoscomponent-rest-${ICOMP_VER}.jar"
RP="$CW_LIB/intelligent-cwoscomponent-rest-${ICOMP_VER}.pom"
for f in "$IJ" "$IP" "$RJ" "$RP"; do
[[ -f "$f" ]] || die "缺少文件: $f"
done
# 在无 reactor pom 的目录执行 deploy:deploy-file,避免误挂到 cw-elevator-application-reactor。
# Release 仓库已存在同版本时 Nexus 返回 400 cannot be updated — 视为已发布,跳过。
deploy_file_or_skip() {
local label="$1"
shift
if [[ "${DRY_RUN:-}" == "1" ]]; then
echo "DRY-RUN [$label]:" "$@"
return 0
fi
local out rc
set +e
out="$(cd "$CW_LIB" && mvn -B -q deploy:deploy-file "$@" 2>&1)"
rc=$?
set -e
if [[ "$rc" -eq 0 ]]; then
echo "OK [$label]"
return 0
fi
if echo "$out" | grep -qE 'cannot be updated|status code: 400'; then
echo "SKIP [$label]Nexus 已存在该 release 坐标,不可覆盖)"
return 0
fi
echo "$out" >&2
return "$rc"
}
echo "==> Nexus releases: $NEXUS_RELEASES_URL (id=$NEXUS_RELEASES_ID)"
echo "==> cw_lib: $CW_LIB"
echo "==> [1/3] deploy 父 POM cn.cloudwalk.intelligent:intelligent-cwoscomponent:${ICOMP_VER}"
deploy_file_or_skip "parent pom" \
-DrepositoryId="$NEXUS_RELEASES_ID" \
-Durl="$NEXUS_RELEASES_URL" \
-Dfile="$PARENT_STUB" \
-DpomFile="$PARENT_STUB" \
-DgroupId=cn.cloudwalk.intelligent \
-DartifactId=intelligent-cwoscomponent \
-Dversion="$ICOMP_VER" \
-Dpackaging=pom
echo "==> [2/3] deploy intelligent-cwoscomponent-interface"
deploy_file_or_skip "interface" \
-DrepositoryId="$NEXUS_RELEASES_ID" \
-Durl="$NEXUS_RELEASES_URL" \
-Dfile="$IJ" \
-DpomFile="$IP" \
-Dpackaging=jar
echo "==> [3/3] deploy intelligent-cwoscomponent-rest"
deploy_file_or_skip "rest" \
-DrepositoryId="$NEXUS_RELEASES_ID" \
-Durl="$NEXUS_RELEASES_URL" \
-Dfile="$RJ" \
-DpomFile="$RP" \
-Dpackaging=jar
if [[ "${DRY_RUN:-}" == "1" ]]; then
echo "DRY-RUN 结束。"
exit 0
fi
if [[ "${ELEVATOR_INSTALL_LOCAL_M2:-1}" == "1" ]]; then
echo "==> 本机 ~/.m2:父 POM 桩 + install-file(与 build_nexus_only 闭包一致)"
mvn -B -q -N -f "$PARENT_STUB" install -DskipTests
mvn -B -q org.apache.maven.plugins:maven-install-plugin:3.1.1:install-file \
-DpomFile="$IP" -Dfile="$IJ" -Dpackaging=jar
mvn -B -q org.apache.maven.plugins:maven-install-plugin:3.1.1:install-file \
-DpomFile="$RP" -Dfile="$RJ" -Dpackaging=jar
else
echo "==> 跳过本机 ~/.m2ELEVATOR_INSTALL_LOCAL_M2=0"
fi
echo "完成。"
echo " ~/.m2: ls \"\$HOME/.m2/repository/cn/cloudwalk/intelligent/intelligent-cwoscomponent-rest/$ICOMP_VER/\""
@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.18.RELEASE</version>
<relativePath/>
</parent>
<groupId>cn.cloudwalk.intelligent</groupId>
<artifactId>intelligent-cwoscomponent</artifactId>
<version>2.9.2-xinghewan</version>
<packaging>pom</packaging>
<name>intelligent-cwoscomponent (2.9.2 parent stub)</name>
<description>与 V1 cw_lib 内 intelligent-cwoscomponent-*.pom 中 parent 坐标一致;DM 与电梯 reactor 3.7.2 / Greenwich.SR6 对齐,供 install-file 安装到本机库或隔离库。</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR6</spring-cloud.version>
<cloudwalk.legacy.public.version>3.7.2-Brussels-SRX</cloudwalk.legacy.public.version>
<cloudwalk.internal.version>3.7.2-Brussels-SRX</cloudwalk.internal.version>
<fastjson.version>1.2.73</fastjson.version>
<cloudwalk.device.sdk.version>2.2.0</cloudwalk.device.sdk.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>cn.cloudwalk.cloud</groupId>
<artifactId>cloudwalk-common-result</artifactId>
<version>${cloudwalk.legacy.public.version}</version>
</dependency>
<dependency>
<groupId>cn.cloudwalk.cloud</groupId>
<artifactId>cloudwalk-common-service</artifactId>
<version>${cloudwalk.internal.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<dependency>
<groupId>cn.cloudwalk</groupId>
<artifactId>cloudwalk-device-sdk-protocol-entity</artifactId>
<version>${cloudwalk.device.sdk.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
@@ -0,0 +1,34 @@
#!/usr/bin/env bash
# 本脚本位于 maven-cw-elevator-application/scripts/:先打新包,再跑对拍用例与报告
set -e
REPO="$(cd "$(dirname "$0")/.." && pwd)"
TOOL="${REPO}/tools/elevator_api_parity"
JAR_NEW="${REPO}/cw-elevator-application-starter/target/cw-elevator-application-2.0.0.jar"
JAR_LEGACY_DEFAULT="$(cd "$REPO/.." && pwd)/cw-elevator-application-V1.0.0.20211103/cw-elevator-application-V1.0.0.20211103.jar"
JAR_LEGACY="${ELEVATOR_JAR_LEGACY:-$JAR_LEGACY_DEFAULT}"
if [[ -z "${JAVA_8:-}" ]]; then
for d in /usr/lib/jvm/java-8-openjdk-amd64 /usr/lib/jvm/java-1.8.0-openjdk; do
if [[ -x "$d/bin/java" ]]; then
export JAVA_8="$d"
break
fi
done
fi
: "${JAVA_8:=/usr/lib/jvm/java-8-openjdk-amd64}"
export JAVA_HOME="$JAVA_8"
export PATH="$JAVA_HOME/bin:$PATH"
cd "$REPO"
echo "==> mvn package (skip tests)"
mvn -q -DskipTests clean package
echo "==> 新 JAR: $JAR_NEW [$(test -f "$JAR_NEW" && echo OK || echo 缺失)]"
echo "==> 基线 JAR(路径): $JAR_LEGACY [$(test -f "$JAR_LEGACY" && echo 存在 || echo 不存在,可设ELEVATOR_JAR_LEGACY)]"
echo " (对拍为 HTTP; 需另开终端分别 java -jar --server.port=18080/18081 与相同配置)"
(cd "$TOOL" && pip install -q -r requirements.txt 2>/dev/null || pip3 install -q -r requirements.txt 2>/dev/null || true)
echo "==> 单元(无联调): test_unit_compare"
export PYTEST_DISABLE_PLUGIN_AUTOLOAD=1
(cd "$TOOL" && python3 -m pytest tests/test_unit_compare.py -q --tb=short)
echo "==> 对拍(无两实例时跳过 test_parity_endpoints);不含单机 smoke"
(cd "$TOOL" && python3 -m pytest tests/test_unit_compare.py tests/test_parity_endpoints.py -q --tb=line)
echo "报告: $TOOL/report/ (对拍有执行且成功时由 pytest 会话写出 parity-*.md)"
@@ -0,0 +1,84 @@
#!/usr/bin/env bash
# 完整接口测试:V1/V2 单机冒烟 + 双端对拍 + 套件总览 Markdown。
# 前置:两 JAR 已分别启动(默认 http://127.0.0.1:18080 为 V1、18081 为 V2),且配置同一数据源/Redis。
# 用法:在 maven-cw-elevator-application 目录执行 ./scripts/run_full_elevator_api_suite.sh
#
# ELEVATOR_SUITE_STRICT=1:冒烟与对拍失败时脚本退出非 0(默认由 run_v1v2_parity_automated.sh 传入)。
# ELEVATOR_SUITE_STRICT=0:与旧行为一致,冒烟/对拍用「|| true」始终生成总览(便于无服务时只看单元测试)。
set -euo pipefail
REPO="$(cd "$(dirname "$0")/.." && pwd)"
TOOL="${REPO}/tools/elevator_api_parity"
MARKER="${TOOL}/.suite_run_marker"
export PYTEST_DISABLE_PLUGIN_AUTOLOAD=1
export PIP_DISABLE_PIP_VERSION_CHECK=1
export ELEVATOR_BASE_OLD="${ELEVATOR_BASE_OLD:-http://127.0.0.1:18080}"
export ELEVATOR_BASE_NEW="${ELEVATOR_BASE_NEW:-http://127.0.0.1:18081}"
SUITE_STRICT="${ELEVATOR_SUITE_STRICT:-0}"
SUITE_FAIL=0
_py_maybe_ignore() {
if [[ "${SUITE_STRICT}" == "1" ]]; then
python3 -m pytest "$@" && return 0
return 1
fi
python3 -m pytest "$@" || true
return 0
}
cd "$TOOL"
python3 -m pip install -q -r requirements.txt 2>/dev/null || true
touch "$MARKER"
# -rs 在结束时打印 skip 原因;s=skip 通常表示目标端口无服务或 /actuator/health 无 200
PTF="-q -rs --tb=line"
echo "==> 单元(compare 逻辑)"
python3 -m pytest tests/test_unit_compare.py -q --tb=short
echo "==> 冒烟 V1 ($ELEVATOR_BASE_OLD) [需该地址可访问 /actuator/health 等健康端点]"
_py_maybe_ignore tests/test_smoke_catalog.py -m smoke \
--smoke-base="$ELEVATOR_BASE_OLD" --smoke-label=v1_legacy $PTF || SUITE_FAIL=1
echo "==> 冒烟 V2 ($ELEVATOR_BASE_NEW) [需该地址可访问 /actuator/health 等健康端点]"
_py_maybe_ignore tests/test_smoke_catalog.py -m smoke \
--smoke-base="$ELEVATOR_BASE_NEW" --smoke-label=v2_build $PTF || SUITE_FAIL=1
echo "==> 横向对拍(两实例均需通过健康探针) [ELEVATOR_SUITE_STRICT=${SUITE_STRICT} ELEVATOR_PARITY_BOUNDARY=${ELEVATOR_PARITY_BOUNDARY:-0}]"
_py_maybe_ignore tests/test_parity_endpoints.py -m live $PTF \
--base-old="$ELEVATOR_BASE_OLD" --base-new="$ELEVATOR_BASE_NEW" || SUITE_FAIL=1
SUITE_TS="$(date +%Y%m%d-%H%M%S)"
_pick_newer() {
local pattern="$1"
local f=""
for f in $(ls -t "${TOOL}/report"/${pattern} 2>/dev/null); do
if [[ -f "$f" && "$f" -nt "$MARKER" ]]; then echo "$f"; return; fi
done
}
SMOKE_V1="$(_pick_newer 'smoke-v1_legacy-*.md')"
SMOKE_V2="$(_pick_newer 'smoke-v2_build-*.md')"
PARITY="$(_pick_newer 'parity-*.md')"
OUT="${TOOL}/report/SUITE-${SUITE_TS}.md"
python3 report/generate_suite_summary.py --out "$OUT" \
--catalog "${TOOL}/api_catalog.json" \
${PARITY:+--parity "$PARITY"} \
${SMOKE_V1:+--smoke-v1 "$SMOKE_V1"} \
${SMOKE_V2:+--smoke-v2 "$SMOKE_V2"}
echo "==> 套件总览: $OUT"
if [[ -z "$SMOKE_V1" && -z "$SMOKE_V2" && -z "$PARITY" ]]; then
echo "==> 提示: 未生成 smoke/parity 子报告(多为本机未起 JAR 或健康检查未通过)。"
echo " 先起两进程: java -jar V1.jar --server.port=18080 --spring.config.location=... 与 V2 用 18081"
echo " 快速探活: curl -s -o /dev/null -w '%{http_code}' $ELEVATOR_BASE_OLD/actuator/health"
fi
rm -f "$MARKER"
if [[ "${SUITE_FAIL}" -ne 0 ]]; then
echo "==> 套件步骤存在失败 (ELEVATOR_SUITE_STRICT=${SUITE_STRICT}, exit=${SUITE_FAIL})" >&2
fi
exit "${SUITE_FAIL}"
@@ -0,0 +1,225 @@
#!/usr/bin/env bash
# 一键:构建 V2 → sync-jars → 后台启动 V1/V2(默认同 deploy 配置、异端口)→ 健康等待 → 跑完整 API 套件。
#
# 【能力边界|审阅说明】
# - 会做:按 api_catalog.json 对 V1/V2 **顺序**发 HTTP(冒烟 + 双端对拍),比对返回(compare_modecode_only / deep / status_only),
# 产出 report/smoke-*.md、parity-*.md、SUITE-*.mdstrict 模式下不一致则 pytest 失败、脚本非 0。
# - 不会做:**并发压测**(无固定 RPS、并发连接数、持续时间、p95 延迟统计);若需压测请另用 hey/wrk/k6 等指向同一 ELEVATOR_BASE_OLD/NEW。
#
# 用法(在 maven-cw-elevator-application 目录):
# ./scripts/run_v1v2_parity_automated.sh
#
# 环境变量(节选):
# ELEVATOR_SKIP_BUILD=1 跳过 mvn package(已有 target JAR
# ELEVATOR_SKIP_SYNC=1 跳过 deploy/sync-jars.shdeploy 下已有 JAR
# ELEVATOR_SKIP_START=1 不启动进程,仅跑套件(需已监听 ELEVATOR_BASE_OLD/NEW
# ELEVATOR_SUITE_STRICT=1 默认值;smoke/parity 失败则脚本非 0(传给 run_full_elevator_api_suite.sh
# ELEVATOR_SUITE_STRICT=0 smoke/parity 与旧版一致用 || true,便于只看报告
# ELEVATOR_PARITY_BOUNDARY=0 对拍仅基线体,不合并 boundary_patches(默认本脚本为 1
# ELEVATOR_PORT_V1=18080 ELEVATOR_PORT_V2=18081
# ELEVATOR_STARTUP_TIMEOUT=240 单端就绪最长等待秒数
# ELEVATOR_AUTO_KILL=1 默认退出时结束本脚本启动的 java 子进程
# ELEVATOR_JAVA_OPTS 传给两边的 JVM(如 -Xmx512m
# ELEVATOR_USE_ENV_JAVA=1 使用当前 JAVA_HOME(见 deploy/common-java.sh
# ELEVATOR_PARITY_OFFLINE=1 默认:禁用 Consul(笔记本无 8500 / 避免误连 JAR 内嵌机房地址)。
# ELEVATOR_PARITY_OFFLINE=0 使用 deploy/*/bootstrap.properties 中的 Consul(默认 host 192.168.3.12:8500,与该机 Docker consul 一致)。
#
set -euo pipefail
REPO="$(cd "$(dirname "$0")/.." && pwd)"
DEPLOY="${REPO}/deploy"
PARITY_OFFLINE_PROPS="${DEPLOY}/parity-offline-overrides.properties"
TOOL="${REPO}/tools/elevator_api_parity"
SCRIPTS="${REPO}/scripts"
# shellcheck source=../deploy/common-java.sh
source "${DEPLOY}/common-java.sh"
MERGE="${DEPLOY}/merge-redis-json.sh"
PORT_V1="${ELEVATOR_PORT_V1:-18080}"
PORT_V2="${ELEVATOR_PORT_V2:-18081}"
BASE_V1="${ELEVATOR_BASE_OLD:-http://127.0.0.1:${PORT_V1}}"
BASE_V2="${ELEVATOR_BASE_NEW:-http://127.0.0.1:${PORT_V2}}"
START_TIMEOUT="${ELEVATOR_STARTUP_TIMEOUT:-240}"
AUTO_KILL="${ELEVATOR_AUTO_KILL:-1}"
export ELEVATOR_BASE_OLD="$BASE_V1"
export ELEVATOR_BASE_NEW="$BASE_V2"
export ELEVATOR_SUITE_STRICT="${ELEVATOR_SUITE_STRICT:-1}"
# 对拍时展开 api_catalog 中 boundary_patches(入参边界);设为 0 仅跑基线 default 体以缩短耗时
export ELEVATOR_PARITY_BOUNDARY="${ELEVATOR_PARITY_BOUNDARY:-1}"
PID_DIR=""
STARTED_V1=""
STARTED_V2=""
cleanup() {
if [[ "${AUTO_KILL}" != "1" ]] || [[ -z "${PID_DIR}" ]] || [[ ! -d "${PID_DIR}" ]]; then
return 0
fi
for key in v1 v2; do
f="${PID_DIR}/${key}.pid"
if [[ -f "$f" ]]; then
pid="$(cat "$f" 2>/dev/null || true)"
if [[ -n "${pid}" ]] && kill -0 "$pid" 2>/dev/null; then
echo "==> 停止 ${key} (pid ${pid})"
kill "$pid" 2>/dev/null || true
wait "$pid" 2>/dev/null || true
fi
fi
done
rm -rf "${PID_DIR}"
}
trap cleanup EXIT INT TERM
_port_in_use() {
local port="$1"
if command -v nc >/dev/null 2>&1; then
nc -z 127.0.0.1 "$port" 2>/dev/null
return $?
fi
timeout 0.3 bash -c "echo >/dev/tcp/127.0.0.1/${port}" 2>/dev/null
}
_wait_healthy() {
local base="$1"
local label="$2"
local pid_file="$3"
local log_file="$4"
local end=$(( $(date +%s) + START_TIMEOUT ))
echo "==> 等待就绪 ${label} (${base}),最长 ${START_TIMEOUT}s"
while (( $(date +%s) < end )); do
if [[ -f "${pid_file}" ]]; then
local pid=""
pid="$(cat "${pid_file}" 2>/dev/null || true)"
if [[ -n "${pid}" ]] && ! kill -0 "${pid}" 2>/dev/null; then
echo "ERROR: ${label} 进程已退出(pid=${pid}),无需继续等待健康检查。" >&2
echo " 请检查日志: ${log_file}" >&2
return 1
fi
fi
for path in /actuator/health /health; do
code="$(curl -s -o /tmp/elev_h$$ -w '%{http_code}' "${base}${path}" 2>/dev/null || echo 0)"
if [[ "${code}" == "200" ]] && grep -qiE 'up|"status"[[:space:]]*:[[:space:]]*"OK"' /tmp/elev_h$$ 2>/dev/null; then
rm -f /tmp/elev_h$$
echo " OK ${label} ${path}"
return 0
fi
done
sleep 2
done
rm -f /tmp/elev_h$$
echo "ERROR: ${label}${START_TIMEOUT}s 内未通过健康检查: ${base}" >&2
return 1
}
_pick_java_home
if [[ ! -x "${JAVA_HOME}/bin/java" ]]; then
echo "ERROR: 未找到 JDK。请安装 openjdk-8-jdk 或设置 JAVA_HOME / ELEVATOR_USE_ENV_JAVA=1" >&2
exit 1
fi
JAVA="${JAVA_HOME}/bin/java"
OPEN_FLAGS=()
while IFS= read -r line; do
[[ -n "${line}" ]] && OPEN_FLAGS+=("${line}")
done < <(_jdk8_open_flags "$JAVA")
if [[ ! -x "${MERGE}" ]]; then
chmod +x "${MERGE}" 2>/dev/null || true
fi
if [[ "${ELEVATOR_SKIP_BUILD:-0}" != "1" ]]; then
OLD_TARGET_JAR="${REPO}/cw-elevator-application-starter/target/cw-elevator-application-2.0.0.jar"
OLD_DEPLOY_JAR="${DEPLOY}/v2-maven/cw-elevator-application-2.0.0.jar"
echo "==> 删除旧 V2 JAR(确保全量重编译产物)"
rm -f "${OLD_TARGET_JAR}" "${OLD_DEPLOY_JAR}"
echo "==> mvn package (skip tests)"
(cd "${REPO}" && mvn -q -DskipTests clean package)
else
echo "==> 跳过构建 (ELEVATOR_SKIP_BUILD=1)"
fi
if [[ "${ELEVATOR_SKIP_SYNC:-0}" != "1" ]]; then
echo "==> sync-jarsV1 来自仓库根 cw-elevator-application-V1.0.0.20211103/"
# 默认用当前 Maven data 模块覆盖 V1 fat-jar 内嵌 data JAR,避免历史包与源码分片实现分叉导致 record_page 等对拍假差异;纯正历史 V1 请 ELEVATOR_SKIP_SYNC=1 或 PARITY_PATCH_V1_DATA=0
export PARITY_PATCH_V1_DATA="${PARITY_PATCH_V1_DATA:-1}"
bash "${DEPLOY}/sync-jars.sh"
else
echo "==> 跳过 sync-jars (ELEVATOR_SKIP_SYNC=1)"
fi
V1_DIR="${DEPLOY}/v1-legacy"
V2_DIR="${DEPLOY}/v2-maven"
JAR_V1="${V1_DIR}/cw-elevator-application-V1.0.0.20211103.jar"
JAR_V2="${V2_DIR}/cw-elevator-application-2.0.0.jar"
if [[ ! -f "${JAR_V1}" ]] || [[ ! -f "${JAR_V2}" ]]; then
echo "ERROR: 缺少 JAR。请执行 ${DEPLOY}/sync-jars.sh 或先 mvn package。" >&2
echo " 期望: ${JAR_V1}" >&2
echo " ${JAR_V2}" >&2
exit 1
fi
LOG_DIR="${REPO}/.elevator-parity-logs"
mkdir -p "${LOG_DIR}"
if [[ "${ELEVATOR_SKIP_START:-0}" != "1" ]]; then
if _port_in_use "${PORT_V1}" && [[ "${ELEVATOR_ALLOW_BUSY_PORTS:-0}" != "1" ]]; then
echo "ERROR: 端口 ${PORT_V1} 已被占用。可先停占用进程,或设 ELEVATOR_SKIP_START=1 使用已启动实例。" >&2
exit 1
fi
if _port_in_use "${PORT_V2}" && [[ "${ELEVATOR_ALLOW_BUSY_PORTS:-0}" != "1" ]]; then
echo "ERROR: 端口 ${PORT_V2} 已被占用。" >&2
exit 1
fi
PID_DIR="$(mktemp -d "${REPO}/.elevator-parity-pids.XXXXXX")"
# Consul:若脚本未加载 bootstrap、且无本地 ConsulJAR 内嵌地址会导致 agentServiceRegister 失败→整进程退出(日志见 TransportException 8500)。
OFF_JVM=()
LOC_CHAIN_V1="file:${V1_DIR}/bootstrap.properties,file:${V1_DIR}/application.properties,file:${V1_DIR}/application-access-control.properties,file:${V1_DIR}/redis-override.properties"
LOC_CHAIN_V2="file:${V2_DIR}/bootstrap.properties,file:${V2_DIR}/application.properties,file:${V2_DIR}/application-access-control.properties,file:${V2_DIR}/redis-override.properties"
if [[ "${ELEVATOR_PARITY_OFFLINE:-1}" == "1" ]] && [[ -f "${PARITY_OFFLINE_PROPS}" ]]; then
LOC_CHAIN_V1+=",file:${PARITY_OFFLINE_PROPS}"
LOC_CHAIN_V2+=",file:${PARITY_OFFLINE_PROPS}"
# 覆盖 Spring Cloud 先于 spring.config 解析的 classpath bootstrap,避免仍指向机房 Consul
OFF_JVM=("-Dspring.cloud.consul.enabled=false")
echo "==> Consul: 离线模式(ELEVATOR_PARITY_OFFLINE=1,禁用注册)。若在本机 192.168.3.12 已有 Docker Consul,可改用 ELEVATOR_PARITY_OFFLINE=0"
else
echo "==> Consul: 联机模式(ELEVATOR_PARITY_OFFLINE=0,按 bootstrap 连接 Consuldeploy 默认 192.168.3.12:8500"
fi
echo "==> 启动 V1 :${PORT_V1}"
export SPRING_APPLICATION_JSON="$("${MERGE}" "${V1_DIR}/redis-override.properties")"
# shellcheck disable=SC2086
nohup "${JAVA}" "${OPEN_FLAGS[@]}" "${OFF_JVM[@]}" ${ELEVATOR_JAVA_OPTS:-} -jar "${JAR_V1}" \
--spring.config.location="${LOC_CHAIN_V1}" \
--server.port="${PORT_V1}" >>"${LOG_DIR}/v1-legacy.log" 2>&1 &
echo $! > "${PID_DIR}/v1.pid"
STARTED_V1=1
echo "==> 启动 V2 :${PORT_V2}"
export SPRING_APPLICATION_JSON="$("${MERGE}" "${V2_DIR}/redis-override.properties")"
# shellcheck disable=SC2086
nohup "${JAVA}" "${OPEN_FLAGS[@]}" "${OFF_JVM[@]}" ${ELEVATOR_JAVA_OPTS:-} -jar "${JAR_V2}" \
--spring.config.location="${LOC_CHAIN_V2}" \
--server.port="${PORT_V2}" >>"${LOG_DIR}/v2-maven.log" 2>&1 &
echo $! > "${PID_DIR}/v2.pid"
STARTED_V2=1
unset SPRING_APPLICATION_JSON
echo " V1 pid=$(cat "${PID_DIR}/v1.pid") log=${LOG_DIR}/v1-legacy.log"
echo " V2 pid=$(cat "${PID_DIR}/v2.pid") log=${LOG_DIR}/v2-maven.log"
_wait_healthy "${BASE_V1}" "V1" "${PID_DIR}/v1.pid" "${LOG_DIR}/v1-legacy.log" || exit 1
_wait_healthy "${BASE_V2}" "V2" "${PID_DIR}/v2.pid" "${LOG_DIR}/v2-maven.log" || exit 1
else
echo "==> 跳过启动 (ELEVATOR_SKIP_START=1),假定 ${BASE_V1} / ${BASE_V2} 已可用"
fi
echo "==> 完整 API 套件(ELEVATOR_SUITE_STRICT=${ELEVATOR_SUITE_STRICT}"
bash "${SCRIPTS}/run_full_elevator_api_suite.sh"
SUITE_EXIT=$?
exit "${SUITE_EXIT}"
@@ -0,0 +1,57 @@
#!/usr/bin/env bash
# 校验私服上 intelligent-cwoscomponent 2.9.2 线是否「可解析」:父 POM、interface、rest 均存在,
# 且 rest 的 POM 必须声明对 intelligent-cwoscomponent-interface 的依赖(否则仅依赖 rest 时编译缺 client 包)。
#
# 环境变量:
# NEXUS_PUBLIC_BASE 默认 http://192.168.3.12:8081/repository/maven-public/
# ELEVATOR_ICOMP_VER 默认 2.9.2-xinghewan
# CURL_OPTS 追加传给 curl(如内网 Basic-u user:pass
#
# 退出码:0 校验通过;1 缺文件或 rest POM 不完整
set -euo pipefail
NEXUS_PUBLIC_BASE="${NEXUS_PUBLIC_BASE:-http://192.168.3.12:8081/repository/maven-public/}"
ICOMP_VER="${ELEVATOR_ICOMP_VER:-2.9.2-xinghewan}"
BASE="${NEXUS_PUBLIC_BASE%/}/"
die() { echo "ERROR: $*" >&2; exit 1; }
need_curl() { command -v curl >/dev/null 2>&1 || die "需要 curl"; }
fetch() {
local url="$1"
local out
if ! out="$(curl -sfL ${CURL_OPTS:-} "$url" 2>&1)"; then
echo "ERROR: 无法拉取: $url" >&2
echo "$out" >&2
exit 1
fi
printf '%s' "$out"
}
need_curl
G="cn/cloudwalk/intelligent"
PARENT_URL="${BASE}${G}/intelligent-cwoscomponent/${ICOMP_VER}/intelligent-cwoscomponent-${ICOMP_VER}.pom"
IFACE_POM_URL="${BASE}${G}/intelligent-cwoscomponent-interface/${ICOMP_VER}/intelligent-cwoscomponent-interface-${ICOMP_VER}.pom"
IFACE_JAR_URL="${BASE}${G}/intelligent-cwoscomponent-interface/${ICOMP_VER}/intelligent-cwoscomponent-interface-${ICOMP_VER}.jar"
REST_POM_URL="${BASE}${G}/intelligent-cwoscomponent-rest/${ICOMP_VER}/intelligent-cwoscomponent-rest-${ICOMP_VER}.pom"
REST_JAR_URL="${BASE}${G}/intelligent-cwoscomponent-rest/${ICOMP_VER}/intelligent-cwoscomponent-rest-${ICOMP_VER}.jar"
echo "==> NEXUS_PUBLIC_BASE=$NEXUS_PUBLIC_BASE"
echo "==> 检查父 POM: $PARENT_URL"
fetch "$PARENT_URL" >/dev/null
echo "==> 检查 interface POM + JAR"
fetch "$IFACE_POM_URL" >/dev/null
curl -sfL ${CURL_OPTS:-} -o /dev/null -I "$IFACE_JAR_URL" || die "interface JAR 不可访问: $IFACE_JAR_URL"
echo "==> 检查 rest POM + JAR"
rest_pom="$(fetch "$REST_POM_URL")"
curl -sfL ${CURL_OPTS:-} -o /dev/null -I "$REST_JAR_URL" || die "rest JAR 不可访问: $REST_JAR_URL"
if ! printf '%s' "$rest_pom" | grep -qE '<artifactId>intelligent-cwoscomponent-interface</artifactId>'; then
die "rest 的 POM 未声明 intelligent-cwoscomponent-interface(常见原因:deploy-file 未带 -DpomFileNexus 生成了空模型 POM)。请在 Nexus 删除该版本 rest 构件后,用 deploy_intelligent_cwoscomponent_to_nexus.sh 按 cw_lib 内 .pom 重新上传。"
fi
echo "OK: 私服 intelligent-cwoscomponent${ICOMP_VER})父 POM + interface + rest 齐全,且 rest POM 声明 interface。"