feat: expand vehicle data platform capabilities

This commit is contained in:
lingniu
2026-07-27 16:46:15 +08:00
parent e3a1f80f86
commit 3c4bece72c
650 changed files with 62155 additions and 2552 deletions

View File

@@ -0,0 +1,121 @@
#!/usr/bin/env bash
set -euo pipefail
RELEASE_ID=${1:?release id is required}
WEB_ARCHIVE=${2:?open portal web archive is required}
API_BINARY=${3:?open platform API binary is required}
ROOT=${OPEN_PLATFORM_ROOT:-/opt/lingniu-vehicle-open-platform}
BASE_URL=${OPEN_PLATFORM_BASE_URL:-http://127.0.0.1:20310}
SERVICE=${OPEN_PLATFORM_SERVICE:-lingniu-vehicle-open-platform}
SYSTEMCTL_BIN=${SYSTEMCTL_BIN:-systemctl}
CURL_BIN=${CURL_BIN:-curl}
RELEASE_HISTORY_LIMIT=${RELEASE_HISTORY_LIMIT:-12}
case "$RELEASE_ID" in
''|*[!A-Za-z0-9._-]*) printf 'invalid release id: %s\n' "$RELEASE_ID" >&2; exit 1 ;;
esac
test -f "$WEB_ARCHIVE" || { printf 'open portal archive is missing\n' >&2; exit 1; }
test -f "$API_BINARY" || { printf 'open platform API binary is missing\n' >&2; exit 1; }
old=
if test -L "$ROOT/current"; then
old=$(readlink -f "$ROOT/current")
fi
next="$ROOT/releases/$RELEASE_ID"
env_file="$ROOT/env/open-platform.env"
switched=false
set_release_env() {
python3 - "$env_file" "$1" <<'PY'
import pathlib
import sys
path = pathlib.Path(sys.argv[1])
release = sys.argv[2]
lines = path.read_text(encoding="utf-8").splitlines() if path.exists() else []
updated = []
found = False
for line in lines:
if line.startswith("OPEN_PLATFORM_RELEASE="):
updated.append("OPEN_PLATFORM_RELEASE=" + release)
found = True
else:
updated.append(line)
if not found:
updated.append("OPEN_PLATFORM_RELEASE=" + release)
path.write_text("\n".join(updated) + "\n", encoding="utf-8")
PY
chmod 0600 "$env_file"
}
rollback() {
status=$?
trap - ERR
set +e
if test "$switched" = true && test -n "$old"; then
ln -s "$old" "$ROOT/current.rollback"
python3 -c 'import os,sys; os.replace(sys.argv[1],sys.argv[2])' "$ROOT/current.rollback" "$ROOT/current"
set_release_env "$(basename "$old")"
"$SYSTEMCTL_BIN" restart "$SERVICE"
elif test "$switched" = true; then
"$SYSTEMCTL_BIN" stop "$SERVICE"
rm -f "$ROOT/current"
set_release_env ""
fi
printf 'open platform release failed; current restored to %s\n' "${old:-none}" >&2
exit "$status"
}
trap rollback ERR
test ! -e "$next" || { printf 'release already exists: %s\n' "$next" >&2; exit 1; }
mkdir -p "$next/web" "$ROOT/env"
cp "$API_BINARY" "$next/open-platform-api"
chmod 0755 "$next/open-platform-api"
while IFS= read -r member; do
case "$member" in
/*|../*|*/../*|*/..) printf 'web archive contains unsafe path: %s\n' "$member" >&2; exit 1 ;;
esac
done < <(tar -tzf "$WEB_ARCHIVE")
tar --no-same-owner -xzf "$WEB_ARCHIVE" -C "$next/web"
test -f "$next/web/index.html" || { printf 'open portal index is missing\n' >&2; exit 1; }
ln -s "$next" "$ROOT/current.next"
python3 -c 'import os,sys; os.replace(sys.argv[1],sys.argv[2])' "$ROOT/current.next" "$ROOT/current"
switched=true
set_release_env "$RELEASE_ID"
"$SYSTEMCTL_BIN" restart "$SERVICE"
ready=false
for _ in $(seq 1 20); do
if "$SYSTEMCTL_BIN" is-active --quiet "$SERVICE" && "$CURL_BIN" -fsS "$BASE_URL/healthz" >/dev/null; then
ready=true
break
fi
sleep 1
done
test "$ready" = true || { printf 'open platform service did not become ready\n' >&2; exit 1; }
"$CURL_BIN" -fsS "$BASE_URL/" | grep -q '<div id="root"></div>'
"$CURL_BIN" -fsS "$BASE_URL/open-api/openapi.yaml" | grep -q '^openapi: 3.0.3'
"$CURL_BIN" -fsS "$BASE_URL/portal-api/catalog" | grep -q 'daily_hydrogen'
python3 - "$ROOT" "$RELEASE_HISTORY_LIMIT" "$next" "$old" <<'PY'
import pathlib
import shutil
import sys
root = pathlib.Path(sys.argv[1])
limit = int(sys.argv[2])
protected = {pathlib.Path(value).resolve() for value in sys.argv[3:] if value}
releases = sorted(
(p for p in (root / "releases").iterdir() if p.is_dir()),
key=lambda p: p.stat().st_mtime,
reverse=True,
)
for path in releases[limit:]:
if path.resolve() not in protected:
shutil.rmtree(path)
PY
switched=false
trap - ERR
printf 'open_platform_release_install=ok release=%s previous=%s\n' "$RELEASE_ID" "${old##*/}"