#!/usr/bin/env python3 """Validate the exact CI artifact, then transfer it with one SSH connection.""" import base64 import hashlib import json import os from pathlib import Path import re import shlex import subprocess import sys import tarfile def validate(folder): manifest = json.loads((folder / 'manifest.json').read_text()) if manifest.get('schemaVersion') != 1 or manifest.get('runtime') != 'java-25': raise SystemExit('Unsupported release manifest/runtime') if not re.fullmatch(r'[0-9a-f]{40}', manifest.get('commit', '')): raise SystemExit('Missing full source commit') with (folder / 'werkjournal.jar').open('rb') as stream: actual = hashlib.file_digest(stream, 'sha256').hexdigest() if actual != manifest.get('sha256') or manifest.get('files') != {'werkjournal.jar': actual}: raise SystemExit('Artifact checksum does not match manifest') return manifest if __name__ == '__main__': target, folder = sys.argv[1], Path(sys.argv[2]).resolve() manifest = validate(folder) mode = sys.argv[3] if len(sys.argv) == 4 else '--prototype' remote_script = {'--prototype': 'deploy-prototype-remote.py', '--guest-preview': 'deploy-guest-preview-remote.py', '--update': 'deploy-update-remote.py', '--upload': 'deploy-update-remote.py'}[mode] script = Path(__file__).with_name(remote_script).read_bytes() encoded = base64.b64encode(script).decode('ascii') command = 'python3 -c ' + shlex.quote("import base64; exec(compile(base64.b64decode('" + encoded + "'), 'deploy-prototype-remote.py', 'exec'))") if mode == '--upload': command += ' --upload' print(('Uploading' if mode == '--upload' else 'Deploying') + ' verified application commit ' + manifest['commit'], flush=True) ssh = ['ssh', '-o', 'BatchMode=yes'] key = os.environ.get('WERKJOURNAL_DEPLOY_KEY') host_keys = os.environ.get('WERKJOURNAL_DEPLOY_HOST_KEYS') if bool(key) != bool(host_keys): raise SystemExit('Deployment identity and pinned host keys must be configured together') if key: ssh += ['-i', key, '-o', 'IdentitiesOnly=yes', '-o', 'StrictHostKeyChecking=yes', '-o', 'UserKnownHostsFile=' + host_keys] process = subprocess.Popen([*ssh, target, command], stdin=subprocess.PIPE) try: with tarfile.open(fileobj=process.stdin, mode='w|') as archive: for name in ['manifest.json', 'werkjournal.jar']: archive.add(folder / name, arcname=name, recursive=False) finally: process.stdin.close() raise SystemExit(process.wait())