mkdocs-auto/script_creator.py
2025-03-30 01:20:08 +01:00

133 lines
4.8 KiB
Python

from flask import Flask, request, jsonify
import os
import subprocess
import base64
import requests
import redis
import shutil
from threading import Lock
from webdav3.client import Client
def safe_download_file(self, remote_path, local_path, progress=None, progress_args=()):
url = self.get_url(remote_path)
response = self.session.get(url, stream=True, headers={"Accept-Encoding": "identity"})
content_length = response.headers.get("Content-Length")
if content_length is None:
print(f"⚠️ Skipping file without content-length: {remote_path}")
return
total = int(content_length)
os.makedirs(os.path.dirname(local_path), exist_ok=True)
with open(local_path, "wb") as f:
for chunk in response.iter_content(chunk_size=1024):
if chunk:
f.write(chunk)
# 🩹 Patch de la méthode originale
Client.download_file = safe_download_file
app = Flask(__name__)
# Environment variables
NEXTCLOUD_URL_DAV = os.getenv("NEXTCLOUD_URL_DAV")
NEXTCLOUD_USER = os.getenv("NEXTCLOUD_USER")
NEXTCLOUD_PASSWORD = os.getenv("NEXTCLOUD_PASSWORD")
NEXTCLOUD_PATH = os.getenv("NEXTCLOUD_PATH")
N8N_WEBHOOK_URL = os.getenv("N8N_WEBHOOK_URL", "https://n8n.n8n.svc.kube.ia86.cc/webhook/7950310f-e526-475a-82d1-63818da79339")
DEBUG = bool(os.getenv("DEBUG", True))
redis_host = os.getenv("REDIS_HOST", "redis.redis.svc.cluster.local")
redis_port = int(os.getenv("REDIS_PORT", 6379))
redis_client = redis.Redis(host=redis_host, port=redis_port, decode_responses=True)
lock_prefix = "lock:mkdocs:"
local_lock = Lock()
def log_debug(msg):
if DEBUG:
print(f"🔍 DEBUG: {msg}", flush=True)
def sync_from_nextcloud(website, tmp_path):
remote_path = f"/{NEXTCLOUD_PATH}/@{website}/"
local_path = tmp_path
if os.path.exists(local_path):
shutil.rmtree(local_path)
os.makedirs(local_path, exist_ok=True)
options = {
'webdav_hostname': NEXTCLOUD_URL_DAV,
'webdav_login': NEXTCLOUD_USER,
'webdav_password': NEXTCLOUD_PASSWORD
}
client = Client(options)
log_debug(f"Starting WebDAV sync from '{remote_path}' to '{local_path}'")
client.download_sync(remote_path=remote_path, local_path=local_path)
log_debug("WebDAV sync completed successfully.")
@app.route("/build", methods=["POST"])
def build_mkdocs():
log_debug("POST request received at /build")
data = request.json
website = data.get("WEBSITE")
error_callback = data.get("ERROR_CALLBACK", N8N_WEBHOOK_URL)
if not website:
log_debug("Error: Missing 'WEBSITE' parameter in request.")
return jsonify({"error": "WEBSITE parameter missing"}), 400
lock_key = f"{lock_prefix}{website}"
log_debug(f"Attempting to acquire Redis lock: {lock_key}a")
try:
lock_acquired = redis_client.set(lock_key, "locked", nx=True, ex=60)
except redis.exceptions.ConnectionError as e:
log_debug(f"Redis connection failed: {e}")
return jsonify({"error": "Redis connection error"}), 500
if not lock_acquired:
log_debug(f"Build already active for website: {website}")
return jsonify({"status": "busy", "message": f"Build already active: {website}"}), 429
tmp_path = f"/tmp/{website}"
compile_path = f"{tmp_path}#compile"
final_path = f"/srv/{website}"
try:
sync_from_nextcloud(website, tmp_path)
src = os.path.join(tmp_path, "mkdocs.yml")
log_debug(f"Checking if mkdocs.yml exists at {src}")
if not os.path.exists(src):
log_debug(f"{src} not found after sync")
return jsonify({"error": f"{src} not found after sync"}), 404
log_debug(f"Running MkDocs build: {src} -> {compile_path}")
cmd = f"mkdocs build --quiet --no-strict --config-file {src} --site-dir {compile_path}"
result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
if result.returncode != 0:
build_error = base64.b64encode(result.stderr.encode()).decode()
json_payload = {"site": website, "error": build_error}
log_debug(f"MkDocs build failed: {result.stderr}")
#requests.post(error_callback, json=json_payload, headers={"Content-Type": "application/json"})
return jsonify({"status": "error", "message": "Build failed", "error": result.stderr}), 500
log_debug(f"Performing differential copy from {compile_path} to {final_path}")
subprocess.run(f"rsync -a --delete {compile_path}/ {final_path}/", shell=True, check=True)
log_debug(f"MkDocs build and sync successful for website: {website}")
return jsonify({"status": "success", "message": "Build successful"}), 200
finally:
redis_client.delete(lock_key)
log_debug(f"Redis lock released for website: {website}")
if __name__ == "__main__":
log_debug("Starting Flask server on 0.0.0.0:80")
app.run(host="0.0.0.0", port=80)