feat: with rclone -PREVIOUS IS GOOD
This commit is contained in:
parent
015fcde8ee
commit
85319bebee
@ -2,31 +2,8 @@ from flask import Flask, request, jsonify
|
|||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import base64
|
import base64
|
||||||
import requests
|
|
||||||
import redis
|
import redis
|
||||||
import shutil
|
|
||||||
from threading import Lock
|
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__)
|
app = Flask(__name__)
|
||||||
|
|
||||||
@ -49,25 +26,37 @@ def log_debug(msg):
|
|||||||
if DEBUG:
|
if DEBUG:
|
||||||
print(f"🔍 DEBUG: {msg}", flush=True)
|
print(f"🔍 DEBUG: {msg}", flush=True)
|
||||||
|
|
||||||
def sync_from_nextcloud(website, tmp_path):
|
def write_rclone_config():
|
||||||
remote_path = f"/{NEXTCLOUD_PATH}/@{website}/"
|
"""Write rclone config file dynamically"""
|
||||||
local_path = tmp_path
|
config_dir = "/tmp/rclone"
|
||||||
|
os.makedirs(config_dir, exist_ok=True)
|
||||||
|
config_path = os.path.join(config_dir, "rclone.conf")
|
||||||
|
|
||||||
if os.path.exists(local_path):
|
with open(config_path, "w") as f:
|
||||||
shutil.rmtree(local_path)
|
f.write(f"""[nextcloud]
|
||||||
os.makedirs(local_path, exist_ok=True)
|
type = webdav
|
||||||
|
url = {NEXTCLOUD_URL_DAV}
|
||||||
|
vendor = nextcloud
|
||||||
|
user = {NEXTCLOUD_USER}
|
||||||
|
pass = {NEXTCLOUD_PASSWORD}""")
|
||||||
|
|
||||||
options = {
|
return config_path
|
||||||
'webdav_hostname': NEXTCLOUD_URL_DAV,
|
|
||||||
'webdav_login': NEXTCLOUD_USER,
|
|
||||||
'webdav_password': NEXTCLOUD_PASSWORD
|
|
||||||
}
|
|
||||||
|
|
||||||
client = Client(options)
|
def mount_nextcloud(website, mount_path="/mnt"):
|
||||||
|
config_file = write_rclone_config()
|
||||||
|
remote_path = f"nextcloud:{NEXTCLOUD_PATH}/@{website}"
|
||||||
|
|
||||||
log_debug(f"Starting WebDAV sync from '{remote_path}' to '{local_path}'")
|
log_debug(f"Mounting {remote_path} to {mount_path}")
|
||||||
client.download_sync(remote_path=remote_path, local_path=local_path)
|
os.makedirs(mount_path, exist_ok=True)
|
||||||
log_debug("WebDAV sync completed successfully.")
|
|
||||||
|
# Try to unmount first in case of stale mount
|
||||||
|
subprocess.run(f"fusermount -u {mount_path}", shell=True, stderr=subprocess.DEVNULL)
|
||||||
|
|
||||||
|
cmd = f"rclone --config {config_file} mount {remote_path} {mount_path} --vfs-cache-mode full --daemon"
|
||||||
|
result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
|
||||||
|
|
||||||
|
if result.returncode != 0:
|
||||||
|
raise RuntimeError(f"Failed to mount: {result.stderr}")
|
||||||
|
|
||||||
@app.route("/build", methods=["POST"])
|
@app.route("/build", methods=["POST"])
|
||||||
def build_mkdocs():
|
def build_mkdocs():
|
||||||
@ -81,7 +70,7 @@ def build_mkdocs():
|
|||||||
return jsonify({"error": "WEBSITE parameter missing"}), 400
|
return jsonify({"error": "WEBSITE parameter missing"}), 400
|
||||||
|
|
||||||
lock_key = f"{lock_prefix}{website}"
|
lock_key = f"{lock_prefix}{website}"
|
||||||
log_debug(f"Attempting to acquire Redis lock: {lock_key}a")
|
log_debug(f"Attempting to acquire Redis lock: {lock_key}")
|
||||||
try:
|
try:
|
||||||
lock_acquired = redis_client.set(lock_key, "locked", nx=True, ex=60)
|
lock_acquired = redis_client.set(lock_key, "locked", nx=True, ex=60)
|
||||||
except redis.exceptions.ConnectionError as e:
|
except redis.exceptions.ConnectionError as e:
|
||||||
@ -92,19 +81,18 @@ def build_mkdocs():
|
|||||||
log_debug(f"Build already active for website: {website}")
|
log_debug(f"Build already active for website: {website}")
|
||||||
return jsonify({"status": "busy", "message": f"Build already active: {website}"}), 429
|
return jsonify({"status": "busy", "message": f"Build already active: {website}"}), 429
|
||||||
|
|
||||||
tmp_path = f"/tmp/{website}"
|
mount_path = "/mnt"
|
||||||
compile_path = f"{tmp_path}#compile"
|
compile_path = f"/tmp/{website}#compile"
|
||||||
final_path = f"/srv/{website}"
|
final_path = f"/srv/{website}"
|
||||||
|
src = os.path.join(mount_path, "mkdocs.yml")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
sync_from_nextcloud(website, tmp_path)
|
mount_nextcloud(website, mount_path)
|
||||||
|
|
||||||
src = os.path.join(tmp_path, "mkdocs.yml")
|
|
||||||
|
|
||||||
log_debug(f"Checking if mkdocs.yml exists at {src}")
|
log_debug(f"Checking if mkdocs.yml exists at {src}")
|
||||||
if not os.path.exists(src):
|
if not os.path.exists(src):
|
||||||
log_debug(f"{src} not found after sync")
|
log_debug(f"{src} not found after mount")
|
||||||
return jsonify({"error": f"{src} not found after sync"}), 404
|
return jsonify({"error": f"{src} not found after mount"}), 404
|
||||||
|
|
||||||
log_debug(f"Running MkDocs build: {src} -> {compile_path}")
|
log_debug(f"Running MkDocs build: {src} -> {compile_path}")
|
||||||
cmd = f"mkdocs build --quiet --no-strict --config-file {src} --site-dir {compile_path}"
|
cmd = f"mkdocs build --quiet --no-strict --config-file {src} --site-dir {compile_path}"
|
||||||
@ -114,7 +102,7 @@ def build_mkdocs():
|
|||||||
build_error = base64.b64encode(result.stderr.encode()).decode()
|
build_error = base64.b64encode(result.stderr.encode()).decode()
|
||||||
json_payload = {"site": website, "error": build_error}
|
json_payload = {"site": website, "error": build_error}
|
||||||
log_debug(f"MkDocs build failed: {result.stderr}")
|
log_debug(f"MkDocs build failed: {result.stderr}")
|
||||||
#requests.post(error_callback, json=json_payload, headers={"Content-Type": "application/json"})
|
# requests.post(error_callback, json=json_payload, headers={"Content-Type": "application/json"})
|
||||||
return jsonify({"status": "error", "message": "Build failed", "error": result.stderr}), 500
|
return jsonify({"status": "error", "message": "Build failed", "error": result.stderr}), 500
|
||||||
|
|
||||||
log_debug(f"Performing differential copy from {compile_path} to {final_path}")
|
log_debug(f"Performing differential copy from {compile_path} to {final_path}")
|
||||||
@ -125,7 +113,8 @@ def build_mkdocs():
|
|||||||
|
|
||||||
finally:
|
finally:
|
||||||
redis_client.delete(lock_key)
|
redis_client.delete(lock_key)
|
||||||
log_debug(f"Redis lock released for website: {website}")
|
subprocess.run(f"fusermount -u {mount_path}", shell=True, stderr=subprocess.DEVNULL)
|
||||||
|
log_debug(f"Redis lock released and mount cleaned for website: {website}")
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
log_debug("Starting Flask server on 0.0.0.0:80")
|
log_debug("Starting Flask server on 0.0.0.0:80")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user