Files
han-app/VM1_app/codebase/backend/deployment/scripts/print-frontend-env.sh
T

190 lines
5.8 KiB
Bash

#!/bin/sh
# Print frontend build-time env derived from deployment .env.
# Usage:
# ./deployment/scripts/print-frontend-env.sh
# CONFIG_FILE=/opt/han-chat/backend/.env ./deployment/scripts/print-frontend-env.sh --check-oidc
set -eu
cd "$(dirname "$0")/../.."
CONFIG_FILE=${CONFIG_FILE:-.env}
CHECK_OIDC=0
FRONTEND_CLIENT_ID=${FRONTEND_CLIENT_ID:-han-chat-frontend}
for arg in "$@"; do
case "$arg" in
--check-oidc) CHECK_OIDC=1 ;;
-h|--help)
cat <<'EOF'
Usage: print-frontend-env.sh [--check-oidc]
Reads deployment .env and prints EXPO_PUBLIC_* build args for frontend-test-site.
Environment:
CONFIG_FILE path to .env (default: .env)
FRONTEND_CLIENT_ID OIDC client id (default: han-chat-frontend)
Options:
--check-oidc curl OpenID discovery using derived auth base URL
EOF
exit 0
;;
*)
echo "Unknown option: $arg" >&2
exit 64
;;
esac
done
[ -f "$CONFIG_FILE" ] || {
echo "Config file not found: $CONFIG_FILE" >&2
exit 66
}
env_value() {
python3 - "$CONFIG_FILE" "$1" <<'PY'
import sys
from pathlib import Path
path, wanted = sys.argv[1:]
found = False
for raw in Path(path).read_text(encoding="utf-8").splitlines():
line = raw.strip()
if not line or line.startswith("#") or "=" not in line:
continue
key, value = line.split("=", 1)
if key.strip() == wanted:
value = value.strip()
if len(value) >= 2 and value[0] == value[-1] and value[0] in "\"'":
value = value[1:-1]
print(value)
found = True
break
if not found:
raise SystemExit(f"missing environment variable: {wanted}")
PY
}
env_value_or_default() {
python3 - "$CONFIG_FILE" "$1" "$2" <<'PY'
import sys
from pathlib import Path
path, wanted, default = sys.argv[1:]
for raw in Path(path).read_text(encoding="utf-8").splitlines():
line = raw.strip()
if not line or line.startswith("#") or "=" not in line:
continue
key, value = line.split("=", 1)
if key.strip() == wanted:
value = value.strip()
if len(value) >= 2 and value[0] == value[-1] and value[0] in "\"'":
value = value[1:-1]
print(value or default)
break
else:
print(default)
PY
}
strip_trailing_slash() {
python3 - "$1" <<'PY'
import sys
print(sys.argv[1].rstrip("/"))
PY
}
PUBLIC_HOST=$(env_value PUBLIC_HOST)
PUBLIC_WEB_URL=$(strip_trailing_slash "$(env_value PUBLIC_WEB_URL)")
PUBLIC_AUTH_URL=$(strip_trailing_slash "$(env_value_or_default PUBLIC_AUTH_URL "")")
KEYCLOAK_PUBLIC_URL=$(strip_trailing_slash "$(env_value KEYCLOAK_PUBLIC_URL)")
KEYCLOAK_REALM=$(env_value KEYCLOAK_REALM)
APP_ENV=$(env_value_or_default APP_ENV production-like)
FRONTEND_STATIC_IMAGE=$(env_value_or_default FRONTEND_STATIC_IMAGE "")
if [ -z "$PUBLIC_AUTH_URL" ]; then
PUBLIC_AUTH_URL="$KEYCLOAK_PUBLIC_URL"
fi
EXPO_PUBLIC_API_BASE_URL="$PUBLIC_WEB_URL"
EXPO_PUBLIC_AUTH_BASE_URL="$PUBLIC_AUTH_URL"
EXPO_PUBLIC_KEYCLOAK_REALM="$KEYCLOAK_REALM"
EXPO_PUBLIC_KEYCLOAK_CLIENT_ID="$FRONTEND_CLIENT_ID"
EXPO_PUBLIC_APP_ENV="$APP_ENV"
OIDC_ISSUER="${EXPO_PUBLIC_AUTH_BASE_URL}/realms/${EXPO_PUBLIC_KEYCLOAK_REALM}"
OIDC_DISCOVERY="${OIDC_ISSUER}/.well-known/openid-configuration"
errors=0
warn() {
printf 'WARN: %s\n' "$1" >&2
errors=$((errors + 1))
}
for name in \
EXPO_PUBLIC_API_BASE_URL \
EXPO_PUBLIC_AUTH_BASE_URL \
EXPO_PUBLIC_KEYCLOAK_REALM \
EXPO_PUBLIC_KEYCLOAK_CLIENT_ID; do
eval "value=\$$name"
case "$value" in
""|http://localhost:*|https://chat.example.ru*|https://tohin.ru*)
warn "$name looks unset or still uses example/default value: '$value'"
;;
esac
done
printf '%s\n' "=== deployment .env (source: ${CONFIG_FILE}) ==="
printf '%s=%s\n' PUBLIC_HOST "$PUBLIC_HOST"
printf '%s=%s\n' PUBLIC_WEB_URL "$PUBLIC_WEB_URL"
printf '%s=%s\n' PUBLIC_AUTH_URL "$PUBLIC_AUTH_URL"
printf '%s=%s\n' KEYCLOAK_PUBLIC_URL "$KEYCLOAK_PUBLIC_URL"
printf '%s=%s\n' KEYCLOAK_REALM "$KEYCLOAK_REALM"
printf '%s=%s\n' APP_ENV "$APP_ENV"
printf '%s=%s\n' FRONTEND_STATIC_IMAGE "${FRONTEND_STATIC_IMAGE:-<not set>}"
printf '\n%s\n' "=== frontend build-time env (EXPO_PUBLIC_*) ==="
printf '%s=%s\n' EXPO_PUBLIC_API_BASE_URL "$EXPO_PUBLIC_API_BASE_URL"
printf '%s=%s\n' EXPO_PUBLIC_AUTH_BASE_URL "$EXPO_PUBLIC_AUTH_BASE_URL"
printf '%s=%s\n' EXPO_PUBLIC_KEYCLOAK_REALM "$EXPO_PUBLIC_KEYCLOAK_REALM"
printf '%s=%s\n' EXPO_PUBLIC_KEYCLOAK_CLIENT_ID "$EXPO_PUBLIC_KEYCLOAK_CLIENT_ID"
printf '%s=%s\n' EXPO_PUBLIC_APP_ENV "$EXPO_PUBLIC_APP_ENV"
printf '\n%s\n' "=== derived OIDC ==="
printf '%s=%s\n' OIDC_ISSUER "$OIDC_ISSUER"
printf '%s=%s\n' OIDC_DISCOVERY "$OIDC_DISCOVERY"
printf '%s=%s\n' AUTH_CALLBACK "${PUBLIC_WEB_URL}/auth/callback"
printf '\n%s\n' "=== docker build (frontend-test-site) ==="
cat <<EOF
docker build --target static \\
-t han-chat-frontend-static:local \\
--build-arg EXPO_PUBLIC_API_BASE_URL=${EXPO_PUBLIC_API_BASE_URL} \\
--build-arg EXPO_PUBLIC_AUTH_BASE_URL=${EXPO_PUBLIC_AUTH_BASE_URL} \\
--build-arg EXPO_PUBLIC_KEYCLOAK_REALM=${EXPO_PUBLIC_KEYCLOAK_REALM} \\
--build-arg EXPO_PUBLIC_KEYCLOAK_CLIENT_ID=${EXPO_PUBLIC_KEYCLOAK_CLIENT_ID} \\
--build-arg EXPO_PUBLIC_APP_ENV=${EXPO_PUBLIC_APP_ENV} \\
frontend-test-site
EOF
printf '\n%s\n' "=== redeploy static into compose volume ==="
cat <<'EOF'
docker compose --env-file .env up -d --force-recreate frontend-static
docker compose --env-file .env up -d --force-recreate nginx
EOF
if [ "$CHECK_OIDC" -eq 1 ]; then
printf '\n%s\n' "=== OIDC discovery check ==="
curl -fsS "$OIDC_DISCOVERY" | python3 - <<'PY'
import json, sys
doc = json.load(sys.stdin)
print("issuer=", doc.get("issuer"))
print("authorization_endpoint=", doc.get("authorization_endpoint"))
PY
fi
if [ "$errors" -gt 0 ]; then
printf '\nFound %s warning(s). Fix .env or rebuild frontend with the command above.\n' "$errors" >&2
exit 1
fi
printf '\nOK: frontend build env looks consistent with %s\n' "$CONFIG_FILE"