fix(deploy): publish unified services to temporary gray environment

This commit is contained in:
2026-10-07 11:02:47 +08:00
parent 6346e7bd95
commit ec0c06ff88
9 changed files with 211 additions and 72 deletions
+43 -4
View File
@@ -29,18 +29,23 @@ for value_name in HEALTH_TIMEOUT_SECONDS HEALTH_POLL_SECONDS; do
done
[ "$DEPLOY_ENV" = "test" ] || { echo "Only test is supported" >&2; exit 2; }
case "$DEPLOY_ENV" in test|production) ;; *) echo "Only test and production are supported" >&2; exit 2 ;; esac
case "$SERVICE" in
gateway|auth|iam|firstleg|finance|order|warehouse|file|print|integration-service|lastleg-service|warehouse-overseas-service|audit-service) ;;
*) echo "Unknown or retired service: $SERVICE" >&2; exit 2 ;;
esac
[ "${TARGET_IS_LOCAL:-false}" = "true" ] || { echo "TEST deploy must run on the target host" >&2; exit 2; }
case "$IMAGE_REPOSITORY" in ''|*[!a-zA-Z0-9._:/-]*) echo "Invalid image repository" >&2; exit 2 ;; esac
case "$IMAGE_TAG" in ''|*[!a-zA-Z0-9_.-]*) echo "Invalid image tag" >&2; exit 2 ;; esac
case "${ALLOW_SAME_CONTRACT_ROLLBACK:-false}" in true|false) ;; *) exit 2 ;; esac
if [ "$DEPLOY_ENV" = "test" ] && [ "${TARGET_IS_LOCAL:-false}" != "true" ]; then
echo "TEST deploy must run on the target host" >&2; exit 2
fi
[ -f "$ENV_FILE" ] || { echo "Environment file missing" >&2; exit 2; }
env_file_value() { sed -n "s/^$1=//p" "$ENV_FILE" | tail -n 1 | tr -d '\r'; }
for key in NACOS_SERVER_ADDR NACOS_NAMESPACE NACOS_USERNAME NACOS_PASSWORD REDIS_HOST REDIS_PORT REDIS_DATABASE REDIS_TOKEN_KEY_PREFIX INTERNAL_SERVICE_TOKEN JWT_RSA_JWK_SET JWT_CURRENT_KID ROCKETMQ_NAME_SERVER; do
[ -n "$(env_file_value "$key")" ] || { echo "Missing $key" >&2; exit 2; }
done
[ "$(env_file_value MQ_TOPIC_PREFIX)" = "test-" ] || { echo "MQ_TOPIC_PREFIX must be test-" >&2; exit 2; }
[ "$(env_file_value MQ_TOPIC_PREFIX)" = "$DEPLOY_ENV-" ] || { echo "MQ_TOPIC_PREFIX must be $DEPLOY_ENV-" >&2; exit 2; }
case "$SERVICE" in
gateway|print|integration-service) db_prefix='' ;;
lastleg-service) db_prefix=LASTLEG ;;
@@ -138,6 +143,7 @@ wait_for_local_health() {
}
deploy_local() {
export DEPLOY_ENV IMAGE_REPOSITORY IMAGE_TAG
deploy_docker_config=$(mktemp -d)
DOCKER_CONFIG="$deploy_docker_config"
export DOCKER_CONFIG
@@ -223,4 +229,37 @@ deploy_local() {
return 1
}
deploy_local
deploy_remote() {
: "${TARGET_SSH_TARGET:?TARGET_SSH_TARGET required}"
: "${TARGET_SSH_KEY:?TARGET_SSH_KEY required}"
: "${TARGET_SSH_KNOWN_HOSTS:?TARGET_SSH_KNOWN_HOSTS required}"
[ -f "$TARGET_SSH_KEY" ] && [ -f "$TARGET_SSH_KNOWN_HOSTS" ] || exit 2
run_ssh() {
ssh -i "$TARGET_SSH_KEY" -o BatchMode=yes -o StrictHostKeyChecking=yes \
-o UserKnownHostsFile="$TARGET_SSH_KNOWN_HOSTS" -o ConnectTimeout=10 "$TARGET_SSH_TARGET" "$@"
}
run_scp() {
scp -i "$TARGET_SSH_KEY" -o BatchMode=yes -o StrictHostKeyChecking=yes \
-o UserKnownHostsFile="$TARGET_SSH_KNOWN_HOSTS" -o ConnectTimeout=10 "$@"
}
remote_dir=$(run_ssh 'umask 077; mktemp -d /tmp/firstleg-production-release.XXXXXXXXXX')
case "$remote_dir" in /tmp/firstleg-production-release.*) ;; *) echo "Invalid remote temporary directory" >&2; exit 2 ;; esac
case "$remote_dir" in *[!a-zA-Z0-9/._-]*) exit 2 ;; esac
cleanup_remote() { run_ssh "rm -rf -- '$remote_dir'" >/dev/null 2>&1; }
trap cleanup_remote EXIT HUP INT TERM
run_ssh "mkdir -p '$remote_dir/deploy/scripts'"
run_scp "$ENV_FILE" "$TARGET_SSH_TARGET:$remote_dir/deployment.env"
run_scp "$COMPOSE_FILE" "$TARGET_SSH_TARGET:$remote_dir/deploy/docker-compose.yml"
run_scp deploy/scripts/deploy-built-service.sh "$TARGET_SSH_TARGET:$remote_dir/deploy/scripts/deploy-built-service.sh"
# Registry credentials only travel over stdin, never in process arguments or files.
{ printf '%s\n' "$REGISTRY_USER"; printf '%s' "$REGISTRY_PASSWORD"; } | run_ssh \
"cd '$remote_dir' && IFS= read -r REGISTRY_USER && REGISTRY_PASSWORD=\$(cat) && export REGISTRY_USER REGISTRY_PASSWORD TARGET_IS_LOCAL=true ALLOW_SAME_CONTRACT_ROLLBACK='${ALLOW_SAME_CONTRACT_ROLLBACK:-false}' DEPLOY_HEALTH_TIMEOUT_SECONDS='$HEALTH_TIMEOUT_SECONDS' DEPLOY_HEALTH_POLL_SECONDS='$HEALTH_POLL_SECONDS' && sh deploy/scripts/deploy-built-service.sh production '$IMAGE_REPOSITORY' '$IMAGE_TAG' '$SERVICE' deployment.env"
cleanup_remote
trap - EXIT HUP INT TERM
}
if [ "${TARGET_IS_LOCAL:-false}" = "true" ]; then
deploy_local
else
deploy_remote
fi