XuqmGroup-PrivateDeploy/scripts/alert-webhook.sh
徐勤民 9eabe0d699 feat: implement complete private deployment scripts (P1-P4)
- upgrade.sh/rollback.sh: backup→pull→rolling restart→healthcheck→auto-rollback
- backup.sh/restore.sh: mysqldump+redis BGSAVE+config tar, SHA256 manifest, restore with checksum verification
- healthcheck.sh: Docker/container/MySQL/Redis/HTTP/disk checks, JSON output to .deploy-state/
- doctor.sh: sanitized diagnostics archive, vendor API TCP connectivity, cert expiry
- export-offline-bundle.sh: docker pull+save for all profile images, load-images.sh, SHA256
- configure.sh: interactive/non-interactive mode, MySQL/Redis mode selection, domain prompts
- enable-service.sh: domain validation, docker pull + compose up, healthcheck
- disable-service.sh: compose stop+rm, profile removal, render-config
- renew-cert.sh: acme.sh/certbot, --dry-run, backup old cert, nginx reload on success
- alert-webhook.sh: WeCom/DingTalk/Feishu webhook, message sanitization
- bench.sh: ab/wrk/curl benchmark, JSON report with docker stats
- rotate-secrets.sh: JWT and internal token rotation
- vendor credential templates: push.env and store-submit.env with full credential comments
- render-config.sh: auto-sync SDK URL env vars (SDK_FILE_SERVICE_URL, SDK_IM_API_URL, SDK_IM_WS_URL)
- All scripts pass bash -n syntax check

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 20:49:25 +08:00

72 行
2.2 KiB
Bash
可执行文件

#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
. "$ROOT_DIR/scripts/lib.sh"
load_env
EVENT="${1:-UNKNOWN}"
MESSAGE="${2:-}"
TIMESTAMP="$(now)"
# Webhook URL from config (never logged)
WEBHOOK_URL="${ALERT_WEBHOOK_URL:-}"
WEBHOOK_TYPE="${ALERT_WEBHOOK_TYPE:-wecom}" # wecom | dingtalk | feishu
[ -n "$WEBHOOK_URL" ] || {
printf 'ALERT_WEBHOOK_URL not configured; alert suppressed: [%s] %s\n' "$EVENT" "$MESSAGE" >&2
exit 0
}
# Sanitize message: strip any passwords, tokens, keys
SAFE_MSG="$(printf '%s' "$MESSAGE" | sed 's/password=[^ ]*/password=***/gi; s/token=[^ ]*/token=***/gi; s/secret=[^ ]*/secret=***/gi')"
build_payload() {
local event="$1"
local msg="$2"
local ts="$3"
local version="${PRIVATE_VERSION:-unknown}"
case "$WEBHOOK_TYPE" in
dingtalk)
printf '{"msgtype":"markdown","markdown":{"title":"[%s] XuqmGroup Private","text":"**[%s]** %s\n\n版本: %s\n时间: %s"}}' \
"$event" "$event" "$msg" "$version" "$ts"
;;
feishu)
printf '{"msg_type":"text","content":{"text":"[%s] %s\n版本: %s\n时间: %s"}}' \
"$event" "$msg" "$version" "$ts"
;;
*)
# WeCom (企业微信)
printf '{"msgtype":"markdown","markdown":{"content":"**[%s]** %s\n>版本: `%s`\n>时间: %s"}}' \
"$event" "$msg" "$version" "$ts"
;;
esac
}
PAYLOAD="$(build_payload "$EVENT" "$SAFE_MSG" "$TIMESTAMP")"
if command -v curl >/dev/null 2>&1; then
HTTP_CODE="$(curl -s -o /dev/null -w '%{http_code}' \
-X POST -H 'Content-Type: application/json' \
-d "$PAYLOAD" \
--max-time 10 \
"$WEBHOOK_URL" 2>/dev/null || echo '000')"
if [ "$HTTP_CODE" = "200" ]; then
audit "alert" "SENT" "event=$EVENT"
else
audit "alert" "FAILED" "event=$EVENT http=$HTTP_CODE"
fi
else
audit "alert" "SKIPPED" "curl not available event=$EVENT"
fi
# Consecutive failure tracking for auto-alert on healthcheck failures
FAIL_COUNT_FILE="$ROOT_DIR/.deploy-state/healthcheck-fail-count.txt"
if [ "$EVENT" = "HEALTHCHECK_FAILED" ]; then
COUNT="$(cat "$FAIL_COUNT_FILE" 2>/dev/null || echo 0)"
COUNT=$((COUNT + 1))
printf '%s\n' "$COUNT" > "$FAIL_COUNT_FILE"
else
printf '0\n' > "$FAIL_COUNT_FILE"
fi