Files
jobtrackingapp/docs/redesign/phase-9/p9-sec-02/model/run.py
T
cesnimda b48f25c4ff
MariaDB persistence qualification / mariadb (push) Has been cancelled
test: qualify immutable models and Phase 9 regression
2026-10-25 13:43:50 +01:00

60 lines
4.0 KiB
Python

"""Run one immutable local qualification lane; retain each attempt and teardown outcome."""
from pathlib import Path
import datetime
import json
import subprocess
import sys
import time
import uuid
from cleanup import container_absent
ROOT=Path(__file__).resolve().parents[5]
HERE=Path(__file__).resolve().parent
lane=sys.argv[1];attempt=sys.argv[2] if len(sys.argv)>2 else lane
assert Path(attempt).name==attempt and attempt not in ['.','..']
assert lane in ['safetensors','weights-only','cache','parsers','inventory','sidecar']
out=ROOT/'.artifacts/p9-sec-02/qualified'/attempt
assert not out.exists(),'Preserve earlier lane evidence.'
out.mkdir(parents=True)
runtime=json.loads((HERE/'RUNTIME.json').read_text())
image=runtime['qualificationImageId']
name='jt-sec02-'+lane+'-'+uuid.uuid4().hex[:8]
args=['docker','run','--rm','--name',name,'--label','jobtracker.qualification=p9-sec02','--entrypoint','python','--user','65534:65534','--network','none','--read-only','--cap-drop','ALL','--security-opt','no-new-privileges','--pids-limit','128','--cpus','2','--memory','2g','--memory-swap','2g','--tmpfs','/tmp:rw,nosuid,nodev,size=384m,mode=1777']
for value in ['HF_HUB_OFFLINE=1','TRANSFORMERS_OFFLINE=1','HF_HUB_DISABLE_TELEMETRY=1','HF_HOME=/tmp/hf-home','OMP_NUM_THREADS=1','MKL_NUM_THREADS=1','OLLAMA_BASE_URL=http://127.0.0.1:11434','OLLAMA_MODEL=','EXTERNAL_AI_ENABLED=0']:
args+=['-e',value]
args+=['--mount',f'type=bind,src={HERE},dst=/qualification,readonly','--mount',f'type=bind,src={out},dst=/evidence']
if lane in ['safetensors','weights-only','cache','parsers']:
fixture='artifact-bin' if lane=='weights-only' else 'artifact'
args+=['--mount',f'type=bind,src={ROOT/".artifacts/p9-sec-02"/fixture},dst=/fixture,readonly']
if lane=='sidecar':args+=['-e','AI_SERVICE_SKIP_MODEL_LOAD=1']
args+=[image]
if lane in ['safetensors','weights-only']:args+=['/qualification/probe.py',lane,'/fixture']
elif lane=='cache':args+=['/qualification/cache_probe.py','/fixture']
elif lane=='parsers':args+=['/qualification/parser_probe.py']
elif lane=='inventory':args+=['/qualification/runtime_inventory.py']
else:args+=['-m','pytest','-q','-o','cache_dir=/tmp/pytest-cache','/app/tests','--junitxml=/evidence/sidecar.xml']
started=datetime.datetime.now(datetime.timezone.utc).isoformat()
with (out/'process.log').open('w',encoding='utf-8') as log:
try:code=subprocess.run(['rtk','proxy',*args],cwd=ROOT,stdout=log,stderr=subprocess.STDOUT,timeout=180).returncode
except subprocess.TimeoutExpired:
code=124
try:
check=subprocess.run(['rtk','proxy','docker','inspect','--format','{{index .Config.Labels "jobtracker.qualification"}}',name],capture_output=True,text=True,timeout=5)
if check.returncode==0 and check.stdout.strip()=='p9-sec02':subprocess.run(['rtk','proxy','docker','kill',name],capture_output=True,timeout=10)
except (OSError,subprocess.TimeoutExpired):pass
deadline=time.monotonic()+5
cleanup_error=None
while True:
try:absent=container_absent(name)
except RuntimeError as error:
absent=None;cleanup_error=str(error);break
if absent or time.monotonic()>=deadline:break
time.sleep(.1)
record={'lane':lane,'attempt':attempt,'startedUtc':started,'finishedUtc':datetime.datetime.now(datetime.timezone.utc).isoformat(),'exitCode':code,'command':args,'localImageId':image,'runtimeImageId':runtime['runtimeImageId'],'containerAbsent':absent,'network':'none','readOnly':True,'user':'65534:65534','memoryLimitBytes':2147483648,'cpuLimit':2,'pidsLimit':128,'wallClockDeadlineSeconds':180,'scope':'Actual locally built source image plus exact test-only extras; no app source mount, production cache, external network, registry push or deployment.'}
record['cleanupStatus']='ABSENT' if absent else 'UNKNOWN' if absent is None else 'PRESENT'
record['cleanupError']=cleanup_error
(out/'process.json').write_text(json.dumps(record,indent=2)+'\n')
print(json.dumps(record))
print((out/'process.log').read_text(encoding='utf-8',errors='replace')[-2500:].encode('ascii','replace').decode())
raise SystemExit(code if absent else 1)