91 lines
2.8 KiB
Bash
Executable File
91 lines
2.8 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
TARGET_HOST="${1:?target host is required}"
|
|
BINARY_PATH="${2:?binary path is required}"
|
|
EXPECTED_COMMIT="${3:?expected short commit is required}"
|
|
REMOTE_TMP="/tmp/xworkmate-bridge-${EXPECTED_COMMIT}"
|
|
REMOTE_BINARY="${REMOTE_BINARY:-/usr/local/bin/xworkmate-go-core}"
|
|
STALE_DROPIN="/etc/systemd/system/xworkmate-bridge.service.d/10-hotfix-openclaw-artifacts.conf"
|
|
SERVICE_NAME="xworkmate-bridge.service"
|
|
|
|
if [[ ! "${TARGET_HOST}" =~ ^[A-Za-z0-9._-]+$ ]]; then
|
|
echo "invalid target host: ${TARGET_HOST}" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [[ ! "${EXPECTED_COMMIT}" =~ ^[0-9a-f]{7,40}$ ]]; then
|
|
echo "invalid expected commit: ${EXPECTED_COMMIT}" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [[ ! -f "${BINARY_PATH}" ]]; then
|
|
echo "native bridge binary not found: ${BINARY_PATH}" >&2
|
|
exit 1
|
|
fi
|
|
|
|
chmod +x "${BINARY_PATH}"
|
|
scp -q "${BINARY_PATH}" "root@${TARGET_HOST}:${REMOTE_TMP}"
|
|
|
|
ssh "root@${TARGET_HOST}" "EXPECTED_COMMIT='${EXPECTED_COMMIT}' REMOTE_TMP='${REMOTE_TMP}' REMOTE_BINARY='${REMOTE_BINARY}' STALE_DROPIN='${STALE_DROPIN}' SERVICE_NAME='${SERVICE_NAME}' bash -s" <<'REMOTE'
|
|
set -euo pipefail
|
|
|
|
had_immutable=0
|
|
restore_immutable() {
|
|
if [[ "${had_immutable}" == "1" ]] && command -v chattr >/dev/null 2>&1 && [[ -e "${REMOTE_BINARY}" ]]; then
|
|
chattr +i "${REMOTE_BINARY}" 2>/dev/null || true
|
|
fi
|
|
}
|
|
trap restore_immutable EXIT
|
|
|
|
if command -v lsattr >/dev/null 2>&1 && [[ -e "${REMOTE_BINARY}" ]]; then
|
|
attrs="$(lsattr "${REMOTE_BINARY}" 2>/dev/null || true)"
|
|
if [[ "${attrs}" == *i* ]]; then
|
|
had_immutable=1
|
|
chattr -i "${REMOTE_BINARY}"
|
|
fi
|
|
fi
|
|
|
|
install -o root -g root -m 0755 "${REMOTE_TMP}" "${REMOTE_BINARY}"
|
|
|
|
restore_immutable
|
|
|
|
rm -f "${STALE_DROPIN}"
|
|
rmdir --ignore-fail-on-non-empty "$(dirname "${STALE_DROPIN}")" 2>/dev/null || true
|
|
|
|
version_json="$("${REMOTE_BINARY}" version)"
|
|
actual_commit="$(VERSION_JSON="${version_json}" python3 - <<'PY'
|
|
import json
|
|
import os
|
|
payload = json.loads(os.environ["VERSION_JSON"])
|
|
print(str(payload.get("commit", "")))
|
|
PY
|
|
)"
|
|
if [[ "${actual_commit}" != "${EXPECTED_COMMIT}" ]]; then
|
|
echo "deployed binary commit mismatch: expected ${EXPECTED_COMMIT}, got ${actual_commit}" >&2
|
|
exit 1
|
|
fi
|
|
|
|
systemctl daemon-reload
|
|
systemctl restart "${SERVICE_NAME}"
|
|
deadline=$((SECONDS + 20))
|
|
actual_exe=""
|
|
pid=""
|
|
while (( SECONDS < deadline )); do
|
|
pid="$(systemctl show -p MainPID --value "${SERVICE_NAME}")"
|
|
if [[ -n "${pid}" && "${pid}" != "0" && -e "/proc/${pid}/exe" ]]; then
|
|
actual_exe="$(readlink -f "/proc/${pid}/exe" 2>/dev/null || true)"
|
|
if [[ "${actual_exe}" == "${REMOTE_BINARY}" ]]; then
|
|
exit 0
|
|
fi
|
|
fi
|
|
sleep 1
|
|
done
|
|
if [[ -z "${pid}" || "${pid}" == "0" ]]; then
|
|
echo "${SERVICE_NAME} did not start" >&2
|
|
exit 1
|
|
fi
|
|
echo "${SERVICE_NAME} is not running ${REMOTE_BINARY}; pid=${pid}; actual=${actual_exe:-unknown}" >&2
|
|
exit 1
|
|
REMOTE
|