SPB Git forge
29commits 1branches 0releases
684.0 KBsize
maindefault branch
2 days agolast push
Python 95.8% Shell 4.2%
3.3 KB · 83 lines python
Raw Blame History
1"""Génération des fichiers de lancement : ecosystem PM2 (.cjs) et plists launchd."""2import json3import plistlib4import shlex567def _mem(v):8    if not v:9        return None10    if isinstance(v, str):11        return v12    return "%dM" % (int(v) // (1024 * 1024))131415def _home(path, ctx):16    """PM2/launchd n'expandent pas « ~ » : chemin absolu obligatoire."""17    if isinstance(path, str) and path.startswith("~"):18        return ctx["HOME"] + path[1:]19    return path202122def ecosystem(m, ctx):23    """Retourne le contenu JS d'un ecosystem.config.cjs pour les processus PM2 (l'exposition publique est une route24    Caddy sur la passerelle du MacLustr Tunnel, plus aucun processus ngrok local)."""25    from .manifest import render26    apps = []27    for p in m["processes"]:28        if p.get("manager", "pm2") != "pm2":29            continue30        a = {31            "name": p["name"],32            "script": _home(render(p["script"], ctx), ctx),33            "cwd": _home(render(p.get("cwd") or m["dir"], ctx), ctx),34            "exec_mode": "fork",35            "instances": 1,36            "autorestart": p.get("autorestart", True),37            "merge_logs": True,38            "time": True,39            "env": render(p.get("env") or {}, ctx),40        }41        if p.get("args"):42            args = p["args"]43            a["args"] = " ".join(shlex.quote(str(x)) for x in render(args, ctx)) if isinstance(args, list) else render(args, ctx)44        interp = p.get("interpreter")45        if interp and interp not in ("none", "N/A"):46            a["interpreter"] = render(interp, ctx)47        elif interp in ("none",) or (p["script"].endswith((".sh", ".mjs", ".js", ".py", ".cjs")) is False):48            a["interpreter"] = "none"49        if p.get("cron_restart"):50            a["cron_restart"] = p["cron_restart"]51        if p.get("max_memory_restart"):52            a["max_memory_restart"] = _mem(p["max_memory_restart"])53        if p.get("restart_delay"):54            a["restart_delay"] = p["restart_delay"]55        if p.get("node_args"):56            a["node_args"] = p["node_args"]57        apps.append(a)58    head = "// généré par maclustr-dispatch — ne pas éditer à la main (app: %s, nœud: %s)\n" % (m["app"], ctx.get("NODE"))59    return head + "module.exports = { apps: %s };\n" % json.dumps(apps, indent=2, ensure_ascii=False)606162def plist(item, ctx):63    from .manifest import render64    d = {65        "Label": item["label"],66        "ProgramArguments": render(item["program_arguments"], ctx),67        "RunAtLoad": item.get("run_at_load", True),68        "KeepAlive": item.get("keep_alive", True),69        "StandardOutPath": render(item.get("stdout") or "{{HOME}}/Library/Logs/%s.log" % item["label"], ctx),70        "StandardErrorPath": render(item.get("stderr") or "{{HOME}}/Library/Logs/%s.err.log" % item["label"], ctx),71    }72    if item.get("working_directory"):73        d["WorkingDirectory"] = _home(render(item["working_directory"], ctx), ctx)74    env = dict(item.get("env") or {})75    env.setdefault("HOME", ctx["HOME"])76    env.setdefault("PATH", "/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin")77    d["EnvironmentVariables"] = render(env, ctx)78    if item.get("start_interval"):79        d["StartInterval"] = int(item["start_interval"])80    if item.get("throttle_interval"):81        d["ThrottleInterval"] = int(item["throttle_interval"])82    return plistlib.dumps(d).decode()83