2026-05-21 23:52:39 +00:00
|
|
|
|
#!/usr/bin/env bash
|
|
|
|
|
|
# Shared helpers for e2e-run / e2e-up / e2e-down.
|
|
|
|
|
|
# shellcheck disable=SC2034
|
|
|
|
|
|
|
2026-05-22 09:18:36 +00:00
|
|
|
|
# Colors(非 TTY 自動關掉,CI log 才不會有 ANSI 噪音)
|
|
|
|
|
|
if [[ -t 1 ]]; then
|
|
|
|
|
|
E2E_BOLD=$'\033[1m'; E2E_DIM=$'\033[2m'; E2E_GREEN=$'\033[32m'
|
|
|
|
|
|
E2E_CYAN=$'\033[36m'; E2E_YELLOW=$'\033[33m'; E2E_RESET=$'\033[0m'
|
|
|
|
|
|
else
|
|
|
|
|
|
E2E_BOLD=""; E2E_DIM=""; E2E_GREEN=""; E2E_CYAN=""; E2E_YELLOW=""; E2E_RESET=""
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
|
# e2e_step "1/6" "fresh docker compose"
|
|
|
|
|
|
e2e_step() {
|
|
|
|
|
|
local idx="$1"; shift
|
|
|
|
|
|
printf "\n${E2E_BOLD}${E2E_CYAN}== [%s] %s ==${E2E_RESET}\n" "$idx" "$*"
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# e2e_info "啟動 mailhog(http://localhost:8025)"
|
|
|
|
|
|
e2e_info() { printf "${E2E_DIM}>> %s${E2E_RESET}\n" "$*"; }
|
|
|
|
|
|
e2e_ok() { printf "${E2E_GREEN}✔ %s${E2E_RESET}\n" "$*"; }
|
|
|
|
|
|
e2e_warn() { printf "${E2E_YELLOW}! %s${E2E_RESET}\n" "$*"; }
|
|
|
|
|
|
|
2026-05-21 23:52:39 +00:00
|
|
|
|
e2e_root_dir() {
|
|
|
|
|
|
cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-22 09:18:36 +00:00
|
|
|
|
# 把所有 e2e services 列出來(給使用者知道環境準備好了什麼)
|
|
|
|
|
|
e2e_print_services() {
|
|
|
|
|
|
local with_smtp="${1:-}"
|
|
|
|
|
|
echo
|
|
|
|
|
|
printf "${E2E_BOLD}E2E 環境服務${E2E_RESET}\n"
|
|
|
|
|
|
printf " %-12s %-32s %s\n" "MongoDB" "127.0.0.1:27017" "${E2E_DIM}database=gateway_e2e${E2E_RESET}"
|
|
|
|
|
|
printf " %-12s %-32s %s\n" "Redis" "127.0.0.1:6379" "${E2E_DIM}OTP / Casbin policy / blacklist${E2E_RESET}"
|
|
|
|
|
|
printf " %-12s %-32s %s\n" "Gateway" "http://127.0.0.1:18888" "${E2E_DIM}health: /api/v1/health${E2E_RESET}"
|
|
|
|
|
|
if [[ "${with_smtp}" == "1" ]]; then
|
|
|
|
|
|
printf " %-12s %-32s %s\n" "MailHog" "http://127.0.0.1:8025" "${E2E_DIM}SMTP=1025(E2E_WITH_SMTP=1)${E2E_RESET}"
|
|
|
|
|
|
fi
|
|
|
|
|
|
echo
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-21 23:52:39 +00:00
|
|
|
|
# Stop gateway started for E2E: pid file → port listeners → stale go run orphans.
|
|
|
|
|
|
e2e_stop_gateway() {
|
|
|
|
|
|
local port="${1:-18888}"
|
|
|
|
|
|
local pid_file="${2:-}"
|
|
|
|
|
|
|
|
|
|
|
|
if [[ -n "${pid_file}" && -f "${pid_file}" ]]; then
|
|
|
|
|
|
local pid
|
|
|
|
|
|
pid="$(cat "${pid_file}")"
|
|
|
|
|
|
if [[ -n "${pid}" ]] && kill -0 "${pid}" 2>/dev/null; then
|
|
|
|
|
|
echo ">> stopping gateway pid=${pid}"
|
|
|
|
|
|
kill "${pid}" 2>/dev/null || true
|
|
|
|
|
|
for _ in $(seq 1 10); do
|
|
|
|
|
|
kill -0 "${pid}" 2>/dev/null || break
|
|
|
|
|
|
sleep 0.2
|
|
|
|
|
|
done
|
|
|
|
|
|
if kill -0 "${pid}" 2>/dev/null; then
|
|
|
|
|
|
kill -9 "${pid}" 2>/dev/null || true
|
|
|
|
|
|
fi
|
|
|
|
|
|
wait "${pid}" 2>/dev/null || true
|
|
|
|
|
|
fi
|
|
|
|
|
|
rm -f "${pid_file}"
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
|
if command -v lsof >/dev/null 2>&1; then
|
|
|
|
|
|
local pids
|
|
|
|
|
|
pids="$(lsof -ti tcp:"${port}" 2>/dev/null | tr '\n' ' ' || true)"
|
|
|
|
|
|
if [[ -n "${pids// /}" ]]; then
|
|
|
|
|
|
echo ">> stopping listener(s) on :${port} (${pids})"
|
|
|
|
|
|
# shellcheck disable=SC2086
|
|
|
|
|
|
kill ${pids} 2>/dev/null || true
|
|
|
|
|
|
sleep 0.5
|
|
|
|
|
|
pids="$(lsof -ti tcp:"${port}" 2>/dev/null | tr '\n' ' ' || true)"
|
|
|
|
|
|
if [[ -n "${pids// /}" ]]; then
|
|
|
|
|
|
# shellcheck disable=SC2086
|
|
|
|
|
|
kill -9 ${pids} 2>/dev/null || true
|
|
|
|
|
|
fi
|
|
|
|
|
|
fi
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
|
# go run leaves a compiled binary under $TMPDIR; kill by e2e config path if still up.
|
|
|
|
|
|
if command -v pgrep >/dev/null 2>&1; then
|
|
|
|
|
|
while IFS= read -r orphan; do
|
|
|
|
|
|
[[ -z "${orphan}" ]] && continue
|
|
|
|
|
|
echo ">> stopping orphan gateway pid=${orphan}"
|
|
|
|
|
|
kill "${orphan}" 2>/dev/null || true
|
|
|
|
|
|
done < <(pgrep -f "gateway(-e2e)? .*${port}|gateway.go -f .*e2e.yaml" 2>/dev/null || true)
|
|
|
|
|
|
fi
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# Build a real binary so $! is the server PID (go run only tracks the wrapper).
|
|
|
|
|
|
e2e_start_gateway() {
|
|
|
|
|
|
local root="$1"
|
|
|
|
|
|
local config="$2"
|
|
|
|
|
|
local port="$3"
|
|
|
|
|
|
local pid_file="$4"
|
|
|
|
|
|
|
|
|
|
|
|
local bin="${root}/.cache/e2e-gateway"
|
|
|
|
|
|
mkdir -p "${root}/.cache"
|
|
|
|
|
|
|
|
|
|
|
|
e2e_stop_gateway "${port}" "${pid_file}"
|
|
|
|
|
|
|
|
|
|
|
|
echo ">> building e2e gateway binary"
|
|
|
|
|
|
(cd "${root}" && go build -o "${bin}" gateway.go)
|
|
|
|
|
|
|
|
|
|
|
|
echo ">> starting gateway on :${port}"
|
|
|
|
|
|
GATEWAY_E2E=1 "${bin}" -f "${config}" &
|
|
|
|
|
|
local pid=$!
|
|
|
|
|
|
echo "${pid}" > "${pid_file}"
|
|
|
|
|
|
echo "${pid}"
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
e2e_wait_gateway() {
|
|
|
|
|
|
local port="$1"
|
|
|
|
|
|
local url="http://127.0.0.1:${port}/api/v1/health"
|
|
|
|
|
|
for i in $(seq 1 60); do
|
|
|
|
|
|
if curl -sf "${url}" >/dev/null; then
|
|
|
|
|
|
return 0
|
|
|
|
|
|
fi
|
|
|
|
|
|
sleep 1
|
|
|
|
|
|
done
|
|
|
|
|
|
echo "timeout waiting for gateway ${url}" >&2
|
|
|
|
|
|
return 1
|
|
|
|
|
|
}
|