45 lines
3.2 KiB
Python
45 lines
3.2 KiB
Python
import pathlib,subprocess,datetime,shutil,time,urllib.request,urllib.parse,hashlib,json,sqlite3
|
|
base=pathlib.Path('/www/dk_project/dk_app/trilium');release=pathlib.Path('/tmp/trilium-korean-phase9');m=json.loads((release/'manifest.json').read_text());digest=lambda p:hashlib.sha256(p.read_bytes()).hexdigest()
|
|
meta='doc_notes/en/User Guide/!!!meta.json';pending=base/'data/korean-phase9-pending.json'
|
|
assert digest(base/'patched/main.cjs')==m['previousMainSha256']
|
|
assert digest(base/'i18n_ko'/meta)==m['previousMetaSha256']
|
|
assert not pending.exists();assert not (base/'i18n_ko/doc_notes/en/api-ko').exists()
|
|
for rel,h in m['files'].items():assert digest(release/rel)==h,rel
|
|
backup=base/'backups'/('before-korean-phase9-'+datetime.datetime.now().strftime('%Y%m%d-%H%M%S'));backup.mkdir(parents=True,mode=0o700)
|
|
shutil.copy2(base/'patched/main.cjs',backup/'main.cjs');shutil.copy2(base/'i18n_ko'/meta,backup/'meta.json')
|
|
db=sqlite3.connect('file:'+str(base/'data/document.db')+'?mode=ro',uri=True)
|
|
with sqlite3.connect(str(backup/'document.db')) as dest:db.backup(dest)
|
|
db.close()
|
|
for rel in m['files']:
|
|
if rel.startswith('doc_notes/'):
|
|
dest=base/'i18n_ko'/rel;dest.parent.mkdir(parents=True,exist_ok=True);dest.write_bytes((release/rel).read_bytes())
|
|
shutil.copy2(release/'korean-phase9-pending.json',pending)
|
|
(base/'patched/main.cjs').write_bytes((release/'main.cjs').read_bytes())
|
|
try:
|
|
subprocess.run(['docker','restart','trilium'],check=True)
|
|
for i in range(40):
|
|
try:
|
|
with urllib.request.urlopen('http://127.0.0.1:18082/api/health-check',timeout=2) as r:assert r.status==200
|
|
if pending.exists():raise RuntimeError('Migration pending')
|
|
break
|
|
except Exception:
|
|
if i==39:raise
|
|
time.sleep(1)
|
|
checked=0
|
|
for rel,h in m['files'].items():
|
|
if not rel.startswith('doc_notes/'):continue
|
|
with urllib.request.urlopen('http://127.0.0.1:18082/assets/v0.95.0-ko-20260913-r8/'+urllib.parse.quote(rel),timeout=5) as r:assert hashlib.sha256(r.read()).hexdigest()==h,rel
|
|
checked+=1
|
|
for route,needle in [('/etapi/docs/','외부 API 참고 자료'),('/api/docs/','내부 API 참고 자료')]:
|
|
with urllib.request.urlopen('http://127.0.0.1:18082'+route,timeout=5) as r:assert needle in r.read().decode()
|
|
for route,source in [('/etapi/docs/swagger-ui-init.js','etapi.json'),('/api/docs/swagger-ui-init.js','internal.json')]:
|
|
with urllib.request.urlopen('http://127.0.0.1:18082'+route,timeout=5) as r:text=r.read().decode()
|
|
expected=json.loads((release/'doc_notes/en/api-ko'/source).read_text())['info']['description'];assert json.dumps(expected,ensure_ascii=False)[1:-1] in text,route
|
|
db=sqlite3.connect('file:'+str(base/'data/document.db')+'?mode=ro',uri=True)
|
|
for row in json.loads((release/'korean-phase9-pending.json').read_text()):assert db.execute('SELECT value FROM attributes WHERE attributeId=?',(row['attributeId'],)).fetchone()[0]==row['value']
|
|
db.close()
|
|
result={'status':'verified','backup':str(backup),'servedFiles':checked,'swaggerPages':2,'scriptLinks':3,'assetVersion':'v0.95.0-ko-20260913-r8'}
|
|
(base/'i18n_ko/phase9-result.json').write_text(json.dumps(result,indent=2));print(json.dumps(result))
|
|
except Exception:
|
|
print('Verification failed; full backup preserved at '+str(backup));raise
|