Apollo Beach on its own: a standalone panel to send them
- tools/standalone.py builds dist/<Name> Status Panel.zip: program, install.command, READ ME FIRST.txt - setup --standalone: campuses.json standalone, tells nobody, no hub, no NA key - Standalone backs itself up nightly to ~/Documents/Status Panel Backups/<id> - upgrade-companion --from <.dmg/.zip from bitfocus.io> (no NA needed) - Only the hub lists campuses or shows other campuses' install lines Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+53
-9
@@ -153,7 +153,7 @@ def wait_applied(applier, limit=240):
|
||||
return applier.status or {}
|
||||
|
||||
|
||||
def companion_version_problem(cfg):
|
||||
def companion_version_problem(cfg, standalone=False):
|
||||
"""None when this Companion can take the panel (5.x), else what to tell the person."""
|
||||
try:
|
||||
discover.companion_get(cfg, "/api/connections", 5)
|
||||
@@ -162,6 +162,11 @@ def companion_version_problem(cfg):
|
||||
pass
|
||||
try:
|
||||
discover.companion_get(cfg, "/socket.io/?EIO=4&transport=polling", 5)
|
||||
if standalone:
|
||||
return ("This Companion is older than version 5. The panel needs Companion 5.0.7: download it for Mac from\n"
|
||||
" https://bitfocus.io/companion (5.0.7, the .dmg), then on this Mac run\n"
|
||||
" cd \"$HOME/Library/Application Support/status-panel\" && /usr/bin/python3 -m settings.campus upgrade-companion --from ~/Downloads/<the .dmg>\n"
|
||||
"(its settings come along; the old version stays installed), then run the installer again.")
|
||||
return ("This Companion is older than version 5 (Woonsocket ran 4.0.3). The panel needs 5.0.7, as North "
|
||||
"Attleboro runs. Upgrade it from NA's copy (its settings come along; the old version stays installed):\n"
|
||||
" cd \"$HOME/Library/Application Support/status-panel\" && /usr/bin/python3 -m settings.campus upgrade-companion\n"
|
||||
@@ -170,12 +175,18 @@ def companion_version_problem(cfg):
|
||||
return "Companion does not answer on port 8000: open Companion (and its HTTP API, Settings > Protocols), then paste the line again."
|
||||
|
||||
|
||||
def setup(data_dir, cid, name=None, say=print, home=None):
|
||||
"""The first setup of a campus (or, when it is set up already, a look for what is new)."""
|
||||
def setup(data_dir, cid, name=None, say=print, home=None, standalone=False):
|
||||
"""The first setup of a campus (or, when it is set up already, a look for what is new).
|
||||
Standalone: it reports to nobody and nobody else sees it (Apollo Beach runs its own)."""
|
||||
from settings import server, campuses
|
||||
if home: # where it was installed from: the campus list lives there
|
||||
if home or standalone: # where it was installed from: the campus list lives there
|
||||
data = campuses.load(data_dir)
|
||||
data["home"] = home
|
||||
if standalone:
|
||||
data.pop("home", None)
|
||||
data["standalone"] = True
|
||||
else:
|
||||
data["home"] = home
|
||||
data.pop("standalone", None)
|
||||
campuses.save(data_dir, data)
|
||||
site = server.Site(data_dir)
|
||||
cfg = site.load()
|
||||
@@ -183,7 +194,7 @@ def setup(data_dir, cid, name=None, say=print, home=None):
|
||||
say("%s is set up already: looking for what is new." % (cfg.get("site") or {}).get("name", "This campus"))
|
||||
return look_and_add(site, say=say, force=True)
|
||||
name = name or CAMPUSES.get(cid) or cid.upper()
|
||||
problem = companion_version_problem(cfg)
|
||||
problem = companion_version_problem(cfg, standalone)
|
||||
if problem:
|
||||
raise RuntimeError(problem)
|
||||
for line in companion_prepare(cfg):
|
||||
@@ -271,7 +282,7 @@ def clear_old_page(cfg, page):
|
||||
return "cleared"
|
||||
|
||||
|
||||
def upgrade_companion(base, say=print):
|
||||
def upgrade_companion(base, say=print, source=None):
|
||||
"""Companion 5.0.7 from `base` (North Attleboro's settings page), as Woonsocket was upgraded on 2026-10-20:
|
||||
the running Companion is quit, the newest settings folder is copied for 5.0 (and marked newest, or the
|
||||
launcher stops on "Config version mismatch"), 5.0.7 is installed beside the old one and started."""
|
||||
@@ -281,6 +292,8 @@ def upgrade_companion(base, say=print):
|
||||
import urllib.request
|
||||
root = os.path.expanduser("~/Library/Application Support/companion")
|
||||
app = "/Applications/Companion 5.0.7.app"
|
||||
if not os.path.exists(app) and source: # standalone: the .dmg (or .zip) downloaded from bitfocus.io
|
||||
install_companion_from(source, app, say)
|
||||
if not os.path.exists(app):
|
||||
say("Downloading Companion 5.0.7 from %s ..." % base)
|
||||
tmp = "/tmp/companion-5.0.7.zip"
|
||||
@@ -316,6 +329,35 @@ def upgrade_companion(base, say=print):
|
||||
raise RuntimeError("Companion 5.0.7 did not start within 90 s: look at its window on this Mac")
|
||||
|
||||
|
||||
def install_companion_from(source, app, say=print):
|
||||
"""Companion copied from a downloaded .dmg or .zip to `app` (beside any older one)."""
|
||||
import shutil
|
||||
import subprocess
|
||||
import tempfile
|
||||
source = os.path.expanduser(source)
|
||||
tmp = tempfile.mkdtemp(prefix="companion-")
|
||||
try:
|
||||
if source.lower().endswith(".dmg"):
|
||||
mnt = os.path.join(tmp, "mnt")
|
||||
subprocess.run(["/usr/bin/hdiutil", "attach", "-nobrowse", "-readonly", "-mountpoint", mnt, source], check=True, capture_output=True)
|
||||
try:
|
||||
found = [n for n in os.listdir(mnt) if n.startswith("Companion") and n.endswith(".app")]
|
||||
if not found:
|
||||
raise RuntimeError("no Companion app inside %s" % source)
|
||||
subprocess.run(["/usr/bin/ditto", os.path.join(mnt, found[0]), app], check=True)
|
||||
finally:
|
||||
subprocess.run(["/usr/bin/hdiutil", "detach", mnt], capture_output=True)
|
||||
else:
|
||||
subprocess.run(["/usr/bin/ditto", "-x", "-k", source, tmp], check=True)
|
||||
found = [n for n in os.listdir(tmp) if n.startswith("Companion") and n.endswith(".app")]
|
||||
if not found:
|
||||
raise RuntimeError("no Companion app inside %s" % source)
|
||||
subprocess.run(["/usr/bin/ditto", os.path.join(tmp, found[0]), app], check=True)
|
||||
say("Companion installed as %s" % app)
|
||||
finally:
|
||||
shutil.rmtree(tmp, ignore_errors=True)
|
||||
|
||||
|
||||
def summary(inv):
|
||||
known = set(autoconf.COMPANION)
|
||||
return {"connections": len(inv.get("connections") or []),
|
||||
@@ -564,13 +606,15 @@ def main(argv=None):
|
||||
ap.add_argument("--data-dir", default=PARENT)
|
||||
ap.add_argument("--home", help="the settings page this campus was installed from (the campus list lives there)")
|
||||
ap.add_argument("--pages", help="rebuild onto these Status,Restart pages (19,20 on every campus)")
|
||||
ap.add_argument("--standalone", action="store_true", help="a campus that runs on its own: reports to no other campus")
|
||||
ap.add_argument("--from", dest="source", help="upgrade-companion: a Companion .dmg or .zip downloaded from bitfocus.io")
|
||||
a = ap.parse_args(argv)
|
||||
if a.what == "setup":
|
||||
setup(a.data_dir, a.id, a.name, home=a.home)
|
||||
setup(a.data_dir, a.id, a.name, home=a.home, standalone=a.standalone)
|
||||
elif a.what == "rebuild":
|
||||
rebuild(a.data_dir, pages=tuple(int(p) for p in a.pages.split(",")) if a.pages else None)
|
||||
elif a.what == "upgrade-companion":
|
||||
upgrade_companion(a.home or (load_campuses_home(a.data_dir) or "http://10.1.1.1:8020"))
|
||||
upgrade_companion(a.home or (load_campuses_home(a.data_dir) or "http://10.1.1.1:8020"), source=a.source)
|
||||
elif a.what == "look":
|
||||
cfg = sp.load_config(os.path.join(a.data_dir, "config.json"))
|
||||
inv = discover.look(cfg, a.data_dir)
|
||||
|
||||
Reference in New Issue
Block a user