SPB Git
3.7 KB · 90 lines python
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 + tunnel ngrok."""24    from .manifest import render25    apps = []26    for p in m["processes"]:27        if p.get("manager", "pm2") != "pm2":28            continue29        a = {30            "name": p["name"],31            "script": _home(render(p["script"], ctx), ctx),32            "cwd": _home(render(p.get("cwd") or m["dir"], ctx), ctx),33            "exec_mode": "fork",34            "instances": 1,35            "autorestart": p.get("autorestart", True),36            "merge_logs": True,37            "time": True,38            "env": render(p.get("env") or {}, ctx),39        }40        if p.get("args"):41            args = p["args"]42            a["args"] = " ".join(shlex.quote(str(x)) for x in render(args, ctx)) if isinstance(args, list) else render(args, ctx)43        interp = p.get("interpreter")44        if interp and interp not in ("none", "N/A"):45            a["interpreter"] = render(interp, ctx)46        elif interp in ("none",) or (p["script"].endswith((".sh", ".mjs", ".js", ".py", ".cjs")) is False):47            a["interpreter"] = "none"48        if p.get("cron_restart"):49            a["cron_restart"] = p["cron_restart"]50        if p.get("max_memory_restart"):51            a["max_memory_restart"] = _mem(p["max_memory_restart"])52        if p.get("restart_delay"):53            a["restart_delay"] = p["restart_delay"]54        if p.get("node_args"):55            a["node_args"] = p["node_args"]56        apps.append(a)57    if m.get("ngrok"):58        n = m["ngrok"]59        args = ["http", "--url=%s" % n["url"], str(n["port"]), "--log=stdout"] + list(n.get("extra_args") or [])60        apps.append({61            "name": n["name"], "script": n.get("binary") or "/opt/homebrew/bin/ngrok", "args": " ".join(args),62            "interpreter": "none", "cwd": _home(render(m["dir"], ctx), ctx), "exec_mode": "fork", "autorestart": True,63            "restart_delay": 5000, "merge_logs": True, "time": True,64        })65    head = "// généré par maclustr-dispatch — ne pas éditer à la main (app: %s, nœud: %s)\n" % (m["app"], ctx.get("NODE"))66    return head + "module.exports = { apps: %s };\n" % json.dumps(apps, indent=2, ensure_ascii=False)676869def plist(item, ctx):70    from .manifest import render71    d = {72        "Label": item["label"],73        "ProgramArguments": render(item["program_arguments"], ctx),74        "RunAtLoad": item.get("run_at_load", True),75        "KeepAlive": item.get("keep_alive", True),76        "StandardOutPath": render(item.get("stdout") or "{{HOME}}/Library/Logs/%s.log" % item["label"], ctx),77        "StandardErrorPath": render(item.get("stderr") or "{{HOME}}/Library/Logs/%s.err.log" % item["label"], ctx),78    }79    if item.get("working_directory"):80        d["WorkingDirectory"] = _home(render(item["working_directory"], ctx), ctx)81    env = dict(item.get("env") or {})82    env.setdefault("HOME", ctx["HOME"])83    env.setdefault("PATH", "/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin")84    d["EnvironmentVariables"] = render(env, ctx)85    if item.get("start_interval"):86        d["StartInterval"] = int(item["start_interval"])87    if item.get("throttle_interval"):88        d["ThrottleInterval"] = int(item["throttle_interval"])89    return plistlib.dumps(d).decode()90
Files · 29a50362078452d2dd01b6b79868199cb58a3d0f
Menu

Theme