Files

28 lines
2.4 KiB
Python

import pathlib,subprocess,json,urllib.request,time,sqlite3,hashlib,os
root=pathlib.Path('/tmp/trilium-release-test-20260913-r1');assert root.resolve()==root
env={**os.environ,'COMPOSE_PROJECT_NAME':'trilium-ko-release-test','TRILIUM_KO_IMAGE':'trilium-korean:2.0.0-test','TRILIUM_KO_PORT':'19092','TRILIUM_KO_BIND':'127.0.0.1','TRILIUM_KO_DATA_DIR':'./data-r2'}
dockerfile=root/'Dockerfile';original=dockerfile.read_bytes();old=subprocess.check_output(['docker','inspect','--format','{{.Image}}','trilium-ko-release-test-trilium-1'],text=True).strip()
try:
dockerfile.write_bytes(original+b'\nCMD ["/bin/sh", "-c", "exit 42"]\n')
with open(root/'rollback-test.log','w') as log:r=subprocess.run(['bash','install.sh'],cwd=root,env=env,stdout=log,stderr=subprocess.STDOUT,timeout=240)
assert r.returncode!=0,'Bad image unexpectedly succeeded'
current=subprocess.check_output(['docker','inspect','--format','{{.Image}}','trilium-ko-release-test-trilium-1'],text=True).strip();assert old==current,'Rollback image differs'
with urllib.request.urlopen('http://127.0.0.1:19092/api/health-check',timeout=5) as response:assert response.status==200
finally:dockerfile.write_bytes(original)
# 가장 최근에 이 검사에서 만든 백업을 별도 경로에 복원합니다.
backup=sorted((root/'backups').glob('*/data.tar.gz'))[-1];restore=root/'restore-check';restore.mkdir(exist_ok=False)
subprocess.run(['tar','-xzpf',str(backup),'-C',str(restore)],check=True)
db=sqlite3.connect('file:'+str(restore/'document.db')+'?mode=ro',uri=True)
rows=list(db.execute('SELECT noteId,title,blobId FROM notes WHERE isDeleted=0'));digest=hashlib.sha256(json.dumps(sorted(rows),ensure_ascii=False).encode()).hexdigest();db.close()
assert digest==json.loads((root/'before-update.json').read_text())['noteSnapshotSha256']
subprocess.run(['docker','run','-d','--name','trilium-ko-restore-test','-p','127.0.0.1:19093:8080','-v',str(restore)+':/home/node/trilium-data',old],check=True,stdout=subprocess.DEVNULL)
for i in range(60):
try:
with urllib.request.urlopen('http://127.0.0.1:19093/api/setup/status',timeout=2) as response:assert json.load(response)['isInitialized']
break
except Exception:
if i==59:raise
time.sleep(1)
report={'forcedFailureRejected':True,'previousImageRestored':True,'backupDataMatched':True,'restoredContainerStarted':True,'backup':str(backup),'restoredNoteSnapshotSha256':digest}
(root/'recovery-result.json').write_text(json.dumps(report,indent=2));print(json.dumps(report))