47 lines
3.3 KiB
Python
47 lines
3.3 KiB
Python
# Sage4274/4276 cleared whole-file gate. Product source is fixed before invocation.
|
||
import datetime,hashlib,json,os,pathlib,re,subprocess,threading,time
|
||
REPO=pathlib.Path(__file__).resolve().parents[4]
|
||
BASE=REPO/'agents/magica/work/queue-329'
|
||
OUT=BASE/'gate-r2'
|
||
def utc():return datetime.datetime.now(datetime.timezone.utc).isoformat(timespec='milliseconds')
|
||
def load():return pathlib.Path('/proc/loadavg').read_text().split()[0]
|
||
def nice19():os.setpriority(os.PRIO_PROCESS,0,19)
|
||
def run(label,cmd,seconds=1800):
|
||
scratch=subprocess.check_output(['mktemp','-d','/mnt/storage/scratch/tmp/XXXXXX'],text=True).strip()
|
||
env=dict(os.environ,TMPDIR=scratch,npm_config_offline='true',MOSAIC_REQUIRE_EDITOR_BUILD='1')
|
||
raw=pathlib.Path(scratch)/'stdout.txt';log=OUT/(label+'.txt');begin={'utc':utc(),'load1':load()};started=time.monotonic();events=[]
|
||
stop=threading.Event()
|
||
def sample():
|
||
with (OUT/(label+'.load.jsonl')).open('w') as f:
|
||
while not stop.is_set():f.write(json.dumps({'utc':utc(),'load1':load()})+'\n');f.flush();stop.wait(1)
|
||
thread=threading.Thread(target=sample);thread.start()
|
||
try:
|
||
with raw.open('w') as f:
|
||
f.write('command: '+json.dumps(['timeout','-k','10',str(seconds),*cmd])+'\nTMPDIR: '+scratch+'\nbegin: '+json.dumps(begin)+'\n');f.flush()
|
||
p=subprocess.Popen(['timeout','-k','10',str(seconds),*cmd],cwd=REPO,env=env,stdout=subprocess.PIPE,stderr=subprocess.STDOUT,text=True,preexec_fn=nice19)
|
||
priority=os.getpriority(os.PRIO_PROCESS,p.pid);f.write('launch nice: '+str(priority)+'\n');f.flush()
|
||
for line in p.stdout:
|
||
f.write(line);f.flush()
|
||
if re.match(r'^\s*(✖|not ok )',line):events.append({'utc':utc(),'load1':load(),'event':line.rstrip()})
|
||
rc=p.wait()
|
||
finally:stop.set();thread.join()
|
||
text=raw.read_text();log.write_text(''.join(line.rstrip()+'\n' for line in text.splitlines()))
|
||
counts={}
|
||
for k in ['tests','pass','fail','skipped','cancelled']:
|
||
matches=re.findall(r'^(?:ℹ |# )'+k+r' (\d+)',text,re.M);counts[k]=int(matches[-1]) if matches else None
|
||
receipt={'label':label,'rc':rc,'nice':priority,'begin':begin,'end':{'utc':utc(),'load1':load()},'seconds':round(time.monotonic()-started,3),'counts':counts,'failure_events':events,'log':str(log.relative_to(REPO)),'raw':str(raw),'raw_sha256':hashlib.sha256(raw.read_bytes()).hexdigest(),'review_sha256':hashlib.sha256(log.read_bytes()).hexdigest(),'normalization':'trailing whitespace only; raw retained'}
|
||
with (OUT/'runs.jsonl').open('a') as f:f.write(json.dumps(receipt)+'\n')
|
||
print(json.dumps(receipt),flush=True)
|
||
return rc
|
||
for file in sorted((REPO/'packages/model-proxy/tests').glob('*.test.mjs')):
|
||
if run('model-proxy-'+file.stem,['node','--test',str(file)]):raise SystemExit(1)
|
||
readers=json.loads((BASE/'r2-reader-files.json').read_text())
|
||
for name in readers:
|
||
if name.endswith('/federation-acceptance.test.mjs'):
|
||
if run('cli-federation-acceptance-runner',['bash',str(REPO/'scripts/test-federation-acceptance.sh')],600):raise SystemExit(1)
|
||
else:
|
||
f=pathlib.Path(name)
|
||
if run(f.parts[1]+'-'+f.stem,['node','--test',str(REPO/f)]):raise SystemExit(1)
|
||
if run('test-config.sh',['bash',str(REPO/'scripts/test-config.sh')],600):raise SystemExit(1)
|
||
print('Round2 gate complete.',flush=True)
|