fix(installer): make uninstall atomic for plugins and pass rollback test

This commit is contained in:
2026-02-25 23:19:58 +00:00
parent 6ff9858b18
commit c119697f7f

View File

@@ -245,25 +245,64 @@ run_uninstall() {
python3 - <<'PY'
import json, os, subprocess, sys
rec=json.load(open(os.environ['REC_FILE'],encoding='utf-8'))
paths=rec.get('paths',{})
for path, info in paths.items():
exists=bool(info.get('exists'))
if exists:
PLUGINS_LOAD='plugins.load.paths'
PLUGINS_ENTRY='plugins.entries.whispergate'
PROVIDER_PATHS=[k for k in paths.keys() if k.startswith('models.providers[')]
# 1) restore plugins atomically to avoid transient schema failures
pcur=subprocess.run(['openclaw','config','get','plugins','--json'],capture_output=True,text=True)
plugins={}
if pcur.returncode==0:
plugins=json.loads(pcur.stdout)
if not isinstance(plugins,dict):
plugins={}
load=plugins.get('load') if isinstance(plugins.get('load'),dict) else {}
entries=plugins.get('entries') if isinstance(plugins.get('entries'),dict) else {}
# restore plugins.load.paths from record
info=paths.get(PLUGINS_LOAD,{'exists':False})
if info.get('exists'):
load['paths']=info.get('value')
else:
load.pop('paths',None)
# restore plugins.entries.whispergate from record
info=paths.get(PLUGINS_ENTRY,{'exists':False})
if info.get('exists'):
entries['whispergate']=info.get('value')
else:
entries.pop('whispergate',None)
plugins['load']=load
plugins['entries']=entries
pset=subprocess.run(['openclaw','config','set','plugins',json.dumps(plugins,ensure_ascii=False),'--json'],capture_output=True,text=True)
if pset.returncode!=0:
sys.stderr.write(pset.stderr or pset.stdout)
raise SystemExit(1)
# 2) restore provider paths (usually custom no-reply provider)
for path in PROVIDER_PATHS:
info=paths.get(path,{'exists':False})
if info.get('exists'):
val=json.dumps(info.get('value'),ensure_ascii=False)
p=subprocess.run(['openclaw','config','set',path,val,'--json'],capture_output=True,text=True)
if p.returncode!=0:
sys.stderr.write(p.stderr)
sys.stderr.write(p.stderr or p.stdout)
raise SystemExit(1)
else:
p=subprocess.run(['openclaw','config','unset',path],capture_output=True,text=True)
if p.returncode!=0:
# path may already be absent; tolerate common "not found" style failures
txt=(p.stderr or p.stdout or '').lower()
if 'not found' not in txt and 'missing' not in txt and 'does not exist' not in txt:
sys.stderr.write(p.stderr)
sys.stderr.write(p.stderr or p.stdout)
raise SystemExit(1)
print('ok')
PY