feat: Umami/ntfy 可观测性栈与 WordPress AdSense 部署
This commit is contained in:
197
deploy/observability/sync_and_deploy_ops.py
Normal file
197
deploy/observability/sync_and_deploy_ops.py
Normal file
@@ -0,0 +1,197 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Commit & push dirty repos (local + server) with eric credentials, deploy douyinWEB ops."""
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
import paramiko
|
||||
|
||||
HOST = "107.173.30.245"
|
||||
PASS = "Xiao4669805"
|
||||
GIT_USER = "eric"
|
||||
GIT_PASS = "Xiao4669805"
|
||||
AUTH = f"{GIT_USER}:{GIT_PASS}@"
|
||||
|
||||
DOUYIN = Path(r"C:\Users\admin\Desktop\douyinWEB")
|
||||
NOMADRO = Path(r"C:\project\gitlab-instance-0a899031_nomadro")
|
||||
|
||||
|
||||
def local(cmd: list[str] | str, cwd: Path) -> str:
|
||||
print(f"\n[{cwd.name}] $", cmd if isinstance(cmd, str) else " ".join(cmd))
|
||||
r = subprocess.run(
|
||||
cmd,
|
||||
cwd=str(cwd),
|
||||
shell=isinstance(cmd, str),
|
||||
capture_output=True,
|
||||
text=True,
|
||||
encoding="utf-8",
|
||||
errors="replace",
|
||||
)
|
||||
out = (r.stdout or "") + (r.stderr or "")
|
||||
print(out[-3000:] if len(out) > 3000 else out)
|
||||
if r.returncode != 0:
|
||||
raise RuntimeError(f"cmd failed in {cwd}: {cmd}\n{out}")
|
||||
return out
|
||||
|
||||
|
||||
def ensure_auth_remote(cwd: Path) -> None:
|
||||
url = local(["git", "remote", "get-url", "origin"], cwd).strip()
|
||||
if "gitea.dsx2020.com" in url and AUTH not in url:
|
||||
if url.startswith("https://"):
|
||||
new = url.replace("https://", f"https://{AUTH}", 1)
|
||||
# strip existing userinfo
|
||||
if "@gitea" in url:
|
||||
new = "https://" + AUTH + url.split("@", 1)[1]
|
||||
local(["git", "remote", "set-url", "origin", new], cwd)
|
||||
|
||||
|
||||
def commit_push_local(cwd: Path, paths: list[str], message: str) -> None:
|
||||
ensure_auth_remote(cwd)
|
||||
local(["git", "add", *paths], cwd)
|
||||
st = local(["git", "status", "--porcelain"], cwd)
|
||||
if not st.strip():
|
||||
print(f"[{cwd.name}] nothing to commit")
|
||||
# still try push in case ahead
|
||||
local(["git", "push", "-u", "origin", "HEAD"], cwd)
|
||||
return
|
||||
local(["git", "commit", "-m", message], cwd)
|
||||
local(["git", "push", "-u", "origin", "HEAD"], cwd)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
# 1) Local douyinWEB — ops page
|
||||
commit_push_local(
|
||||
DOUYIN,
|
||||
[
|
||||
"frontend/src/app/ops/page.tsx",
|
||||
"frontend/src/components/Shell.tsx",
|
||||
"frontend/src/app/layout.tsx",
|
||||
"backend/app/ops_panel.py",
|
||||
"backend/app/notify.py",
|
||||
"backend/app/main.py",
|
||||
],
|
||||
"feat(ops): Umami/ntfy/DNS 运维控制台页面与 API",
|
||||
)
|
||||
|
||||
# 2) Local nomadro — observability stack
|
||||
commit_push_local(
|
||||
NOMADRO,
|
||||
[
|
||||
"app/layout.tsx",
|
||||
"components/umami-analytics.tsx",
|
||||
"deploy/Caddyfile",
|
||||
"deploy/README.md",
|
||||
"deploy/caddy-sites",
|
||||
"deploy/umami",
|
||||
"deploy/ntfy",
|
||||
"deploy/observability",
|
||||
"deploy/router",
|
||||
"deploy/wordpress",
|
||||
"deploy/deploy.sh",
|
||||
"deploy/setup-server.sh",
|
||||
],
|
||||
"feat: Umami/ntfy 可观测性栈与 WordPress AdSense 部署",
|
||||
)
|
||||
|
||||
# 3) Server repos: commit layout umami injections + sync + deploy douyin
|
||||
c = paramiko.SSHClient()
|
||||
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
c.connect(HOST, username="root", password=PASS, timeout=30, allow_agent=False, look_for_keys=False)
|
||||
|
||||
def run(cmd: str, timeout: int = 600) -> str:
|
||||
print("\n$ ", cmd[:160])
|
||||
_i, o, e = c.exec_command(cmd, timeout=timeout)
|
||||
out = (o.read() + e.read()).decode("utf-8", errors="replace")
|
||||
print(out[-3500:] if len(out) > 3500 else out)
|
||||
return out
|
||||
|
||||
# Ensure remotes have credentials
|
||||
for repo in ("/opt/douyinWEB", "/opt/tiktokWEB", "/opt/wauto", "/var/www/nomadro.com"):
|
||||
run(
|
||||
f"""
|
||||
cd {repo} || exit 0
|
||||
url=$(git remote get-url origin 2>/dev/null || true)
|
||||
[ -z "$url" ] && exit 0
|
||||
case "$url" in
|
||||
*{AUTH}*) ;;
|
||||
https://*@gitea.dsx2020.com/*)
|
||||
rest=$(echo "$url" | sed 's|https://[^@]*@|https://|')
|
||||
git remote set-url origin "https://{AUTH}${{rest#https://}}"
|
||||
;;
|
||||
https://gitea.dsx2020.com/*)
|
||||
git remote set-url origin "https://{AUTH}${{url#https://}}"
|
||||
;;
|
||||
esac
|
||||
git remote -v | head -2
|
||||
"""
|
||||
)
|
||||
|
||||
# Pull douyin first then apply — better: push already done, pull on server
|
||||
run(
|
||||
"""
|
||||
cd /opt/douyinWEB
|
||||
git fetch origin
|
||||
git stash push -u -m 'pre-ops-deploy' -- frontend/src/app/layout.tsx 2>/dev/null || true
|
||||
git checkout test1
|
||||
git pull --ff-only origin test1
|
||||
""",
|
||||
timeout=120,
|
||||
)
|
||||
|
||||
# Commit other server-only dirty files (tiktok/wauto/nomadro layouts) if still dirty
|
||||
run(
|
||||
r"""
|
||||
commit_if_dirty() {
|
||||
local dir="$1"; local msg="$2"; shift 2
|
||||
cd "$dir" || return 0
|
||||
git add "$@" 2>/dev/null || true
|
||||
if [ -n "$(git status --porcelain -- "$@" 2>/dev/null)" ]; then
|
||||
git -c user.email=ops@nomadro.com -c user.name=ops commit -m "$msg" || true
|
||||
git push origin HEAD || true
|
||||
else
|
||||
echo "$dir: clean for selected paths"
|
||||
fi
|
||||
}
|
||||
commit_if_dirty /opt/tiktokWEB 'chore: inject Umami analytics tracker' frontend/src/app/layout.tsx
|
||||
commit_if_dirty /opt/wauto 'chore: inject Umami analytics tracker' web/app/layout.tsx
|
||||
commit_if_dirty /var/www/nomadro.com 'chore: Umami analytics component' app/layout.tsx components/umami-analytics.tsx
|
||||
"""
|
||||
)
|
||||
|
||||
# Deploy douyinWEB frontend + restart API
|
||||
run(
|
||||
"""
|
||||
cd /opt/douyinWEB/frontend
|
||||
# ensure umami env
|
||||
grep -q '^NEXT_PUBLIC_UMAMI_WEBSITE_ID=' .env.local 2>/dev/null || echo 'NEXT_PUBLIC_UMAMI_WEBSITE_ID=f18d3484-be2e-4344-8882-b80c5b53f9cf' >> .env.local
|
||||
npm run build
|
||||
systemctl restart douyinweb-web
|
||||
systemctl restart douyinweb-api
|
||||
sleep 2
|
||||
systemctl is-active douyinweb-web douyinweb-api
|
||||
curl -fsS -o /dev/null -w 'ops_page:%{http_code}\\n' https://dylive.nomadro.com/ops || true
|
||||
curl -fsS -o /dev/null -w 'ops_api:%{http_code}\\n' -H 'Cookie: ' https://dylive.nomadro.com/api/ops || true
|
||||
""",
|
||||
timeout=600,
|
||||
)
|
||||
|
||||
# Sync nomadro.com from git if needed
|
||||
run(
|
||||
"""
|
||||
cd /var/www/nomadro.com
|
||||
git fetch origin
|
||||
git pull --ff-only origin test || git pull --ff-only || true
|
||||
# copy observability deploy assets already in repo; ensure router files synced if present
|
||||
""",
|
||||
timeout=120,
|
||||
)
|
||||
|
||||
c.close()
|
||||
print("\nALL DONE")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user