83 lines
4.8 KiB
Python
83 lines
4.8 KiB
Python
#!/usr/bin/python3
|
|
"""New private receipt per attempt; no compiler/native build or installed state."""
|
|
import argparse
|
|
import hashlib
|
|
import json
|
|
import os
|
|
from pathlib import Path
|
|
import subprocess
|
|
import shutil
|
|
import time
|
|
|
|
repo = Path(__file__).resolve().parents[2]
|
|
base = Path('/home/archipelago/Reports/opencode-full-release-20261029')
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument('label', help='unused alphanumeric receipt label')
|
|
parser.add_argument('stop', nargs='?', default='revoke', choices=('revoke', 'stall'))
|
|
parser.add_argument('--terminal-tests', type=Path, help='already rebuilt archipelago backend test binary; never builds here')
|
|
args = parser.parse_args()
|
|
assert args.label.isalnum(), 'supply an unused alphanumeric attempt label'
|
|
stop_case = args.stop
|
|
lane = base / ('c01-runtime-service-' + args.label)
|
|
lane.mkdir(mode=0o700, exist_ok=False)
|
|
source_paths = [repo / 'scripts' / name for name in ('runtime_owner.py', 'c01_runtime.py', 'c01_runtime_groups.py', 'c01_runtime_view.py')]
|
|
source_paths += list((repo / 'scripts/tests').glob('*runtime*.py'))
|
|
source_paths += list((repo / 'image-recipe/configs').glob('*runtime*'))
|
|
frozen = [repo / 'scripts' / name for name in ('c01_supervisor.py', 'c01_children.py', 'c01_views.py',
|
|
'c01_nts.py', 'c01_recovery.py', 'c01_host_watch.py')]
|
|
frozen += [repo / 'core/runtime-proxy.c']
|
|
frozen += [repo / 'core/archipelago/src/api/handler/terminal.rs',
|
|
repo / 'tests/regression/c01-supervisor.py', repo / 'tests/regression/terminal-workspace-sandbox.py']
|
|
def hashes(paths):
|
|
return {str(path.relative_to(repo)): hashlib.sha256(path.read_bytes()).hexdigest() for path in paths}
|
|
before = hashes(source_paths)
|
|
frozen_before = hashes(frozen)
|
|
(lane / 'source.json').write_text(json.dumps(before, indent=2))
|
|
(lane / 'frozen.json').write_text(json.dumps(frozen_before, indent=2))
|
|
oci = base / 'indee-frontend-oci-r1/indeehub-frontend-56ad62d0535b-linux-amd64.oci.tar'
|
|
assert oci.is_file()
|
|
proxy_source = base / 'isolation-build-target/debug/build/archipelago-47fc6b7c7bb86b2b/out/archipelago-runtime-proxy'
|
|
proxy = lane / 'archipelago-runtime-proxy'
|
|
shutil.copyfile(proxy_source, proxy)
|
|
proxy.chmod(0o755)
|
|
(lane / 'proxy.json').write_text(json.dumps({'source': str(proxy_source),
|
|
'sha256': hashlib.sha256(proxy.read_bytes()).hexdigest(), 'rebuilt_here': False}, indent=2))
|
|
terminal_bind = ''
|
|
if args.terminal_tests is not None:
|
|
source = args.terminal_tests.resolve(strict=True)
|
|
assert source.is_file()
|
|
terminal = lane / 'runtime-terminal-tests'
|
|
shutil.copyfile(source, terminal)
|
|
terminal.chmod(0o755)
|
|
(lane / 'terminal-tests.json').write_text(json.dumps({'source': str(source),
|
|
'sha256': hashlib.sha256(terminal.read_bytes()).hexdigest(), 'rebuilt_here': False}, indent=2))
|
|
terminal_bind = f' {terminal}:/opt/runtime-terminal-tests'
|
|
unit = 'c01-runtime-fixture-' + args.label + '-' + str(os.getpid())
|
|
command = ['sudo', '-n', 'systemd-run', '--quiet', '--wait', '--pipe', '--collect', '--unit=' + unit,
|
|
'-p', 'Delegate=yes', '-p', 'PrivateMounts=yes', '-p', 'PrivateNetwork=yes',
|
|
'-p', 'ProtectSystem=strict', '-p', 'NoNewPrivileges=no',
|
|
'-p', 'TemporaryFileSystem=/run /home /root /var/lib /tmp /var/tmp /opt',
|
|
'-p', f'BindReadOnlyPaths={repo}:/opt/source {oci}:/run/public.oci.tar {proxy}:/opt/archipelago-runtime-proxy{terminal_bind}',
|
|
'-p', 'CPUAffinity=2 3', '-p', 'AllowedCPUs=2-3', '-p', 'CPUQuota=200%',
|
|
'-p', 'MemoryMax=2G', '-p', 'MemorySwapMax=0', '-p', 'TasksMax=512',
|
|
'-p', 'RuntimeMaxSec=240', '-p', 'TimeoutStopSec=10',
|
|
'--setenv=ARCHY_RUNTIME_FIXTURE=1', '--setenv=PYTHONDONTWRITEBYTECODE=1',
|
|
'--setenv=ARCHY_RUNTIME_STOP=' + stop_case,
|
|
'/usr/bin/python3', '-B', '/opt/source/scripts/tests/runtime_service_fixture.py']
|
|
(lane / 'command.json').write_text(json.dumps(command, indent=2))
|
|
start = time.monotonic()
|
|
with (lane / 'stdout.log').open('wb') as out, (lane / 'stderr.log').open('wb') as err:
|
|
try:
|
|
result = subprocess.run(command, stdout=out, stderr=err, timeout=270)
|
|
code = result.returncode
|
|
except subprocess.TimeoutExpired:
|
|
code = 124
|
|
subprocess.run(['sudo', '-n', 'systemctl', 'stop', unit], timeout=20, check=False)
|
|
receipt = {'exit_code': code, 'seconds': time.monotonic() - start, 'source_unchanged': hashes(source_paths) == before,
|
|
'frozen_unchanged': hashes(frozen) == frozen_before, 'compiler_run': False, 'installed_acceptance': False,
|
|
'native_terminal_fixture_requested': args.terminal_tests is not None,
|
|
'system_manager_dropin_qualification': False}
|
|
(lane / 'result.json').write_text(json.dumps(receipt, indent=2))
|
|
print(lane, json.dumps(receipt), flush=True)
|
|
raise SystemExit(code)
|