- Updated branding from "SolaceScanScout" to "Solace" across various files including deployment scripts, API responses, and documentation. - Changed default base URL for Playwright tests and updated security headers to reflect the new branding. - Enhanced README and API documentation to include new authentication endpoints and product access details. This refactor aligns the project branding and improves clarity in the API documentation.
183 lines
6.4 KiB
Bash
Executable File
183 lines
6.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
# Deploy the current Next.js standalone frontend to VMID 5000.
|
|
# This is the canonical deployment path for the current SolaceScan frontend.
|
|
# It builds the local frontend, uploads the standalone bundle, installs a systemd
|
|
# service, and starts the Node server on 127.0.0.1:3000 inside the container.
|
|
|
|
set -euo pipefail
|
|
|
|
VMID="${VMID:-5000}"
|
|
FRONTEND_PORT="${FRONTEND_PORT:-3000}"
|
|
SERVICE_NAME="solacescanscout-frontend"
|
|
APP_ROOT="/opt/solacescanscout/frontend"
|
|
PROXMOX_R630_02="${PROXMOX_HOST_R630_02:-192.168.11.12}"
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
WORKSPACE_ROOT="$(cd "$REPO_ROOT/.." && pwd)"
|
|
FRONTEND_ROOT="${REPO_ROOT}/frontend"
|
|
SERVICE_TEMPLATE="${REPO_ROOT}/deployment/systemd/solacescanscout-frontend.service"
|
|
NGINX_SNIPPET="${REPO_ROOT}/deployment/common/nginx-next-frontend-proxy.conf"
|
|
VERIFY_SCRIPT="${WORKSPACE_ROOT}/scripts/verify/check-explorer-e2e.sh"
|
|
RELEASE_ID="$(date +%Y%m%d_%H%M%S)"
|
|
TMP_DIR="$(mktemp -d)"
|
|
ARCHIVE_NAME="solacescanscout-next-${RELEASE_ID}.tar"
|
|
STATIC_SYNC_FILES=(
|
|
"index.html"
|
|
"docs.html"
|
|
"privacy.html"
|
|
"terms.html"
|
|
"acknowledgments.html"
|
|
"chain138-command-center.html"
|
|
"favicon.ico"
|
|
"apple-touch-icon.png"
|
|
"explorer-spa.js"
|
|
)
|
|
|
|
cleanup() {
|
|
rm -rf "$TMP_DIR"
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
if [[ ! -f "$SERVICE_TEMPLATE" ]]; then
|
|
echo "Missing service template: $SERVICE_TEMPLATE" >&2
|
|
exit 1
|
|
fi
|
|
|
|
push_into_vmid() {
|
|
local source_path="$1"
|
|
local destination_path="$2"
|
|
local perms="${3:-0644}"
|
|
|
|
if [[ -f /proc/1/cgroup ]] && grep -q "lxc" /proc/1/cgroup 2>/dev/null; then
|
|
install -D -m "$perms" "$source_path" "$destination_path"
|
|
elif command -v pct >/dev/null 2>&1; then
|
|
pct push "$VMID" "$source_path" "$destination_path" --perms "$perms"
|
|
else
|
|
local remote_tmp="/tmp/$(basename "$source_path").$$"
|
|
scp -o ConnectTimeout=10 -o StrictHostKeyChecking=no "$source_path" "root@${PROXMOX_R630_02}:${remote_tmp}"
|
|
ssh -o ConnectTimeout=10 -o StrictHostKeyChecking=no "root@${PROXMOX_R630_02}" \
|
|
"pct push ${VMID} ${remote_tmp} ${destination_path} --perms ${perms} && rm -f ${remote_tmp}"
|
|
fi
|
|
}
|
|
|
|
run_in_vmid() {
|
|
local command="$1"
|
|
|
|
if [[ -f /proc/1/cgroup ]] && grep -q "lxc" /proc/1/cgroup 2>/dev/null; then
|
|
bash -lc "$command"
|
|
elif command -v pct >/dev/null 2>&1; then
|
|
pct exec "$VMID" -- bash -lc "$command"
|
|
else
|
|
ssh -o ConnectTimeout=10 -o StrictHostKeyChecking=no "root@${PROXMOX_R630_02}" \
|
|
"pct exec ${VMID} -- bash -lc $(printf '%q' "$command")"
|
|
fi
|
|
}
|
|
|
|
echo "=========================================="
|
|
echo "Deploying Next SolaceScan Frontend"
|
|
echo "=========================================="
|
|
echo "VMID: $VMID"
|
|
echo "Frontend root: $FRONTEND_ROOT"
|
|
echo "Release: $RELEASE_ID"
|
|
echo ""
|
|
|
|
if [[ "${SKIP_BUILD:-0}" != "1" ]]; then
|
|
echo "== Building frontend =="
|
|
(cd "$FRONTEND_ROOT" && npm run build)
|
|
echo ""
|
|
fi
|
|
|
|
if [[ ! -f "${FRONTEND_ROOT}/.next/standalone/server.js" ]]; then
|
|
echo "Missing standalone server build. Run \`npm run build\` in ${FRONTEND_ROOT} first." >&2
|
|
exit 1
|
|
fi
|
|
|
|
STAGE_DIR="${TMP_DIR}/stage"
|
|
mkdir -p "${STAGE_DIR}/.next"
|
|
cp -R "${FRONTEND_ROOT}/.next/standalone/." "$STAGE_DIR/"
|
|
cp -R "${FRONTEND_ROOT}/.next/static" "${STAGE_DIR}/.next/static"
|
|
cp -R "${FRONTEND_ROOT}/public" "${STAGE_DIR}/public"
|
|
tar -C "$STAGE_DIR" -cf "${TMP_DIR}/${ARCHIVE_NAME}" .
|
|
|
|
cp "$SERVICE_TEMPLATE" "${TMP_DIR}/${SERVICE_NAME}.service"
|
|
sed -i "s|/opt/solacescanscout/frontend/current|${APP_ROOT}/current|g" "${TMP_DIR}/${SERVICE_NAME}.service"
|
|
sed -i "s|Environment=PORT=3000|Environment=PORT=${FRONTEND_PORT}|g" "${TMP_DIR}/${SERVICE_NAME}.service"
|
|
|
|
cat > "${TMP_DIR}/install-next-frontend.sh" <<EOF
|
|
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
APP_ROOT="${APP_ROOT}"
|
|
RELEASE_DIR="\${APP_ROOT}/releases/${RELEASE_ID}"
|
|
SERVICE_NAME="${SERVICE_NAME}"
|
|
FRONTEND_PORT="${FRONTEND_PORT}"
|
|
|
|
mkdir -p "\${APP_ROOT}/releases"
|
|
mkdir -p "\${RELEASE_DIR}"
|
|
tar -xf "/tmp/${ARCHIVE_NAME}" -C "\${RELEASE_DIR}"
|
|
ln -sfn "\${RELEASE_DIR}" "\${APP_ROOT}/current"
|
|
chown -R www-data:www-data "\${APP_ROOT}"
|
|
|
|
install -m 0644 "/tmp/${SERVICE_NAME}.service" "/etc/systemd/system/\${SERVICE_NAME}.service"
|
|
systemctl daemon-reload
|
|
systemctl enable "\${SERVICE_NAME}.service" >/dev/null
|
|
systemctl restart "\${SERVICE_NAME}.service"
|
|
|
|
for attempt in \$(seq 1 45); do
|
|
if curl -fsS --max-time 5 "http://127.0.0.1:\${FRONTEND_PORT}/" > /tmp/\${SERVICE_NAME}-health.out; then
|
|
break
|
|
fi
|
|
sleep 1
|
|
done
|
|
|
|
if ! grep -qiE "SolaceScan|Chain 138 Explorer by DBIS" /tmp/\${SERVICE_NAME}-health.out; then
|
|
systemctl status "\${SERVICE_NAME}.service" --no-pager || true
|
|
journalctl -u "\${SERVICE_NAME}.service" -n 50 --no-pager || true
|
|
echo "Frontend health check did not find the expected SolaceScan marker." >&2
|
|
exit 1
|
|
fi
|
|
|
|
mkdir -p /var/www/html
|
|
for relpath in ${STATIC_SYNC_FILES[*]}; do
|
|
if [[ -f "\${RELEASE_DIR}/public/\${relpath}" ]]; then
|
|
install -D -m 0644 "\${RELEASE_DIR}/public/\${relpath}" "/var/www/html/\${relpath}"
|
|
fi
|
|
done
|
|
if [[ -d "\${RELEASE_DIR}/public/thirdparty" ]]; then
|
|
mkdir -p /var/www/html/thirdparty
|
|
cp -a "\${RELEASE_DIR}/public/thirdparty/." /var/www/html/thirdparty/
|
|
fi
|
|
if [[ -d "\${RELEASE_DIR}/public/config" ]]; then
|
|
mkdir -p /var/www/html/config
|
|
cp -a "\${RELEASE_DIR}/public/config/." /var/www/html/config/
|
|
fi
|
|
EOF
|
|
chmod +x "${TMP_DIR}/install-next-frontend.sh"
|
|
|
|
echo "== Uploading release bundle =="
|
|
push_into_vmid "${TMP_DIR}/${ARCHIVE_NAME}" "/tmp/${ARCHIVE_NAME}" 0644
|
|
push_into_vmid "${TMP_DIR}/${SERVICE_NAME}.service" "/tmp/${SERVICE_NAME}.service" 0644
|
|
push_into_vmid "${TMP_DIR}/install-next-frontend.sh" "/tmp/install-next-frontend.sh" 0755
|
|
echo ""
|
|
|
|
echo "== Installing release and restarting service =="
|
|
run_in_vmid "/tmp/install-next-frontend.sh"
|
|
echo ""
|
|
|
|
echo "== Verification =="
|
|
run_in_vmid "systemctl is-active ${SERVICE_NAME}.service"
|
|
run_in_vmid "curl -fsS --max-time 5 http://127.0.0.1:${FRONTEND_PORT}/ | grep -qiE 'SolaceScan|Chain 138 Explorer by DBIS'"
|
|
echo "Service ${SERVICE_NAME} is running on 127.0.0.1:${FRONTEND_PORT}"
|
|
echo ""
|
|
echo "Nginx follow-up:"
|
|
echo " Switch the explorer server block to proxy / and /_next/ to 127.0.0.1:${FRONTEND_PORT}"
|
|
echo " while preserving /api/, /api/config/*, /explorer-api/v1/, /token-aggregation/api/v1/, /snap/, and /health."
|
|
echo " Snippet: ${NGINX_SNIPPET}"
|
|
if [[ -f "${VERIFY_SCRIPT}" ]]; then
|
|
echo " After nginx/NPMplus cutover, verify with:"
|
|
echo " bash ${VERIFY_SCRIPT} https://blockscout.defi-oracle.io"
|
|
fi
|
|
echo ""
|
|
echo "Next frontend deployment complete."
|