237 lines
9.2 KiB
Python
237 lines
9.2 KiB
Python
#!/usr/bin/env python3
|
|
"""Push ExposedGays to Gitea, create Coolify app, apply Supabase schema."""
|
|
import json
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
import urllib.request
|
|
import urllib.error
|
|
|
|
try:
|
|
import paramiko
|
|
except ImportError:
|
|
subprocess.check_call([sys.executable, "-m", "pip", "install", "paramiko", "-q"])
|
|
import paramiko
|
|
|
|
HOST = "10.10.0.10"
|
|
SUPA_HOST = "10.10.0.11"
|
|
USER = "localadministrator"
|
|
PASS = os.environ.get("COOLIFY_SSH_PASS", "Bbt9115xty9176!")
|
|
GITEA_TOKEN = os.environ.get("GITEA_TOKEN", "dbf033cee4b0e3be5699f374a15f3fa240e2896a")
|
|
COOLIFY_TOKEN = os.environ.get("COOLIFY_TOKEN", "1|zALRdpUD3VkejNVlEV5UuRzTeoYVhshZtke5VkCNa6e9262d")
|
|
REPO_NAME = "exposedgays"
|
|
PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
GIT_AUTH = f"https://{USER}:{GITEA_TOKEN}@gitea.onsethost.com/localadministrator/{REPO_NAME}.git"
|
|
|
|
|
|
def ssh_run(host, cmd, timeout=120):
|
|
c = paramiko.SSHClient()
|
|
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
|
c.connect(host, username=USER, password=PASS, timeout=20, allow_agent=False, look_for_keys=False)
|
|
print(f"[{host}] $ {cmd[:120]}")
|
|
_, o, e = c.exec_command(cmd, timeout=timeout)
|
|
code = o.channel.recv_exit_status()
|
|
out = (o.read() + e.read()).decode(errors="replace")
|
|
if out.strip():
|
|
print(out[-8000:])
|
|
print(f"exit={code}")
|
|
c.close()
|
|
return code, out
|
|
|
|
|
|
def gitea_api(method, path, data=None):
|
|
url = f"https://gitea.onsethost.com/api/v1{path}"
|
|
body = json.dumps(data).encode() if data else None
|
|
req = urllib.request.Request(url, data=body, method=method)
|
|
req.add_header("Authorization", f"token {GITEA_TOKEN}")
|
|
req.add_header("Content-Type", "application/json")
|
|
try:
|
|
with urllib.request.urlopen(req, timeout=30) as resp:
|
|
return resp.status, json.loads(resp.read().decode())
|
|
except urllib.error.HTTPError as ex:
|
|
body = ex.read().decode()
|
|
try:
|
|
return ex.code, json.loads(body)
|
|
except Exception:
|
|
return ex.code, {"message": body}
|
|
|
|
|
|
def coolify_api(method, path, data=None):
|
|
url = f"https://coolify.onsethost.com/api/v1{path}"
|
|
body = json.dumps(data).encode() if data else None
|
|
req = urllib.request.Request(url, data=body, method=method)
|
|
req.add_header("Authorization", f"Bearer {COOLIFY_TOKEN}")
|
|
req.add_header("Content-Type", "application/json")
|
|
try:
|
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
|
raw = resp.read().decode()
|
|
return resp.status, json.loads(raw) if raw else {}
|
|
except urllib.error.HTTPError as ex:
|
|
body = ex.read().decode()
|
|
try:
|
|
return ex.code, json.loads(body)
|
|
except Exception:
|
|
return ex.code, {"message": body}
|
|
|
|
|
|
def push_gitea():
|
|
print("\n=== 1. Create Gitea repo (if missing) ===")
|
|
code, resp = gitea_api("POST", "/user/repos", {
|
|
"name": REPO_NAME,
|
|
"private": True,
|
|
"auto_init": False,
|
|
"description": "ExposedGays — free gay cruising + shop",
|
|
})
|
|
if code in (201, 409):
|
|
print(f"Repo ready (HTTP {code})")
|
|
else:
|
|
print(f"Repo create: {code} {resp}")
|
|
|
|
print("\n=== 2. Git commit + push from COOLIFY_01 ===")
|
|
schema_sql = open(os.path.join(PROJECT_ROOT, "supabase", "schema.sql"), encoding="utf-8").read()
|
|
functions_sql = open(os.path.join(PROJECT_ROOT, "supabase", "functions.sql"), encoding="utf-8").read()
|
|
|
|
# Tar project and upload via SSH
|
|
c = paramiko.SSHClient()
|
|
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
|
c.connect(HOST, username=USER, password=PASS, timeout=20, allow_agent=False, look_for_keys=False)
|
|
sftp = c.open_sftp()
|
|
|
|
import tarfile
|
|
import io
|
|
buf = io.BytesIO()
|
|
with tarfile.open(fileobj=buf, mode="w:gz") as tar:
|
|
for root, dirs, files in os.walk(PROJECT_ROOT):
|
|
dirs[:] = [d for d in dirs if d not in (".next", "node_modules", ".git")]
|
|
for f in files:
|
|
if f in (".env.local",):
|
|
continue
|
|
full = os.path.join(root, f)
|
|
arc = os.path.relpath(full, PROJECT_ROOT)
|
|
tar.add(full, arcname=arc)
|
|
buf.seek(0)
|
|
sftp.putfo(buf, "/tmp/exposedgays.tar.gz")
|
|
sftp.close()
|
|
|
|
cmds = [
|
|
"rm -rf /tmp/exposedgays && mkdir -p /tmp/exposedgays && tar -xzf /tmp/exposedgays.tar.gz -C /tmp/exposedgays",
|
|
f"cd /tmp/exposedgays && git init -b main && git config user.email 'ryan.salazar@justtworoommates.com' && git config user.name 'Ryan Salazar'",
|
|
"cd /tmp/exposedgays && git add -A && git commit -m 'ExposedGays: map, shop, auth, Supabase schema' || true",
|
|
f"cd /tmp/exposedgays && git remote remove origin 2>/dev/null; git remote add origin {GIT_AUTH}",
|
|
f"cd /tmp/exposedgays && git push -u origin main --force",
|
|
]
|
|
for cmd in cmds:
|
|
_, o, e = c.exec_command(cmd, timeout=180)
|
|
code = o.channel.recv_exit_status()
|
|
out = (o.read() + e.read()).decode(errors="replace")
|
|
print(out[-3000:])
|
|
print(f"exit={code}")
|
|
c.close()
|
|
return GIT_AUTH.replace(GITEA_TOKEN, "***")
|
|
|
|
|
|
def apply_supabase_schema():
|
|
print("\n=== 3. Apply Supabase schema on SUPABASE_01 ===")
|
|
schema_path = os.path.join(PROJECT_ROOT, "supabase", "schema.sql")
|
|
func_path = os.path.join(PROJECT_ROOT, "supabase", "functions.sql")
|
|
|
|
c = paramiko.SSHClient()
|
|
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
|
c.connect(SUPA_HOST, username=USER, password=PASS, timeout=20, allow_agent=False, look_for_keys=False)
|
|
sftp = c.open_sftp()
|
|
sftp.put(schema_path, "/tmp/eg_schema.sql")
|
|
sftp.put(func_path, "/tmp/eg_functions.sql")
|
|
sftp.close()
|
|
|
|
cmd = (
|
|
"docker exec -i supabase-db psql -U postgres -d postgres "
|
|
"-f /dev/stdin < /tmp/eg_schema.sql 2>&1; "
|
|
"docker exec -i supabase-db psql -U postgres -d postgres "
|
|
"-f /dev/stdin < /tmp/eg_functions.sql 2>&1"
|
|
)
|
|
# Copy into container first
|
|
for f in ("eg_schema.sql", "eg_functions.sql"):
|
|
c.exec_command(f"docker cp /tmp/{f} supabase-db:/tmp/{f}")
|
|
import time
|
|
time.sleep(2)
|
|
_, o, e = c.exec_command(
|
|
"docker exec supabase-db psql -U postgres -d postgres -f /tmp/eg_schema.sql 2>&1; "
|
|
"docker exec supabase-db psql -U postgres -d postgres -f /tmp/eg_functions.sql 2>&1",
|
|
timeout=120,
|
|
)
|
|
out = (o.read() + e.read()).decode(errors="replace")
|
|
print(out[-5000:])
|
|
c.close()
|
|
|
|
|
|
def create_coolify_app(git_url_auth):
|
|
print("\n=== 4. Create Coolify application ===")
|
|
# List projects
|
|
code, projects = coolify_api("GET", "/projects")
|
|
print(f"Projects: {code}")
|
|
project_uuid = None
|
|
if code == 200 and projects:
|
|
items = projects if isinstance(projects, list) else projects.get("data", projects)
|
|
if items:
|
|
project_uuid = items[0].get("uuid") or items[0].get("id")
|
|
print(f"Using project: {project_uuid}")
|
|
|
|
payload = {
|
|
"project_uuid": project_uuid,
|
|
"server_uuid": None,
|
|
"environment_name": "production",
|
|
"git_repository": f"https://gitea.onsethost.com/localadministrator/{REPO_NAME}.git",
|
|
"git_branch": "main",
|
|
"build_pack": "dockerfile",
|
|
"dockerfile_location": "/Dockerfile",
|
|
"ports_exposes": "3000",
|
|
"name": "exposedgays",
|
|
"description": "ExposedGays — free cruising + shop",
|
|
"domains": "https://exposedgays.com,https://www.exposedgays.com",
|
|
"instant_deploy": True,
|
|
}
|
|
|
|
code, resp = coolify_api("POST", "/applications/public", payload)
|
|
print(f"Create app: HTTP {code}")
|
|
print(json.dumps(resp, indent=2)[:3000])
|
|
|
|
app_uuid = resp.get("uuid") if isinstance(resp, dict) else None
|
|
if not app_uuid and isinstance(resp, dict):
|
|
app_uuid = resp.get("id")
|
|
|
|
if app_uuid:
|
|
print(f"\n=== 5. Set env vars on {app_uuid} ===")
|
|
envs = [
|
|
("NEXT_PUBLIC_SUPABASE_URL", "https://supabase.onsethost.com"),
|
|
("NEXT_PUBLIC_SUPABASE_ANON_KEY", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiYW5vbiIsImlzcyI6InN1cGFiYXNlIiwiaWF0IjoxNzc2NzEzOTczLCJleHAiOjIwOTIwNzM5NzN9.oRPm6uJt4Gj-ASOixznas7-IC1pCtlZtEFew-SmY9wo"),
|
|
("NEXT_PUBLIC_APP_URL", "https://exposedgays.com"),
|
|
("NEXT_PUBLIC_DEFAULT_CITY", "Fort Lauderdale"),
|
|
("NEXT_PUBLIC_DEFAULT_LAT", "26.1224"),
|
|
("NEXT_PUBLIC_DEFAULT_LNG", "-80.1373"),
|
|
]
|
|
for key, value in envs:
|
|
c, r = coolify_api("POST", f"/applications/{app_uuid}/envs", {"key": key, "value": value})
|
|
print(f" {key}: HTTP {c}")
|
|
|
|
print("\n=== 6. Trigger deploy ===")
|
|
code, dep = coolify_api("POST", f"/deploy?uuid={app_uuid}&force_rebuild=true")
|
|
print(f"Deploy: HTTP {code} {dep}")
|
|
|
|
return app_uuid
|
|
|
|
|
|
def main():
|
|
git_url = push_gitea()
|
|
try:
|
|
apply_supabase_schema()
|
|
except Exception as ex:
|
|
print(f"Supabase schema warning: {ex}")
|
|
app_uuid = create_coolify_app(git_url)
|
|
print("\n=== DONE ===")
|
|
print(f"Gitea: https://gitea.onsethost.com/localadministrator/{REPO_NAME}")
|
|
print(f"Coolify app: {app_uuid or 'check Coolify UI'}")
|
|
print("Next: add exposedgays.com to Cloudflare tunnel → Coolify container")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main() |