#!/usr/bin/env python3 """Capture only a completed, byte-identical and CRC-verified Forgejo ZIP.""" import argparse import hashlib from pathlib import Path import secrets import subprocess import time import zipfile ESSENTIALS_FLAGS = ['--skip-package-data', '--skip-log', '--skip-index', '--skip-repo-archives'] def validate_archive(path, profile="full"): with zipfile.ZipFile(path) as archive: if sum(i.file_size for i in archive.infolist()) > 20*1024**3: raise ValueError('archive exceeds recovery size bound') names = set(archive.namelist()) if 'forgejo-db.sql' not in names or not any(n.startswith('repos/') for n in names): raise ValueError('required archive content missing') if profile == 'essentials' and any(n.startswith(('data/packages/', 'data/repo-archive/', 'data/indexers/')) and not n.endswith('/') for n in names): raise ValueError('excluded data present in essentials archive') if archive.testzip() is not None: raise ValueError('archive checksum failure') def capture(namespace, pod, destination, profile="full"): if profile not in ("full", "essentials"): raise ValueError("unknown archive profile") k = ['kubectl', 'exec', '--request-timeout=120s', '-n', namespace, pod, '-c', 'gitea', '--'] def call(args, timeout=150): r = subprocess.run(k + args, capture_output=True, timeout=timeout) if r.returncode: raise ValueError('capture command failed') return r.stdout remote = '/tmp/wp0029-backup-' + secrets.token_hex(12) completed = False try: # Completion belongs to this exact process, not a global pgrep or file existence. flags = ' '.join(ESSENTIALS_FLAGS) if profile == 'essentials' else '' command = f'umask 077; forgejo dump {flags} -f {remote}.zip >{remote}.log 2>&1; result=$?; printf "%s" "$result" >{remote}.exit' call(['sh','-c', 'nohup sh -c "$1" >/dev/null 2>&1