aslan-server/.deploy/test-deploy/deploy-likei-services.sh

257 lines
6.7 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
BASE_DIR="${BASE_DIR:-/opt/aslan-test}"
SRC_DIR="${SRC_DIR:-$BASE_DIR/source/aslan-server}"
COMPOSE_FILE="${COMPOSE_FILE:-$BASE_DIR/docker-compose.yml}"
ENV_FILE="${ENV_FILE:-$BASE_DIR/config/.env}"
LOCK_FILE="${LOCK_FILE:-$BASE_DIR/deploy.lock}"
GIT_REMOTE_URL="${GIT_REMOTE_URL:-git@gitea.haiyihy.com:hy/aslan-server.git}"
GIT_REF="${GIT_REF:-aslan_test}"
ALLOWED_GIT_REFS="${ALLOWED_GIT_REFS:-aslan_test}"
MAVEN_GOALS="${MAVEN_GOALS:-clean package}"
MAVEN_PROFILE="${MAVEN_PROFILE:-prod}"
MAVEN_EXTRA_ARGS="${MAVEN_EXTRA_ARGS:-}"
SKIP_BUILD="${SKIP_BUILD:-0}"
MODE="${MODE:-compose}"
BUILD_TS="${BUILD_TS:-$(date +%Y%m%d%H%M%S)}"
ALL_SERVICES=(auth gateway external wallet order live other console)
usage() {
cat <<'EOF'
Usage:
deploy-likei-services.sh [--mode compose|build-only|status] [--skip-build] [--fast] [auth|gateway|external|wallet|order|live|other|console ...]
Examples:
/opt/aslan-test/deploy-likei-services.sh status
/opt/aslan-test/deploy-likei-services.sh other
/opt/aslan-test/deploy-likei-services.sh --fast other external console
GIT_REF=aslan_test /opt/aslan-test/deploy-likei-services.sh auth gateway external wallet order live other console
Notes:
- This is the single-machine test deployment flow.
- It pulls aslan_test, builds local aslan-test/* images, then replaces docker compose app containers.
- MySQL/Mongo/Redis/Nacos/RocketMQ are not rebuilt or restarted by this script.
EOF
}
log() {
printf '[%s] %s\n' "$(date '+%F %T')" "$*"
}
need_cmd() {
command -v "$1" >/dev/null 2>&1 || {
echo "missing command: $1" >&2
exit 2
}
}
acquire_deploy_lock() {
need_cmd flock
mkdir -p "$(dirname "$LOCK_FILE")"
exec 9>"$LOCK_FILE"
# The visual ops panel and manual SSH deploys share this lock so builds cannot interleave.
flock -n 9 || {
echo "another deploy is already running: $LOCK_FILE" >&2
exit 5
}
}
validate_git_ref() {
if [[ ! "$GIT_REF" =~ ^[A-Za-z0-9._/-]{1,80}$ || "$GIT_REF" == -* || "$GIT_REF" == *..* ]]; then
echo "invalid GIT_REF: $GIT_REF" >&2
exit 2
fi
local allowed
for allowed in $ALLOWED_GIT_REFS; do
[[ "$GIT_REF" == "$allowed" ]] && return 0
done
echo "GIT_REF is not allowed for test deploy: $GIT_REF (allowed: $ALLOWED_GIT_REFS)" >&2
exit 2
}
service_module() {
case "$1" in
auth) echo "rc-auth" ;;
gateway) echo "rc-gateway" ;;
external) echo "rc-service/rc-service-external/external-start" ;;
wallet) echo "rc-service/rc-service-wallet/wallet-start" ;;
order) echo "rc-service/rc-service-order/order-start" ;;
live) echo "rc-service/rc-service-live/live-start" ;;
other) echo "rc-service/rc-service-other/other-start" ;;
console) echo "rc-service/rc-service-console/console-start" ;;
*) echo "unsupported service: $1" >&2; exit 2 ;;
esac
}
service_dir() {
case "$1" in
auth) echo "rc-auth" ;;
gateway) echo "rc-gateway" ;;
external) echo "rc-service/rc-service-external" ;;
wallet) echo "rc-service/rc-service-wallet" ;;
order) echo "rc-service/rc-service-order" ;;
live) echo "rc-service/rc-service-live" ;;
other) echo "rc-service/rc-service-other" ;;
console) echo "rc-service/rc-service-console" ;;
*) echo "unsupported service: $1" >&2; exit 2 ;;
esac
}
service_image() {
case "$1" in
auth|gateway|external|wallet|order|live|other|console) echo "aslan-test/$1:latest" ;;
*) echo "unsupported service: $1" >&2; exit 2 ;;
esac
}
contains_service() {
local needle="$1"
local item
for item in "${ALL_SERVICES[@]}"; do
[[ "$item" == "$needle" ]] && return 0
done
return 1
}
update_source_from_git() {
need_cmd git
validate_git_ref
[[ -d "$SRC_DIR/.git" ]] || { echo "missing git source: $SRC_DIR" >&2; exit 2; }
log "reset source to origin/$GIT_REF from $GIT_REMOTE_URL"
git -C "$SRC_DIR" remote set-url origin "$GIT_REMOTE_URL"
git -C "$SRC_DIR" fetch origin "$GIT_REF"
git -C "$SRC_DIR" checkout -B "$GIT_REF" "origin/$GIT_REF"
git -C "$SRC_DIR" reset --hard "origin/$GIT_REF"
}
package_services() {
local services=("$@")
local modules=()
local svc
for svc in "${services[@]}"; do
modules+=("$(service_module "$svc")")
done
local module_csv
module_csv="$(IFS=,; echo "${modules[*]}")"
if [[ "$SKIP_BUILD" == "1" ]]; then
log "skip maven build"
return
fi
cd "$SRC_DIR"
log "maven $MAVEN_GOALS -pl $module_csv -P $MAVEN_PROFILE"
# The test compose stack still reads the prod-profile Nacos configs; use -P prod unless the caller overrides it.
# shellcheck disable=SC2086
mvn $MAVEN_GOALS -pl "$module_csv" -am -P "$MAVEN_PROFILE" -Dmaven.test.skip=true $MAVEN_EXTRA_ARGS
}
build_image() {
local svc="$1"
local dir image
dir="$(service_dir "$svc")"
image="$(service_image "$svc")"
cd "$SRC_DIR"
log "docker build $image"
docker build \
--build-arg "SERVICE_VERSION=aslan-test:${svc}-${BUILD_TS}" \
-f "$dir/Dockerfile" \
-t "$image" \
"$dir"
}
compose_up() {
local services=("$@")
cd "$BASE_DIR"
log "docker compose recreate: ${services[*]}"
docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" up -d --no-deps --force-recreate "${services[@]}"
}
status() {
log "source"
git -C "$SRC_DIR" status -sb || true
git -C "$SRC_DIR" log -1 --oneline --decorate || true
log "compose"
docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" ps --format table
}
main() {
local services=()
while [[ "$#" -gt 0 ]]; do
case "$1" in
--mode)
[[ -n "${2:-}" ]] || { echo "--mode requires an argument" >&2; exit 2; }
MODE="$2"
shift 2
;;
--skip-build)
SKIP_BUILD=1
shift
;;
--fast)
MAVEN_GOALS=package
shift
;;
-h|--help)
usage
exit 0
;;
status)
MODE=status
shift
;;
*)
services+=("$1")
shift
;;
esac
done
need_cmd git
need_cmd docker
[[ -f "$COMPOSE_FILE" ]] || { echo "missing compose file: $COMPOSE_FILE" >&2; exit 2; }
[[ -f "$ENV_FILE" ]] || { echo "missing env file: $ENV_FILE" >&2; exit 2; }
if [[ "$MODE" == "status" ]]; then
status
exit 0
fi
need_cmd java
need_cmd mvn
acquire_deploy_lock
update_source_from_git
if [[ "${#services[@]}" -eq 0 ]]; then
services=("${ALL_SERVICES[@]}")
fi
local svc
for svc in "${services[@]}"; do
contains_service "$svc" || { echo "unsupported service: $svc" >&2; exit 2; }
done
package_services "${services[@]}"
for svc in "${services[@]}"; do
build_image "$svc"
done
case "$MODE" in
compose)
compose_up "${services[@]}"
;;
build-only)
log "build-only completed: ${services[*]}"
;;
*)
echo "unsupported MODE: $MODE" >&2
exit 2
;;
esac
status
}
main "$@"