feat: optimize backend build with conditional martial-tool install
This commit is contained in:
@@ -44,3 +44,10 @@ nul
|
|||||||
minio_data/
|
minio_data/
|
||||||
minio_data/
|
minio_data/
|
||||||
.m2-repo/
|
.m2-repo/
|
||||||
|
|
||||||
|
# Keep deploy scripts tracked
|
||||||
|
!scripts/ensure-martial-tool-installed.sh
|
||||||
|
!scripts/deploy-backend.sh
|
||||||
|
|
||||||
|
# Local build cache
|
||||||
|
.build-cache/
|
||||||
|
|||||||
@@ -62,10 +62,20 @@ docker compose ps
|
|||||||
### 快速构建(开发迭代)
|
### 快速构建(开发迭代)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 本地编译后构建镜像
|
# 只做后端打包(不会重建容器)
|
||||||
mvn clean package -DskipTests && docker-compose up --build
|
./scripts/deploy-backend.sh --skip-docker
|
||||||
|
|
||||||
|
# 打包 + 重建并重启 martial-api 容器
|
||||||
|
./scripts/deploy-backend.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
|
说明:
|
||||||
|
- `./scripts/ensure-martial-tool-installed.sh` 会自动检测 `martial-tool` 是否已安装到本地 Maven 仓库。
|
||||||
|
- 只有在以下情况才会重新执行 `martial-tool` 的 `mvn install`:
|
||||||
|
- 本地 Maven 仓库缺少 BladeX 依赖产物。
|
||||||
|
- `martial-tool` 代码发生变化(基于 git 状态检测)。
|
||||||
|
- 日常迭代只改后端业务代码时,会跳过 `martial-tool` 编译,减少构建时间。
|
||||||
|
|
||||||
> 详细的 Docker 部署说明请参考 [Docker 部署指南](docs/guides/docker-deployment.md)
|
> 详细的 Docker 部署说明请参考 [Docker 部署指南](docs/guides/docker-deployment.md)
|
||||||
|
|
||||||
## 项目结构
|
## 项目结构
|
||||||
|
|||||||
Executable
+80
@@ -0,0 +1,80 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<'USAGE'
|
||||||
|
Usage: ./scripts/deploy-backend.sh [--skip-docker]
|
||||||
|
|
||||||
|
Options:
|
||||||
|
--skip-docker Build jar only, skip docker compose build/up
|
||||||
|
USAGE
|
||||||
|
}
|
||||||
|
|
||||||
|
log() {
|
||||||
|
printf '[deploy] %s\n' "$*"
|
||||||
|
}
|
||||||
|
|
||||||
|
SKIP_DOCKER=0
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--skip-docker)
|
||||||
|
SKIP_DOCKER=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-h|--help)
|
||||||
|
usage
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unknown option: $1" >&2
|
||||||
|
usage
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
"$SCRIPT_DIR/ensure-martial-tool-installed.sh"
|
||||||
|
|
||||||
|
log "Packaging backend jar ..."
|
||||||
|
(
|
||||||
|
cd "$PROJECT_DIR"
|
||||||
|
mvn clean package -DskipTests
|
||||||
|
)
|
||||||
|
|
||||||
|
if [[ "$SKIP_DOCKER" -eq 1 ]]; then
|
||||||
|
log "--skip-docker enabled, jar build finished."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "Building and restarting martial-api ..."
|
||||||
|
(
|
||||||
|
cd "$PROJECT_DIR"
|
||||||
|
docker compose build martial-api
|
||||||
|
docker compose up -d --no-deps martial-api
|
||||||
|
)
|
||||||
|
|
||||||
|
log "Waiting for martial-api health ..."
|
||||||
|
for _ in $(seq 1 60); do
|
||||||
|
json="$(cd "$PROJECT_DIR" && docker compose ps --format json martial-api 2>/dev/null || true)"
|
||||||
|
health="$(printf '%s\n' "$json" | sed -n 's/.*"Health":"\([^"]*\)".*/\1/p' | head -n 1)"
|
||||||
|
status="$(printf '%s\n' "$json" | sed -n 's/.*"Status":"\([^"]*\)".*/\1/p' | head -n 1)"
|
||||||
|
|
||||||
|
if [[ "$health" == "healthy" ]]; then
|
||||||
|
log "martial-api is healthy."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if printf '%s' "$status" | grep -Eiq 'unhealthy|exited|dead'; then
|
||||||
|
echo "[deploy] ERROR: martial-api status=$status" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
sleep 3
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "[deploy] ERROR: timed out waiting for martial-api health" >&2
|
||||||
|
(cd "$PROJECT_DIR" && docker compose ps martial-api)
|
||||||
|
exit 1
|
||||||
Executable
+93
@@ -0,0 +1,93 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||||
|
TOOL_DIR="${TOOL_DIR:-$PROJECT_DIR/../martial-tool}"
|
||||||
|
CACHE_DIR="$PROJECT_DIR/.build-cache"
|
||||||
|
STATE_FILE="$CACHE_DIR/martial-tool.state"
|
||||||
|
|
||||||
|
log() {
|
||||||
|
printf '[martial-tool] %s\n' "$*"
|
||||||
|
}
|
||||||
|
|
||||||
|
fail() {
|
||||||
|
printf '[martial-tool] ERROR: %s\n' "$*" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
[[ -d "$TOOL_DIR" ]] || fail "martial-tool directory not found: $TOOL_DIR"
|
||||||
|
[[ -f "$TOOL_DIR/pom.xml" ]] || fail "pom.xml not found in $TOOL_DIR"
|
||||||
|
command -v mvn >/dev/null 2>&1 || fail "mvn command not found"
|
||||||
|
|
||||||
|
revision="$(sed -n 's:.*<revision>\([^<]*\)</revision>.*:\1:p' "$TOOL_DIR/pom.xml" | head -n 1)"
|
||||||
|
[[ -n "$revision" ]] || fail "Unable to parse <revision> from $TOOL_DIR/pom.xml"
|
||||||
|
|
||||||
|
mapfile -t modules < <(sed -n 's:.*<module>\([^<]*\)</module>.*:\1:p' "$TOOL_DIR/pom.xml")
|
||||||
|
(( ${#modules[@]} > 0 )) || fail "No modules found in $TOOL_DIR/pom.xml"
|
||||||
|
|
||||||
|
missing=()
|
||||||
|
for artifact in "${modules[@]}"; do
|
||||||
|
if [[ "$artifact" == "blade-bom" ]]; then
|
||||||
|
group_path="org/springblade/platform"
|
||||||
|
else
|
||||||
|
group_path="org/springblade"
|
||||||
|
fi
|
||||||
|
|
||||||
|
version_dir="$HOME/.m2/repository/$group_path/$artifact/$revision"
|
||||||
|
if [[ ! -d "$version_dir" ]]; then
|
||||||
|
missing+=("$artifact")
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! find "$version_dir" -maxdepth 1 -type f \( -name "$artifact-$revision.jar" -o -name "$artifact-$revision.pom" \) | grep -q .; then
|
||||||
|
missing+=("$artifact")
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if git -C "$TOOL_DIR" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
||||||
|
git_head="$(git -C "$TOOL_DIR" rev-parse HEAD)"
|
||||||
|
git_status="$(git -C "$TOOL_DIR" status --porcelain)"
|
||||||
|
|
||||||
|
if [[ -n "$git_status" ]]; then
|
||||||
|
if command -v sha256sum >/dev/null 2>&1; then
|
||||||
|
dirty_hash="$(printf '%s' "$git_status" | sha256sum | awk '{print $1}')"
|
||||||
|
else
|
||||||
|
dirty_hash="$(printf '%s' "$git_status" | shasum -a 256 | awk '{print $1}')"
|
||||||
|
fi
|
||||||
|
tool_state="${git_head}-dirty-${dirty_hash}"
|
||||||
|
else
|
||||||
|
tool_state="$git_head"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
pom_hash="$(find "$TOOL_DIR" -name pom.xml -type f -print0 | sort -z | xargs -0 cat | sha256sum | awk '{print $1}')"
|
||||||
|
tool_state="nogit-${pom_hash}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "$CACHE_DIR"
|
||||||
|
previous_state=""
|
||||||
|
if [[ -f "$STATE_FILE" ]]; then
|
||||||
|
previous_state="$(cat "$STATE_FILE")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ${#missing[@]} -eq 0 && "$tool_state" == "$previous_state" ]]; then
|
||||||
|
log "Artifacts already installed for revision $revision and source state unchanged, skip install."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ${#missing[@]} -gt 0 ]]; then
|
||||||
|
log "Missing artifacts detected (${#missing[@]}): ${missing[*]}"
|
||||||
|
else
|
||||||
|
log "martial-tool source changed, reinstall required."
|
||||||
|
log "cached state: ${previous_state:-<none>}"
|
||||||
|
log "current state: $tool_state"
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "Installing martial-tool from $TOOL_DIR ..."
|
||||||
|
(
|
||||||
|
cd "$TOOL_DIR"
|
||||||
|
mvn -T 1C -DskipTests install
|
||||||
|
)
|
||||||
|
|
||||||
|
printf '%s\n' "$tool_state" > "$STATE_FILE"
|
||||||
|
log "Install complete. State cache updated: $STATE_FILE"
|
||||||
Reference in New Issue
Block a user