Files
openwork/packaging/docker/otel-hono-live-validate.sh

124 lines
5.4 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
repo_root="$(cd "$script_dir/../.." && pwd)"
project_default="openwork-otel-hono-live-$$"
project="${OTEL_HONO_PROJECT:-$project_default}"
den_compose_file="${OTEL_HONO_DEN_COMPOSE_FILE:-$repo_root/packaging/docker/docker-compose.den-dev.yml}"
otel_compose_file="${OTEL_HONO_LGTM_COMPOSE_FILE:-$repo_root/packaging/docker/docker-compose.otel-lgtm.yml}"
keep_stack="${KEEP_STACK:-0}"
skip_build="${SKIP_BUILD:-0}"
wait_seconds="${OTEL_HONO_COMPOSE_WAIT_SECONDS:-420}"
port_base="${OTEL_HONO_PORT_BASE:-$((22000 + ($$ % 1000) * 20))}"
case "$den_compose_file" in
/*) ;;
*) den_compose_file="$repo_root/$den_compose_file" ;;
esac
case "$otel_compose_file" in
/*) ;;
*) otel_compose_file="$repo_root/$otel_compose_file" ;;
esac
if [[ ! "$project" =~ ^[a-z0-9][a-z0-9_-]*$ ]]; then
echo "OTEL_HONO_PROJECT must start with a lowercase letter or digit and contain only lowercase letters, digits, underscores, or dashes" >&2
exit 1
fi
for file in "$den_compose_file" "$otel_compose_file" "$script_dir/otel-hono-live-validate.mjs"; do
if [ ! -f "$file" ]; then
echo "Required file not found: $file" >&2
exit 1
fi
done
for command in docker node; do
if ! command -v "$command" >/dev/null 2>&1; then
echo "$command is required for live OTEL/Hono validation" >&2
exit 1
fi
done
export DEN_API_PORT="${DEN_API_PORT:-$((port_base + 1))}"
export DEN_WEB_PORT="${DEN_WEB_PORT:-$((port_base + 2))}"
export DEN_MYSQL_PORT="${DEN_MYSQL_PORT:-$((port_base + 3))}"
export OTEL_LGTM_GRAFANA_PORT="${OTEL_LGTM_GRAFANA_PORT:-$((port_base + 4))}"
export OTEL_LGTM_OTLP_GRPC_PORT="${OTEL_LGTM_OTLP_GRPC_PORT:-$((port_base + 5))}"
export OTEL_LGTM_OTLP_HTTP_PORT="${OTEL_LGTM_OTLP_HTTP_PORT:-$((port_base + 6))}"
export DEN_OBSERVABILITY_BACKEND="${DEN_OBSERVABILITY_BACKEND:-otel}"
export NEXT_PUBLIC_DEN_OBSERVABILITY_BACKEND="${NEXT_PUBLIC_DEN_OBSERVABILITY_BACKEND:-otel}"
export OTEL_EXPORTER_OTLP_ENDPOINT="${OTEL_EXPORTER_OTLP_ENDPOINT:-http://otel-lgtm:4318}"
export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT="${OTEL_EXPORTER_OTLP_TRACES_ENDPOINT:-http://otel-lgtm:4318/v1/traces}"
export OTEL_EXPORTER_OTLP_METRICS_ENDPOINT="${OTEL_EXPORTER_OTLP_METRICS_ENDPOINT:-http://otel-lgtm:4318/v1/metrics}"
export OTEL_EXPORTER_OTLP_LOGS_ENDPOINT="${OTEL_EXPORTER_OTLP_LOGS_ENDPOINT:-http://otel-lgtm:4318/v1/logs}"
export OTEL_EXPORTER_OTLP_PROTOCOL="${OTEL_EXPORTER_OTLP_PROTOCOL:-http/protobuf}"
export OTEL_EXPORTER_OTLP_TRACES_PROTOCOL="${OTEL_EXPORTER_OTLP_TRACES_PROTOCOL:-http/protobuf}"
export OTEL_EXPORTER_OTLP_METRICS_PROTOCOL="${OTEL_EXPORTER_OTLP_METRICS_PROTOCOL:-http/protobuf}"
export OTEL_EXPORTER_OTLP_LOGS_PROTOCOL="${OTEL_EXPORTER_OTLP_LOGS_PROTOCOL:-http/protobuf}"
export OTEL_TRACES_EXPORTER="${OTEL_TRACES_EXPORTER:-otlp}"
export OTEL_METRICS_EXPORTER="${OTEL_METRICS_EXPORTER:-otlp}"
export OTEL_LOGS_EXPORTER="${OTEL_LOGS_EXPORTER:-otlp}"
export OTEL_TRACES_SAMPLER="${OTEL_TRACES_SAMPLER:-parentbased_always_on}"
export DEN_API_OTEL_SERVICE_NAME="${DEN_API_OTEL_SERVICE_NAME:-den-api}"
export DEN_WEB_OTEL_SERVICE_NAME="${DEN_WEB_OTEL_SERVICE_NAME:-den-web}"
export DEN_BETTER_AUTH_URL="${DEN_BETTER_AUTH_URL:-http://127.0.0.1:${DEN_WEB_PORT}}"
export DEN_API_PUBLIC_URL="${DEN_API_PUBLIC_URL:-http://127.0.0.1:${DEN_API_PORT}}"
export DEN_MCP_RESOURCE_URL="${DEN_MCP_RESOURCE_URL:-http://127.0.0.1:${DEN_API_PORT}/mcp}"
export DEN_CORS_ORIGINS="${DEN_CORS_ORIGINS:-http://127.0.0.1:${DEN_WEB_PORT},http://localhost:${DEN_WEB_PORT},http://127.0.0.1:${DEN_API_PORT},http://localhost:${DEN_API_PORT}}"
export DEN_BETTER_AUTH_TRUSTED_ORIGINS="${DEN_BETTER_AUTH_TRUSTED_ORIGINS:-$DEN_CORS_ORIGINS}"
report_dir="${OTEL_HONO_REPORT_DIR:-$repo_root/tmp/otel-hono-live-$project}"
report_json="${OTEL_HONO_REPORT_JSON:-$report_dir/report.json}"
docker_log="$report_dir/docker.log"
mkdir -p "$report_dir"
cleanup() {
status=$?
if [ "$keep_stack" != "1" ]; then
docker compose -p "$project" -f "$den_compose_file" -f "$otel_compose_file" down --volumes >>"$docker_log" 2>&1 || true
else
echo "KEEP_STACK=1; leaving Compose project $project running" >&2
fi
exit "$status"
}
trap cleanup EXIT
trap 'exit 130' INT
trap 'exit 143' TERM
run_step() {
label="$1"
shift
echo "==> $label"
if "$@" >>"$docker_log" 2>&1; then
echo "ok: $label"
return
fi
echo "failed: $label (see $docker_log)" >&2
tail -n 120 "$docker_log" >&2 || true
exit 1
}
echo "report_json=$report_json"
echo "project=$project"
echo "ports den_web=$DEN_WEB_PORT den_api=$DEN_API_PORT mysql=$DEN_MYSQL_PORT grafana=$OTEL_LGTM_GRAFANA_PORT otlp_http=$OTEL_LGTM_OTLP_HTTP_PORT"
run_step "render merged compose config" docker compose -p "$project" -f "$den_compose_file" -f "$otel_compose_file" config
if [ "$skip_build" != "1" ]; then
run_step "build Den API and Den Web images" docker compose -p "$project" -f "$den_compose_file" -f "$otel_compose_file" build den web
else
echo "SKIP_BUILD=1; reusing existing images"
fi
run_step "start and wait for live Den + OTEL LGTM stack" docker compose -p "$project" -f "$den_compose_file" -f "$otel_compose_file" up -d --wait --wait-timeout "$wait_seconds" mysql otel-lgtm den web
node "$script_dir/otel-hono-live-validate.mjs" \
--project "$project" \
--den-compose-file "$den_compose_file" \
--otel-compose-file "$otel_compose_file" \
--grafana-url "http://127.0.0.1:${OTEL_LGTM_GRAFANA_PORT}" \
--web-url "http://127.0.0.1:${DEN_WEB_PORT}" \
--report-json "$report_json"